Mercurial
diff seobeo/s_linux_network.c @ 18:fa2b8af609d9
[Seobeo] Fixed a bug with pathing. Support SSL.
| author | June Park <parkjune1995@gmail.com> |
|---|---|
| date | Mon, 06 Oct 2025 08:21:34 -0700 |
| parents | d97ec3ded2ae |
| children | 875bb6e10db7 |
line wrap: on
line diff
--- a/seobeo/s_linux_network.c Sat Oct 04 07:53:12 2025 -0700 +++ b/seobeo/s_linux_network.c Mon Oct 06 08:21:34 2025 -0700 @@ -1,20 +1,20 @@ #include "seobeo/seobeo.h" -int Seobeo_CreateSocket(int32 stream, const char *host, const char* port) -{ - struct addrinfo hints = {0}, *server_infos, *free_server_info; - int32 sock_fd, yes = 1; // Need this for setsockopt - hints.ai_family = AF_INET; - hints.ai_socktype = stream ? SOCK_STREAM : SOCK_DGRAM; - hints.ai_protocol = stream ? IPPROTO_TCP : IPPROTO_UDP; - hints.ai_flags = stream ? AI_PASSIVE : 0; +Seobeo_PHandle Seobeo_Stream_Handle_Server_Create(const char *host, const char* port) +{ + Seobeo_PHandle p_handle; + struct addrinfo hints, *server_infos, *free_server_info; + int32 socket_fd, yes = 1; // Need this for setsockopt + + memset(&hints, 0, sizeof hints); + hints.ai_family = AF_UNSPEC; + hints.ai_socktype = SOCK_STREAM; + hints.ai_protocol = IPPROTO_TCP; + hints.ai_flags = AI_PASSIVE; if (getaddrinfo(host, port, &hints, &server_infos) != 0) - { - perror("getaddrinfo"); - return -1; - } + { perror("getaddrinfo"); return NULL; } for ( @@ -23,88 +23,107 @@ free_server_info = free_server_info->ai_next ) { - if - ( - (sock_fd = socket( - free_server_info->ai_family, free_server_info->ai_socktype, - free_server_info->ai_protocol - )) == -1 - ) - { - perror("socket"); - continue; - } - - if (setsockopt(sock_fd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes)) == -1) - { - perror("setsockopt"); - continue; - } + if((socket_fd = socket(free_server_info->ai_family, + free_server_info->ai_socktype, free_server_info->ai_protocol)) == -1) + { perror("socket"); continue; } - if (host != NULL) - { - if (connect(sock_fd, free_server_info->ai_addr, free_server_info->ai_addrlen) == -1) - { - perror("connect"); - continue; - } + if (setsockopt(socket_fd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes)) == -1) + { perror("setsockopt"); continue; } - } - else - { - if (bind(sock_fd, free_server_info->ai_addr, free_server_info->ai_addrlen) == -1) - { - perror("v_network: Couldn't make socket non-blocking\n"); - continue; - } + if (bind(socket_fd, free_server_info->ai_addr, free_server_info->ai_addrlen) == -1) + { perror("v_network: Couldn't make socket non-blocking\n"); continue; } - // UDP should be non blocking - if(!stream) - { - if (fcntl(sock_fd, F_SETFL, O_NONBLOCK) != 0) - { - close(sock_fd); - perror("v_network: Couldn't make socket non-blocking\n"); - return -1; - } - } - } - // binded to a open server infos; break; } - // No longer need these values + if (listen(socket_fd, 16) != 0) + { perror("listen"); close(socket_fd); return NULL; } + + if(fcntl(socket_fd, F_SETFL, O_NONBLOCK) != 0) { perror("fcntl"); return NULL; } freeaddrinfo(server_infos); - if (free_server_info == NULL) - { - perror("No free server"); - return -1; - } + p_handle = malloc(sizeof(*p_handle)); + p_handle->socket = socket_fd; + p_handle->type = SEOBEO_STREAM_TYPE_SERVER; + p_handle->connected = FALSE; + + p_handle->host = host != NULL ? strdup(host) : "localhost"; + p_handle->port = strdup(port); + + p_handle->ssl_ctx = NULL; + p_handle->ssl = NULL; + - if (host == NULL) - { - if (listen(sock_fd, 16) != 0) - { - perror("listen"); - close(sock_fd); - return -1; - } - } + p_handle->read_buffer = malloc(sizeof(*p_handle->read_buffer) * INITIAL_BUFFER_CAPACITY); + p_handle->read_buffer_capacity = INITIAL_BUFFER_CAPACITY; + p_handle->read_buffer_len = 0; - return sock_fd; + p_handle->write_buffer = malloc(sizeof(*p_handle->read_buffer) * INITIAL_BUFFER_CAPACITY); + p_handle->write_buffer_capacity = INITIAL_BUFFER_CAPACITY; + p_handle->write_buffer_len = 0; + + p_handle->file = NULL; + p_handle->text_copy = NULL; + p_handle->file_name = NULL; + p_handle->destroyed = false; + + return p_handle; } -Seobeo_PHandle Seobeo_Stream_Handle_Create(const char *host, const char* port) + +Seobeo_PHandle Seobeo_Stream_Handle_Client_Create(const char *host, const char* port, boolean use_tls) { Seobeo_PHandle p_handle; p_handle = malloc(sizeof(*p_handle)); - p_handle->socket = Seobeo_CreateSocket(1, host, port); // socke fd - if (!p_handle->socket) + struct addrinfo hints, *server_infos, *free_server_info; + int32 socket_fd, yes = 1; // Need this for setsockopt + + memset(&hints, 0, sizeof hints); + hints.ai_family = AF_UNSPEC; + hints.ai_socktype = SOCK_STREAM; + + if (getaddrinfo(host, port, &hints, &server_infos) != 0) + { perror("getaddrinfo"); return NULL; } + + + if((socket_fd = socket(server_infos->ai_family, + server_infos->ai_socktype, server_infos->ai_protocol)) == -1) + { perror("socket"); return NULL; } + + if (connect(socket_fd, server_infos->ai_addr, server_infos->ai_addrlen) != 0) + { perror("connect"); return NULL; } + freeaddrinfo(server_infos); + + p_handle->socket = socket_fd; + p_handle->type = SEOBEO_STREAM_TYPE_CLIENT; + if (use_tls) { - perror("Seobeo_CreateSocket"); + printf("USE SSL\n\n"); + init_openssl(); + p_handle->ssl_ctx = SSL_CTX_new(TLS_client_method()); + SSL_CTX_set_default_verify_paths(p_handle->ssl_ctx); + + p_handle->ssl = SSL_new(p_handle->ssl_ctx); + SSL_set_fd(p_handle->ssl, p_handle->socket); + + SSL_set_tlsext_host_name(p_handle->ssl, host); + // Blocking for TSL handshake + fcntl(socket_fd, F_SETFL, 0); + + if (SSL_connect(p_handle->ssl) != 1) + { + fprintf(stderr, "SSL_connect failed\n"); + ERR_print_errors_fp(stderr); + return NULL; + } + }else + { + p_handle->ssl_ctx = NULL; + p_handle->ssl = NULL; } + p_handle->connected = true; + p_handle->host = host != NULL ? strdup(host) : "localhost"; p_handle->port = strdup(port); @@ -142,9 +161,16 @@ return NULL; } - Seobeo_PHandle p_client_handle = malloc(sizeof *p_client_handle); + Seobeo_PHandle p_client_handle = malloc(sizeof *p_client_handle); p_client_handle->socket = client_fd; + p_client_handle->type = SEOBEO_STREAM_TYPE_CLIENT; + p_client_handle->connected = true; + + // TODO: support SSL in the future. + p_client_handle->ssl_ctx = NULL; + p_client_handle->ssl = NULL; + p_client_handle->host = strdup(client_inet_addr); p_client_handle->port = NULL; @@ -156,6 +182,8 @@ p_client_handle->write_buffer_len = 0; p_client_handle->write_buffer = malloc(p_client_handle->write_buffer_capacity); + p_client_handle->destroyed = false; + return p_client_handle; } @@ -181,35 +209,56 @@ free(p_handle); } -int Seobeo_Handle_Flush(Seobeo_PHandle p_handle) + +int32 Seobeo_Handle_Flush(Seobeo_PHandle p_handle) { uint32 total = p_handle->write_buffer_len; uint32 sent = 0; + printf("Total: %d\n\n", p_handle->write_buffer_len); + while (sent < total) { - ssize_t n = write( - p_handle->socket, - p_handle->write_buffer + sent, - total - sent - ); - if (n < 0) { - if (errno == EINTR) continue; - if (errno == EAGAIN) return 1; - return -1; + if (p_handle->ssl) + { + int n = SSL_write(p_handle->ssl, p_handle->write_buffer + sent, total - sent); + if (n < 0) + { + int err = SSL_get_error(p_handle->ssl, n); + if (err == SSL_ERROR_WANT_READ || err == SSL_ERROR_WANT_WRITE) + { + // caller must wait for socket readiness and retry + return 0; + } + ERR_print_errors_fp(stderr); + return -1; + } + sent += (uint32)n; + }else + { + ssize_t n = write( + p_handle->socket, + p_handle->write_buffer + sent, + total - sent + ); + if (n < 0) { + if (errno == EINTR) continue; + if (errno == EAGAIN) return 1; + return -1; + } + sent += (uint32)n; } - sent += (uint32)n; } p_handle->write_buffer_len = 0; return 0; } -int Seobeo_Handle_Queue(Seobeo_PHandle p_handle, const uint8 *data, uint32 data_size) +int32 Seobeo_Handle_Queue(Seobeo_PHandle p_handle, const uint8 *data, uint32 data_size) { if (p_handle->write_buffer_len + data_size > p_handle->write_buffer_capacity) { - int rc = Seobeo_Handle_Flush(p_handle); + int32 rc = Seobeo_Handle_Flush(p_handle); if (rc < 0) return -1; if (rc > 0) return 1; } @@ -222,14 +271,29 @@ ssize_t n = write(p_handle->socket, data + offset, data_size - offset); + if (n==0) + { + // DEBUG + printf("NONE %d\n", offset); + break; + } if (n < 0) { - if (errno == EINTR) continue; + if (errno == EINTR || errno == EAGAIN) + { + // DEBUG + printf("Partial write, returning early (offset=%d)\n", offset); + continue; + } if (errno == EAGAIN) return 1; return -1; } offset += (uint32)n; + // DEBUG + printf("\n\noffset: %d data_size: %d\n\n", offset, data_size); } + // DEBUG + printf("\n\nTotal: %d\n", offset); return 0; } @@ -237,32 +301,54 @@ data, data_size); p_handle->write_buffer_len += data_size; + // DEBUG + printf("\nheader data_size: %d\n\n", data_size); return 0; } -int Seobeo_Handle_Read(Seobeo_PHandle p_handle) +int32 Seobeo_Handle_Read(Seobeo_PHandle p_handle) { + int32 read_size; + if (!p_handle) return -1; + // How many bytes we can still read into the buffer uint32 free_space = p_handle->read_buffer_capacity - p_handle->read_buffer_len; if (free_space == 0) return -1; - ssize_t n = read( - p_handle->socket, - p_handle->read_buffer + p_handle->read_buffer_len, - free_space - ); - if (n < 0) { - if (errno == EINTR) return Seobeo_Handle_Read(p_handle); - if (errno == EAGAIN) return 0; // no data available right now - return -1; // fatal error - } - if (n == 0) { - return -2; // peer closed the connection + if (p_handle->ssl) + { + read_size = (int32)SSL_read(p_handle->ssl, p_handle->read_buffer, + free_space); + if (read_size <= 0) + { + int err = SSL_get_error(p_handle->ssl, read_size); + switch (err) + { + case SSL_ERROR_WANT_READ: + case SSL_ERROR_WANT_WRITE: + return 0; + case SSL_ERROR_ZERO_RETURN: + default: + // TODO: Handle these errors + return -2; + } + } + }else + { + read_size = (int32)read(p_handle->socket, + p_handle->read_buffer + p_handle->read_buffer_len, + free_space); + if (read_size == 0) return -2; + if (read_size < 0) + { + if (errno == EAGAIN || errno == EWOULDBLOCK) return 0; + return -1; + } } - p_handle->read_buffer_len += (uint32)n; - return (int)n; // number of bytes read + p_handle->read_buffer_len += (uint32)read_size; + return read_size; } void Seobeo_Handle_Consume(Seobeo_PHandle p_handle, uint32 consumed)