From 9da7bb3f30a8a99bdb8564636e599babdcd883b4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Wed, 2 Nov 2022 17:29:43 +0800 Subject: [PATCH] Networking: support nowait connection (Posix) Thread was used for now. It's possible to do nonblocking connect & send with io_uring on Linux, but it requires newer kernel and linking to liburing. I don't think it is worth the effort. --- src/common/networking.h | 13 +++++-- src/common/networking_linux.c | 66 ++++++++++++++++++++++++----------- 2 files changed, 56 insertions(+), 23 deletions(-) diff --git a/src/common/networking.h b/src/common/networking.h index aaad894c9..f27850477 100644 --- a/src/common/networking.h +++ b/src/common/networking.h @@ -3,6 +3,7 @@ #ifndef FF_INCLUDED_common_networking #define FF_INCLUDED_common_networking +#include "common/thread.h" #include "util/FFstrbuf.h" #ifdef _WIN32 @@ -11,10 +12,16 @@ typedef struct FFNetworkingState { #ifdef _WIN32 - uintptr_t sockfd; - OVERLAPPED overlapped; + uintptr_t sockfd; + OVERLAPPED overlapped; #else - int sockfd; + int sockfd; + FFstrbuf host; + FFstrbuf command; + + #ifdef FF_HAVE_THREADS + FFThreadType thread; + #endif #endif } FFNetworkingState; diff --git a/src/common/networking_linux.c b/src/common/networking_linux.c index 22e5311fa..5d656fddd 100644 --- a/src/common/networking_linux.c +++ b/src/common/networking_linux.c @@ -6,7 +6,7 @@ #include #include -bool ffNetworkingSendHttpRequest(FFNetworkingState* state, const char* host, const char* path, const char* headers) +static void connectAndSend(FFNetworkingState* state) { struct addrinfo hints = { .ai_family = AF_INET, @@ -15,47 +15,73 @@ bool ffNetworkingSendHttpRequest(FFNetworkingState* state, const char* host, con struct addrinfo* addr; - if(getaddrinfo(host, "80", &hints, &addr) != 0) - return false; + if(getaddrinfo(state->host.chars, "80", &hints, &addr) != 0) + goto error; state->sockfd = socket(addr->ai_family, addr->ai_socktype, addr->ai_protocol); if(state->sockfd == -1) { freeaddrinfo(addr); - return false; + goto error; } if(connect(state->sockfd, addr->ai_addr, addr->ai_addrlen) == -1) { close(state->sockfd); freeaddrinfo(addr); - return false; + goto error; } freeaddrinfo(addr); - FFstrbuf command; - ffStrbufInitA(&command, 64); - ffStrbufAppendS(&command, "GET "); - ffStrbufAppendS(&command, path); - ffStrbufAppendS(&command, " HTTP/1.1\nHost: "); - ffStrbufAppendS(&command, host); - ffStrbufAppendS(&command, "\r\n"); - ffStrbufAppendS(&command, headers); - ffStrbufAppendS(&command, "\r\n"); - - if(send(state->sockfd, command.chars, command.length, 0) < 0) + if(send(state->sockfd, state->command.chars, state->command.length, 0) < 0) { - ffStrbufDestroy(&command); close(state->sockfd); - return false; + goto error; } - ffStrbufDestroy(&command); - return true; + + goto exit; + +error: + state->sockfd = -1; + +exit: + ffStrbufDestroy(&state->host); + ffStrbufDestroy(&state->command); +} + +FF_THREAD_ENTRY_DECL_WRAPPER(connectAndSend, FFNetworkingState*); + +bool ffNetworkingSendHttpRequest(FFNetworkingState* state, const char* host, const char* path, const char* headers) +{ + ffStrbufInitS(&state->host, host); + + ffStrbufInitA(&state->command, 64); + ffStrbufAppendS(&state->command, "GET "); + ffStrbufAppendS(&state->command, path); + ffStrbufAppendS(&state->command, " HTTP/1.1\nHost: "); + ffStrbufAppendS(&state->command, host); + ffStrbufAppendS(&state->command, "\r\n"); + ffStrbufAppendS(&state->command, headers); + ffStrbufAppendS(&state->command, "\r\n"); + + #ifdef FF_HAVE_THREADS + state->thread = ffThreadCreate(connectAndSendThreadMain, state); + return state->thread != NULL; + #else + connectAndSend(state); + return state->sockfd != -1; + #endif } bool ffNetworkingRecvHttpResponse(FFNetworkingState* state, FFstrbuf* buffer, uint32_t timeout) { + #ifdef FF_HAVE_THREADS + ffThreadJoin(state->thread); + #endif + if(state->sockfd == -1) + return false; + if(timeout > 0) { struct timeval timev;