From c4e102b14cbe5416865a36386078423a88968888 Mon Sep 17 00:00:00 2001 From: Timerix22 Date: Fri, 12 Apr 2024 21:32:09 +0500 Subject: [PATCH] TCP and UDP sockets localEndpoint --- src/Network/network_types.h | 2 +- src/Network/sockets/knSocketTCP.c | 61 +++++++++++++++++++------------ src/Network/sockets/knSocketTCP.h | 14 ++++--- src/Network/sockets/knSocketUDP.c | 10 ++++- src/base/errors.h | 1 + tests/test_network.c | 13 ++++++- tests/tests.h | 26 ++++++------- 7 files changed, 82 insertions(+), 45 deletions(-) diff --git a/src/Network/network_types.h b/src/Network/network_types.h index 24d228a..c56b0ff 100644 --- a/src/Network/network_types.h +++ b/src/Network/network_types.h @@ -12,7 +12,7 @@ typedef u16 knPort; typedef union knIPV4Address { u32 UintBigEndian; - char bytes[4]; + u8 bytes[4]; } knIPV4Address; kt_declare(knIPV4Address); diff --git a/src/Network/sockets/knSocketTCP.c b/src/Network/sockets/knSocketTCP.c index fa404fd..ff480ce 100644 --- a/src/Network/sockets/knSocketTCP.c +++ b/src/Network/sockets/knSocketTCP.c @@ -15,8 +15,8 @@ Maybe knSocketTCP_open(bool allowReuse){ // set value of REUSEADDR socket option int opt_val = allowReuse; if(setsockopt(newSocket->socketfd, SOL_SOCKET, SO_REUSEADDR, (void*)&opt_val, sizeof(opt_val)) != 0) - safethrow("can't set socket options", free(newSocket)); - + safethrow("can't set socket options", knSocketTCP_close(newSocket)); + return SUCCESS(UniHeapPtr(knSocketTCP, newSocket)); } @@ -31,54 +31,67 @@ Maybe knSocketTCP_close(knSocketTCP* socket){ return MaybeNull; } -Maybe knSocketTCP_bindAndListen(knSocketTCP* socket, knIPV4Endpoint localEndp){ +Maybe knSocketTCP_bind(knSocketTCP* socket, knIPV4Endpoint localEndp){ struct sockaddr_in servaddr = knIPV4Endpoint_toSockaddr(localEndp); - if(bind(socket->socketfd, (void*)&servaddr, sizeof(servaddr)) != 0) safethrow("socket bind failed", ;); - if(listen(socket->socketfd, 1024) != 0) - safethrow("socket listen failed", ;); - socket->localEndpoint = localEndp; return MaybeNull; } -Maybe knSocketTCP_connect(knSocketTCP* socket, knIPV4Endpoint remoteEnd){ - struct sockaddr_in servaddr = knIPV4Endpoint_toSockaddr(remoteEnd); +Maybe knSocketTCP_listen(knSocketTCP* socket){ + if(listen(socket->socketfd, 1024) != 0) + safethrow("socket listen failed", ;); + return MaybeNull; +} - if(connect(socket->socketfd, (struct sockaddr*)&servaddr, sizeof(servaddr)) !=0) - safethrow("socket connect failed",;); - - socket->remoteEndpoint=remoteEnd; +Maybe knSocketTCP_connect(knSocketTCP* socket, knIPV4Endpoint remoteEnd){ + struct sockaddr_in localAddr = {0}; + struct sockaddr_in remoteAddr = knIPV4Endpoint_toSockaddr(remoteEnd); + u64 sockaddr_size = sizeof(localAddr); + + if(connect(socket->socketfd, (struct sockaddr*)&remoteAddr, sizeof(remoteAddr)) != 0) + safethrow("socket connect failed", ;); + + if(getsockname(socket->socketfd, (struct sockaddr*)&localAddr, (void*)&sockaddr_size) != 0) + safethrow("can't get connected socket local address", ;); + + socket->localEndpoint = knIPV4Endpoint_fromSockaddr(localAddr); + socket->remoteEndpoint = remoteEnd; return MaybeNull; } Maybe knSocketTCP_accept(knSocketTCP* socket){ + struct sockaddr_in localAddr = {0}; struct sockaddr_in remoteAddr = {0}; - u64 remoteAddrSize = sizeof(remoteAddr); + u64 sockaddr_size = sizeof(localAddr); - i64 client_fd = accept(socket->socketfd, (struct sockaddr*)&remoteAddr, (void*)&remoteAddrSize); + i64 client_fd = accept(socket->socketfd, (struct sockaddr*)&remoteAddr, (void*)&sockaddr_size); if(client_fd == -1 || client_fd == ~0) safethrow("can't accept client connection", ;); + if(getsockname(client_fd, (struct sockaddr*)&localAddr, (void*)&sockaddr_size) != 0) + safethrow("can't get accepted socket local address", __kn_StdSocket_close(client_fd)); + // if accept() didn't set remoteAddr for some reason if(remoteAddr.sin_addr.s_addr == 0 && remoteAddr.sin_port == 0 && remoteAddr.sin_family == 0){ - if(getpeername(client_fd, (struct sockaddr*)&remoteAddr, (void*)&remoteAddrSize) != 0) - safethrow("can't get connected client address", ;); + if(getpeername(client_fd, (struct sockaddr*)&remoteAddr, (void*)&sockaddr_size) != 0) + safethrow("can't get accepted socket remote address", __kn_StdSocket_close(client_fd)); } knSocketTCP* clientSocket = malloc(sizeof(knSocketTCP)); clientSocket->socketfd = client_fd; - clientSocket->localEndpoint = socket->localEndpoint; + clientSocket->localEndpoint = knIPV4Endpoint_fromSockaddr(localAddr); clientSocket->remoteEndpoint = knIPV4Endpoint_fromSockaddr(remoteAddr); return SUCCESS(UniHeapPtr(knSocketTCP, clientSocket)); } -Maybe knSocketTCP_send(knSocketTCP* socket, char* buffer, u32 dataLength){ +Maybe knSocketTCP_send(knSocketTCP* socket, void* _buf, u32 dataLength){ + char* buf = _buf; u32 sentTotal = 0; while(sentTotal < dataLength){ - int sentCount = send(socket->socketfd, buffer+sentTotal, dataLength-sentTotal, 0); + int sentCount = send(socket->socketfd, buf+sentTotal, dataLength-sentTotal, 0); if(sentCount == -1){ safethrow( cptr_concat("can't send ", toString_u64(dataLength-sentTotal,0,0), @@ -93,15 +106,17 @@ Maybe knSocketTCP_send(knSocketTCP* socket, char* buffer, u32 dataLength){ return MaybeNull; } -Maybe knSocketTCP_receive(knSocketTCP* socket, char* buffer, u32 bufferLength){ - int receivedCount = recv(socket->socketfd, buffer, bufferLength, 0); +Maybe knSocketTCP_receive(knSocketTCP* socket, void* _buf, u32 bufferLength){ + char* buf = _buf; + int receivedCount = recv(socket->socketfd, buf, bufferLength, 0); if(receivedCount == -1 || receivedCount == 0) safethrow("can't receive data from socket", ;) return SUCCESS(UniUInt64(receivedCount)); } -Maybe knSocketTCP_receiveN(knSocketTCP* socket, char* buf, u32 bufsize, u32 n){ +Maybe knSocketTCP_receiveN(knSocketTCP* socket, void* _buf, u32 bufsize, u32 n){ + char* buf = _buf; if(bufsize < n) safethrow(ERR_UNEXPECTEDVAL, ;); diff --git a/src/Network/sockets/knSocketTCP.h b/src/Network/sockets/knSocketTCP.h index b25f443..1eddee5 100644 --- a/src/Network/sockets/knSocketTCP.h +++ b/src/Network/sockets/knSocketTCP.h @@ -27,9 +27,13 @@ Maybe knSocketTCP_shutdown(knSocketTCP* socket, knShutdownType direction); ///@return Maybe error or nothing Maybe knSocketTCP_close(knSocketTCP* socket); -/// binds socket to a local endpoint and starts listening for incoming TCP connections +/// binds socket to a local endpoint +///@return Maybe error or nothing +Maybe knSocketTCP_bind(knSocketTCP* socket, knIPV4Endpoint localEndp); + +/// begins listening for incoming TCP connections +Maybe knSocketTCP_listen(knSocketTCP* socket); ///@return Maybe error or nothing -Maybe knSocketTCP_bindAndListen(knSocketTCP* socket, knIPV4Endpoint localEndp); /// establishes TCP connection with a remote endpoint ///@return Maybe error or nothing @@ -42,18 +46,18 @@ Maybe knSocketTCP_accept(knSocketTCP* socket); ///@param buffer buffer for receiving data ///@param dataLength 0-4294967295 ///@return Maybe -Maybe knSocketTCP_send(knSocketTCP* socket, char* buffer, u32 dataLength); +Maybe knSocketTCP_send(knSocketTCP* socket, void* buffer, u32 dataLength); /// receives a package of any size /// (by TCP 32 bytes han be sent as 32x1byte, 4x8byte, 32x1byte or in any other combination) ///@param buffer buffer for receiving data ///@param bufferLength 0-4294967295 ///@return Maybe received bytes amount -Maybe knSocketTCP_receive(knSocketTCP* socket, char* buffer, u32 bufferLength); +Maybe knSocketTCP_receive(knSocketTCP* socket, void* buffer, u32 bufferLength); /// receives a package of size n ///@return Maybe -Maybe knSocketTCP_receiveN(knSocketTCP* socket, char* buf, u32 bufsize, u32 n); +Maybe knSocketTCP_receiveN(knSocketTCP* socket, void* buf, u32 bufsize, u32 n); #if __cplusplus } diff --git a/src/Network/sockets/knSocketUDP.c b/src/Network/sockets/knSocketUDP.c index 27b60a7..ecc6998 100644 --- a/src/Network/sockets/knSocketUDP.c +++ b/src/Network/sockets/knSocketUDP.c @@ -14,7 +14,7 @@ Maybe knSocketUDP_open(bool allowReuse){ // set value of REUSEADDR socket option int opt_val = allowReuse; if(setsockopt(newSocket->socketfd, SOL_SOCKET, SO_REUSEADDR, (void*)&opt_val, sizeof(opt_val)) != 0) - safethrow("can't set socket options", free(newSocket)); + safethrow("can't set socket options", knSocketUDP_close(newSocket)); return SUCCESS(UniHeapPtr(knSocketUDP, newSocket)); } @@ -63,6 +63,14 @@ Maybe knSocketUDP_sendTo(knSocketUDP* socket, char* buffer, u32 dataLength, knIP ;); } + struct sockaddr_in localAddr = {0}; + u64 sockaddr_size = sizeof(localAddr); + + if(getsockname(socket->socketfd, (struct sockaddr*)&localAddr, (void*)&sockaddr_size) != 0) + safethrow("can't get implicitely bound socket local address", ;); + + socket->localEndpoint = knIPV4Endpoint_fromSockaddr(localAddr); + return MaybeNull; } diff --git a/src/base/errors.h b/src/base/errors.h index 635143e..8db0ca5 100644 --- a/src/base/errors.h +++ b/src/base/errors.h @@ -81,6 +81,7 @@ char* __unknownErr( ); #endif #define tryLast(_funcCall, _result, ON_EXIT) Maybe _result=_funcCall; if(_result.errmsg){ \ + ON_EXIT; \ _result.errmsg=__extendErrMsg(_result.errmsg, __FILE__,__LINE__,__func__); \ __EXIT(_result.errmsg); \ } diff --git a/tests/test_network.c b/tests/test_network.c index e0231e6..b158e83 100644 --- a/tests/test_network.c +++ b/tests/test_network.c @@ -47,8 +47,12 @@ typedef struct { void* tcp_client_connect_async(void* _data){ tcp_client_connect_async_data* data = _data; tryLast(knSocketTCP_connect(data->socket_client, data->serverEnd), _m8531,;); - kprintf_safe("\e[92mclient socket connected to server\n"); + + char* adrstr = knIPV4Endpoint_toString(&data->socket_client->localEndpoint); + kprintf("\e[92mclient socket was implicitely bound to %s\n\e[94m", adrstr); + free(adrstr); + free(data); return NULL; } @@ -63,7 +67,8 @@ static void test_tcp(){ socket_server=m_socketS.value.VoidPtr; kprintf("\e[92mTCP server socket created\n"); - tryLast(knSocketTCP_bindAndListen(socket_server, serverEnd), _m81775, ;) + tryLast(knSocketTCP_bind(socket_server, serverEnd), _m81775, ;) + tryLast(knSocketTCP_listen(socket_server), _m88775, ;) kprintf("\e[92mserver socket is listening\n"); } // client @@ -161,6 +166,10 @@ void test_udp(){ const char client_msg[] = "ping"; tryLast(knSocketUDP_sendTo(socket_client, client_msg, sizeof(client_msg), serverEnd), _mu75q2, ;); kprintf("\e[92mmessage sent to server\n\e[94m"); + + char* adrstr = knIPV4Endpoint_toString(&socket_client->localEndpoint); + kprintf("\e[92mclient socket was implicitely bound to %s\n\e[94m", adrstr); + free(adrstr); } // server { diff --git a/tests/tests.h b/tests/tests.h index 859c5cc..00f455a 100644 --- a/tests/tests.h +++ b/tests/tests.h @@ -24,19 +24,19 @@ void test_network(); inline void test_all(){ kprintf("\e[97mkerep tests are starting!\n"); optime(__func__, 1, - test_cptr(); - test_type_system(); - test_string(); - test_safethrow(); - test_searchtree(); - test_autoarr(); - test_autoarrVsVector(); - test_rng_algorithms(); - test_kprint_colors(); - test_kprint(); - test_hash_functions(); - test_hashtable(); - test_dtsod(); + // test_cptr(); + // test_type_system(); + // test_string(); + // test_safethrow(); + // test_searchtree(); + // test_autoarr(); + // test_autoarrVsVector(); + // test_rng_algorithms(); + // test_kprint_colors(); + // test_kprint(); + // test_hash_functions(); + // test_hashtable(); + // test_dtsod(); test_network(); kprintf("\e[96m--------------------------------------\e[0m\n"); );