1#include "../include/socket.h"
9static void printLastErrorMessage(
const char* prefix) {
10 LPSTR errorText = NULL;
12 DWORD flags = FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_IGNORE_INSERTS;
14 FormatMessageA(flags, NULL, (DWORD)WSAGetLastError(), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPSTR)&errorText,
17 if (errorText != NULL) {
18 fprintf(stderr,
"%s failed with error %d: %s\n", prefix, WSAGetLastError(), errorText);
21 fprintf(stderr,
"%s failed with unknown error %d\n", prefix, WSAGetLastError());
27void socket_initialize() {
29 WSAStartup(MAKEWORD(2, 2), &wsaData);
32void socket_cleanup() { WSACleanup(); }
34void socket_initialize(
void) {
37void socket_cleanup(
void) {
43Socket* socket_create(
int domain,
int type,
int protocol) {
44 Socket* sock = (Socket*)malloc(
sizeof(Socket));
50 sock->handle = socket(domain, type, protocol);
51 if (sock->handle == INVALID_SOCKET) {
54 printLastErrorMessage(
"socket");
58 sock->handle = socket(domain, type, protocol);
59 if (sock->handle == -1) {
68int socket_close(Socket* sock) {
72 ret = closesocket(sock->handle);
74 ret = close(sock->handle);
82int socket_bind(Socket* sock,
const struct sockaddr* addr, socklen_t addrlen) {
85 if ((ret = bind(sock->handle, addr, addrlen)) != 0) {
86 printLastErrorMessage(
"bind");
89 ret = bind(sock->handle, addr, addrlen);
98int socket_listen(Socket* sock,
int backlog) {
return listen(sock->handle, backlog); }
101Socket* socket_accept(Socket* sock,
struct sockaddr* addr, socklen_t* addrlen) {
102 Socket* client = (Socket*)malloc(
sizeof(Socket));
108 client->handle = accept(sock->handle, addr, addrlen);
109 if (client->handle == INVALID_SOCKET) {
111 printLastErrorMessage(
"accept");
115 client->handle = accept(sock->handle, addr, addrlen);
116 if (client->handle == -1) {
126int socket_connect(Socket* sock,
const struct sockaddr* addr, socklen_t addrlen) {
128 if (connect(sock->handle, addr, addrlen) == 0) {
145ssize_t socket_recv(Socket* sock,
void* buffer,
size_t size,
int flags) {
147 bytes = recv(sock->handle, buffer, size, flags);
158ssize_t socket_send(Socket* sock,
const void* buffer,
size_t size,
int flags) {
159 return send(sock->handle, buffer, size, flags);
163int socket_fd(Socket* sock) {
return sock->handle; }
165int socket_error(
void) {
167 return WSAGetLastError();
173void socket_strerror(
int err,
char* buffer,
size_t size) {
174 if (!buffer || size == 0)
return;
177 FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM, NULL, (DWORD)err, 0, buffer, (DWORD)size, NULL);
179 buffer[size - 1] =
'\0';
181#if defined(__GLIBC__) || defined(__linux__)
186 char* msg = strerror_r(err, buffer, size);
187 if (msg != buffer && msg != NULL) {
188 strncpy(buffer, msg, size - 1);
189 buffer[size - 1] =
'\0';
193 strerror_r(err, buffer, size);
194 buffer[size - 1] =
'\0';
200int socket_get_option(Socket* sock,
int level,
int optname,
void* optval, socklen_t* optlen) {
203 ret = getsockopt(sock->handle, level, optname, (
char*)optval, optlen);
205 ret = getsockopt(sock->handle, level, optname, optval, optlen);
211int socket_set_option(Socket* sock,
int level,
int optname,
const void* optval, socklen_t optlen) {
215 ret = setsockopt(sock->handle, level, optname, (
const char*)optval, optlen);
217 ret = setsockopt(sock->handle, level, optname, optval, optlen);
222int socket_reuse_port(Socket* sock,
int enable) {
225 if (setsockopt(sock->handle, SOL_SOCKET, SO_REUSEADDR, (
char*)&enable,
sizeof(
int)) == SOCKET_ERROR) {
226 perror(
"setsockopt");
227 fprintf(stderr,
"setsockopt SO_REUSEADDR failed\n");
232 if (setsockopt(sock->handle, SOL_SOCKET, SO_EXCLUSIVEADDRUSE, (
char*)&enable,
sizeof(
int)) == SOCKET_ERROR) {
233 perror(
"setsockopt");
234 fprintf(stderr,
"setsockopt SO_EXCLUSIVEADDRUSE failed\n");
241 if (setsockopt(sock->handle, SOL_SOCKET, SO_REUSEADDR, &enable,
sizeof(
int)) != 0) {
247 if (setsockopt(sock->handle, SOL_SOCKET, SO_REUSEPORT, &enable,
sizeof(
int)) != 0) {
257int socket_get_address(Socket* sock,
struct sockaddr* addr, socklen_t* addrlen) {
260 ret = getsockname(sock->handle, addr, addrlen);
262 ret = getsockname(sock->handle, addr, addrlen);
268int socket_get_peer_address(Socket* sock,
struct sockaddr* addr, socklen_t* addrlen) {
269 return getpeername(sock->handle, addr, addrlen);
272int socket_type(Socket* sock) {
275 socklen_t len =
sizeof(type);
276 if (socket_get_option(sock, SOL_SOCKET, SO_TYPE, &type, &len) == 0) {
282int socket_family(Socket* sock) {
284 socklen_t len =
sizeof(domain);
286 domain = socket_get_option(sock, SOL_SOCKET, SO_TYPE, &domain, &len);
287#elif defined(__APPLE__)
290 struct sockaddr_storage addr;
291 socklen_t addr_len =
sizeof(addr);
292 if (getsockname(sock->handle, (
struct sockaddr*)&addr, &addr_len) == 0) {
293 domain = addr.ss_family;
296 socket_get_option(sock, SOL_SOCKET, SO_DOMAIN, &domain, &len);
302int socket_set_non_blocking(Socket* sock,
int enable) {
304 u_long mode = enable ? 1 : 0;
305 return ioctlsocket(sock->handle, FIONBIO, &mode);
307 int flags = fcntl(sock->handle, F_GETFL, 0);
315 flags &= ~O_NONBLOCK;
317 return fcntl(sock->handle, F_SETFL, flags);
323struct sockaddr_in* socket_ipv4_address(
const char* ip, uint16_t port) {
324 struct sockaddr_in* addr = (
struct sockaddr_in*)malloc(
sizeof(
struct sockaddr_in));
329 memset(addr, 0,
sizeof(
struct sockaddr_in));
330 addr->sin_family = AF_INET;
331 addr->sin_port = htons(port);
332 addr->sin_addr.s_addr = inet_addr(ip);
338struct sockaddr_in6* socket_ipv6_address(
const char* ip, uint16_t port) {
339 struct sockaddr_in6* addr = (
struct sockaddr_in6*)malloc(
sizeof(
struct sockaddr_in6));
344 memset(addr, 0,
sizeof(
struct sockaddr_in6));
345 addr->sin6_family = AF_INET6;
346 addr->sin6_port = htons(port);
347 inet_pton(AF_INET6, ip, &addr->sin6_addr);