Networking: report detailed error messages; support --thread false for debugging

This commit is contained in:
李通洲
2024-03-20 13:52:39 +08:00
parent f73c3b85c2
commit 85da30ccf5
4 changed files with 56 additions and 44 deletions
+2 -10
View File
@@ -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);
+29 -16
View File
@@ -6,22 +6,25 @@
#include <sys/socket.h>
#include <netdb.h>
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";
}
+13 -9
View File
@@ -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)
{
+12 -9
View File
@@ -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;
}