From 9f0560fb9e352191830be67d4cc4475538cc7383 Mon Sep 17 00:00:00 2001 From: Francesco Cozzuto Date: Sun, 23 Nov 2025 23:39:48 +0100 Subject: [PATCH] Add http_client_wait_response for client who don't care about calling poll() directly --- chttp.c | 50 +++++++++++++++++++++++++++++++++------- chttp.h | 3 +++ examples/simple_client.c | 41 +++++--------------------------- src/client.c | 50 +++++++++++++++++++++++++++++++++------- src/client.h | 3 +++ 5 files changed, 96 insertions(+), 51 deletions(-) diff --git a/chttp.c b/chttp.c index aa3da41..8b8a65a 100644 --- a/chttp.c +++ b/chttp.c @@ -3720,14 +3720,6 @@ int http_client_wakeup(HTTP_Client *client) return 0; } -int http_client_register_events(HTTP_Client *client, - EventRegister *reg) -{ - if (socket_manager_register_events(&client->sockets, reg) < 0) - return -1; - return 0; -} - // Get a connection pointer from a request builder. // If the builder is invalid, returns NULL. static HTTP_ClientConn* @@ -4154,6 +4146,14 @@ static void save_cookies(HTTP_CookieJar *cookie_jar, save_one_cookie(cookie_jar, headers[i], domain, path); } +int http_client_register_events(HTTP_Client *client, + EventRegister *reg) +{ + if (socket_manager_register_events(&client->sockets, reg) < 0) + return -1; + return 0; +} + int http_client_process_events(HTTP_Client *client, EventRegister *reg) { @@ -4331,6 +4331,40 @@ void http_free_response(HTTP_Response *response) client->num_conns--; } +#ifdef _WIN32 +#define POLL WSAPoll +#else +#define POLL poll +#endif + +int http_client_wait_response(HTTP_Client *client, HTTP_Response **response, void **user) +{ + for (;;) { + void *ptrs[HTTP_CLIENT_POLL_CAPACITY]; + struct pollfd polled[HTTP_CLIENT_POLL_CAPACITY]; + + EventRegister reg = { + .ptrs=ptrs, + .polled=polled, + .num_polled=0, + .max_polled=HTTP_CLIENT_POLL_CAPACITY, + }; + if (http_client_register_events(client, ®) < 0) + return -1; + + if (reg.num_polled > 0) + POLL(reg.polled, reg.num_polled, -1); + + if (http_client_process_events(client, ®) < 0) + return -1; + + if (http_client_next_response(client, response, user)) + break; + } + + return 0; +} + //////////////////////////////////////////////////////////////////////////////////////// // src/server.c //////////////////////////////////////////////////////////////////////////////////////// diff --git a/chttp.h b/chttp.h index 9b567a0..1aaa98d 100644 --- a/chttp.h +++ b/chttp.h @@ -1026,6 +1026,9 @@ int http_client_process_events(HTTP_Client *client, bool http_client_next_response(HTTP_Client *client, HTTP_Response **response, void **user); +// TODO: comment +int http_client_wait_response(HTTP_Client *client, HTTP_Response **response, void **user); + // Free a response object. You can't access its fields // again after this. void http_free_response(HTTP_Response *response); diff --git a/examples/simple_client.c b/examples/simple_client.c index d9c03a2..8f125d7 100644 --- a/examples/simple_client.c +++ b/examples/simple_client.c @@ -17,9 +17,7 @@ int main(void) http_request_builder_set_trace_bytes(builder, true); http_request_builder_url(builder, - HTTP_METHOD_GET, - HTTP_STR("http://coz.is") - ); + HTTP_METHOD_GET, HTTP_STR("http://coz.is")); http_request_builder_header(builder, HTTP_STR("Greeting: Hello from the cHTTP example!")); @@ -27,39 +25,12 @@ int main(void) if (http_request_builder_send(builder) < 0) return -1; - for (;;) { + void *user; + HTTP_Response *response; + if (http_client_wait_response(&client, &response, &user) < 0) + return -1; - void *ptrs[HTTP_CLIENT_POLL_CAPACITY]; - struct pollfd polled[HTTP_CLIENT_POLL_CAPACITY]; - - EventRegister reg = { - .ptrs=ptrs, - .polled=polled, - .num_polled=0, - .max_polled=HTTP_CLIENT_POLL_CAPACITY, - }; - - if (http_client_register_events(&client, ®) < 0) - return -1; - - if (reg.num_polled > 0) - POLL(reg.polled, reg.num_polled, -1); - - if (http_client_process_events(&client, ®) < 0) - return -1; - - bool done = false; - - HTTP_Response *response; - void *user; - while (http_client_next_response(&client, &response, &user)) { - printf("Received response\n"); - http_free_response(response); - done = true; - } - - if (done) break; - } + printf("Received a response!\n"); http_client_free(&client); return 0; diff --git a/src/client.c b/src/client.c index 8de2aad..f0c0567 100644 --- a/src/client.c +++ b/src/client.c @@ -61,14 +61,6 @@ int http_client_wakeup(HTTP_Client *client) return 0; } -int http_client_register_events(HTTP_Client *client, - EventRegister *reg) -{ - if (socket_manager_register_events(&client->sockets, reg) < 0) - return -1; - return 0; -} - // Get a connection pointer from a request builder. // If the builder is invalid, returns NULL. static HTTP_ClientConn* @@ -495,6 +487,14 @@ static void save_cookies(HTTP_CookieJar *cookie_jar, save_one_cookie(cookie_jar, headers[i], domain, path); } +int http_client_register_events(HTTP_Client *client, + EventRegister *reg) +{ + if (socket_manager_register_events(&client->sockets, reg) < 0) + return -1; + return 0; +} + int http_client_process_events(HTTP_Client *client, EventRegister *reg) { @@ -671,3 +671,37 @@ void http_free_response(HTTP_Response *response) byte_queue_free(&conn->output); client->num_conns--; } + +#ifdef _WIN32 +#define POLL WSAPoll +#else +#define POLL poll +#endif + +int http_client_wait_response(HTTP_Client *client, HTTP_Response **response, void **user) +{ + for (;;) { + void *ptrs[HTTP_CLIENT_POLL_CAPACITY]; + struct pollfd polled[HTTP_CLIENT_POLL_CAPACITY]; + + EventRegister reg = { + .ptrs=ptrs, + .polled=polled, + .num_polled=0, + .max_polled=HTTP_CLIENT_POLL_CAPACITY, + }; + if (http_client_register_events(client, ®) < 0) + return -1; + + if (reg.num_polled > 0) + POLL(reg.polled, reg.num_polled, -1); + + if (http_client_process_events(client, ®) < 0) + return -1; + + if (http_client_next_response(client, response, user)) + break; + } + + return 0; +} diff --git a/src/client.h b/src/client.h index 3bc8141..e770720 100644 --- a/src/client.h +++ b/src/client.h @@ -207,6 +207,9 @@ int http_client_process_events(HTTP_Client *client, bool http_client_next_response(HTTP_Client *client, HTTP_Response **response, void **user); +// TODO: comment +int http_client_wait_response(HTTP_Client *client, HTTP_Response **response, void **user); + // Free a response object. You can't access its fields // again after this. void http_free_response(HTTP_Response *response);