some fixes in sockets and complete tcp client/server test
This commit is contained in:
parent
336bde5fb0
commit
9d2f5ddc2a
@ -37,12 +37,12 @@ case "$OS" in
|
|||||||
WINDOWS)
|
WINDOWS)
|
||||||
EXEC_FILE="$PROJECT.exe"
|
EXEC_FILE="$PROJECT.exe"
|
||||||
SHARED_LIB_FILE="$PROJECT.dll"
|
SHARED_LIB_FILE="$PROJECT.dll"
|
||||||
LINKER_LIBS="-lws2_32"
|
LINKER_LIBS="-lpthread -lws2_32"
|
||||||
;;
|
;;
|
||||||
LINUX)
|
LINUX)
|
||||||
EXEC_FILE="$PROJECT"
|
EXEC_FILE="$PROJECT"
|
||||||
SHARED_LIB_FILE="$PROJECT.so"
|
SHARED_LIB_FILE="$PROJECT.so"
|
||||||
LINKER_LIBS=""
|
LINKER_LIBS="-lpthread"
|
||||||
;;
|
;;
|
||||||
*)
|
*)
|
||||||
error "operating system $OS has no configuration variants"
|
error "operating system $OS has no configuration variants"
|
||||||
|
|||||||
@ -28,7 +28,7 @@ Maybe kt_tryDispose(){
|
|||||||
|
|
||||||
|
|
||||||
Maybe __kn_StdSocket_shutdown(i64 socketfd, knShutdownType direction){
|
Maybe __kn_StdSocket_shutdown(i64 socketfd, knShutdownType direction){
|
||||||
if(shutdown(socketfd, SD_SEND) == -1)
|
if(shutdown(socketfd, (int)direction) == -1)
|
||||||
safethrow("can't shutdown socket", ;);
|
safethrow("can't shutdown socket", ;);
|
||||||
return MaybeNull;
|
return MaybeNull;
|
||||||
}
|
}
|
||||||
@ -37,7 +37,7 @@ Maybe __kn_StdSocket_close(i64 socketfd){
|
|||||||
#if KN_USE_WINSOCK
|
#if KN_USE_WINSOCK
|
||||||
if(closesocket(socketfd) == -1)
|
if(closesocket(socketfd) == -1)
|
||||||
#else
|
#else
|
||||||
if(close(socket->socketfd) == -1)
|
if(close(socketfd) == -1)
|
||||||
#endif
|
#endif
|
||||||
safethrow("can't close socket", ;);
|
safethrow("can't close socket", ;);
|
||||||
|
|
||||||
|
|||||||
@ -1,28 +1,28 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#if __cplusplus
|
#if __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "../base/base.h"
|
#include "../base/base.h"
|
||||||
|
|
||||||
#include "network_types.h"
|
#include "network_types.h"
|
||||||
#include "sockets/knSocketTCP.h"
|
#include "sockets/knSocketTCP.h"
|
||||||
#include "sockets/knSocketUDP.h"
|
#include "sockets/knSocketUDP.h"
|
||||||
#include "sockets/knSocketChanneled.h"
|
#include "sockets/knSocketChanneled.h"
|
||||||
|
|
||||||
Maybe kn_tryInit();
|
Maybe kn_tryInit();
|
||||||
Maybe kt_tryDispose();
|
Maybe kt_tryDispose();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* INTERNAL */
|
/* INTERNAL */
|
||||||
|
|
||||||
/// shutdown TCP/UDP/other std socket
|
/// shutdown TCP/UDP/other std socket
|
||||||
Maybe __kn_StdSocket_shutdown(i64 socketfd, knShutdownType direction);
|
Maybe __kn_StdSocket_shutdown(i64 socketfd, knShutdownType direction);
|
||||||
/// close TCP/UDP/other std socket
|
/// close TCP/UDP/other std socket
|
||||||
Maybe __kn_StdSocket_close(i64 socketfd);
|
Maybe __kn_StdSocket_close(i64 socketfd);
|
||||||
|
|
||||||
#if __cplusplus
|
#if __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@ -1,59 +1,59 @@
|
|||||||
#include "../network.h"
|
#include "../network.h"
|
||||||
#include "../socket_impl_includes.h"
|
#include "../socket_impl_includes.h"
|
||||||
|
|
||||||
ktid_define(knPackage);
|
ktid_define(knPackage);
|
||||||
ktid_define(knPackageQueueElem);
|
ktid_define(knPackageQueueElem);
|
||||||
ktid_define(knChannel);
|
ktid_define(knChannel);
|
||||||
ktid_define(knSocketChanneled);
|
ktid_define(knSocketChanneled);
|
||||||
|
|
||||||
Maybe knSocketChanneled_open(){
|
Maybe knSocketChanneled_open(){
|
||||||
knSocketChanneled* newSocket=malloc(sizeof(knSocketChanneled));
|
knSocketChanneled* newSocket=malloc(sizeof(knSocketChanneled));
|
||||||
newSocket->localEndpoint=knIPV4Endpoint_create(knIPV4Address_fromBytes(0,0,0,0),0);
|
newSocket->localEndpoint=knIPV4Endpoint_create(knIPV4Address_fromBytes(0,0,0,0),0);
|
||||||
newSocket->remoteEndpoint=newSocket->localEndpoint;
|
newSocket->remoteEndpoint=newSocket->localEndpoint;
|
||||||
newSocket->channels=NULL;
|
newSocket->channels=NULL;
|
||||||
newSocket->channelsAmount=0;
|
newSocket->channelsAmount=0;
|
||||||
return SUCCESS(UniHeapPtr(knSocketChanneled, newSocket));
|
return SUCCESS(UniHeapPtr(knSocketChanneled, newSocket));
|
||||||
}
|
}
|
||||||
|
|
||||||
Maybe knSocketChanneled_close(knSocketChanneled* socket){
|
Maybe knSocketChanneled_close(knSocketChanneled* socket){
|
||||||
int result=
|
int result=
|
||||||
#if KN_USE_WINSOCK
|
#if KN_USE_WINSOCK
|
||||||
closesocket
|
closesocket
|
||||||
#else
|
#else
|
||||||
close
|
close
|
||||||
#endif
|
#endif
|
||||||
(socket->socketfd);
|
(socket->socketfd);
|
||||||
if(result==-1) {
|
if(result==-1) {
|
||||||
safethrow("can't close socket",;);
|
safethrow("can't close socket",;);
|
||||||
}
|
}
|
||||||
else return MaybeNull;
|
else return MaybeNull;
|
||||||
}
|
}
|
||||||
|
|
||||||
knChannel* __createChannel(){
|
knChannel* __createChannel(){
|
||||||
knChannel* ch=malloc(sizeof(knChannel));
|
knChannel* ch=malloc(sizeof(knChannel));
|
||||||
ch->queueStart=NULL;
|
ch->queueStart=NULL;
|
||||||
return ch;
|
return ch;
|
||||||
}
|
}
|
||||||
|
|
||||||
Maybe knSocketChanneled_createChannel(knSocketChanneled* socket){
|
Maybe knSocketChanneled_createChannel(knSocketChanneled* socket){
|
||||||
if(socket->channelsAmount == 65535)
|
if(socket->channelsAmount == 65535)
|
||||||
safethrow("max amount of channels",;);
|
safethrow("max amount of channels",;);
|
||||||
u16 channelsAmountPrev=socket->channelsAmount;
|
u16 channelsAmountPrev=socket->channelsAmount;
|
||||||
socket->channelsAmount++;
|
socket->channelsAmount++;
|
||||||
if(channelsAmountPrev==0)
|
if(channelsAmountPrev==0)
|
||||||
socket->channels=malloc(sizeof(knChannel*));
|
socket->channels=malloc(sizeof(knChannel*));
|
||||||
else
|
else
|
||||||
socket->channels=realloc(socket->channels, socket->channelsAmount*sizeof(knChannel*));
|
socket->channels=realloc(socket->channels, socket->channelsAmount*sizeof(knChannel*));
|
||||||
socket->channels[channelsAmountPrev]=__createChannel();
|
socket->channels[channelsAmountPrev]=__createChannel();
|
||||||
return SUCCESS(UniUInt64(channelsAmountPrev));
|
return SUCCESS(UniUInt64(channelsAmountPrev));
|
||||||
}
|
}
|
||||||
|
|
||||||
Maybe knSocketChanneled_listen(knSocketChanneled* socket, knIPV4Endpoint localEndp);
|
Maybe knSocketChanneled_listen(knSocketChanneled* socket, knIPV4Endpoint localEndp);
|
||||||
|
|
||||||
Maybe knSocketChanneled_connect(knSocketChanneled* socket, knIPV4Endpoint remoteEndp);
|
Maybe knSocketChanneled_connect(knSocketChanneled* socket, knIPV4Endpoint remoteEndp);
|
||||||
|
|
||||||
Maybe knSocketChanneled_accept(knSocketChanneled* socket);
|
Maybe knSocketChanneled_accept(knSocketChanneled* socket);
|
||||||
|
|
||||||
Maybe knSocketChanneled_send(knSocketChanneled* socket, u16 destinationIndex, u8* data, u32 dataLength);
|
Maybe knSocketChanneled_send(knSocketChanneled* socket, u16 destinationIndex, u8* data, u32 dataLength);
|
||||||
|
|
||||||
Maybe knSocketChanneled_receive(knSocketChanneled* socket, u16 destinationIndex, u8* buffer, u32 bufferLength);
|
Maybe knSocketChanneled_receive(knSocketChanneled* socket, u16 destinationIndex, u8* buffer, u32 bufferLength);
|
||||||
@ -1,97 +1,102 @@
|
|||||||
#include "../network.h"
|
#include "../network.h"
|
||||||
#include "../socket_impl_includes.h"
|
#include "../socket_impl_includes.h"
|
||||||
ktid_define(knSocketTCP);
|
ktid_define(knSocketTCP);
|
||||||
|
|
||||||
Maybe knSocketTCP_open(){
|
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_create(IPV4_NONE,0);
|
||||||
newSocket->remoteEndpoint=newSocket->localEndpoint;
|
newSocket->remoteEndpoint=knIPV4Endpoint_create(IPV4_NONE,0);
|
||||||
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 TCP socket", free(newSocket));
|
safethrow("can't create socket", free(newSocket));
|
||||||
|
|
||||||
return SUCCESS(UniHeapPtr(knSocketTCP, newSocket));
|
// 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)
|
||||||
Maybe knSocketTCP_shutdown(knSocketTCP* socket, knShutdownType direction){
|
safethrow("can't set socket options", free(newSocket));
|
||||||
try(__kn_StdSocket_shutdown(socket->socketfd, direction), _m875, ;);
|
|
||||||
return MaybeNull;
|
return SUCCESS(UniHeapPtr(knSocketTCP, newSocket));
|
||||||
}
|
}
|
||||||
|
|
||||||
Maybe knSocketTCP_close(knSocketTCP* socket){
|
Maybe knSocketTCP_shutdown(knSocketTCP* socket, knShutdownType direction){
|
||||||
try(__kn_StdSocket_close(socket->socketfd), _m875, ;);
|
try(__kn_StdSocket_shutdown(socket->socketfd, direction), _m875, ;);
|
||||||
socket->socketfd = 0;
|
return MaybeNull;
|
||||||
socket->localEndpoint = knIPV4Endpoint_create(IPV4_NONE, -1);
|
}
|
||||||
socket->remoteEndpoint = knIPV4Endpoint_create(IPV4_NONE, -1);
|
|
||||||
return MaybeNull;
|
Maybe knSocketTCP_close(knSocketTCP* socket){
|
||||||
}
|
try(__kn_StdSocket_close(socket->socketfd), _m875, ;);
|
||||||
|
free(socket);
|
||||||
Maybe knSocketTCP_listen(knSocketTCP* socket, knIPV4Endpoint localEndp){
|
return MaybeNull;
|
||||||
struct sockaddr_in servaddr;
|
}
|
||||||
servaddr.sin_family = AF_INET;
|
|
||||||
servaddr.sin_addr.s_addr = localEndp.address.UintBigEndian;
|
Maybe knSocketTCP_listen(knSocketTCP* socket, knIPV4Endpoint localEndp){
|
||||||
servaddr.sin_port = htons(localEndp.port);
|
struct sockaddr_in servaddr;
|
||||||
if(bind(socket->socketfd,(struct sockaddr*)&servaddr, sizeof(servaddr)) !=0)
|
servaddr.sin_family = AF_INET;
|
||||||
safethrow("socket bind failed",;);
|
servaddr.sin_addr.s_addr = localEndp.address.UintBigEndian;
|
||||||
socket->localEndpoint=localEndp;
|
servaddr.sin_port = htons(localEndp.port);
|
||||||
if(listen(socket->socketfd, 256) !=0)
|
int r = bind(socket->socketfd,(struct sockaddr*)&servaddr, sizeof(servaddr));
|
||||||
safethrow("socket listen failed",;);
|
if(r != 0)
|
||||||
return MaybeNull;
|
safethrow("socket bind failed",;);
|
||||||
}
|
socket->localEndpoint=localEndp;
|
||||||
|
|
||||||
Maybe knSocketTCP_connect(knSocketTCP* socket, knIPV4Endpoint remoteEndp){
|
r = listen(socket->socketfd, 1024);
|
||||||
struct sockaddr_in servaddr;
|
if(r != 0)
|
||||||
servaddr.sin_family=AF_INET;
|
safethrow("socket listen failed",;);
|
||||||
servaddr.sin_addr.s_addr = remoteEndp.address.UintBigEndian;
|
return MaybeNull;
|
||||||
servaddr.sin_port = htons(remoteEndp.port);
|
}
|
||||||
if(connect(socket->socketfd, (struct sockaddr*)&servaddr, sizeof(servaddr)) !=0)
|
|
||||||
safethrow("socket connect failed",;);
|
Maybe knSocketTCP_connect(knSocketTCP* socket, knIPV4Endpoint remoteEndp){
|
||||||
socket->remoteEndpoint=remoteEndp;
|
struct sockaddr_in servaddr;
|
||||||
return MaybeNull;
|
servaddr.sin_family=AF_INET;
|
||||||
}
|
servaddr.sin_addr.s_addr = remoteEndp.address.UintBigEndian;
|
||||||
|
servaddr.sin_port = htons(remoteEndp.port);
|
||||||
Maybe knSocketTCP_accept(knSocketTCP* socket){
|
if(connect(socket->socketfd, (struct sockaddr*)&servaddr, sizeof(servaddr)) !=0)
|
||||||
struct sockaddr_in remoteAddr = {0};
|
safethrow("socket connect failed",;);
|
||||||
int remoteAddrSize = sizeof(remoteAddr);
|
socket->remoteEndpoint=remoteEndp;
|
||||||
i64 client_fd = accept(socket->socketfd, (struct sockaddr*)&remoteAddr, &remoteAddrSize);
|
return MaybeNull;
|
||||||
if(client_fd == -1 || client_fd == ~0)
|
}
|
||||||
safethrow("can't accept client connection", ;);
|
|
||||||
// if accept() didn't set remoteAddr for some reason
|
Maybe knSocketTCP_accept(knSocketTCP* socket){
|
||||||
if(remoteAddr.sin_addr.s_addr == 0 && remoteAddr.sin_port == 0 && remoteAddr.sin_family == 0){
|
struct sockaddr_in remoteAddr = {0};
|
||||||
if(getpeername(client_fd, (struct sockaddr*)&remoteAddr, &remoteAddrSize) != 0)
|
u64 remoteAddrSize = sizeof(remoteAddr);
|
||||||
safethrow("can't get connected client address", ;);
|
i64 client_fd = accept(socket->socketfd, (struct sockaddr*)&remoteAddr, (void*)&remoteAddrSize);
|
||||||
}
|
if(client_fd == -1 || client_fd == ~0)
|
||||||
|
safethrow("can't accept client connection", ;);
|
||||||
knSocketTCP* clientSocket = malloc(sizeof(knSocketTCP));
|
// if accept() didn't set remoteAddr for some reason
|
||||||
clientSocket->socketfd = client_fd;
|
if(remoteAddr.sin_addr.s_addr == 0 && remoteAddr.sin_port == 0 && remoteAddr.sin_family == 0){
|
||||||
clientSocket->localEndpoint = socket->localEndpoint;
|
if(getpeername(client_fd, (struct sockaddr*)&remoteAddr, (void*)&remoteAddrSize) != 0)
|
||||||
clientSocket->remoteEndpoint = knIPV4Endpoint_create(
|
safethrow("can't get connected client address", ;);
|
||||||
knIPV4Address_fromU32(remoteAddr.sin_addr.s_addr),
|
}
|
||||||
remoteAddr.sin_port);
|
|
||||||
return SUCCESS(UniHeapPtr(knSocketTCP, clientSocket));
|
knSocketTCP* clientSocket = malloc(sizeof(knSocketTCP));
|
||||||
}
|
clientSocket->socketfd = client_fd;
|
||||||
|
clientSocket->localEndpoint = socket->localEndpoint;
|
||||||
Maybe knSocketTCP_send(knSocketTCP* socket, char* data, u32 dataLength){
|
clientSocket->remoteEndpoint = knIPV4Endpoint_create(
|
||||||
u32 sentTotal = 0;
|
knIPV4Address_fromU32(remoteAddr.sin_addr.s_addr),
|
||||||
while(sentTotal < dataLength){
|
remoteAddr.sin_port);
|
||||||
int sentCount = send(socket->socketfd, data+sentTotal, dataLength-sentTotal, 0);
|
return SUCCESS(UniHeapPtr(knSocketTCP, clientSocket));
|
||||||
if(sentCount == -1){
|
}
|
||||||
safethrow(
|
|
||||||
cptr_concat("can't send ", toString_u64(dataLength-sentTotal,0,0),
|
Maybe knSocketTCP_send(knSocketTCP* socket, char* data, u32 dataLength){
|
||||||
" bytes out of ", toString_u64(dataLength,0,0),
|
u32 sentTotal = 0;
|
||||||
" at index ", toString_u64(sentTotal,0,0),
|
while(sentTotal < dataLength){
|
||||||
" to TCP socket"
|
int sentCount = send(socket->socketfd, data+sentTotal, dataLength-sentTotal, 0);
|
||||||
),
|
if(sentCount == -1){
|
||||||
;);
|
safethrow(
|
||||||
}
|
cptr_concat("can't send ", toString_u64(dataLength-sentTotal,0,0),
|
||||||
sentTotal += sentCount;
|
" bytes out of ", toString_u64(dataLength,0,0),
|
||||||
}
|
" at index ", toString_u64(sentTotal,0,0)
|
||||||
return MaybeNull;
|
),
|
||||||
}
|
;);
|
||||||
|
}
|
||||||
Maybe knSocketTCP_receive(knSocketTCP* socket, char* buffer, u32 bufferLength){
|
sentTotal += sentCount;
|
||||||
int receivedCount = recv(socket->socketfd, buffer, bufferLength, 0);
|
}
|
||||||
if(receivedCount == -1 || receivedCount == 0)
|
return MaybeNull;
|
||||||
safethrow("can't receive data from TCP socket", ;)
|
}
|
||||||
return SUCCESS(UniUInt64(receivedCount));
|
|
||||||
}
|
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));
|
||||||
|
}
|
||||||
|
|||||||
@ -1,49 +1,53 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#if __cplusplus
|
#if __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "../network_types.h"
|
#include "../network_types.h"
|
||||||
|
|
||||||
typedef struct knSocketTCP {
|
typedef struct knSocketTCP {
|
||||||
i64 socketfd;
|
i64 socketfd;
|
||||||
knIPV4Endpoint localEndpoint;
|
knIPV4Endpoint localEndpoint;
|
||||||
knIPV4Endpoint remoteEndpoint;
|
knIPV4Endpoint remoteEndpoint;
|
||||||
// TODO socket status enum
|
// TODO socket status enum
|
||||||
} knSocketTCP;
|
} knSocketTCP;
|
||||||
ktid_declare(knSocketTCP);
|
ktid_declare(knSocketTCP);
|
||||||
|
|
||||||
///@return Maybe<knSocketTCP*> new socket
|
///@note EXAMPLE 1: socket = open(false); bind(socket, localhost:8080); close(socket); - the socket on port 8080 still unavaliable for several minutes
|
||||||
Maybe knSocketTCP_open();
|
///@note EXAMPLE 2: socket = open(true); bind(socket, localhost:8080); close(socket); - the socket on port 8080 can be opened again
|
||||||
|
///@param allowReuse enables binding multiple sockets to single port. Set to TRUE on a listening socket if you want to bind it to the same port after close.
|
||||||
///@param direction receive/send/both
|
///@return Maybe<knSocketTCP*> new socket
|
||||||
///@return Maybe<void> error or nothing
|
Maybe knSocketTCP_open(bool allowReuse);
|
||||||
Maybe knSocketTCP_shutdown(knSocketTCP* socket, knShutdownType direction);
|
|
||||||
|
///@param direction receive/send/both
|
||||||
///@return Maybe<void> error or nothing
|
///@return Maybe<void> error or nothing
|
||||||
Maybe knSocketTCP_close(knSocketTCP* socket);
|
Maybe knSocketTCP_shutdown(knSocketTCP* socket, knShutdownType direction);
|
||||||
|
|
||||||
///start listening at local endpoint
|
/// closes file descriptor and frees socket pointer
|
||||||
///@return Maybe<void> error or nothing
|
///@return Maybe<void> error or nothing
|
||||||
Maybe knSocketTCP_listen(knSocketTCP* socket, knIPV4Endpoint localEndp);
|
Maybe knSocketTCP_close(knSocketTCP* socket);
|
||||||
|
|
||||||
///sets socket remote endpoint
|
///start listening at local endpoint
|
||||||
///@return Maybe<void> error or nothing
|
///@return Maybe<void> error or nothing
|
||||||
Maybe knSocketTCP_connect(knSocketTCP* socket, knIPV4Endpoint remoteEndp);
|
Maybe knSocketTCP_listen(knSocketTCP* socket, knIPV4Endpoint localEndp);
|
||||||
|
|
||||||
///@return Maybe<knSocketTCP*> new socket connected to client
|
///sets socket remote endpoint
|
||||||
Maybe knSocketTCP_accept(knSocketTCP* socket);
|
///@return Maybe<void> error or nothing
|
||||||
|
Maybe knSocketTCP_connect(knSocketTCP* socket, knIPV4Endpoint remoteEndp);
|
||||||
///@param dataLength 0-4294967295
|
|
||||||
///@return Maybe<void>
|
///@return Maybe<knSocketTCP*> new socket connected to client
|
||||||
Maybe knSocketTCP_send(knSocketTCP* socket, char* data, u32 dataLength);
|
Maybe knSocketTCP_accept(knSocketTCP* socket);
|
||||||
|
|
||||||
///@param buffer buffer for receiving data
|
///@param dataLength 0-4294967295
|
||||||
///@param bufferLength 0-4294967295
|
///@return Maybe<void>
|
||||||
///@return Maybe<u64> received bytes amount
|
Maybe knSocketTCP_send(knSocketTCP* socket, char* data, u32 dataLength);
|
||||||
Maybe knSocketTCP_receive(knSocketTCP* socket, char* buffer, u32 bufferLength);
|
|
||||||
|
///@param buffer buffer for receiving data
|
||||||
#if __cplusplus
|
///@param bufferLength 0-4294967295
|
||||||
}
|
///@return Maybe<u64> received bytes amount
|
||||||
|
Maybe knSocketTCP_receive(knSocketTCP* socket, char* buffer, u32 bufferLength);
|
||||||
|
|
||||||
|
#if __cplusplus
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
@ -1,33 +1,37 @@
|
|||||||
#include "../network.h"
|
#include "../network.h"
|
||||||
#include "../socket_impl_includes.h"
|
#include "../socket_impl_includes.h"
|
||||||
ktid_define(knSocketUDP);
|
ktid_define(knSocketUDP);
|
||||||
|
|
||||||
Maybe knSocketUDP_open(){
|
Maybe knSocketUDP_open(bool allowReuse){
|
||||||
knSocketUDP* newSocket=malloc(sizeof(knSocketUDP));
|
knSocketUDP* newSocket=malloc(sizeof(knSocketUDP));
|
||||||
newSocket->localEndpoint=knIPV4Endpoint_create(knIPV4Address_fromBytes(0,0,0,0),0);
|
newSocket->localEndpoint=knIPV4Endpoint_create(knIPV4Address_fromBytes(0,0,0,0),0);
|
||||||
newSocket->socketfd=socket(AF_INET, SOCK_DGRAM, 0);
|
newSocket->socketfd=socket(AF_INET, SOCK_DGRAM, 0);
|
||||||
if(newSocket->socketfd==-1)
|
if(newSocket->socketfd==-1)
|
||||||
safethrow("can't create UDP socket", free(newSocket));
|
safethrow("can't create socket", free(newSocket));
|
||||||
|
|
||||||
return SUCCESS(UniHeapPtr(knSocketUDP, newSocket));
|
// 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)
|
||||||
Maybe knSocketUDP_shutdown(knSocketUDP* socket, knShutdownType direction){
|
safethrow("can't set socket options", free(newSocket));
|
||||||
try(__kn_StdSocket_shutdown(socket->socketfd, direction), _m875, ;);
|
|
||||||
return MaybeNull;
|
return SUCCESS(UniHeapPtr(knSocketUDP, newSocket));
|
||||||
}
|
}
|
||||||
|
|
||||||
Maybe knSocketUDP_close(knSocketUDP* socket){
|
Maybe knSocketUDP_shutdown(knSocketUDP* socket, knShutdownType direction){
|
||||||
try(__kn_StdSocket_close(socket->socketfd), _m875, ;);
|
try(__kn_StdSocket_shutdown(socket->socketfd, direction), _m875, ;);
|
||||||
socket->socketfd = 0;
|
return MaybeNull;
|
||||||
socket->localEndpoint = knIPV4Endpoint_create(IPV4_NONE, -1);
|
}
|
||||||
return MaybeNull;
|
|
||||||
}
|
Maybe knSocketUDP_close(knSocketUDP* socket){
|
||||||
|
try(__kn_StdSocket_close(socket->socketfd), _m875, ;);
|
||||||
Maybe knSocketUDP_listen(knSocketUDP* socket, knIPV4Endpoint localEndp);
|
free(socket);
|
||||||
|
return MaybeNull;
|
||||||
Maybe knSocketUDP_accept(knSocketUDP* socket);
|
}
|
||||||
|
|
||||||
Maybe knSocketUDP_sendto(knSocketUDP* socket, char* data, u32 dataLength, knIPV4Endpoint destination);
|
Maybe knSocketUDP_listen(knSocketUDP* socket, knIPV4Endpoint localEndp);
|
||||||
|
|
||||||
Maybe knSocketUDP_receive(knSocketUDP* socket, char* buffer, u32 bufferLength);
|
Maybe knSocketUDP_accept(knSocketUDP* socket);
|
||||||
|
|
||||||
|
Maybe knSocketUDP_sendto(knSocketUDP* socket, char* data, u32 dataLength, knIPV4Endpoint destination);
|
||||||
|
|
||||||
|
Maybe knSocketUDP_receive(knSocketUDP* socket, char* buffer, u32 bufferLength);
|
||||||
|
|||||||
@ -1,45 +1,49 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#if __cplusplus
|
#if __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "../network_types.h"
|
#include "../network_types.h"
|
||||||
|
|
||||||
typedef struct knSocketUDP {
|
typedef struct knSocketUDP {
|
||||||
i64 socketfd;
|
i64 socketfd;
|
||||||
knIPV4Endpoint localEndpoint;
|
knIPV4Endpoint localEndpoint;
|
||||||
// TODO socket status enum
|
// TODO socket status enum
|
||||||
} knSocketUDP;
|
} knSocketUDP;
|
||||||
ktid_declare(knSocketUDP);
|
ktid_declare(knSocketUDP);
|
||||||
|
|
||||||
///@return Maybe<knSocketUDP*> new socket
|
///@note EXAMPLE 1: socket = open(false); bind(socket, localhost:8080); close(socket); - the socket on port 8080 still unavaliable for several minutes
|
||||||
Maybe knSocketUDP_open();
|
///@note EXAMPLE 2: socket = open(true); bind(socket, localhost:8080); close(socket); - the socket on port 8080 can be opened again
|
||||||
|
///@param allowReuse enables binding multiple sockets to single port. Set to TRUE on a listening socket if you want to bind it to the same port after close.
|
||||||
///@param direction receive/send/both
|
///@return Maybe<knSocketUDP*> new socket
|
||||||
///@return Maybe<void> error or nothing
|
Maybe knSocketUDP_open(bool allowReuse);
|
||||||
Maybe knSocketUDP_shutdown(knSocketUDP* socket, knShutdownType direction);
|
|
||||||
|
///@param direction receive/send/both
|
||||||
///@return Maybe<void> error or nothing
|
///@return Maybe<void> error or nothing
|
||||||
Maybe knSocketUDP_close(knSocketUDP* socket);
|
Maybe knSocketUDP_shutdown(knSocketUDP* socket, knShutdownType direction);
|
||||||
|
|
||||||
///start listening at local endpoint
|
/// closes file descriptor and frees socket pointer
|
||||||
///@return Maybe<void> error or nothing
|
///@return Maybe<void> error or nothing
|
||||||
Maybe knSocketUDP_listen(knSocketUDP* socket, knIPV4Endpoint localEndp);
|
Maybe knSocketUDP_close(knSocketUDP* socket);
|
||||||
|
|
||||||
///@return Maybe<knSocketUDP*> new socket connected to client
|
///start listening at local endpoint
|
||||||
Maybe knSocketUDP_accept(knSocketUDP* socket);
|
///@return Maybe<void> error or nothing
|
||||||
|
Maybe knSocketUDP_listen(knSocketUDP* socket, knIPV4Endpoint localEndp);
|
||||||
///@param dataLength 0-4294967295
|
|
||||||
///@return Maybe<void>
|
///@return Maybe<knSocketUDP*> new socket connected to client
|
||||||
Maybe knSocketUDP_sendto(knSocketUDP* socket, char* data, u32 dataLength, knIPV4Endpoint destination);
|
Maybe knSocketUDP_accept(knSocketUDP* socket);
|
||||||
|
|
||||||
///@param buffer buffer for receiving data
|
///@param dataLength 0-4294967295
|
||||||
///@param bufferLength 0-4294967295
|
///@return Maybe<void>
|
||||||
///@return Maybe<u64> received bytes amount
|
Maybe knSocketUDP_sendto(knSocketUDP* socket, char* data, u32 dataLength, knIPV4Endpoint destination);
|
||||||
Maybe knSocketUDP_receive(knSocketUDP* socket, char* buffer, u32 bufferLength);
|
|
||||||
|
///@param buffer buffer for receiving data
|
||||||
|
///@param bufferLength 0-4294967295
|
||||||
#if __cplusplus
|
///@return Maybe<u64> received bytes amount
|
||||||
}
|
Maybe knSocketUDP_receive(knSocketUDP* socket, char* buffer, u32 bufferLength);
|
||||||
|
|
||||||
|
|
||||||
|
#if __cplusplus
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
@ -1,78 +1,169 @@
|
|||||||
#include "tests.h"
|
#include "tests.h"
|
||||||
#include "../src/Network/network.h"
|
#include "../src/Network/network.h"
|
||||||
|
#include "pthread.h"
|
||||||
void __test_knIPV4Address_fromStr(char* addrStr, u8 a, u8 b, u8 c, u8 d){
|
#include "../src/Network/socket_impl_includes.h"
|
||||||
tryLast(knIPV4Address_fromStr(addrStr), maybeAddr, ;)
|
|
||||||
knIPV4Address addr;
|
static void __test_knIPV4Address_fromStr(char* addrStr, u8 a, u8 b, u8 c, u8 d){
|
||||||
addr.UintBigEndian=(u32)maybeAddr.value.UInt64;
|
tryLast(knIPV4Address_fromStr(addrStr), maybeAddr, ;)
|
||||||
kprintf("\e[94mknIPV4Address_fromStr(\e[96m%s\e[94m) -> ", addrStr);
|
knIPV4Address addr;
|
||||||
if(maybeAddr.value.UInt64!=knIPV4Address_fromBytes(a,b,c,d).UintBigEndian){
|
addr.UintBigEndian=(u32)maybeAddr.value.UInt64;
|
||||||
kprintf("\e[91m%u.%u.%u.%u\n",
|
kprintf("\e[92mknIPV4Address_fromStr(\e[96m%s\e[92m) -> ", addrStr);
|
||||||
(u8)addr.bytes[0], (u8)addr.bytes[1], (u8)addr.bytes[2], (u8)addr.bytes[3]);
|
if(maybeAddr.value.UInt64!=knIPV4Address_fromBytes(a,b,c,d).UintBigEndian){
|
||||||
throw("knIPV4Address_fromStr returned wrong value");
|
kprintf("\e[91m%u.%u.%u.%u\n",
|
||||||
}
|
(u8)addr.bytes[0], (u8)addr.bytes[1], (u8)addr.bytes[2], (u8)addr.bytes[3]);
|
||||||
else {
|
throw("knIPV4Address_fromStr returned wrong value");
|
||||||
kprintf("\e[92m%u.%u.%u.%u\n",
|
}
|
||||||
(u8)addr.bytes[0], (u8)addr.bytes[1], (u8)addr.bytes[2], (u8)addr.bytes[3]);
|
else {
|
||||||
}
|
kprintf("\e[94m%u.%u.%u.%u\n",
|
||||||
|
(u8)addr.bytes[0], (u8)addr.bytes[1], (u8)addr.bytes[2], (u8)addr.bytes[3]);
|
||||||
}
|
}
|
||||||
#define test_knIPV4Address_fromStr(a,b,c,d) __test_knIPV4Address_fromStr(#a"."#b"."#c"."#d, a,b,c,d)
|
|
||||||
|
}
|
||||||
void test_network(){
|
#define test_knIPV4Address_fromStr(a,b,c,d) __test_knIPV4Address_fromStr(#a"."#b"."#c"."#d, a,b,c,d)
|
||||||
optime(__func__,1,({
|
|
||||||
kprintf("\e[96m------------[test_network]------------\n");
|
static void test_network_types(){
|
||||||
tryLast(kn_tryInit(), _mjj64g, ;);
|
PRINT_SIZEOF(knIPV4Address);
|
||||||
kprintf("\e[92m\nkerepNetwork initialized");
|
PRINT_SIZEOF(knPort);
|
||||||
|
PRINT_SIZEOF(knIPV4Endpoint);
|
||||||
PRINT_SIZEOF(knIPV4Address);
|
PRINT_SIZEOF(knSocketTCP);
|
||||||
PRINT_SIZEOF(knPort);
|
PRINT_SIZEOF(knSocketUDP);
|
||||||
PRINT_SIZEOF(knIPV4Endpoint);
|
PRINT_SIZEOF(knPackage);
|
||||||
PRINT_SIZEOF(knSocketTCP);
|
PRINT_SIZEOF(knChannel);
|
||||||
PRINT_SIZEOF(knSocketUDP);
|
|
||||||
PRINT_SIZEOF(knPackage);
|
test_knIPV4Address_fromStr(127,0,0,1);
|
||||||
PRINT_SIZEOF(knChannel);
|
test_knIPV4Address_fromStr(34,255,45,0);
|
||||||
|
test_knIPV4Address_fromStr(3,3,3,128);
|
||||||
test_knIPV4Address_fromStr(127,0,0,1);
|
fflush(stdout);
|
||||||
test_knIPV4Address_fromStr(34,255,45,0);
|
}
|
||||||
test_knIPV4Address_fromStr(3,3,3,128);
|
|
||||||
|
static pthread_mutex_t stdout_mutex = {0};
|
||||||
knSocketTCP* socket;
|
|
||||||
tryLast(knSocketTCP_open(), m_socket, ;);
|
// thread-safe print
|
||||||
socket=m_socket.value.VoidPtr;
|
#define kprintf_safe(ARGS...) pthread_mutex_lock(&stdout_mutex); kprintf(ARGS); fflush(stdout); pthread_mutex_unlock(&stdout_mutex);
|
||||||
kprintf("\e[92mTCP socket created\n");
|
|
||||||
|
typedef struct {
|
||||||
knIPV4Endpoint localEnd = knIPV4Endpoint_create(IPV4_LOOPBACK, 4444);
|
knSocketTCP* socket_client;
|
||||||
tryLast(knSocketTCP_listen(socket, localEnd), _m81775, ;)
|
knIPV4Endpoint serverEnd;
|
||||||
kprintf("\e[92msocket is listening\n");
|
} tcp_client_connect_async_data;
|
||||||
|
|
||||||
tryLast(knSocketTCP_accept(socket), m_connection, ;);
|
void* tcp_client_connect_async(void* _data){
|
||||||
knSocketTCP* clientConnection = m_connection.value.VoidPtr;
|
tcp_client_connect_async_data* data = _data;
|
||||||
kprintf("\e[92mclient connection accepted\n");
|
tryLast(knSocketTCP_connect(data->socket_client, data->serverEnd), _m8531,;);
|
||||||
|
|
||||||
char buf[4096];
|
kprintf_safe("\e[92mclient socket connected to server\n");
|
||||||
while(true){
|
free(data);
|
||||||
tryLast(knSocketTCP_receive(clientConnection, buf, sizeof(buf)), m_recCount, ;);
|
return NULL;
|
||||||
u64 recCount = m_recCount.value.UInt64;
|
}
|
||||||
fwrite(buf, sizeof(char), recCount, stdout);
|
|
||||||
// end of received data
|
static void test_tcp(){
|
||||||
if(recCount != sizeof(buf))
|
kprintf("\e[96m----------[test_network/tcp]----------\n");
|
||||||
break;
|
knIPV4Endpoint serverEnd = knIPV4Endpoint_create(IPV4_LOOPBACK, 4444);
|
||||||
}
|
knSocketTCP *socket_server, *clientConnection, *socket_client;
|
||||||
kprintf("\e[92mmessage received\n");
|
// server
|
||||||
|
{
|
||||||
const char msg[] = "pong";
|
tryLast(knSocketTCP_open(true), m_socketS, ;);
|
||||||
tryLast(knSocketTCP_send(clientConnection, msg, sizeof(msg)), _mu75q2, ;);
|
socket_server=m_socketS.value.VoidPtr;
|
||||||
kprintf("\e[92mmessage sent\n");
|
kprintf("\e[92mTCP server socket created\n");
|
||||||
|
|
||||||
tryLast(knSocketTCP_shutdown(clientConnection, knShutdownType_Both), _m2351, ;);
|
tryLast(knSocketTCP_listen(socket_server, serverEnd), _m81775, ;)
|
||||||
tryLast(knSocketTCP_close(clientConnection), _m9776, ;);
|
kprintf("\e[92mserver socket is listening\n");
|
||||||
kprintf("\e[92mclient connection closed\n");
|
}
|
||||||
|
// client
|
||||||
tryLast(knSocketTCP_close(socket), _m676, ;);
|
{
|
||||||
kprintf("\e[92mTCP socket closed\n");
|
tryLast(knSocketTCP_open(false), m_socketC, ;);
|
||||||
|
socket_client=m_socketC.value.VoidPtr;
|
||||||
tryLast(kt_tryDispose(), _m88ag, ;);
|
kprintf("\e[92mTCP client socket created\n");
|
||||||
kprintf("\e[92mkerepNetwork disposed\n");
|
|
||||||
}));
|
tcp_client_connect_async_data* client_connection_data = malloc(sizeof(tcp_client_connect_async_data));
|
||||||
|
client_connection_data->serverEnd = serverEnd;
|
||||||
|
client_connection_data->socket_client = socket_client;
|
||||||
|
pthread_t client_connection_thread;
|
||||||
|
fflush(stdout);
|
||||||
|
if(pthread_create(&client_connection_thread, NULL, tcp_client_connect_async, client_connection_data) != 0)
|
||||||
|
throw("can't create client connection thread");
|
||||||
|
if(pthread_detach(client_connection_thread) != 0)
|
||||||
|
throw("can't detatch client connection thread");
|
||||||
|
}
|
||||||
|
// server
|
||||||
|
{
|
||||||
|
tryLast(knSocketTCP_accept(socket_server), m_connection, ;);
|
||||||
|
clientConnection = m_connection.value.VoidPtr;
|
||||||
|
kprintf_safe("\e[92mserver accepted client connection\n");
|
||||||
|
}
|
||||||
|
// client
|
||||||
|
{
|
||||||
|
const char client_msg[] = "ping";
|
||||||
|
tryLast(knSocketTCP_send(socket_client, client_msg, sizeof(client_msg)), _mu75q2, ;);
|
||||||
|
kprintf("\e[92mmessage sent to server\n\e[94m");
|
||||||
|
}
|
||||||
|
// server
|
||||||
|
{
|
||||||
|
char received_client_msg[32];
|
||||||
|
tryLast(knSocketTCP_receive(clientConnection, received_client_msg, sizeof(received_client_msg)), m_recCount, ;);
|
||||||
|
u64 recCount = m_recCount.value.UInt64;
|
||||||
|
fwrite(received_client_msg, sizeof(char), recCount, stdout);
|
||||||
|
fputc('\n', stdout);
|
||||||
|
if(!cptr_equals(received_client_msg, "ping"))
|
||||||
|
throw("received_client_msg != \"ping\"");
|
||||||
|
kprintf("\e[92mmessage received by server\n");
|
||||||
|
|
||||||
|
const char server_msg[] = "pong";
|
||||||
|
tryLast(knSocketTCP_send(clientConnection, server_msg, sizeof(server_msg)), _mu75q2, ;);
|
||||||
|
kprintf("\e[92mmessage sent to client\n\e[94m");
|
||||||
|
fflush(stdout);
|
||||||
|
}
|
||||||
|
// client
|
||||||
|
{
|
||||||
|
char received_server_msg[32];
|
||||||
|
tryLast(knSocketTCP_receive(socket_client, received_server_msg, sizeof(received_server_msg)), m_recCount, ;);
|
||||||
|
u64 recCount = m_recCount.value.UInt64;
|
||||||
|
fwrite(received_server_msg, sizeof(char), recCount, stdout);
|
||||||
|
fputc('\n', stdout);
|
||||||
|
if(!cptr_equals(received_server_msg, "pong"))
|
||||||
|
throw("received_server_msg != \"pong\"");
|
||||||
|
kprintf("\e[92mmessage received by client\n");
|
||||||
|
fflush(stdout);
|
||||||
|
}
|
||||||
|
// server
|
||||||
|
{
|
||||||
|
tryLast(knSocketTCP_shutdown(clientConnection, knShutdownType_Both), _m2351, ;);
|
||||||
|
tryLast(knSocketTCP_close(clientConnection), _m9776, ;);
|
||||||
|
kprintf("\e[92mclient connection closed\n");
|
||||||
|
|
||||||
|
tryLast(knSocketTCP_close(socket_server), _m676, ;);
|
||||||
|
kprintf("\e[92mTCP server socket closed\n");
|
||||||
|
}
|
||||||
|
// client
|
||||||
|
{
|
||||||
|
tryLast(knSocketTCP_close(socket_client), _m964, ;);
|
||||||
|
kprintf("\e[92mTCP client socket closed\n");
|
||||||
|
}
|
||||||
|
fflush(stdout);
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_udp(){
|
||||||
|
kprintf("\e[96m----------[test_network/udp]----------\n");
|
||||||
|
|
||||||
|
fflush(stdout);
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_network(){
|
||||||
|
optime(__func__,1,({
|
||||||
|
kprintf("\e[96m------------[test_network]------------\n");
|
||||||
|
tryLast(kn_tryInit(), _mjj64g, ;);
|
||||||
|
kprintf("\e[92mkerepNetwork initialized\n");
|
||||||
|
|
||||||
|
if(pthread_mutex_init(&stdout_mutex, NULL) != 0)
|
||||||
|
throw("can't init mutex");
|
||||||
|
|
||||||
|
test_network_types();
|
||||||
|
test_tcp();
|
||||||
|
test_udp();
|
||||||
|
|
||||||
|
if(pthread_mutex_destroy(&stdout_mutex) != 0)
|
||||||
|
throw("can't destroy mutex");
|
||||||
|
|
||||||
|
tryLast(kt_tryDispose(), _m88ag, ;);
|
||||||
|
kprintf("\e[92mkerepNetwork disposed\n");
|
||||||
|
}));
|
||||||
}
|
}
|
||||||
Loading…
Reference in New Issue
Block a user