udp implementation

This commit is contained in:
timerix 2024-01-02 23:30:25 +06:00
parent 9d2f5ddc2a
commit 59b3772d5a
10 changed files with 182 additions and 109 deletions

View File

@ -1,5 +1,4 @@
#include "network.h" #include "network_internal.h"
#include "socket_impl_includes.h"
Maybe kn_tryInit(){ Maybe kn_tryInit(){
#if _WIN32 #if _WIN32

View File

@ -14,15 +14,6 @@ extern "C" {
Maybe kn_tryInit(); Maybe kn_tryInit();
Maybe kt_tryDispose(); Maybe kt_tryDispose();
/* INTERNAL */
/// shutdown TCP/UDP/other std socket
Maybe __kn_StdSocket_shutdown(i64 socketfd, knShutdownType direction);
/// close TCP/UDP/other std socket
Maybe __kn_StdSocket_close(i64 socketfd);
#if __cplusplus #if __cplusplus
} }
#endif #endif

View File

@ -0,0 +1,32 @@
#pragma once
#if __cplusplus
extern "C" {
#endif
#include "network.h"
#include "socket_impl_includes.h"
/// shutdown TCP/UDP/other std socket
Maybe __kn_StdSocket_shutdown(i64 socketfd, knShutdownType direction);
/// close TCP/UDP/other std socket
Maybe __kn_StdSocket_close(i64 socketfd);
static inline struct sockaddr_in knIPV4Endpoint_toSockaddr(knIPV4Endpoint end){
struct sockaddr_in saddr = {0};
saddr.sin_family = AF_INET;
saddr.sin_addr.s_addr = end.address.UintBigEndian;
saddr.sin_port = htons(end.port); /* transforms port number to big endian (network order) */
return saddr;
}
static inline knIPV4Endpoint knIPV4Endpoint_fromSockaddr(struct sockaddr_in saddr_ptr){
knIPV4Address ipv4 = knIPV4Address_fromU32(saddr_ptr.sin_addr.s_addr);
u16 port = ntohs(saddr_ptr.sin_port); /* transforms port number to little endian (normal order) */
return knIPV4Endpoint_create(ipv4, port);
}
#if __cplusplus
}
#endif

View File

@ -21,9 +21,9 @@ ktid_declare(knIPV4Address);
///@return Maybe<knIPV4Address> as Maybe<knIPV4Address> ///@return Maybe<knIPV4Address> as Maybe<knIPV4Address>
Maybe knIPV4Address_fromStr(char* addrStr); Maybe knIPV4Address_fromStr(char* addrStr);
#define IPV4_NONE knIPV4Address_fromBytes(255,255,255,255) #define knIPV4Address_INVALID knIPV4Address_fromBytes(255,255,255,255)
#define IPV4_ANY knIPV4Address_fromBytes(0,0,0,0) #define knIPV4Address_ANY knIPV4Address_fromBytes(0,0,0,0)
#define IPV4_LOOPBACK knIPV4Address_fromBytes(127,0,0,1) #define knIPV4Address_LOOPBACK knIPV4Address_fromBytes(127,0,0,1)
typedef struct knIPV4Endpoint { typedef struct knIPV4Endpoint {
@ -34,6 +34,8 @@ ktid_declare(knIPV4Endpoint);
#define knIPV4Endpoint_create(ADDR, PORT) ((knIPV4Endpoint){ADDR, PORT}) #define knIPV4Endpoint_create(ADDR, PORT) ((knIPV4Endpoint){ADDR, PORT})
#define knIPV4Endpoint_INVALID knIPV4Endpoint_create(knIPV4Address_INVALID, ~0)
typedef enum knShutdownType { typedef enum knShutdownType {
knShutdownType_Receive = 0, knShutdownType_Receive = 0,
knShutdownType_Send = 1, knShutdownType_Send = 1,

View File

@ -1,5 +1,4 @@
#include "../network.h" #include "../network_internal.h"
#include "../socket_impl_includes.h"
ktid_define(knPackage); ktid_define(knPackage);
ktid_define(knPackageQueueElem); ktid_define(knPackageQueueElem);

View File

@ -1,11 +1,11 @@
#include "../network.h" #include "../network_internal.h"
#include "../socket_impl_includes.h"
ktid_define(knSocketTCP); ktid_define(knSocketTCP);
Maybe knSocketTCP_open(bool allowReuse){ Maybe knSocketTCP_open(bool allowReuse){
knSocketTCP* newSocket=malloc(sizeof(knSocketTCP)); knSocketTCP* newSocket=malloc(sizeof(knSocketTCP));
newSocket->localEndpoint=knIPV4Endpoint_create(IPV4_NONE,0); newSocket->localEndpoint=knIPV4Endpoint_INVALID;
newSocket->remoteEndpoint=knIPV4Endpoint_create(IPV4_NONE,0); newSocket->remoteEndpoint=knIPV4Endpoint_INVALID;
newSocket->socketfd=socket(AF_INET, SOCK_STREAM, 0); newSocket->socketfd=socket(AF_INET, SOCK_STREAM, 0);
if(newSocket->socketfd==-1 || newSocket->socketfd == ~0) if(newSocket->socketfd==-1 || newSocket->socketfd == ~0)
safethrow("can't create socket", free(newSocket)); safethrow("can't create socket", free(newSocket));
@ -29,39 +29,37 @@ Maybe knSocketTCP_close(knSocketTCP* socket){
return MaybeNull; return MaybeNull;
} }
Maybe knSocketTCP_listen(knSocketTCP* socket, knIPV4Endpoint localEndp){ Maybe knSocketTCP_bindAndListen(knSocketTCP* socket, knIPV4Endpoint localEndp){
struct sockaddr_in servaddr; struct sockaddr_in servaddr = knIPV4Endpoint_toSockaddr(localEndp);
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr = localEndp.address.UintBigEndian;
servaddr.sin_port = htons(localEndp.port);
int r = bind(socket->socketfd,(struct sockaddr*)&servaddr, sizeof(servaddr));
if(r != 0)
safethrow("socket bind failed",;);
socket->localEndpoint=localEndp;
r = listen(socket->socketfd, 1024); if(bind(socket->socketfd, (void*)&servaddr, sizeof(servaddr)) != 0)
if(r != 0) safethrow("socket bind failed", ;);
if(listen(socket->socketfd, 1024) != 0)
safethrow("socket listen failed", ;); safethrow("socket listen failed", ;);
socket->localEndpoint = localEndp;
return MaybeNull; return MaybeNull;
} }
Maybe knSocketTCP_connect(knSocketTCP* socket, knIPV4Endpoint remoteEndp){ Maybe knSocketTCP_connect(knSocketTCP* socket, knIPV4Endpoint remoteEnd){
struct sockaddr_in servaddr; struct sockaddr_in servaddr = knIPV4Endpoint_toSockaddr(remoteEnd);
servaddr.sin_family=AF_INET;
servaddr.sin_addr.s_addr = remoteEndp.address.UintBigEndian;
servaddr.sin_port = htons(remoteEndp.port);
if(connect(socket->socketfd, (struct sockaddr*)&servaddr, sizeof(servaddr)) !=0) if(connect(socket->socketfd, (struct sockaddr*)&servaddr, sizeof(servaddr)) !=0)
safethrow("socket connect failed",;); safethrow("socket connect failed",;);
socket->remoteEndpoint=remoteEndp;
socket->remoteEndpoint=remoteEnd;
return MaybeNull; return MaybeNull;
} }
Maybe knSocketTCP_accept(knSocketTCP* socket){ Maybe knSocketTCP_accept(knSocketTCP* socket){
struct sockaddr_in remoteAddr = {0}; struct sockaddr_in remoteAddr = {0};
u64 remoteAddrSize = sizeof(remoteAddr); u64 remoteAddrSize = sizeof(remoteAddr);
i64 client_fd = accept(socket->socketfd, (struct sockaddr*)&remoteAddr, (void*)&remoteAddrSize); i64 client_fd = accept(socket->socketfd, (struct sockaddr*)&remoteAddr, (void*)&remoteAddrSize);
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 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*)&remoteAddrSize) != 0)
@ -71,16 +69,14 @@ Maybe knSocketTCP_accept(knSocketTCP* socket){
knSocketTCP* clientSocket = malloc(sizeof(knSocketTCP)); knSocketTCP* clientSocket = malloc(sizeof(knSocketTCP));
clientSocket->socketfd = client_fd; clientSocket->socketfd = client_fd;
clientSocket->localEndpoint = socket->localEndpoint; clientSocket->localEndpoint = socket->localEndpoint;
clientSocket->remoteEndpoint = knIPV4Endpoint_create( clientSocket->remoteEndpoint = knIPV4Endpoint_fromSockaddr(remoteAddr);
knIPV4Address_fromU32(remoteAddr.sin_addr.s_addr),
remoteAddr.sin_port);
return SUCCESS(UniHeapPtr(knSocketTCP, clientSocket)); return SUCCESS(UniHeapPtr(knSocketTCP, clientSocket));
} }
Maybe knSocketTCP_send(knSocketTCP* socket, char* data, u32 dataLength){ Maybe knSocketTCP_send(knSocketTCP* socket, char* buffer, u32 dataLength){
u32 sentTotal = 0; u32 sentTotal = 0;
while(sentTotal < dataLength){ while(sentTotal < dataLength){
int sentCount = send(socket->socketfd, data+sentTotal, dataLength-sentTotal, 0); int sentCount = send(socket->socketfd, buffer+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),
@ -91,6 +87,7 @@ Maybe knSocketTCP_send(knSocketTCP* socket, char* data, u32 dataLength){
} }
sentTotal += sentCount; sentTotal += sentCount;
} }
return MaybeNull; return MaybeNull;
} }
@ -98,5 +95,6 @@ Maybe knSocketTCP_receive(knSocketTCP* socket, char* buffer, u32 bufferLength){
int receivedCount = recv(socket->socketfd, buffer, bufferLength, 0); int receivedCount = recv(socket->socketfd, buffer, 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));
} }

View File

@ -28,21 +28,25 @@ 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);
///start listening at local endpoint /// binds socket to a local endpoint and starts listening for incoming TCP connections
///@return Maybe<void> error or nothing ///@return Maybe<void> error or nothing
Maybe knSocketTCP_listen(knSocketTCP* socket, knIPV4Endpoint localEndp); Maybe knSocketTCP_bindAndListen(knSocketTCP* socket, knIPV4Endpoint localEndp);
///sets socket remote endpoint /// establishes TCP connection with a remote endpoint
///@return Maybe<void> error or nothing ///@return Maybe<void> error or nothing
Maybe knSocketTCP_connect(knSocketTCP* socket, knIPV4Endpoint remoteEndp); Maybe knSocketTCP_connect(knSocketTCP* socket, knIPV4Endpoint remoteEnd);
///@return Maybe<knSocketTCP*> new socket connected to client ///@return Maybe<knSocketTCP*> new socket connected to client
Maybe knSocketTCP_accept(knSocketTCP* socket); Maybe knSocketTCP_accept(knSocketTCP* socket);
/// sends <dataLength> bytes from buffer
///@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* data, u32 dataLength); Maybe knSocketTCP_send(knSocketTCP* socket, char* 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 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

View File

@ -1,5 +1,5 @@
#include "../network.h" #include "../network_internal.h"
#include "../socket_impl_includes.h"
ktid_define(knSocketUDP); ktid_define(knSocketUDP);
Maybe knSocketUDP_open(bool allowReuse){ Maybe knSocketUDP_open(bool allowReuse){
@ -28,10 +28,57 @@ Maybe knSocketUDP_close(knSocketUDP* socket){
return MaybeNull; return MaybeNull;
} }
Maybe knSocketUDP_listen(knSocketUDP* socket, knIPV4Endpoint localEndp); Maybe knSocketUDP_bind(knSocketUDP* socket, knIPV4Endpoint localEndp){
struct sockaddr_in servaddr = {
.sin_family = AF_INET,
.sin_addr.s_addr = localEndp.address.UintBigEndian,
.sin_port = htons(localEndp.port) /* transforms port to big endian */
};
Maybe knSocketUDP_accept(knSocketUDP* socket); if(bind(socket->socketfd, (void*)&servaddr, sizeof(servaddr)) != 0)
safethrow("socket bind failed", ;);
Maybe knSocketUDP_sendto(knSocketUDP* socket, char* data, u32 dataLength, knIPV4Endpoint destination); socket->localEndpoint = localEndp;
return MaybeNull;
}
Maybe knSocketUDP_receive(knSocketUDP* socket, char* buffer, u32 bufferLength); Maybe knSocketUDP_sendTo(knSocketUDP* socket, char* buffer, u32 dataLength, knIPV4Endpoint destEnd){
struct sockaddr_in dest_saddr = knIPV4Endpoint_toSockaddr(destEnd);
u32 sentCount = sendto(
socket->socketfd,
buffer,
dataLength,
0,
(struct sockaddr*)&dest_saddr,
sizeof(struct sockaddr_in)
);
if(sentCount != dataLength) {
safethrow(
cptr_concat("can't send ", toString_u64(dataLength-sentCount,0,0),
" bytes out of ", toString_u64(dataLength,0,0)
),
;);
}
return MaybeNull;
}
Maybe knSocketUDP_receiveAny(knSocketUDP* socket, char* buffer, u32 bufferLength, knIPV4Endpoint* senderEnd){
struct sockaddr_in remote_saddr = {0};
u64 remote_saddr_size = sizeof(remote_saddr);
int receivedCount = recvfrom(
socket->socketfd,
buffer,
bufferLength,
0,
(struct sockaddr*)&remote_saddr,
(void*)&remote_saddr_size
);
if(receivedCount == -1 || receivedCount == 0)
safethrow("can't receive data from socket", ;)
*senderEnd = knIPV4Endpoint_fromSockaddr(remote_saddr);
return SUCCESS(UniUInt64(receivedCount));
}

View File

@ -27,22 +27,23 @@ Maybe knSocketUDP_shutdown(knSocketUDP* socket, knShutdownType direction);
///@return Maybe<void> error or nothing ///@return Maybe<void> error or nothing
Maybe knSocketUDP_close(knSocketUDP* socket); Maybe knSocketUDP_close(knSocketUDP* socket);
///start listening at local endpoint /// binds socket to a local endpoint
///@return Maybe<void> error or nothing ///@return Maybe<void> error or nothing
Maybe knSocketUDP_listen(knSocketUDP* socket, knIPV4Endpoint localEndp); Maybe knSocketUDP_bind(knSocketUDP* socket, knIPV4Endpoint localEndp);
///@return Maybe<knSocketUDP*> new socket connected to client
Maybe knSocketUDP_accept(knSocketUDP* socket);
///@param dataLength 0-4294967295
///@return Maybe<void>
Maybe knSocketUDP_sendto(knSocketUDP* socket, char* data, u32 dataLength, knIPV4Endpoint destination);
/// sends one package to destination endpoint
///@param buffer buffer for receiving data ///@param buffer buffer for receiving data
///@param bufferLength 0-4294967295 ///@param dataLength 0-64k
///@return Maybe<u64> received bytes amount ///@param destEnd destination endpoint
Maybe knSocketUDP_receive(knSocketUDP* socket, char* buffer, u32 bufferLength); ///@return Maybe<void>
Maybe knSocketUDP_sendTo(knSocketUDP* socket, char* buffer, u32 dataLength, knIPV4Endpoint destEnd);
/// receives one package from anywhere
///@param buffer buffer for receiving data
///@param bufferLength 0-64k
///@param senderEnd [OUT] endpoint UPD package was sent from
///@return Maybe<u64> received bytes amount
Maybe knSocketUDP_receiveAny(knSocketUDP* socket, char* buffer, u32 bufferLength, knIPV4Endpoint* senderEnd);
#if __cplusplus #if __cplusplus
} }

View File

@ -57,7 +57,7 @@ void* tcp_client_connect_async(void* _data){
static void test_tcp(){ static void test_tcp(){
kprintf("\e[96m----------[test_network/tcp]----------\n"); kprintf("\e[96m----------[test_network/tcp]----------\n");
knIPV4Endpoint serverEnd = knIPV4Endpoint_create(IPV4_LOOPBACK, 4444); knIPV4Endpoint serverEnd = knIPV4Endpoint_create(knIPV4Address_LOOPBACK, 4444);
knSocketTCP *socket_server, *clientConnection, *socket_client; knSocketTCP *socket_server, *clientConnection, *socket_client;
// server // server
{ {
@ -65,7 +65,7 @@ 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_listen(socket_server, serverEnd), _m81775, ;) tryLast(knSocketTCP_bindAndListen(socket_server, serverEnd), _m81775, ;)
kprintf("\e[92mserver socket is listening\n"); kprintf("\e[92mserver socket is listening\n");
} }
// client // client