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 "socket_impl_includes.h"
#include "network_internal.h"
Maybe kn_tryInit(){
#if _WIN32

View File

@ -14,15 +14,6 @@ extern "C" {
Maybe kn_tryInit();
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
}
#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

@ -1,45 +1,47 @@
#pragma once
#if __cplusplus
extern "C" {
#endif
#include "../base/base.h"
typedef u16 knPort;
typedef union knIPV4Address {
u32 UintBigEndian;
char bytes[4];
} knIPV4Address;
ktid_declare(knIPV4Address);
#define knIPV4Address_fromBytes(A, B, C, D) ((knIPV4Address){.bytes={A,B,C,D}})
#define knIPV4Address_fromU32(N) ((knIPV4Address){.UintBigEndian=N})
///@return Maybe<knIPV4Address> as Maybe<knIPV4Address>
Maybe knIPV4Address_fromStr(char* addrStr);
#define IPV4_NONE knIPV4Address_fromBytes(255,255,255,255)
#define IPV4_ANY knIPV4Address_fromBytes(0,0,0,0)
#define IPV4_LOOPBACK knIPV4Address_fromBytes(127,0,0,1)
typedef struct knIPV4Endpoint {
knIPV4Address address;
knPort port;
} knIPV4Endpoint;
ktid_declare(knIPV4Endpoint);
#define knIPV4Endpoint_create(ADDR, PORT) ((knIPV4Endpoint){ADDR, PORT})
typedef enum knShutdownType {
knShutdownType_Receive = 0,
knShutdownType_Send = 1,
knShutdownType_Both = 2,
} knShutdownType;
#if __cplusplus
}
#pragma once
#if __cplusplus
extern "C" {
#endif
#include "../base/base.h"
typedef u16 knPort;
typedef union knIPV4Address {
u32 UintBigEndian;
char bytes[4];
} knIPV4Address;
ktid_declare(knIPV4Address);
#define knIPV4Address_fromBytes(A, B, C, D) ((knIPV4Address){.bytes={A,B,C,D}})
#define knIPV4Address_fromU32(N) ((knIPV4Address){.UintBigEndian=N})
///@return Maybe<knIPV4Address> as Maybe<knIPV4Address>
Maybe knIPV4Address_fromStr(char* addrStr);
#define knIPV4Address_INVALID knIPV4Address_fromBytes(255,255,255,255)
#define knIPV4Address_ANY knIPV4Address_fromBytes(0,0,0,0)
#define knIPV4Address_LOOPBACK knIPV4Address_fromBytes(127,0,0,1)
typedef struct knIPV4Endpoint {
knIPV4Address address;
knPort port;
} knIPV4Endpoint;
ktid_declare(knIPV4Endpoint);
#define knIPV4Endpoint_create(ADDR, PORT) ((knIPV4Endpoint){ADDR, PORT})
#define knIPV4Endpoint_INVALID knIPV4Endpoint_create(knIPV4Address_INVALID, ~0)
typedef enum knShutdownType {
knShutdownType_Receive = 0,
knShutdownType_Send = 1,
knShutdownType_Both = 2,
} knShutdownType;
#if __cplusplus
}
#endif

View File

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

View File

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

View File

@ -28,21 +28,25 @@ Maybe knSocketTCP_shutdown(knSocketTCP* socket, knShutdownType direction);
///@return Maybe<void> error or nothing
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
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
Maybe knSocketTCP_connect(knSocketTCP* socket, knIPV4Endpoint remoteEndp);
Maybe knSocketTCP_connect(knSocketTCP* socket, knIPV4Endpoint remoteEnd);
///@return Maybe<knSocketTCP*> new socket connected to client
Maybe knSocketTCP_accept(knSocketTCP* socket);
/// sends <dataLength> bytes from buffer
///@param buffer buffer for receiving data
///@param dataLength 0-4294967295
///@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 bufferLength 0-4294967295
///@return Maybe<u64> received bytes amount

View File

@ -1,5 +1,5 @@
#include "../network.h"
#include "../socket_impl_includes.h"
#include "../network_internal.h"
ktid_define(knSocketUDP);
Maybe knSocketUDP_open(bool allowReuse){
@ -28,10 +28,57 @@ Maybe knSocketUDP_close(knSocketUDP* socket){
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 */
};
if(bind(socket->socketfd, (void*)&servaddr, sizeof(servaddr)) != 0)
safethrow("socket bind failed", ;);
Maybe knSocketUDP_accept(knSocketUDP* socket);
socket->localEndpoint = localEndp;
return MaybeNull;
}
Maybe knSocketUDP_sendto(knSocketUDP* socket, char* data, u32 dataLength, knIPV4Endpoint destination);
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)
),
;);
}
Maybe knSocketUDP_receive(knSocketUDP* socket, char* buffer, u32 bufferLength);
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
Maybe knSocketUDP_close(knSocketUDP* socket);
///start listening at local endpoint
/// binds socket to a local endpoint
///@return Maybe<void> error or nothing
Maybe knSocketUDP_listen(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);
Maybe knSocketUDP_bind(knSocketUDP* socket, knIPV4Endpoint localEndp);
/// sends one package to destination endpoint
///@param buffer buffer for receiving data
///@param bufferLength 0-4294967295
///@return Maybe<u64> received bytes amount
Maybe knSocketUDP_receive(knSocketUDP* socket, char* buffer, u32 bufferLength);
///@param dataLength 0-64k
///@param destEnd destination endpoint
///@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
}

View File

@ -57,7 +57,7 @@ void* tcp_client_connect_async(void* _data){
static void test_tcp(){
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;
// server
{
@ -65,7 +65,7 @@ static void test_tcp(){
socket_server=m_socketS.value.VoidPtr;
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");
}
// client