From 85da30ccf532c15dd019d9d59eb1890e2953c17e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Wed, 20 Mar 2024 13:52:39 +0800 Subject: [PATCH] Networking: report detailed error messages; support `--thread false` for debugging --- src/common/networking.h | 12 ++------- src/common/networking_linux.c | 45 ++++++++++++++++++++----------- src/detection/publicip/publicip.c | 22 ++++++++------- src/detection/weather/weather.c | 21 ++++++++------- 4 files changed, 56 insertions(+), 44 deletions(-) diff --git a/src/common/networking.h b/src/common/networking.h index 1fb4589d9..2137705bb 100644 --- a/src/common/networking.h +++ b/src/common/networking.h @@ -22,13 +22,5 @@ typedef struct FFNetworkingState { #endif } FFNetworkingState; -bool ffNetworkingSendHttpRequest(FFNetworkingState* state, const char* host, const char* path, const char* headers); -bool ffNetworkingRecvHttpResponse(FFNetworkingState* state, FFstrbuf* buffer, uint32_t timeout); - -static inline bool ffNetworkingGetHttp(const char* host, const char* path, uint32_t timeout, const char* headers, FFstrbuf* buffer) -{ - FFNetworkingState state; - if(ffNetworkingSendHttpRequest(&state, host, path, headers)) - return ffNetworkingRecvHttpResponse(&state, buffer, timeout); - return false; -} +const char* ffNetworkingSendHttpRequest(FFNetworkingState* state, const char* host, const char* path, const char* headers); +const char* ffNetworkingRecvHttpResponse(FFNetworkingState* state, FFstrbuf* buffer, uint32_t timeout); diff --git a/src/common/networking_linux.c b/src/common/networking_linux.c index 37c796276..46719363a 100644 --- a/src/common/networking_linux.c +++ b/src/common/networking_linux.c @@ -6,22 +6,25 @@ #include #include -static void connectAndSend(FFNetworkingState* state) +static const char* connectAndSend(FFNetworkingState* state) { - struct addrinfo hints = { - .ai_family = AF_INET, - .ai_socktype = SOCK_STREAM, - }; - + const char* ret = NULL; struct addrinfo* addr; - if(getaddrinfo(state->host.chars, "80", &hints, &addr) != 0) + if(getaddrinfo(state->host.chars, "80", &(struct addrinfo) { + .ai_family = AF_INET, + .ai_socktype = SOCK_STREAM, + }, &addr) != 0) + { + ret = "getaddrinfo() failed"; goto error; + } state->sockfd = socket(addr->ai_family, addr->ai_socktype, addr->ai_protocol); if(state->sockfd == -1) { freeaddrinfo(addr); + ret = "socket() failed"; goto error; } @@ -29,6 +32,7 @@ static void connectAndSend(FFNetworkingState* state) { close(state->sockfd); freeaddrinfo(addr); + ret = "connect() failed"; goto error; } @@ -37,6 +41,7 @@ static void connectAndSend(FFNetworkingState* state) if(send(state->sockfd, state->command.chars, state->command.length, 0) < 0) { close(state->sockfd); + ret = "send() failed"; goto error; } @@ -48,11 +53,13 @@ error: exit: ffStrbufDestroy(&state->host); ffStrbufDestroy(&state->command); + + return ret; } FF_THREAD_ENTRY_DECL_WRAPPER(connectAndSend, FFNetworkingState*); -bool ffNetworkingSendHttpRequest(FFNetworkingState* state, const char* host, const char* path, const char* headers) +const char* ffNetworkingSendHttpRequest(FFNetworkingState* state, const char* host, const char* path, const char* headers) { ffStrbufInitS(&state->host, host); @@ -66,22 +73,28 @@ bool ffNetworkingSendHttpRequest(FFNetworkingState* state, const char* host, con ffStrbufAppendS(&state->command, "\r\n"); #ifdef FF_HAVE_THREADS + if (instance.config.general.multithreading) + { state->thread = ffThreadCreate(connectAndSendThreadMain, state); - return !!state->thread; - #else - connectAndSend(state); - return state->sockfd != -1; + return state->thread ? NULL : "ffThreadCreate(connectAndSend) failed"; + } #endif + + return connectAndSend(state); } -bool ffNetworkingRecvHttpResponse(FFNetworkingState* state, FFstrbuf* buffer, uint32_t timeout) +const char* ffNetworkingRecvHttpResponse(FFNetworkingState* state, FFstrbuf* buffer, uint32_t timeout) { #ifdef FF_HAVE_THREADS + if (instance.config.general.multithreading) + { if (!ffThreadJoin(state->thread, timeout)) - return false; + return "ffThreadJoin() failed or timeout"; + } #endif + if(state->sockfd == -1) - return false; + return "ffNetworkingSendHttpRequest() failed"; if(timeout > 0) { @@ -100,5 +113,5 @@ bool ffNetworkingRecvHttpResponse(FFNetworkingState* state, FFstrbuf* buffer, ui } close(state->sockfd); - return ffStrbufStartsWithS(buffer, "HTTP/1.1 200 OK\r\n"); + return ffStrbufStartsWithS(buffer, "HTTP/1.1 200 OK\r\n") ? NULL : "Invalid response"; } diff --git a/src/detection/publicip/publicip.c b/src/detection/publicip/publicip.c index 5475fdb4d..8826dde04 100644 --- a/src/detection/publicip/publicip.c +++ b/src/detection/publicip/publicip.c @@ -1,12 +1,13 @@ #include "publicip.h" #include "common/networking.h" +#define FF_UNITIALIZED ((const char*)(uintptr_t) -1) static FFNetworkingState state; -static int status = -1; +static const char* status = FF_UNITIALIZED; void ffPreparePublicIp(FFPublicIpOptions* options) { - if (status != -1) + if (status != FF_UNITIALIZED) { fputs("Error: this module can only be used once due to internal limitations\n", stderr); exit(1); @@ -41,18 +42,21 @@ static inline void wrapYyjsonFree(yyjson_doc** doc) const char* ffDetectPublicIp(FFPublicIpOptions* options, FFPublicIpResult* result) { - if (status == -1) + if (status == FF_UNITIALIZED) ffPreparePublicIp(options); - if (status == 0) - return "Failed to connect to an IP detection server"; + if (status != NULL) + return status; FF_STRBUF_AUTO_DESTROY response = ffStrbufCreateA(4096); - bool success = ffNetworkingRecvHttpResponse(&state, &response, options->timeout); - if (success) ffStrbufSubstrAfterFirstS(&response, "\r\n\r\n"); + const char* error = ffNetworkingRecvHttpResponse(&state, &response, options->timeout); + if (error == NULL) + ffStrbufSubstrAfterFirstS(&response, "\r\n\r\n"); + else + return error; - if (!success || response.length == 0) - return "Failed to receive the server response"; + if (response.length == 0) + return "Empty server response received"; if (options->url.length == 0) { diff --git a/src/detection/weather/weather.c b/src/detection/weather/weather.c index 544105a62..9011bd04e 100644 --- a/src/detection/weather/weather.c +++ b/src/detection/weather/weather.c @@ -1,11 +1,12 @@ #include "weather.h" +#define FF_UNITIALIZED ((const char*)(uintptr_t) -1) static FFNetworkingState state; -static int status = -1; +static const char* status = FF_UNITIALIZED; void ffPrepareWeather(FFWeatherOptions* options) { - if (status != -1) + if (status != FF_UNITIALIZED) { fputs("Error: this module can only be used once due to internal limitations\n", stderr); exit(1); @@ -21,22 +22,24 @@ void ffPrepareWeather(FFWeatherOptions* options) const char* ffDetectWeather(FFWeatherOptions* options, FFstrbuf* result) { - if(status == -1) + if(status == FF_UNITIALIZED) ffPrepareWeather(options); - if(status == 0) - return "Failed to connect to 'wttr.in'"; + if(status != NULL) + return status; ffStrbufEnsureFree(result, 4095); - bool success = ffNetworkingRecvHttpResponse(&state, result, options->timeout); - if (success) + const char* error = ffNetworkingRecvHttpResponse(&state, result, options->timeout); + if (error == NULL) { ffStrbufSubstrAfterFirstS(result, "\r\n\r\n"); ffStrbufTrimRightSpace(result); } + else + return error; - if(!success || result->length == 0) - return "Failed to receive the server response"; + if(result->length == 0) + return "Empty server response received"; return NULL; }