implemented socket_TCP_enableAliveChecks
This commit is contained in:
parent
ebab072835
commit
13ccfc7ff9
@ -13,6 +13,7 @@
|
||||
// include OS-dependent socket headers
|
||||
#if KN_USE_WINSOCK
|
||||
#include <winsock2.h>
|
||||
#include <ws2ipdef.h>
|
||||
// There you can see what error codes mean.
|
||||
#include <winerror.h>
|
||||
#else
|
||||
|
||||
@ -13,13 +13,9 @@ Result(void) network_init(){
|
||||
return RESULT_VOID;
|
||||
}
|
||||
|
||||
Result(void) network_deinit(){
|
||||
void network_deinit(){
|
||||
#if _WIN32
|
||||
// Deinitialize Winsock
|
||||
int result = WSACleanup();
|
||||
if (result != 0) {
|
||||
return RESULT_ERROR_FMT("WSACleanup failed with error code 0x%X", result);
|
||||
}
|
||||
(void)WSACleanup();
|
||||
#endif
|
||||
return RESULT_VOID;
|
||||
}
|
||||
|
||||
@ -2,4 +2,4 @@
|
||||
#include "tlibc/errors.h"
|
||||
|
||||
Result(void) network_init();
|
||||
Result(void) network_deinit();
|
||||
void network_deinit();
|
||||
|
||||
@ -3,7 +3,7 @@
|
||||
#include <assert.h>
|
||||
|
||||
Result(Socket) socket_open_TCP(){
|
||||
Socket s = socket(AF_INET, SOCK_STREAM, 0);
|
||||
Socket s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
|
||||
if(s == -1){
|
||||
return RESULT_ERROR_SOCKET();
|
||||
}
|
||||
@ -25,29 +25,6 @@ Result(void) socket_shutdown(Socket s, SocketShutdownType direction){
|
||||
return RESULT_VOID;
|
||||
}
|
||||
|
||||
Result(void) socket_setTimeout(Socket s, u32 ms){
|
||||
void* opt;
|
||||
u32 optlen;
|
||||
|
||||
#if KN_USE_WINSOCK
|
||||
opt = &ms;
|
||||
optlen = sizeof(ms);
|
||||
#else
|
||||
struct timeval tv = {
|
||||
.tv_sec = ms/1000,
|
||||
.tv_usec = (ms%1000)*1000
|
||||
};
|
||||
opt = &tv;
|
||||
optlen = sizeof(tv);
|
||||
#endif
|
||||
|
||||
if(setsockopt(s, SOL_SOCKET, SO_SNDTIMEO, opt, optlen) != 0)
|
||||
return RESULT_ERROR_SOCKET();
|
||||
if(setsockopt(s, SOL_SOCKET, SO_RCVTIMEO, opt, optlen) != 0)
|
||||
return RESULT_ERROR_SOCKET();
|
||||
return RESULT_VOID;
|
||||
}
|
||||
|
||||
Result(void) socket_bind(Socket s, EndpointIPv4 local_end){
|
||||
struct sockaddr_in sockaddr = EndpointIPv4_toSockaddr(local_end);
|
||||
if(bind(s, (void*)&sockaddr, sizeof(sockaddr)) != 0)
|
||||
@ -146,3 +123,60 @@ Result(i32) socket_recvfrom(Socket s, Array(u8) buffer, SocketRecvFlag flags, NU
|
||||
*remote_end = EndpointIPv4_fromSockaddr(remote_addr);
|
||||
return RESULT_VALUE(i, r);
|
||||
}
|
||||
|
||||
|
||||
|
||||
#define try_setsockopt(socket, level, OPT){ \
|
||||
if(setsockopt(socket, level, OPT, (void*)&opt_##OPT, sizeof(opt_##OPT)) != 0)\
|
||||
return RESULT_ERROR_SOCKET();\
|
||||
}
|
||||
|
||||
Result(void) socket_TCP_enableAliveChecks(Socket s,
|
||||
sec_t first_check_time, u32 checks_count, sec_t checks_interval)
|
||||
{
|
||||
#if KN_USE_WINSOCK
|
||||
BOOL opt_SO_KEEPALIVE = 1; // enable keepalives
|
||||
DWORD opt_TCP_KEEPIDLE = first_check_time;
|
||||
DWORD opt_TCP_KEEPCNT = checks_count;
|
||||
DWORD opt_TCP_KEEPINTVL = checks_interval;
|
||||
try_setsockopt(s, SOL_SOCKET, SO_KEEPALIVE);
|
||||
try_setsockopt(s, IPPROTO_TCP, TCP_KEEPIDLE);
|
||||
try_setsockopt(s, IPPROTO_TCP, TCP_KEEPCNT);
|
||||
try_setsockopt(s, IPPROTO_TCP, TCP_KEEPINTVL);
|
||||
|
||||
// timeout for connect()
|
||||
DWORD opt_TCP_MAXRT = checks_count * checks_interval;
|
||||
try_setsockopt(s, IPPROTO_TCP, TCP_MAXRT);
|
||||
#else
|
||||
int opt_SO_KEEPALIVE = 1; // enable keepalives
|
||||
int opt_TCP_KEEPIDLE = first_check_time;
|
||||
int opt_TCP_KEEPCNT = checks_count;
|
||||
int opt_TCP_KEEPINTVL = checks_interval;
|
||||
try_setsockopt(s, SOL_SOCKET, SO_KEEPALIVE);
|
||||
try_setsockopt(s, IPPROTO_TCP, TCP_KEEPIDLE);
|
||||
try_setsockopt(s, IPPROTO_TCP, TCP_KEEPCNT);
|
||||
try_setsockopt(s, IPPROTO_TCP, TCP_KEEPINTVL);
|
||||
|
||||
// read more in the article
|
||||
int opt_TCP_USER_TIMEOUT = checks_count * checks_interval * 1000;
|
||||
try_setsockopt(s, IPPROTO_TCP, TCP_USER_TIMEOUT);
|
||||
#endif
|
||||
return RESULT_VOID;
|
||||
}
|
||||
|
||||
Result(void) socket_setTimeout(Socket s, u32 ms){
|
||||
#if KN_USE_WINSOCK
|
||||
DWORD opt_SO_SNDTIMEO = ms;
|
||||
DWORD opt_SO_RCVTIMEO = opt_SO_SNDTIMEO;
|
||||
#else
|
||||
struct timeval opt_SO_SNDTIMEO = {
|
||||
.tv_sec = ms/1000,
|
||||
.tv_usec = (ms%1000)*1000
|
||||
};
|
||||
struct timeval opt_SO_RCVTIMEO = opt_SO_SNDTIMEO;
|
||||
#endif
|
||||
|
||||
try_setsockopt(s, SOL_SOCKET, SO_SNDTIMEO);
|
||||
try_setsockopt(s, SOL_SOCKET, SO_RCVTIMEO);
|
||||
return RESULT_VOID;
|
||||
}
|
||||
@ -1,6 +1,7 @@
|
||||
#pragma once
|
||||
#include "endpoint.h"
|
||||
#include "tlibc/errors.h"
|
||||
#include "tlibc/time.h"
|
||||
#include "tlibc/collections/Array.h"
|
||||
|
||||
typedef enum SocketShutdownType {
|
||||
@ -17,13 +18,9 @@ typedef enum SocketRecvFlag {
|
||||
|
||||
typedef i64 Socket;
|
||||
|
||||
#define SOCKET_TIMEOUT_MS_DEFAULT 5000
|
||||
#define SOCKET_TIMEOUT_MS_INFINITE 0
|
||||
|
||||
Result(Socket) socket_open_TCP();
|
||||
void socket_close(Socket s);
|
||||
Result(void) socket_shutdown(Socket s, SocketShutdownType direction);
|
||||
Result(void) socket_setTimeout(Socket s, u32 ms);
|
||||
|
||||
Result(void) socket_bind(Socket s, EndpointIPv4 local_end);
|
||||
Result(void) socket_listen(Socket s, i32 backlog);
|
||||
@ -34,3 +31,18 @@ Result(void) socket_send(Socket s, Array(u8) buffer);
|
||||
Result(void) socket_sendto(Socket s, Array(u8) buffer, EndpointIPv4 dst);
|
||||
Result(i32) socket_recv(Socket s, Array(u8) buffer, SocketRecvFlag flags);
|
||||
Result(i32) socket_recvfrom(Socket s, Array(u8) buffer, SocketRecvFlag flags, NULLABLE(EndpointIPv4*) remote_end);
|
||||
|
||||
/// Enables sending SO_KEEPALIVE packets when socket is idling.
|
||||
/// Also enables TCP_USER_TIMEOUT to handle situations
|
||||
/// when socket is not sending KEEPALIVE packets.
|
||||
/// Read more: https://blog.cloudflare.com/when-tcp-sockets-refuse-to-die/
|
||||
/// RU translaton: https://habr.com/ru/articles/700470/
|
||||
Result(void) socket_TCP_enableAliveChecks(Socket s,
|
||||
sec_t first_check_time, u32 checks_count, sec_t checks_interval);
|
||||
#define socket_TCP_enableAliveChecks_default(socket) \
|
||||
socket_TCP_enableAliveChecks(socket, 1, 4, 5)
|
||||
|
||||
#define SOCKET_TIMEOUT_MS_DEFAULT 5000
|
||||
#define SOCKET_TIMEOUT_MS_INFINITE 0
|
||||
/// @brief sets general timeout for send() and recv()
|
||||
Result(void) socket_setTimeout(Socket s, u32 ms);
|
||||
|
||||
Loading…
Reference in New Issue
Block a user