Mercurial
view seobeo/s_linux_network.c @ 4:0b3b4f5887bb
[Seobeo] Updated so that it create socket for both server and clients.
| author | June Park <parkjune1995@gmail.com> |
|---|---|
| date | Fri, 26 Sep 2025 15:14:46 -0700 |
| parents | 2758f5527d2b |
| children | 1e61008b9980 |
line wrap: on
line source
#include "seobeo/seobeo.h" int Seobeo_CreateSocket(int32 stream, const char *host, const char* port, int32 backlog) { 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; if (getaddrinfo(host, port, &hints, &server_infos) != 0) { perror("getaddrinfo"); return -1; } for ( free_server_info = server_infos; free_server_info != NULL; 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 (bind(sock_fd, free_server_info->ai_addr, free_server_info->ai_addrlen) == -1) { close(sock_fd); perror("setsockopt"); 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 freeaddrinfo(server_infos); if (free_server_info == NULL) { perror("No free server"); return -1; } // TCP listen if(stream) { if (listen(sock_fd, backlog) != 0) { perror("listen"); close(sock_fd); return -1; } } return sock_fd; } Seobeo_PHandle Seobeo_Stream_Handle_Create(const char *host, const char* port) { Seobeo_PHandle p_handle; p_handle = malloc(sizeof(*p_handle)); p_handle->socket = Seobeo_CreateSocket(1, host, port, 10); // socke fd p_handle->host = host != NULL ? strdup(host) : "localhost"; p_handle->port = strdup(port); 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; 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; return p_handle; } Seobeo_PHandle Seobeo_Stream_Handle_Accept(Seobeo_PHandle server_h) { struct sockaddr_storage addr; socklen_t addrlen = sizeof addr; char client_inet_addr[INET6_ADDRSTRLEN]; int client_fd = accept(server_h->socket, (struct sockaddr*)&addr, &addrlen); inet_ntop( addr.ss_family, Seobeo_GetIP4OrIP6((struct sockaddr *)&addr), client_inet_addr, sizeof client_inet_addr); if (client_fd == -1) { return NULL; } Seobeo_PHandle h = malloc(sizeof *h); h->socket = client_fd; h->host = strdup(client_inet_addr); h->port = NULL; h->read_buffer_capacity = server_h->read_buffer_capacity; h->read_buffer_len = 0; h->read_buffer = malloc(h->read_buffer_capacity); h->write_buffer_capacity = server_h->write_buffer_capacity; h->write_buffer_len = 0; h->write_buffer = malloc(h->write_buffer_capacity); return h; } void Seobeo_Handle_Destroy(Seobeo_PHandle h) { close(h->socket); free(h->host); free(h->port); free(h->read_buffer); free(h->write_buffer); free(h->file); free(h->text_copy); free(h->file_name); free(h); } int Seobeo_Handle_Flush(Seobeo_PHandle h) { uint32 total = h->write_buffer_len; uint32 sent = 0; while (sent < total) { ssize_t n = write( h->socket, h->write_buffer + sent, total - sent ); if (n < 0) { if (errno == EINTR) continue; if (errno == EAGAIN) return 1; return -1; } sent += (uint32)n; } h->write_buffer_len = 0; return 0; } int Seobeo_Handle_QueueData(Seobeo_PHandle h, const uint8_t *data, uint32_t data_size) { if (h->write_buffer_len + data_size > h->write_buffer_capacity) { int rc = Seobeo_Handle_Flush(h); if (rc < 0) return -1; if (rc > 0) return 1; } if (data_size > h->write_buffer_capacity) { uint32_t offset = 0; while (offset < data_size) { ssize_t n = write(h->socket, data + offset, data_size - offset); if (n < 0) { if (errno == EINTR) continue; if (errno == EAGAIN) return 1; return -1; } offset += (uint32_t)n; } return 0; } memcpy(h->write_buffer + h->write_buffer_len, data, data_size); h->write_buffer_len += data_size; return 0; } void *Seobeo_GetIP4OrIP6(struct sockaddr *sa) { if (sa->sa_family == AF_INET) { return &(((struct sockaddr_in*)sa)->sin_addr); } return &(((struct sockaddr_in6*)sa)->sin6_addr); }