From aa08240ec98477d02e74c5b12674e48325c53365 Mon Sep 17 00:00:00 2001 From: "alessandro.bason" <1902881@uad.ac.uk> Date: Wed, 20 Oct 2021 10:51:18 +0100 Subject: [PATCH] bit better sockets --- http.c | 2 +- socket.c | 83 ++++++++++++++++++++++++++++++++++++++++++++---------- socket.h | 47 +++++++++++++++++++++++++------ tracelog.c | 4 +++ 4 files changed, 111 insertions(+), 25 deletions(-) diff --git a/http.c b/http.c index 6b562ae..f90cf58 100644 --- a/http.c +++ b/http.c @@ -289,7 +289,7 @@ http_response_t hcliSendRequest(http_client_t *ctx, http_request_t *req) { goto skopen_error; } - ctx->socket = skOpen(); + ctx->socket = skOpen(SOCK_TCP); if(ctx->socket == INVALID_SOCKET) { err("couldn't open socket %s", skGetErrorString()); goto error; diff --git a/socket.c b/socket.c index 7d1f114..7482202 100644 --- a/socket.c +++ b/socket.c @@ -1,6 +1,12 @@ #include "socket.h" #include +#include "tracelog.h" + +#ifndef NDEBUG +// VERY MUCH NOT THREAD SAFE +static int initialize_count = 0; +#endif #if SOCK_WINDOWS #include @@ -13,8 +19,6 @@ static const char *_win_skGetErrorString(); #define SOCK_CALL(fun) _win_##fun #elif SOCK_POSIX -#include -#include #include #include #include @@ -33,18 +37,37 @@ static const char *_posix_skGetErrorString(); #endif bool skInit() { +#ifndef NDEBUG + ++initialize_count; +#endif return SOCK_CALL(skInit()); } bool skCleanup() { +#ifndef NDEBUG + --initialize_count; +#endif return SOCK_CALL(skCleanup()); } -socket_t skOpen() { - return skOpenPro(AF_INET, SOCK_STREAM, 0); +socket_t skOpen(skType type) { + 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) { +#ifndef NDEBUG + if(initialize_count <= 0) { + fatal("skInit has not been called"); + } +#endif struct protoent *proto = getprotobyname(protocol); if(!proto) { return INVALID_SOCKET; @@ -53,9 +76,22 @@ socket_t skOpenEx(const char *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); } +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) { #if SOCK_WINDOWS int error = closesocket(sock); @@ -67,17 +103,17 @@ bool skClose(socket_t sock) { } bool skBind(socket_t sock, const char *ip, uint16_t port) { - struct sockaddr_in addr; + sk_addrin_t addr; addr.sin_family = AF_INET; // TODO use inet_pton instead addr.sin_addr.s_addr = inet_addr(ip); 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; } @@ -90,12 +126,12 @@ bool skListenPro(socket_t sock, int backlog) { } socket_t skAccept(socket_t sock) { - struct sockaddr_in addr; + sk_addrin_t 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); } @@ -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]); } - struct sockaddr_in addr; + sk_addrin_t addr; addr.sin_family = AF_INET; addr.sin_addr.s_addr = inet_addr(address); 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; } -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); } -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); } +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) { 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); } +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) { return sock != INVALID_SOCKET; } diff --git a/socket.h b/socket.h index c369b91..b547536 100644 --- a/socket.h +++ b/socket.h @@ -13,27 +13,38 @@ extern "C" { #define SOCK_POSIX 1 #endif -struct sockaddr; - #if SOCK_WINDOWS + #pragma warning(disable:4996) // _WINSOCK_DEPRECATED_NO_WARNINGS #include typedef SOCKET socket_t; typedef int socket_len_t; #elif SOCK_POSIX #include + #include + #include typedef int socket_t; typedef uint32_t socket_len_t; #define INVALID_SOCKET (-1) #define SOCKET_ERROR (-1) #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 bool skInit(void); // Terminates sockets, returns true on success bool skCleanup(void); // Opens a socket, check socket_t with skValid -socket_t skOpen(void); +socket_t skOpen(skType type); // Opens a socket using 'protocol', options are // ip, icmp, ggp, tcp, egp, pup, udp, hmp, xns-idp, rdp // check socket_t with skValid @@ -41,13 +52,16 @@ socket_t skOpenEx(const char *protocol); // Opens a socket, check socket_t with skValid 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 bool skClose(socket_t sock); // Associate a local address with a socket bool skBind(socket_t sock, const char *ip, uint16_t port); // 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 bool skListen(socket_t sock); @@ -57,21 +71,29 @@ bool skListenPro(socket_t sock, int backlog); // Permits an incoming connection attempt on a socket socket_t skAccept(socket_t sock); // 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 bool skConnect(socket_t sock, const char *server, unsigned short server_port); // 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 -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 -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 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); +// 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 bool skIsValid(socket_t sock); @@ -81,6 +103,13 @@ int skGetError(void); // Returns a human-readable string from a skGetError const char *skGetErrorString(void); +// == UDP SOCKETS ========================================== + +typedef socket_t udpsock_t; + + + + #ifdef __cplusplus } // extern "C" #endif \ No newline at end of file diff --git a/tracelog.c b/tracelog.c index 1ef0bcb..f358eaf 100644 --- a/tracelog.c +++ b/tracelog.c @@ -5,6 +5,10 @@ #include #include +#ifdef _WIN32 + #pragma warning(disable:4996) // _CRT_SECURE_NO_WARNINGS. +#endif + #ifdef TLOG_VS #ifdef _WIN32 #ifndef TLOG_NO_COLOURS