TCP and UDP sockets localEndpoint
This commit is contained in:
@@ -12,7 +12,7 @@ typedef u16 knPort;
|
||||
|
||||
typedef union knIPV4Address {
|
||||
u32 UintBigEndian;
|
||||
char bytes[4];
|
||||
u8 bytes[4];
|
||||
} knIPV4Address;
|
||||
kt_declare(knIPV4Address);
|
||||
|
||||
|
||||
@@ -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, ;);
|
||||
|
||||
|
||||
@@ -27,9 +27,13 @@ Maybe knSocketTCP_shutdown(knSocketTCP* socket, knShutdownType direction);
|
||||
///@return Maybe<void> 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<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
|
||||
Maybe knSocketTCP_bindAndListen(knSocketTCP* socket, knIPV4Endpoint localEndp);
|
||||
|
||||
/// establishes TCP connection with a remote endpoint
|
||||
///@return Maybe<void> error or nothing
|
||||
@@ -42,18 +46,18 @@ Maybe knSocketTCP_accept(knSocketTCP* socket);
|
||||
///@param buffer buffer for receiving data
|
||||
///@param dataLength 0-4294967295
|
||||
///@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
|
||||
/// (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
|
||||
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<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
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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); \
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user