diff --git a/src/common/networking.h b/src/common/networking.h index 2137705bb..cc8285cc5 100644 --- a/src/common/networking.h +++ b/src/common/networking.h @@ -20,7 +20,9 @@ typedef struct FFNetworkingState { FFThreadType thread; #endif #endif + + uint32_t timeout; } FFNetworkingState; const char* ffNetworkingSendHttpRequest(FFNetworkingState* state, const char* host, const char* path, const char* headers); -const char* ffNetworkingRecvHttpResponse(FFNetworkingState* state, FFstrbuf* buffer, uint32_t timeout); +const char* ffNetworkingRecvHttpResponse(FFNetworkingState* state, FFstrbuf* buffer); diff --git a/src/common/networking_linux.c b/src/common/networking_linux.c index 46719363a..67e03887d 100644 --- a/src/common/networking_linux.c +++ b/src/common/networking_linux.c @@ -5,6 +5,8 @@ #include #include #include +#include // For FreeBSD +#include static const char* connectAndSend(FFNetworkingState* state) { @@ -28,6 +30,20 @@ static const char* connectAndSend(FFNetworkingState* state) goto error; } + if (state->timeout > 0) + { + FF_MAYBE_UNUSED uint32_t sec = state->timeout / 1000; + if (sec == 0) sec = 1; + + #ifdef TCP_CONNECTIONTIMEOUT + setsockopt(state->sockfd, IPPROTO_TCP, TCP_CONNECTIONTIMEOUT, &sec, sizeof(sec)); + #elif defined(TCP_KEEPINIT) + setsockopt(state->sockfd, IPPROTO_TCP, TCP_KEEPINIT, &sec, sizeof(sec)); + #elif defined(TCP_USER_TIMEOUT) + setsockopt(state->sockfd, IPPROTO_TCP, TCP_USER_TIMEOUT, &state->timeout, sizeof(state->timeout)); + #endif + } + if(connect(state->sockfd, addr->ai_addr, addr->ai_addrlen) == -1) { close(state->sockfd); @@ -83,8 +99,10 @@ const char* ffNetworkingSendHttpRequest(FFNetworkingState* state, const char* ho return connectAndSend(state); } -const char* ffNetworkingRecvHttpResponse(FFNetworkingState* state, FFstrbuf* buffer, uint32_t timeout) +const char* ffNetworkingRecvHttpResponse(FFNetworkingState* state, FFstrbuf* buffer) { + uint32_t timeout = state->timeout; + #ifdef FF_HAVE_THREADS if (instance.config.general.multithreading) { diff --git a/src/detection/publicip/publicip.c b/src/detection/publicip/publicip.c index 8826dde04..b2e1f641f 100644 --- a/src/detection/publicip/publicip.c +++ b/src/detection/publicip/publicip.c @@ -13,6 +13,8 @@ void ffPreparePublicIp(FFPublicIpOptions* options) exit(1); } + state.timeout = options->timeout; + if (options->url.length == 0) status = ffNetworkingSendHttpRequest(&state, "ipinfo.io", "/json", NULL); else @@ -49,7 +51,7 @@ const char* ffDetectPublicIp(FFPublicIpOptions* options, FFPublicIpResult* resul return status; FF_STRBUF_AUTO_DESTROY response = ffStrbufCreateA(4096); - const char* error = ffNetworkingRecvHttpResponse(&state, &response, options->timeout); + const char* error = ffNetworkingRecvHttpResponse(&state, &response); if (error == NULL) ffStrbufSubstrAfterFirstS(&response, "\r\n\r\n"); else diff --git a/src/detection/weather/weather.c b/src/detection/weather/weather.c index 9011bd04e..de3281348 100644 --- a/src/detection/weather/weather.c +++ b/src/detection/weather/weather.c @@ -12,6 +12,8 @@ void ffPrepareWeather(FFWeatherOptions* options) exit(1); } + state.timeout = options->timeout; + FF_STRBUF_AUTO_DESTROY path = ffStrbufCreateS("/"); if (options->location.length) ffStrbufAppend(&path, &options->location); @@ -29,7 +31,7 @@ const char* ffDetectWeather(FFWeatherOptions* options, FFstrbuf* result) return status; ffStrbufEnsureFree(result, 4095); - const char* error = ffNetworkingRecvHttpResponse(&state, result, options->timeout); + const char* error = ffNetworkingRecvHttpResponse(&state, result); if (error == NULL) { ffStrbufSubstrAfterFirstS(result, "\r\n\r\n");