diff options
Diffstat (limited to 'src/socket')
| -rw-r--r-- | src/socket/socket.h | 22 | ||||
| -rw-r--r-- | src/socket/socket_linux.c | 181 | ||||
| -rw-r--r-- | src/socket/socket_windows.c | 28 |
3 files changed, 105 insertions, 126 deletions
diff --git a/src/socket/socket.h b/src/socket/socket.h index ea307e7..4971c1c 100644 --- a/src/socket/socket.h +++ b/src/socket/socket.h @@ -21,10 +21,6 @@ enum { struct aki_socket { u8 type; - struct { - bool blocking; - bool no_delay; - } config; #ifndef _WIN32 s32 sock; struct sockaddr_in addr_in; @@ -37,20 +33,25 @@ struct aki_socket { #ifndef _WIN32 #define aki_read read -#else -#define aki_read _read -#endif - -#ifndef _WIN32 #define aki_write write +#define aki_htons htons +#define aki_htonl htonl +#define aki_ntohs ntohs #else +#define aki_read _read #define aki_write _write +#define aki_htons(...) 0 +#define aki_htonl(...) 0 +#define aki_ntohs(...) 0 #endif bool aki_socket_init(struct aki_socket *s); void aki_socket_set_blocking(struct aki_socket *s, bool blocking); -void aki_socket_set_no_delay(struct aki_socket *s, bool no_delay); +void aki_socket_set_no_delay(struct aki_socket *s, s32 no_delay); + +void aki_socket_set_send_buf(struct aki_socket *s, u32 sndbuf); +u32 aki_socket_get_send_buf(struct aki_socket *s); bool aki_socket_listen(struct aki_socket *s, str *addr, s32 port); bool aki_socket_accept(struct aki_socket *s, struct aki_socket *c); @@ -61,6 +62,7 @@ s32 aki_socket_get_fd(struct aki_socket *s); ssize_t aki_socket_read(struct aki_socket *s, void *buf, size_t size); ssize_t aki_socket_write(struct aki_socket *s, void *buf, size_t size); ssize_t aki_socket_sendto(struct aki_socket *s, void *buf, size_t size); +ssize_t aki_socket_recvfrom(struct aki_socket *s, void *buf, size_t size); void aki_socket_shutdown(struct aki_socket *s); void aki_socket_close(struct aki_socket *s); diff --git a/src/socket/socket_linux.c b/src/socket/socket_linux.c index b466dea..7bc9ea9 100644 --- a/src/socket/socket_linux.c +++ b/src/socket/socket_linux.c @@ -9,48 +9,6 @@ #include "socket.h" -static void socket_set_blocking(struct aki_socket *s, bool blocking) -{ - s32 flags = fcntl(s->sock, F_GETFL, 0); - al_assert(flags != -1); - flags = blocking ? (flags & ~O_NONBLOCK) : (flags | O_NONBLOCK); - s32 ret = fcntl(s->sock, F_SETFL, flags); - al_assert(ret == 0); -} - -static void socket_set_no_delay(struct aki_socket *s, s32 no_delay) -{ - if (s->type == AKI_SOCKET_TCP) { - setsockopt(s->sock, IPPROTO_TCP, TCP_NODELAY, &no_delay, sizeof(no_delay)); - } -} - -static void socket_set_send_buf(struct aki_socket *s, u32 sndbuf) -{ - u32 send_queue_size = sndbuf; - setsockopt(s->sock, SOL_SOCKET, SO_SNDBUF, &send_queue_size, sizeof(send_queue_size)); - - socklen_t optlen = sizeof(send_queue_size); - getsockopt(s->sock, SOL_SOCKET, SO_SNDBUF, &send_queue_size, &optlen); - - if (send_queue_size != sndbuf * 2) { - al_log_warn("socket", "Failed to set SO_SNDBUF."); - } -} - -static void socket_set_recv_buf(struct aki_socket *s, u32 rcvbuf) -{ - u32 receive_queue_size = rcvbuf; - setsockopt(s->sock, SOL_SOCKET, SO_RCVBUF, &receive_queue_size, sizeof(receive_queue_size)); - - socklen_t optlen = sizeof(receive_queue_size); - getsockopt(s->sock, SOL_SOCKET, SO_RCVBUF, &receive_queue_size, &optlen); - - if (receive_queue_size != rcvbuf * 2) { - al_log_warn("socket", "Failed to set SO_RCVBUF."); - } -} - bool aki_socket_init(struct aki_socket *s) { switch (s->type) { @@ -70,63 +28,52 @@ bool aki_socket_init(struct aki_socket *s) return false; } - aki_socket_set_blocking(s, s->config.blocking); - aki_socket_set_no_delay(s, s->config.no_delay); - return true; } void aki_socket_set_blocking(struct aki_socket *s, bool blocking) { - s->config.blocking = blocking; - socket_set_blocking(s, blocking); + s32 flags = fcntl(s->sock, F_GETFL, 0); + al_assert(flags != -1); + flags = blocking ? (flags & ~O_NONBLOCK) : (flags | O_NONBLOCK); + s32 ret = fcntl(s->sock, F_SETFL, flags); + al_assert(ret == 0); } -void aki_socket_set_no_delay(struct aki_socket *s, bool no_delay) +void aki_socket_set_no_delay(struct aki_socket *s, s32 no_delay) { - s->config.no_delay = no_delay; - socket_set_no_delay(s, no_delay); + if (s->type != AKI_SOCKET_TCP) return; + setsockopt(s->sock, IPPROTO_TCP, TCP_NODELAY, &no_delay, sizeof(no_delay)); } -bool aki_socket_accept(struct aki_socket *s, struct aki_socket *c) +u32 aki_socket_get_send_buf(struct aki_socket *s) { - c->type = s->type; - - struct sockaddr_storage addr; - socklen_t len = sizeof(addr); - if((c->sock = accept(s->sock, (struct sockaddr *)&addr, &len)) == -1) { - return false; - } + u32 send_queue_size; + socklen_t optlen = sizeof(send_queue_size); + getsockopt(s->sock, SOL_SOCKET, SO_SNDBUF, &send_queue_size, &optlen); + return send_queue_size / 2; +} - aki_socket_set_blocking(c, c->config.blocking); - aki_socket_set_no_delay(c, c->config.no_delay); +void aki_socket_set_send_buf(struct aki_socket *s, u32 sndbuf) +{ + u32 send_queue_size = sndbuf; + setsockopt(s->sock, SOL_SOCKET, SO_SNDBUF, &send_queue_size, sizeof(send_queue_size)); + al_assert(aki_socket_get_send_buf(s) == send_queue_size); +} - switch (s->type) { - case AKI_SOCKET_TCP: { - s32 port = 0; - char ipstr[INET6_ADDRSTRLEN] = {0}; - if (addr.ss_family == AF_INET) { - struct sockaddr_in *s = (struct sockaddr_in *)&addr; - port = ntohs(s->sin_port); - inet_ntop(AF_INET, &s->sin_addr, ipstr, sizeof(ipstr)); - } else if (addr.ss_family == AF_INET6) { - struct sockaddr_in6 *s = (struct sockaddr_in6 *)&addr; - port = ntohs(s->sin6_port); - inet_ntop(AF_INET6, &s->sin6_addr, ipstr, sizeof(ipstr)); - } - al_log_info("socket", "Connection from %s:%d.", ipstr, port); - break; - } - case AKI_SOCKET_UNIX: { - al_log_info("socket", "Connection from a UNIX socket."); - break; - } - case AKI_SOCKET_UDP: { - al_assert(false); - } - } +u32 aki_socket_get_recv_buf(struct aki_socket *s) +{ + u32 receive_queue_size; + socklen_t optlen = sizeof(receive_queue_size); + getsockopt(s->sock, SOL_SOCKET, SO_RCVBUF, &receive_queue_size, &optlen); + return receive_queue_size / 2; +} - return true; +void aki_socket_set_recv_buf(struct aki_socket *s, u32 rcvbuf) +{ + u32 receive_queue_size = rcvbuf; + setsockopt(s->sock, SOL_SOCKET, SO_RCVBUF, &receive_queue_size, sizeof(receive_queue_size)); + al_assert(aki_socket_get_recv_buf(s) == receive_queue_size); } bool aki_socket_listen(struct aki_socket *s, str *addr, s32 port) @@ -154,10 +101,9 @@ bool aki_socket_listen(struct aki_socket *s, str *addr, s32 port) addrlen = sizeof(s->addr_un); break; } - case AKI_SOCKET_UDP: { + case AKI_SOCKET_UDP: al_assert(false); } - } if (bind(s->sock, saddr, addrlen) < 0) { al_log_error("socket", "Failed to bind (%.*s:%d).", AL_STR_PRINTF(addr), port); @@ -176,10 +122,47 @@ bool aki_socket_listen(struct aki_socket *s, str *addr, s32 port) return true; } -bool aki_socket_connect(struct aki_socket *s, str *addr, s32 port) +bool aki_socket_accept(struct aki_socket *s, struct aki_socket *c) { + c->type = s->type; + + struct sockaddr_storage addr; + socklen_t len = sizeof(addr); + if ((c->sock = accept(s->sock, (struct sockaddr *)&addr, &len)) == -1) { + return false; + } + switch (s->type) { case AKI_SOCKET_TCP: { + s32 port = 0; + char ipstr[INET6_ADDRSTRLEN] = {0}; + if (addr.ss_family == AF_INET) { + struct sockaddr_in *s = (struct sockaddr_in *)&addr; + port = ntohs(s->sin_port); + inet_ntop(AF_INET, &s->sin_addr, ipstr, sizeof(ipstr)); + } else if (addr.ss_family == AF_INET6) { + struct sockaddr_in6 *s = (struct sockaddr_in6 *)&addr; + port = ntohs(s->sin6_port); + inet_ntop(AF_INET6, &s->sin6_addr, ipstr, sizeof(ipstr)); + } + al_log_info("socket", "Connection from %s:%d.", ipstr, port); + break; + } + case AKI_SOCKET_UNIX: + al_log_info("socket", "Connection from a UNIX socket."); + break; + case AKI_SOCKET_UDP: + al_assert(false); + } + + return true; +} + +bool aki_socket_connect(struct aki_socket *s, str *addr, s32 port) +{ + switch (s->type) { + case AKI_SOCKET_TCP: + case AKI_SOCKET_UDP: { char *c_str = al_str_to_c_str(addr); struct hostent *hptr = gethostbyname(c_str); al_free(c_str); @@ -198,13 +181,20 @@ bool aki_socket_connect(struct aki_socket *s, str *addr, s32 port) s->addr_in.sin_addr.s_addr = ((struct in_addr *)hptr->h_addr_list[0])->s_addr; s->addr_in.sin_port = htons(port); - s32 ret = connect(s->sock, (struct sockaddr *)&s->addr_in, sizeof(s->addr_in)); + break; + } + default: + break; + } + switch (s->type) { + case AKI_SOCKET_TCP: + case AKI_SOCKET_UDP: { + s32 ret = connect(s->sock, (struct sockaddr *)&s->addr_in, sizeof(s->addr_in)); if (ret != 0 && errno != 115) { al_log_error("socket", "Failed to connect: %s (%d).", aki_strerror(errno), errno); return false; } - break; } case AKI_SOCKET_UNIX: { @@ -217,10 +207,9 @@ bool aki_socket_connect(struct aki_socket *s, str *addr, s32 port) } break; } - case AKI_SOCKET_UDP: { + default: al_assert(false); } - } signal(SIGPIPE, SIG_IGN); @@ -239,7 +228,13 @@ ssize_t aki_socket_write(struct aki_socket *s, void *buf, size_t size) ssize_t aki_socket_sendto(struct aki_socket *s, void *buf, size_t size) { - return sendto(s->sock, buf, size, 0, (const struct sockaddr *)&s->addr_un, sizeof(s->addr_un)); + return sendto(s->sock, buf, size, 0, (const struct sockaddr *)&s->addr_in, sizeof(s->addr_in)); +} + +ssize_t aki_socket_recvfrom(struct aki_socket *s, void *buf, size_t size) +{ + socklen_t addrlen = sizeof(s->addr_in); + return recvfrom(s->sock, buf, size, 0, (struct sockaddr *)&s->addr_in, &addrlen); } s32 aki_socket_get_fd(struct aki_socket *s) diff --git a/src/socket/socket_windows.c b/src/socket/socket_windows.c index 6e72aea..b83ae52 100644 --- a/src/socket/socket_windows.c +++ b/src/socket/socket_windows.c @@ -2,18 +2,6 @@ #include "socket.h" -static void socket_set_blocking(struct aki_socket *s, bool blocking) -{ - u_long mode = (blocking) ? 0 : 1; - ioctlsocket(s->sock, FIONBIO, &mode); -} - -static void socket_set_no_delay(struct aki_socket *s, s32 no_delay) -{ - (void)s; - (void)no_delay; -} - bool aki_socket_init(struct aki_socket *s) { switch (s->type) { @@ -33,22 +21,19 @@ bool aki_socket_init(struct aki_socket *s) return false; } - aki_socket_set_blocking(s, s->config.blocking); - aki_socket_set_no_delay(s, s->config.no_delay); - return true; } void aki_socket_set_blocking(struct aki_socket *s, bool blocking) { - s->config.blocking = blocking; - socket_set_blocking(s, blocking); + u_long mode = (blocking) ? 0 : 1; + ioctlsocket(s->sock, FIONBIO, &mode); } -void aki_socket_set_no_delay(struct aki_socket *s, bool no_delay) +void aki_socket_set_no_delay(struct aki_socket *s, s32 no_delay) { - s->config.no_delay = no_delay; - socket_set_no_delay(s, no_delay); + (void)s; + (void)no_delay; } bool aki_socket_listen(struct aki_socket *s, str *addr, s32 port) @@ -76,9 +61,6 @@ bool aki_socket_accept(struct aki_socket *s, struct aki_socket *c) return false; } - aki_socket_set_blocking(c, c->config.blocking); - aki_socket_set_no_delay(c, c->config.no_delay); - return true; } |