TCP and UDP sockets localEndpoint

This commit is contained in:
Timerix22 2024-04-12 21:32:09 +05:00
parent f2847a819d
commit c4e102b14c
7 changed files with 82 additions and 45 deletions

View File

@ -12,7 +12,7 @@ typedef u16 knPort;
typedef union knIPV4Address { typedef union knIPV4Address {
u32 UintBigEndian; u32 UintBigEndian;
char bytes[4]; u8 bytes[4];
} knIPV4Address; } knIPV4Address;
kt_declare(knIPV4Address); kt_declare(knIPV4Address);

View File

@ -15,7 +15,7 @@ Maybe knSocketTCP_open(bool allowReuse){
// set value of REUSEADDR socket option // set value of REUSEADDR socket option
int opt_val = allowReuse; int opt_val = allowReuse;
if(setsockopt(newSocket->socketfd, SOL_SOCKET, SO_REUSEADDR, (void*)&opt_val, sizeof(opt_val)) != 0) 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)); return SUCCESS(UniHeapPtr(knSocketTCP, newSocket));
} }
@ -31,54 +31,67 @@ Maybe knSocketTCP_close(knSocketTCP* socket){
return MaybeNull; return MaybeNull;
} }
Maybe knSocketTCP_bindAndListen(knSocketTCP* socket, knIPV4Endpoint localEndp){ Maybe knSocketTCP_bind(knSocketTCP* socket, knIPV4Endpoint localEndp){
struct sockaddr_in servaddr = knIPV4Endpoint_toSockaddr(localEndp); struct sockaddr_in servaddr = knIPV4Endpoint_toSockaddr(localEndp);
if(bind(socket->socketfd, (void*)&servaddr, sizeof(servaddr)) != 0) if(bind(socket->socketfd, (void*)&servaddr, sizeof(servaddr)) != 0)
safethrow("socket bind failed", ;); safethrow("socket bind failed", ;);
if(listen(socket->socketfd, 1024) != 0)
safethrow("socket listen failed", ;);
socket->localEndpoint = localEndp; socket->localEndpoint = localEndp;
return MaybeNull; return MaybeNull;
} }
Maybe knSocketTCP_connect(knSocketTCP* socket, knIPV4Endpoint remoteEnd){ Maybe knSocketTCP_listen(knSocketTCP* socket){
struct sockaddr_in servaddr = knIPV4Endpoint_toSockaddr(remoteEnd); if(listen(socket->socketfd, 1024) != 0)
safethrow("socket listen failed", ;);
return MaybeNull;
}
if(connect(socket->socketfd, (struct sockaddr*)&servaddr, sizeof(servaddr)) !=0) 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", ;); 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; socket->remoteEndpoint = remoteEnd;
return MaybeNull; return MaybeNull;
} }
Maybe knSocketTCP_accept(knSocketTCP* socket){ Maybe knSocketTCP_accept(knSocketTCP* socket){
struct sockaddr_in localAddr = {0};
struct sockaddr_in remoteAddr = {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) if(client_fd == -1 || client_fd == ~0)
safethrow("can't accept client connection", ;); 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 accept() didn't set remoteAddr for some reason
if(remoteAddr.sin_addr.s_addr == 0 && remoteAddr.sin_port == 0 && remoteAddr.sin_family == 0){ 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) if(getpeername(client_fd, (struct sockaddr*)&remoteAddr, (void*)&sockaddr_size) != 0)
safethrow("can't get connected client address", ;); safethrow("can't get accepted socket remote address", __kn_StdSocket_close(client_fd));
} }
knSocketTCP* clientSocket = malloc(sizeof(knSocketTCP)); knSocketTCP* clientSocket = malloc(sizeof(knSocketTCP));
clientSocket->socketfd = client_fd; clientSocket->socketfd = client_fd;
clientSocket->localEndpoint = socket->localEndpoint; clientSocket->localEndpoint = knIPV4Endpoint_fromSockaddr(localAddr);
clientSocket->remoteEndpoint = knIPV4Endpoint_fromSockaddr(remoteAddr); clientSocket->remoteEndpoint = knIPV4Endpoint_fromSockaddr(remoteAddr);
return SUCCESS(UniHeapPtr(knSocketTCP, clientSocket)); 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; u32 sentTotal = 0;
while(sentTotal < dataLength){ 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){ if(sentCount == -1){
safethrow( safethrow(
cptr_concat("can't send ", toString_u64(dataLength-sentTotal,0,0), 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; return MaybeNull;
} }
Maybe knSocketTCP_receive(knSocketTCP* socket, char* buffer, u32 bufferLength){ Maybe knSocketTCP_receive(knSocketTCP* socket, void* _buf, u32 bufferLength){
int receivedCount = recv(socket->socketfd, buffer, bufferLength, 0); char* buf = _buf;
int receivedCount = recv(socket->socketfd, buf, bufferLength, 0);
if(receivedCount == -1 || receivedCount == 0) if(receivedCount == -1 || receivedCount == 0)
safethrow("can't receive data from socket", ;) safethrow("can't receive data from socket", ;)
return SUCCESS(UniUInt64(receivedCount)); 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) if(bufsize < n)
safethrow(ERR_UNEXPECTEDVAL, ;); safethrow(ERR_UNEXPECTEDVAL, ;);

View File

@ -27,9 +27,13 @@ Maybe knSocketTCP_shutdown(knSocketTCP* socket, knShutdownType direction);
///@return Maybe<void> error or nothing ///@return Maybe<void> error or nothing
Maybe knSocketTCP_close(knSocketTCP* socket); 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<void> error or nothing
Maybe knSocketTCP_bind(knSocketTCP* socket, knIPV4Endpoint localEndp);
/// begins listening for incoming TCP connections
Maybe knSocketTCP_listen(knSocketTCP* socket);
///@return Maybe<void> error or nothing ///@return Maybe<void> error or nothing
Maybe knSocketTCP_bindAndListen(knSocketTCP* socket, knIPV4Endpoint localEndp);
/// establishes TCP connection with a remote endpoint /// establishes TCP connection with a remote endpoint
///@return Maybe<void> error or nothing ///@return Maybe<void> error or nothing
@ -42,18 +46,18 @@ Maybe knSocketTCP_accept(knSocketTCP* socket);
///@param buffer buffer for receiving data ///@param buffer buffer for receiving data
///@param dataLength 0-4294967295 ///@param dataLength 0-4294967295
///@return Maybe<void> ///@return Maybe<void>
Maybe knSocketTCP_send(knSocketTCP* socket, char* buffer, u32 dataLength); Maybe knSocketTCP_send(knSocketTCP* socket, void* buffer, u32 dataLength);
/// receives a package of any size /// receives a package of any size
/// (by TCP 32 bytes han be sent as 32x1byte, 4x8byte, 32x1byte or in any other combination) /// (by TCP 32 bytes han be sent as 32x1byte, 4x8byte, 32x1byte or in any other combination)
///@param buffer buffer for receiving data ///@param buffer buffer for receiving data
///@param bufferLength 0-4294967295 ///@param bufferLength 0-4294967295
///@return Maybe<u64> received bytes amount ///@return Maybe<u64> 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 /// receives a package of size n
///@return Maybe<void> ///@return Maybe<void>
Maybe knSocketTCP_receiveN(knSocketTCP* socket, char* buf, u32 bufsize, u32 n); Maybe knSocketTCP_receiveN(knSocketTCP* socket, void* buf, u32 bufsize, u32 n);
#if __cplusplus #if __cplusplus
} }

View File

@ -14,7 +14,7 @@ Maybe knSocketUDP_open(bool allowReuse){
// set value of REUSEADDR socket option // set value of REUSEADDR socket option
int opt_val = allowReuse; int opt_val = allowReuse;
if(setsockopt(newSocket->socketfd, SOL_SOCKET, SO_REUSEADDR, (void*)&opt_val, sizeof(opt_val)) != 0) 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)); 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; return MaybeNull;
} }

View File

@ -81,6 +81,7 @@ char* __unknownErr( );
#endif #endif
#define tryLast(_funcCall, _result, ON_EXIT) Maybe _result=_funcCall; if(_result.errmsg){ \ #define tryLast(_funcCall, _result, ON_EXIT) Maybe _result=_funcCall; if(_result.errmsg){ \
ON_EXIT; \
_result.errmsg=__extendErrMsg(_result.errmsg, __FILE__,__LINE__,__func__); \ _result.errmsg=__extendErrMsg(_result.errmsg, __FILE__,__LINE__,__func__); \
__EXIT(_result.errmsg); \ __EXIT(_result.errmsg); \
} }

View File

@ -47,8 +47,12 @@ typedef struct {
void* tcp_client_connect_async(void* _data){ void* tcp_client_connect_async(void* _data){
tcp_client_connect_async_data* data = _data; tcp_client_connect_async_data* data = _data;
tryLast(knSocketTCP_connect(data->socket_client, data->serverEnd), _m8531,;); tryLast(knSocketTCP_connect(data->socket_client, data->serverEnd), _m8531,;);
kprintf_safe("\e[92mclient socket connected to server\n"); 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); free(data);
return NULL; return NULL;
} }
@ -63,7 +67,8 @@ static void test_tcp(){
socket_server=m_socketS.value.VoidPtr; socket_server=m_socketS.value.VoidPtr;
kprintf("\e[92mTCP server socket created\n"); 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"); kprintf("\e[92mserver socket is listening\n");
} }
// client // client
@ -161,6 +166,10 @@ void test_udp(){
const char client_msg[] = "ping"; const char client_msg[] = "ping";
tryLast(knSocketUDP_sendTo(socket_client, client_msg, sizeof(client_msg), serverEnd), _mu75q2, ;); tryLast(knSocketUDP_sendTo(socket_client, client_msg, sizeof(client_msg), serverEnd), _mu75q2, ;);
kprintf("\e[92mmessage sent to server\n\e[94m"); 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 // server
{ {

View File

@ -24,19 +24,19 @@ void test_network();
inline void test_all(){ inline void test_all(){
kprintf("\e[97mkerep tests are starting!\n"); kprintf("\e[97mkerep tests are starting!\n");
optime(__func__, 1, optime(__func__, 1,
test_cptr(); // test_cptr();
test_type_system(); // test_type_system();
test_string(); // test_string();
test_safethrow(); // test_safethrow();
test_searchtree(); // test_searchtree();
test_autoarr(); // test_autoarr();
test_autoarrVsVector(); // test_autoarrVsVector();
test_rng_algorithms(); // test_rng_algorithms();
test_kprint_colors(); // test_kprint_colors();
test_kprint(); // test_kprint();
test_hash_functions(); // test_hash_functions();
test_hashtable(); // test_hashtable();
test_dtsod(); // test_dtsod();
test_network(); test_network();
kprintf("\e[96m--------------------------------------\e[0m\n"); kprintf("\e[96m--------------------------------------\e[0m\n");
); );