#define AL_LOG_SECTION "socket" #include #include "../util/error.h" #include "socket.h" #include "socket_internal.h" #include "net.h" bool nn_socket_init(struct nn_socket *sock, s32 flags) { al_assert(sock->type == NNWT_SOCKET_TCP); switch (sock->type) { case NNWT_SOCKET_TCP: sock->fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); break; } if (sock->fd == INVALID_SOCKET) { log_error("socket() failed: %d.", WSAGetLastError()); return false; } nn_socket_apply_flags(sock, flags); sock->internal_fd = _open_osfhandle(sock->fd, 0); return true; } void nn_socket_set_blocking(struct nn_socket *sock, bool blocking) { u_long mode = blocking ? 0 : 1; ioctlsocket(sock->fd, FIONBIO, &mode); } void nn_socket_set_nodelay(struct nn_socket *sock, s32 nodelay) { (void)sock; (void)nodelay; } void nn_socket_set_reuse_addr(struct nn_socket *sock, s32 reuse_addr) { (void)sock; (void)reuse_addr; } bool nn_socket_set(struct nn_socket *sock, str *addr, u16 port) { (void)sock; (void)addr; (void)port; return false; } bool nn_socket_bind(struct nn_socket *sock, str *addr, u16 port) { sock->addr_in.sin_family = AF_INET; al_memset(sock->addr_in.sin_zero, '\0', sizeof(sock->addr_in.sin_zero)); sock->addr_in.sin_addr.s_addr = INADDR_ANY; sock->addr_in.sin_port = nn_htons(port); s32 ret = bind(sock->fd, (SOCKADDR *)&sock->addr_in, sizeof(sock->addr_in)); if (ret == SOCKET_ERROR) { log_error("bind(%.*s:%hu) failed: %d.", nn_addr_x(addr), port, WSAGetLastError()); return false; } log_debug("Socket bound to %.*s:%hu.", nn_addr_x(addr), port); return true; } bool nn_socket_listen(struct nn_socket *sock) { if (listen(sock->fd, SOMAXCONN) == SOCKET_ERROR) { log_error("listen() failed: %d.", WSAGetLastError()); return false; } log_debug("Listening."); return true; } bool nn_socket_accept(struct nn_socket *sock, struct nn_socket *cl, s32 flags) { cl->type = sock->type; if ((cl->fd = accept(sock->fd, NULL, NULL)) == INVALID_SOCKET) { log_error("accept() failed: %d.", WSAGetLastError()); return false; } nn_socket_apply_flags(sock, flags); cl->internal_fd = _open_osfhandle(cl->fd, 0); return true; } bool nn_socket_connect(struct nn_socket *sock, str *addr, u16 port) { sock->addr_in.sin_family = AF_INET; al_memset(sock->addr_in.sin_zero, '\0', sizeof(sock->addr_in.sin_zero)); char *c_str = al_str_to_c_str(addr); sock->addr_in.sin_addr.s_addr = inet_addr(c_str); al_free(c_str); sock->addr_in.sin_port = nn_htons(port); s32 ret = connect(sock->fd, (SOCKADDR *)&sock->addr_in, sizeof(sock->addr_in)); if (ret == SOCKET_ERROR && WSAGetLastError() != WSAEWOULDBLOCK) { log_error("connect(%.*s:%hu) failed: %d.", nn_addr_x(addr), port, WSAGetLastError()); return false; } return true; } s32 nn_socket_get_fd(struct nn_socket *sock) { return sock->internal_fd; } ssize_t nn_socket_read(struct nn_socket *sock, void *buf, size_t size) { return (ssize_t)recv(sock->fd, buf, (s32)size, 0); } ssize_t nn_socket_write(struct nn_socket *sock, void *buf, size_t size) { return (ssize_t)send(sock->fd, buf, (s32)size, 0); } ssize_t nn_socket_sendto(struct nn_socket *sock, void *buf, size_t size) { (void)sock; (void)buf; (void)size; return 0; } ssize_t nn_socket_recvfrom(struct nn_socket *sock, void *buf, size_t size) { (void)sock; (void)buf; (void)size; return 0; } bool nn_socket_check_error(ssize_t ret) { if (ret == SOCKET_ERROR) { s32 err = WSAGetLastError(); char *strerror = nn_win32_error_message(err); log_debug("Socket error: %s (%d).", strerror ? strerror : "(None)", err); return true; } return false; } void nn_socket_shutdown(struct nn_socket *sock) { if (shutdown(sock->fd, SD_BOTH) == SOCKET_ERROR) {} } void nn_socket_close(struct nn_socket *sock) { _close(sock->internal_fd); // https://learn.microsoft.com/en-us/cpp/c-runtime-library/reference/close?view=msvc-170 // Based on these docs, I assume calling closesocket() is not necessary. //closesocket(sock->fd); } void nn_socket_cleanup(struct nn_socket *sock) { (void)sock; }