bit better sockets

This commit is contained in:
alessandro.bason 2021-10-20 10:51:18 +01:00
parent c4d1ffe539
commit aa08240ec9
4 changed files with 111 additions and 25 deletions

2
http.c
View file

@ -289,7 +289,7 @@ http_response_t hcliSendRequest(http_client_t *ctx, http_request_t *req) {
goto skopen_error; goto skopen_error;
} }
ctx->socket = skOpen(); ctx->socket = skOpen(SOCK_TCP);
if(ctx->socket == INVALID_SOCKET) { if(ctx->socket == INVALID_SOCKET) {
err("couldn't open socket %s", skGetErrorString()); err("couldn't open socket %s", skGetErrorString());
goto error; goto error;

View file

@ -1,6 +1,12 @@
#include "socket.h" #include "socket.h"
#include <stdio.h> #include <stdio.h>
#include "tracelog.h"
#ifndef NDEBUG
// VERY MUCH NOT THREAD SAFE
static int initialize_count = 0;
#endif
#if SOCK_WINDOWS #if SOCK_WINDOWS
#include <ws2tcpip.h> #include <ws2tcpip.h>
@ -13,8 +19,6 @@ static const char *_win_skGetErrorString();
#define SOCK_CALL(fun) _win_##fun #define SOCK_CALL(fun) _win_##fun
#elif SOCK_POSIX #elif SOCK_POSIX
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netdb.h> #include <netdb.h>
#include <unistd.h> #include <unistd.h>
#include <errno.h> #include <errno.h>
@ -33,18 +37,37 @@ static const char *_posix_skGetErrorString();
#endif #endif
bool skInit() { bool skInit() {
#ifndef NDEBUG
++initialize_count;
#endif
return SOCK_CALL(skInit()); return SOCK_CALL(skInit());
} }
bool skCleanup() { bool skCleanup() {
#ifndef NDEBUG
--initialize_count;
#endif
return SOCK_CALL(skCleanup()); return SOCK_CALL(skCleanup());
} }
socket_t skOpen() { socket_t skOpen(skType type) {
return skOpenPro(AF_INET, SOCK_STREAM, 0); int sock_type;
switch(type) {
case SOCK_TCP: sock_type = SOCK_STREAM; break;
case SOCK_UDP: sock_type = SOCK_DGRAM; break;
default: fatal("skType not recognized: %d", type); break;
}
return skOpenPro(AF_INET, sock_type, 0);
} }
socket_t skOpenEx(const char *protocol) { socket_t skOpenEx(const char *protocol) {
#ifndef NDEBUG
if(initialize_count <= 0) {
fatal("skInit has not been called");
}
#endif
struct protoent *proto = getprotobyname(protocol); struct protoent *proto = getprotobyname(protocol);
if(!proto) { if(!proto) {
return INVALID_SOCKET; return INVALID_SOCKET;
@ -53,9 +76,22 @@ socket_t skOpenEx(const char *protocol) {
} }
socket_t skOpenPro(int af, int type, int protocol) { socket_t skOpenPro(int af, int type, int protocol) {
#ifndef NDEBUG
if(initialize_count <= 0) {
fatal("skInit has not been called");
}
#endif
return socket(af, type, protocol); return socket(af, type, protocol);
} }
sk_addrin_t skAddrinInit(const char *ip, uint16_t port) {
sk_addrin_t addr;
addr.sin_family = AF_INET;
addr.sin_port = htons(port);
addr.sin_addr.s_addr = inet_addr(ip);
return addr;
}
bool skClose(socket_t sock) { bool skClose(socket_t sock) {
#if SOCK_WINDOWS #if SOCK_WINDOWS
int error = closesocket(sock); int error = closesocket(sock);
@ -67,17 +103,17 @@ bool skClose(socket_t sock) {
} }
bool skBind(socket_t sock, const char *ip, uint16_t port) { bool skBind(socket_t sock, const char *ip, uint16_t port) {
struct sockaddr_in addr; sk_addrin_t addr;
addr.sin_family = AF_INET; addr.sin_family = AF_INET;
// TODO use inet_pton instead // TODO use inet_pton instead
addr.sin_addr.s_addr = inet_addr(ip); addr.sin_addr.s_addr = inet_addr(ip);
addr.sin_port = htons(port); addr.sin_port = htons(port);
return skBindPro(sock, (struct sockaddr *) &addr, sizeof(addr)); return skBindPro(sock, (sk_addr_t *) &addr, sizeof(addr));
} }
bool skBindPro(socket_t sock, const struct sockaddr *name, socket_len_t namelen) { bool skBindPro(socket_t sock, const sk_addr_t *name, socket_len_t namelen) {
return bind(sock, name, namelen) != SOCKET_ERROR; return bind(sock, name, namelen) != SOCKET_ERROR;
} }
@ -90,12 +126,12 @@ bool skListenPro(socket_t sock, int backlog) {
} }
socket_t skAccept(socket_t sock) { socket_t skAccept(socket_t sock) {
struct sockaddr_in addr; sk_addrin_t addr;
socket_len_t addr_size = (socket_len_t)sizeof(addr); socket_len_t addr_size = (socket_len_t)sizeof(addr);
return skAcceptPro(sock, (struct sockaddr *) &addr, &addr_size); return skAcceptPro(sock, (sk_addr_t *) &addr, &addr_size);
} }
socket_t skAcceptPro(socket_t sock, struct sockaddr *addr, socket_len_t *addrlen) { socket_t skAcceptPro(socket_t sock, sk_addr_t *addr, socket_len_t *addrlen) {
return accept(sock, addr, addrlen); return accept(sock, addr, addrlen);
} }
@ -108,26 +144,34 @@ bool skConnect(socket_t sock, const char *server, unsigned short server_port) {
address = inet_ntoa(*(struct in_addr*)host->h_addr_list[0]); address = inet_ntoa(*(struct in_addr*)host->h_addr_list[0]);
} }
struct sockaddr_in addr; sk_addrin_t addr;
addr.sin_family = AF_INET; addr.sin_family = AF_INET;
addr.sin_addr.s_addr = inet_addr(address); addr.sin_addr.s_addr = inet_addr(address);
addr.sin_port = htons(server_port); addr.sin_port = htons(server_port);
return skConnectPro(sock, (struct sockaddr *) &addr, sizeof(addr)); return skConnectPro(sock, (sk_addr_t *) &addr, sizeof(addr));
} }
bool skConnectPro(socket_t sock, const struct sockaddr *name, socket_len_t namelen) { bool skConnectPro(socket_t sock, const sk_addr_t *name, socket_len_t namelen) {
return connect(sock, name, namelen) != SOCKET_ERROR; return connect(sock, name, namelen) != SOCKET_ERROR;
} }
int skSend(socket_t sock, char *buf, int len) { int skSend(socket_t sock, const char *buf, int len) {
return skSendPro(sock, buf, len, 0); return skSendPro(sock, buf, len, 0);
} }
int skSendPro(socket_t sock, char *buf, int len, int flags) { int skSendPro(socket_t sock, const char *buf, int len, int flags) {
return send(sock, buf, len, flags); return send(sock, buf, len, flags);
} }
int skSendTo(socket_t sock, const char *buf, int len, const sk_addrin_t *to) {
return skSendToPro(sock, buf, len, 0, (sk_addr_t*) to, sizeof(sk_addrin_t));
}
int skSendToPro(socket_t sock, const char *buf, int len, int flags, const sk_addr_t *to, int tolen) {
return sendto(sock, buf, len, flags, to, tolen);
}
int skReceive(socket_t sock, char *buf, int len) { int skReceive(socket_t sock, char *buf, int len) {
return skReceivePro(sock, buf, len, 0); return skReceivePro(sock, buf, len, 0);
} }
@ -136,6 +180,15 @@ int skReceivePro(socket_t sock, char *buf, int len, int flags) {
return recv(sock, buf, len, flags); return recv(sock, buf, len, flags);
} }
int skReceiveFrom(socket_t sock, char *buf, int len, sk_addrin_t *from) {
int fromlen = sizeof(sk_addr_t);
return skReceiveFromPro(sock, buf, len, 0, (sk_addr_t*)from, &fromlen);
}
int skReceiveFromPro(socket_t sock, char *buf, int len, int flags, sk_addr_t *from, int *fromlen) {
return recvfrom(sock, buf, len, flags, from, fromlen);
}
bool skIsValid(socket_t sock) { bool skIsValid(socket_t sock) {
return sock != INVALID_SOCKET; return sock != INVALID_SOCKET;
} }

View file

@ -13,27 +13,38 @@ extern "C" {
#define SOCK_POSIX 1 #define SOCK_POSIX 1
#endif #endif
struct sockaddr;
#if SOCK_WINDOWS #if SOCK_WINDOWS
#pragma warning(disable:4996) // _WINSOCK_DEPRECATED_NO_WARNINGS
#include <winsock2.h> #include <winsock2.h>
typedef SOCKET socket_t; typedef SOCKET socket_t;
typedef int socket_len_t; typedef int socket_len_t;
#elif SOCK_POSIX #elif SOCK_POSIX
#include <sys/socket.h> #include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
typedef int socket_t; typedef int socket_t;
typedef uint32_t socket_len_t; typedef uint32_t socket_len_t;
#define INVALID_SOCKET (-1) #define INVALID_SOCKET (-1)
#define SOCKET_ERROR (-1) #define SOCKET_ERROR (-1)
#endif #endif
typedef struct sockaddr sk_addr_t;
typedef struct sockaddr_in sk_addrin_t;
typedef enum {
SOCK_TCP,
SOCK_UDP,
} skType;
// == RAW SOCKETS ==========================================
// Initialize sockets, returns true on success // Initialize sockets, returns true on success
bool skInit(void); bool skInit(void);
// Terminates sockets, returns true on success // Terminates sockets, returns true on success
bool skCleanup(void); bool skCleanup(void);
// Opens a socket, check socket_t with skValid // Opens a socket, check socket_t with skValid
socket_t skOpen(void); socket_t skOpen(skType type);
// Opens a socket using 'protocol', options are // Opens a socket using 'protocol', options are
// ip, icmp, ggp, tcp, egp, pup, udp, hmp, xns-idp, rdp // ip, icmp, ggp, tcp, egp, pup, udp, hmp, xns-idp, rdp
// check socket_t with skValid // check socket_t with skValid
@ -41,13 +52,16 @@ socket_t skOpenEx(const char *protocol);
// Opens a socket, check socket_t with skValid // Opens a socket, check socket_t with skValid
socket_t skOpenPro(int af, int type, int protocol); socket_t skOpenPro(int af, int type, int protocol);
// Fill out a sk_addrin_t structure with "ip" and "port"
sk_addrin_t skAddrinInit(const char *ip, uint16_t port);
// Closes a socket, returns true on success // Closes a socket, returns true on success
bool skClose(socket_t sock); bool skClose(socket_t sock);
// Associate a local address with a socket // Associate a local address with a socket
bool skBind(socket_t sock, const char *ip, uint16_t port); bool skBind(socket_t sock, const char *ip, uint16_t port);
// Associate a local address with a socket // Associate a local address with a socket
bool skBindPro(socket_t sock, const struct sockaddr *name, socket_len_t namelen); bool skBindPro(socket_t sock, const sk_addr_t *name, socket_len_t namelen);
// Place a socket in a state in which it is listening for an incoming connection // Place a socket in a state in which it is listening for an incoming connection
bool skListen(socket_t sock); bool skListen(socket_t sock);
@ -57,21 +71,29 @@ bool skListenPro(socket_t sock, int backlog);
// Permits an incoming connection attempt on a socket // Permits an incoming connection attempt on a socket
socket_t skAccept(socket_t sock); socket_t skAccept(socket_t sock);
// Permits an incoming connection attempt on a socket // Permits an incoming connection attempt on a socket
socket_t skAcceptPro(socket_t sock, struct sockaddr *addr, socket_len_t *addrlen); socket_t skAcceptPro(socket_t sock, sk_addr_t *addr, socket_len_t *addrlen);
// Connects to a server (e.g. "127.0.0.1" or "google.com") with a port(e.g. 1234), returns true on success // Connects to a server (e.g. "127.0.0.1" or "google.com") with a port(e.g. 1234), returns true on success
bool skConnect(socket_t sock, const char *server, unsigned short server_port); bool skConnect(socket_t sock, const char *server, unsigned short server_port);
// Connects to a server, returns true on success // Connects to a server, returns true on success
bool skConnectPro(socket_t sock, const struct sockaddr *name, socket_len_t namelen); bool skConnectPro(socket_t sock, const sk_addr_t *name, socket_len_t namelen);
// Sends data on a socket, returns true on success // Sends data on a socket, returns true on success
int skSend(socket_t sock, char *buf, int len); int skSend(socket_t sock, const char *buf, int len);
// Sends data on a socket, returns true on success // Sends data on a socket, returns true on success
int skSendPro(socket_t sock, char *buf, int len, int flags); int skSendPro(socket_t sock, const char *buf, int len, int flags);
// Sends data to a specific destination
int skSendTo(socket_t sock, const char *buf, int len, const sk_addrin_t *to);
// Sends data to a specific destination
int skSendToPro(socket_t sock, const char *buf, int len, int flags, const sk_addr_t *to, int tolen);
// Receives data from a socket, returns byte count on success, 0 on connection close or -1 on error // Receives data from a socket, returns byte count on success, 0 on connection close or -1 on error
int skReceive(socket_t sock, char *buf, int len); int skReceive(socket_t sock, char *buf, int len);
// Sends data on a socket, returns true on success // Receives data from a socket, returns byte count on success, 0 on connection close or -1 on error
int skReceivePro(socket_t sock, char *buf, int len, int flags); int skReceivePro(socket_t sock, char *buf, int len, int flags);
// Receives a datagram and stores the source address.
int skReceiveFrom(socket_t sock, char *buf, int len, sk_addrin_t *from);
// Receives a datagram and stores the source address.
int skReceiveFromPro(socket_t sock, char *buf, int len, int flags, sk_addr_t *from, int *fromlen);
// Checks that a opened socket is valid, returns true on success // Checks that a opened socket is valid, returns true on success
bool skIsValid(socket_t sock); bool skIsValid(socket_t sock);
@ -81,6 +103,13 @@ int skGetError(void);
// Returns a human-readable string from a skGetError // Returns a human-readable string from a skGetError
const char *skGetErrorString(void); const char *skGetErrorString(void);
// == UDP SOCKETS ==========================================
typedef socket_t udpsock_t;
#ifdef __cplusplus #ifdef __cplusplus
} // extern "C" } // extern "C"
#endif #endif

View file

@ -5,6 +5,10 @@
#include <stdarg.h> #include <stdarg.h>
#include <stdlib.h> #include <stdlib.h>
#ifdef _WIN32
#pragma warning(disable:4996) // _CRT_SECURE_NO_WARNINGS.
#endif
#ifdef TLOG_VS #ifdef TLOG_VS
#ifdef _WIN32 #ifdef _WIN32
#ifndef TLOG_NO_COLOURS #ifndef TLOG_NO_COLOURS