summaryrefslogtreecommitdiff
path: root/src/socket
diff options
context:
space:
mode:
authorAndrew Opalach <andrew@akon.city> 2024-10-04 13:36:54 -0400
committerAndrew Opalach <andrew@akon.city> 2024-10-04 13:36:54 -0400
commit9e63fb59e7b8506183172869ea44b68cdec29be5 (patch)
treea47f51121275477b3ce93b1d2b82ea1f342d68ed /src/socket
parenta320ee672ccf52297dc509b25ed263f165709b31 (diff)
downloadlibnaunet-9e63fb59e7b8506183172869ea44b68cdec29be5.tar.gz
libnaunet-9e63fb59e7b8506183172869ea44b68cdec29be5.tar.bz2
libnaunet-9e63fb59e7b8506183172869ea44b68cdec29be5.zip
Tons of changes
Mainly for things that came up in other projects. Signed-off-by: Andrew Opalach <andrew@akon.city>
Diffstat (limited to 'src/socket')
-rw-r--r--src/socket/socket.h20
-rw-r--r--src/socket/socket_internal.h11
-rw-r--r--src/socket/socket_linux.c170
-rw-r--r--src/socket/socket_windows.c122
4 files changed, 191 insertions, 132 deletions
diff --git a/src/socket/socket.h b/src/socket/socket.h
index bb42a3d..18e3040 100644
--- a/src/socket/socket.h
+++ b/src/socket/socket.h
@@ -1,21 +1,20 @@
#pragma once
+#include <al/types.h>
+#include <al/str.h>
+
#ifndef _WIN32
#include <unistd.h>
#include <sys/socket.h>
+#include <sys/un.h>
+#include <sys/eventfd.h>
#include <netinet/in.h>
#include <arpa/inet.h>
-#include <netinet/in.h>
#include <poll.h>
-#include <sys/un.h>
-#include <sys/eventfd.h>
#else
#include "../winwrap.h"
#endif
-#include <al/types.h>
-#include <al/str.h>
-
enum {
AKI_SOCKET_TCP = 0,
AKI_SOCKET_UDP,
@@ -26,10 +25,11 @@ struct aki_socket {
u8 type;
#ifndef _WIN32
s32 fd;
- struct sockaddr_in addr_in;
+ struct addrinfo *addrinfo;
struct sockaddr_un addr_un;
#else
SOCKET fd;
+ s32 internal_fd;
SOCKADDR_IN addr_in;
#endif
};
@@ -62,9 +62,11 @@ void aki_socket_set_nodelay(struct aki_socket *sock, s32 nodelay);
void aki_socket_set_send_buf(struct aki_socket *sock, u32 sndbuf);
u32 aki_socket_get_send_buf(struct aki_socket *sock);
-bool aki_socket_listen(struct aki_socket *sock, str *addr, s32 port);
+bool aki_socket_set(struct aki_socket *sock, str *addr, u16 port);
+bool aki_socket_bind(struct aki_socket *sock, str *addr, u16 port);
+bool aki_socket_listen(struct aki_socket *sock);
bool aki_socket_accept(struct aki_socket *sock, struct aki_socket *c);
-bool aki_socket_connect(struct aki_socket *sock, str *addr, s32 port);
+bool aki_socket_connect(struct aki_socket *sock, str *addr, u16 port);
s32 aki_socket_get_fd(struct aki_socket *sock);
diff --git a/src/socket/socket_internal.h b/src/socket/socket_internal.h
new file mode 100644
index 0000000..33f6a7b
--- /dev/null
+++ b/src/socket/socket_internal.h
@@ -0,0 +1,11 @@
+#pragma once
+
+#include <al/str.h>
+
+static str *ipany = al_str_c("0.0.0.0");
+static inline str *aki_socket_display_addr(str *addr)
+{
+ return addr ? addr : ipany;
+}
+
+#define aki_socket_printf_addr(addr) AL_STR_PRINTF(aki_socket_display_addr(addr))
diff --git a/src/socket/socket_linux.c b/src/socket/socket_linux.c
index adab91b..753f6b9 100644
--- a/src/socket/socket_linux.c
+++ b/src/socket/socket_linux.c
@@ -1,5 +1,4 @@
#include <al/log.h>
-#include <unistd.h>
#include <sys/fcntl.h>
#include <netinet/tcp.h>
#include <netdb.h>
@@ -7,6 +6,7 @@
#include "../util/error.h"
#include "socket.h"
+#include "socket_internal.h"
void aki_fd_set_blocking(s32 fd, bool blocking)
{
@@ -31,7 +31,7 @@ bool aki_socket_init(struct aki_socket *sock)
{
switch (sock->type) {
case AKI_SOCKET_TCP:
- sock->fd = socket(AF_INET, SOCK_STREAM, 0);
+ sock->fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
break;
case AKI_SOCKET_UDP:
sock->fd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
@@ -39,6 +39,8 @@ bool aki_socket_init(struct aki_socket *sock)
case AKI_SOCKET_UNIX:
sock->fd = socket(AF_UNIX, SOCK_STREAM, 0);
break;
+ default:
+ al_assert_and_return(false);
}
if (sock->fd < 0) {
@@ -46,6 +48,8 @@ bool aki_socket_init(struct aki_socket *sock)
return false;
}
+ sock->addrinfo = NULL;
+
return true;
}
@@ -56,8 +60,7 @@ void aki_socket_set_blocking(struct aki_socket *sock, bool blocking)
void aki_socket_set_nodelay(struct aki_socket *sock, s32 nodelay)
{
- //al_assert(sock->type == AKI_SOCKET_TCP);
- if (sock->type != AKI_SOCKET_TCP) return; // TODO:
+ al_assert(sock->type == AKI_SOCKET_TCP);
setsockopt(sock->fd, IPPROTO_TCP, TCP_NODELAY, &nodelay, sizeof(nodelay));
}
@@ -91,141 +94,155 @@ void aki_socket_set_recv_buf(struct aki_socket *sock, u32 rcvbuf)
al_assert(aki_socket_get_recv_buf(sock) == receive_queue_size);
}
-#define al_log_socket_err(func) \
- al_log_error("socket", #func"(%.*s:%d) failed: %s (%d).", \
- AL_STR_PRINTF(addr), port, aki_strerror(errno), errno);
+static bool parse_address(struct aki_socket *sock, str *addr, u16 port)
+{
+ struct addrinfo hints = { 0 };
+ hints.ai_family = AF_INET;
+ switch (sock->type) {
+ case AKI_SOCKET_TCP:
+ hints.ai_socktype = SOCK_STREAM;
+ hints.ai_protocol = IPPROTO_TCP;
+ break;
+ case AKI_SOCKET_UDP:
+ hints.ai_socktype = SOCK_DGRAM;
+ hints.ai_protocol = IPPROTO_UDP;
+ break;
+ }
+
+ char *c_str = addr ? al_str_to_c_str(addr) : NULL;
+ if (!c_str) hints.ai_flags = AI_PASSIVE;
+ char port_str[6];
+ al_sprintf(port_str, "%hu", port);
+ s32 status = getaddrinfo(c_str, port_str, &hints, &sock->addrinfo);
+ al_free(c_str);
+ if (status != 0) {
+ al_log_error("socket", "Failed to parse address (%s).", gai_strerror(status));
+ return false;
+ }
+
+ return true;
+}
+
+bool aki_socket_set(struct aki_socket *sock, str *addr, u16 port)
+{
+ al_assert(sock->type == AKI_SOCKET_UDP);
+ return parse_address(sock, addr, port);
+}
-bool aki_socket_listen(struct aki_socket *sock, str *addr, s32 port)
+bool aki_socket_bind(struct aki_socket *sock, str *addr, u16 port)
{
struct sockaddr *saddr = NULL;
socklen_t addrlen = 0;
switch (sock->type) {
- case AKI_SOCKET_TCP: {
- sock->addr_in.sin_family = AF_INET;
- sock->addr_in.sin_addr.s_addr = htonl(INADDR_ANY);
- sock->addr_in.sin_port = htons(port);
- saddr = (struct sockaddr *)&sock->addr_in;
- addrlen = sizeof(sock->addr_in);
+ case AKI_SOCKET_TCP:
+ case AKI_SOCKET_UDP: {
+ if (!parse_address(sock, addr, port)) return false;
+ saddr = sock->addrinfo->ai_addr;
+ addrlen = sock->addrinfo->ai_addrlen;
break;
}
case AKI_SOCKET_UNIX: {
+ al_assert(addr);
sock->addr_un.sun_family = AF_UNIX;
char *c_str = al_str_to_c_str(addr);
al_memcpy(sock->addr_un.sun_path, c_str, al_strlen(c_str) + 1);
+ unlink(c_str);
al_free(c_str);
saddr = (struct sockaddr *)&sock->addr_un;
addrlen = sizeof(sock->addr_un);
break;
}
- case AKI_SOCKET_UDP:
- al_assert(false);
+ default:
+ al_assert_and_return(false);
}
if (bind(sock->fd, saddr, addrlen) < 0) {
- al_log_socket_err(bind)
+ al_log_error("socket", "bind(%.*s:%hu) failed: %s (%d).",
+ aki_socket_printf_addr(addr), port, aki_strerror(errno), errno);
return false;
}
+ al_log_info("socket", "Socket bound to %.*s:%hu.", aki_socket_printf_addr(addr), port);
+
+ return true;
+}
+
+bool aki_socket_listen(struct aki_socket *sock)
+{
+ al_assert(sock->type == AKI_SOCKET_TCP || sock->type == AKI_SOCKET_UNIX);
+
if (listen(sock->fd, SOMAXCONN) < 0) {
- al_log_socket_err(listen)
+ al_log_error("socket", "listen() failed: %s (%d).", aki_strerror(errno), errno);
return false;
}
- al_log_info("socket", "Listening on %.*s:%d.", AL_STR_PRINTF(addr), port);
+ al_log_info("socket", "Listening.");
return true;
}
bool aki_socket_accept(struct aki_socket *sock, struct aki_socket *cl)
{
- cl->type = sock->type;
+ al_assert(sock->type == AKI_SOCKET_TCP || sock->type == AKI_SOCKET_UNIX);
+ cl->type = sock->type;
struct sockaddr_storage addr;
- socklen_t len = sizeof(addr);
- if ((cl->fd = accept(sock->fd, (struct sockaddr *)&addr, &len)) == -1) {
+ socklen_t addrlen = sizeof(addr);
+ if ((cl->fd = accept(sock->fd, (struct sockaddr *)&addr, &addrlen)) == -1) {
al_log_error("socket", "accept() failed: %s (%d).", aki_strerror(errno), errno);
return false;
}
+ cl->addrinfo = NULL;
+
switch (cl->type) {
case AKI_SOCKET_TCP: {
- s32 port = 0;
- char ipstr[INET6_ADDRSTRLEN] = { 0 };
+ u16 port = 0;
+ char addr_str[INET6_ADDRSTRLEN] = { 0 };
if (addr.ss_family == AF_INET) {
struct sockaddr_in *saddr = (struct sockaddr_in *)&addr;
port = ntohs(saddr->sin_port);
- inet_ntop(AF_INET, &saddr->sin_addr, ipstr, sizeof(ipstr));
+ inet_ntop(AF_INET, &saddr->sin_addr, addr_str, sizeof(addr_str));
} else if (addr.ss_family == AF_INET6) {
struct sockaddr_in6 *saddr = (struct sockaddr_in6 *)&addr;
port = ntohs(saddr->sin6_port);
- inet_ntop(AF_INET6, &saddr->sin6_addr, ipstr, sizeof(ipstr));
+ inet_ntop(AF_INET6, &saddr->sin6_addr, addr_str, sizeof(addr_str));
}
- al_log_info("socket", "Connection from %s:%d.", ipstr, port);
+ al_log_info("socket", "Connection from %s:%hu.", addr_str, port);
break;
}
case AKI_SOCKET_UNIX:
al_log_info("socket", "Connection on UNIX socket.");
break;
- case AKI_SOCKET_UDP:
- al_assert(false);
}
return true;
}
-bool aki_socket_connect(struct aki_socket *sock, str *addr, s32 port)
+bool aki_socket_connect(struct aki_socket *sock, str *addr, u16 port)
{
+ s32 ret;
switch (sock->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);
-
- if (!hptr) {
- al_log_error("socket", "Failed to parse address.");
- return false;
- }
-
- if (hptr->h_addrtype != AF_INET) {
- al_log_error("socket", "Bad address family.");
- return false;
- }
-
- sock->addr_in.sin_family = AF_INET;
- sock->addr_in.sin_addr.s_addr = ((struct in_addr *)hptr->h_addr_list[0])->s_addr;
- sock->addr_in.sin_port = htons(port);
-
- break;
- }
- default:
- break;
- }
-
- switch (sock->type) {
- case AKI_SOCKET_TCP:
- case AKI_SOCKET_UDP: {
- s32 ret = connect(sock->fd, (struct sockaddr *)&sock->addr_in, sizeof(sock->addr_in));
- if (ret != 0 && errno != EINPROGRESS) {
- al_log_socket_err(connect)
- return false;
- }
+ case AKI_SOCKET_UDP:
+ if (!parse_address(sock, addr, port)) return false;
+ ret = connect(sock->fd, sock->addrinfo->ai_addr, sock->addrinfo->ai_addrlen);
break;
- }
- case AKI_SOCKET_UNIX: {
+ case AKI_SOCKET_UNIX:
sock->addr_un.sun_family = AF_UNIX;
al_memcpy(sock->addr_un.sun_path, addr->data, addr->len);
sock->addr_un.sun_path[addr->len] = '\0';
- if (connect(sock->fd, (struct sockaddr *)&sock->addr_un, sizeof(sock->addr_un)) < 0) {
- al_log_socket_err(connect)
- return false;
- }
+ ret = connect(sock->fd, (struct sockaddr *)&sock->addr_un, sizeof(sock->addr_un));
break;
- }
default:
- al_assert(false);
- break;
+ al_assert_and_return(false);
+ }
+
+ if (ret != 0 && errno != EINPROGRESS) {
+ al_log_error("socket", "connect(%.*s:%hu) failed: %s (%d).",
+ aki_socket_printf_addr(addr), port, aki_strerror(errno), errno);
+ return false;
}
return true;
@@ -243,13 +260,12 @@ ssize_t aki_socket_write(struct aki_socket *sock, void *buf, size_t size)
ssize_t aki_socket_sendto(struct aki_socket *sock, void *buf, size_t size)
{
- return sendto(sock->fd, buf, size, 0, (const struct sockaddr *)&sock->addr_in, sizeof(sock->addr_in));
+ return sendto(sock->fd, buf, size, 0, sock->addrinfo->ai_addr, sock->addrinfo->ai_addrlen);
}
ssize_t aki_socket_recvfrom(struct aki_socket *sock, void *buf, size_t size)
{
- socklen_t addrlen = sizeof(sock->addr_in);
- return recvfrom(sock->fd, buf, size, 0, (struct sockaddr *)&sock->addr_in, &addrlen);
+ return recvfrom(sock->fd, buf, size, 0, sock->addrinfo->ai_addr, &sock->addrinfo->ai_addrlen);
}
s32 aki_socket_get_fd(struct aki_socket *sock)
@@ -265,4 +281,8 @@ void aki_socket_shutdown(struct aki_socket *sock)
void aki_socket_close(struct aki_socket *sock)
{
close(sock->fd);
+ if (sock->addrinfo) {
+ freeaddrinfo(sock->addrinfo);
+ sock->addrinfo = NULL;
+ }
}
diff --git a/src/socket/socket_windows.c b/src/socket/socket_windows.c
index a7192d8..013a5bd 100644
--- a/src/socket/socket_windows.c
+++ b/src/socket/socket_windows.c
@@ -1,116 +1,142 @@
#include <al/log.h>
#include "socket.h"
+#include "socket_internal.h"
-bool aki_socket_init(struct aki_socket *s)
+bool aki_socket_init(struct aki_socket *sock)
{
- switch (s->type) {
+ al_assert(sock->type == AKI_SOCKET_TCP);
+
+ switch (sock->type) {
case AKI_SOCKET_TCP:
- s->sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
+ sock->fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
break;
- case AKI_SOCKET_UDP:
- al_assert(false);
- return false;
- case AKI_SOCKET_UNIX:
- al_assert(false);
- return false;
}
- if (s->sock == INVALID_SOCKET) {
+ if (sock->fd == INVALID_SOCKET) {
al_log_error("socket", "socket() failed: %d.", WSAGetLastError());
return false;
}
+ sock->internal_fd = _open_osfhandle(sock->fd, 0);
+
return true;
}
-void aki_socket_set_blocking(struct aki_socket *s, bool blocking)
+void aki_socket_set_blocking(struct aki_socket *sock, bool blocking)
{
u_long mode = blocking ? 0 : 1;
- ioctlsocket(s->sock, FIONBIO, &mode);
+ ioctlsocket(sock->fd, FIONBIO, &mode);
}
-void aki_socket_set_nodelay(struct aki_socket *s, s32 nodelay)
+void aki_socket_set_nodelay(struct aki_socket *sock, s32 nodelay)
{
- (void)s;
+ (void)sock;
(void)nodelay;
}
-#define al_log_socket_err(func) \
- al_log_error("socket", #func"(%.*s:%d) failed: %d.", \
- AL_STR_PRINTF(addr), port, WSAGetLastError());
+bool aki_socket_set(struct aki_socket *sock, str *addr, u16 port)
+{
+ (void)sock;
+ (void)addr;
+ (void)port;
+ return false;
+}
-bool aki_socket_listen(struct aki_socket *s, str *addr, s32 port)
+bool aki_socket_bind(struct aki_socket *sock, str *addr, u16 port)
{
- s->addr_in.sin_family = AF_INET;
- s->addr_in.sin_addr.s_addr = INADDR_ANY;
- s->addr_in.sin_port = aki_htons(port);
- al_memset(s->addr_in.sin_zero, '\0', 8);
- if (bind(s->sock, (SOCKADDR *)&s->addr_in, sizeof(s->addr_in)) == SOCKET_ERROR) {
- al_log_socket_err(bind);
+ sock->addr_in.sin_family = AF_INET;
+ sock->addr_in.sin_addr.s_addr = INADDR_ANY;
+ sock->addr_in.sin_port = aki_htons(port);
+ al_memset(sock->addr_in.sin_zero, '\0', sizeof(sock->addr_in.sin_zero));
+ if (bind(sock->fd, (SOCKADDR *)&sock->addr_in, sizeof(sock->addr_in)) == SOCKET_ERROR) {
+ al_log_error("socket", "bind(%.*s:%hu) failed: %d.",
+ aki_socket_printf_addr(addr), port, WSAGetLastError());
return false;
}
- if (listen(s->sock, SOMAXCONN) == SOCKET_ERROR) {
- al_log_socket_err(listen);
+
+ al_log_info("socket", "Socket bound to %.*s:%hu.", aki_socket_printf_addr(addr), port);
+
+ return true;
+}
+
+bool aki_socket_listen(struct aki_socket *sock)
+{
+ if (listen(sock->fd, SOMAXCONN) == SOCKET_ERROR) {
+ al_log_error("socket", "listen() failed: %d.", WSAGetLastError());
return false;
}
+
+ al_log_info("socket", "Listening.");
+
return true;
}
-bool aki_socket_accept(struct aki_socket *s, struct aki_socket *c)
+bool aki_socket_accept(struct aki_socket *sock, struct aki_socket *cl)
{
- c->type = s->type;
- if ((c->sock = accept(s->sock, NULL, NULL)) == INVALID_SOCKET) {
+ cl->type = sock->type;
+ if ((cl->fd = accept(sock->fd, NULL, NULL)) == INVALID_SOCKET) {
+ al_log_error("socket", "accept() failed: %d.", WSAGetLastError());
return false;
}
+ cl->internal_fd = _open_osfhandle(cl->fd, 0);
return true;
}
-bool aki_socket_connect(struct aki_socket *s, str *addr, s32 port)
+bool aki_socket_connect(struct aki_socket *sock, str *addr, u16 port)
{
- s->addr_in.sin_family = AF_INET;
+ sock->addr_in.sin_family = AF_INET;
char *c_str = al_str_to_c_str(addr);
- s->addr_in.sin_addr.s_addr = inet_addr(c_str);
+ sock->addr_in.sin_addr.s_addr = inet_addr(c_str);
al_free(c_str);
- s->addr_in.sin_port = aki_htons(port);
- al_memset(s->addr_in.sin_zero, '\0', 8);
- s32 ret = connect(s->sock, (SOCKADDR *)&s->addr_in, sizeof(s->addr_in));
+ sock->addr_in.sin_port = aki_htons(port);
+ al_memset(sock->addr_in.sin_zero, '\0', sizeof(sock->addr_in.sin_zero));
+ s32 ret = connect(sock->fd, (SOCKADDR *)&sock->addr_in, sizeof(sock->addr_in));
if (ret == SOCKET_ERROR && WSAGetLastError() != WSAEWOULDBLOCK) {
- al_log_socket_err(connect);
+ al_log_error("socket", "connect() failed: %d.", WSAGetLastError());
return false;
}
return true;
}
-s32 aki_socket_get_fd(struct aki_socket *s)
+s32 aki_socket_get_fd(struct aki_socket *sock)
+{
+ return sock->internal_fd;
+}
+
+ssize_t aki_socket_read(struct aki_socket *sock, void *buf, size_t size)
{
- return _open_osfhandle(s->sock, 0);
+ return recv(sock->fd, buf, (s32)size, 0);
}
-ssize_t aki_socket_read(struct aki_socket *s, void *buf, size_t size)
+ssize_t aki_socket_write(struct aki_socket *sock, void *buf, size_t size)
{
- return recv(s->sock, buf, (s32)size, 0);
+ return send(sock->fd, buf, (s32)size, 0);
}
-ssize_t aki_socket_write(struct aki_socket *s, void *buf, size_t size)
+ssize_t aki_socket_sendto(struct aki_socket *sock, void *buf, size_t size)
{
- return send(s->sock, buf, (s32)size, 0);
+ (void)sock;
+ (void)buf;
+ (void)size;
+ return 0;
}
-ssize_t aki_socket_sendto(struct aki_socket *s, void *buf, size_t size)
+ssize_t aki_socket_recvfrom(struct aki_socket *sock, void *buf, size_t size)
{
- (void)s;
+ (void)sock;
(void)buf;
(void)size;
return 0;
}
-void aki_socket_shutdown(struct aki_socket *s)
+void aki_socket_shutdown(struct aki_socket *sock)
{
- if (shutdown(s->sock, SD_SEND) == SOCKET_ERROR) {}
+ if (shutdown(sock->fd, SD_BOTH) == SOCKET_ERROR) {}
}
-void aki_socket_close(struct aki_socket *s)
+void aki_socket_close(struct aki_socket *sock)
{
- closesocket(s->sock);
+ _close(sock->internal_fd);
+ //closesocket(sock->fd);
}