diff --git a/chttp.c b/chttp.c index 1c1de95..6f08538 100644 --- a/chttp.c +++ b/chttp.c @@ -2590,16 +2590,9 @@ int socket_manager_wakeup(SocketManager *sm) return ret; } -static int socket_manager_register_events_nolock( +static void socket_manager_register_events_nolock( SocketManager *sm, EventRegister *reg) { - // The poll array must be able to hold descriptors - // for a socket manager at full capacity. Note that - // other than having a number of connection sockets, - // the manager also needs 2 for the listeners and - // one for the wakeup self-pipe. - if (reg->max_polled < sm->max_used+3) - return -1; reg->num_polled = 0; reg->polled[reg->num_polled].fd = sm->wait_sock; @@ -2644,7 +2637,7 @@ static int socket_manager_register_events_nolock( // empty list. if (s->state == SOCKET_STATE_DIED || s->state == SOCKET_STATE_ESTABLISHED_READY) { reg->num_polled = 0; - return 0; + return; } if (s->events) { @@ -2655,8 +2648,6 @@ static int socket_manager_register_events_nolock( reg->num_polled++; } } - - return 0; } int socket_manager_register_events(SocketManager *sm, @@ -2665,11 +2656,11 @@ int socket_manager_register_events(SocketManager *sm, if (mutex_lock(&sm->mutex) < 0) return -1; - int ret = socket_manager_register_events_nolock(sm, reg); + socket_manager_register_events_nolock(sm, reg); if (mutex_unlock(&sm->mutex) < 0) return -1; - return ret; + return 0; } static SocketHandle @@ -2979,13 +2970,14 @@ int socket_connect(SocketManager *sm, int num_targets, s->addrs[i] = resolved[i]; } - s->state = SOCKET_STATE_PENDING; - s->sock = NATIVE_SOCKET_INVALID; - s->user = user; + s->state = SOCKET_STATE_PENDING; + s->sock = NATIVE_SOCKET_INVALID; + s->events = 0; + s->user = user; #ifdef HTTPS_ENABLED s->server_secure_context = NULL; s->client_secure_context = NULL; - s->ssl = NULL; + s->ssl = NULL; if (secure) s->client_secure_context = &sm->client_secure_context; #endif @@ -3659,6 +3651,7 @@ int http_create_test_certificate(HTTP_String C, HTTP_String O, HTTP_String CN, //////////////////////////////////////////////////////////////////////////////////////// // src/client.c //////////////////////////////////////////////////////////////////////////////////////// + static void http_client_conn_free(HTTP_ClientConn *conn) { byte_queue_free(&conn->output); @@ -3879,19 +3872,31 @@ void http_request_builder_url(HTTP_RequestBuilder builder, if (conn->state != HTTP_CLIENT_CONN_WAIT_LINE) return; // Request line already written - // Allocate a copy of the URL string so the parsed URL pointers remain valid + // Allocate a copy of the URL string so the parsed + // URL pointers remain valid char *url_copy = malloc(url.len); - if (url_copy == NULL) - return; // TODO: set error + if (url_copy == NULL) { + conn->state = HTTP_CLIENT_CONN_COMPLETE; + conn->result = -1; + return; + } memcpy(url_copy, url.ptr, url.len); conn->url_buffer.ptr = url_copy; conn->url_buffer.len = url.len; // Parse the copied URL (all url.* pointers will reference url_buffer) - if (http_parse_url(conn->url_buffer.ptr, conn->url_buffer.len, &conn->url) != 1) { - free(conn->url_buffer.ptr); - return; // TODO: set error + if (http_parse_url(conn->url_buffer.ptr, conn->url_buffer.len, &conn->url) < 0) { + conn->state = HTTP_CLIENT_CONN_COMPLETE; + conn->result = -1; + return; + } + + if (!http_streq(conn->url.scheme, HTTP_STR("http")) && + !http_streq(conn->url.scheme, HTTP_STR("https"))) { + conn->state = HTTP_CLIENT_CONN_COMPLETE; + conn->result = -1; + return; } // Write method @@ -4031,6 +4036,9 @@ int http_request_builder_send(HTTP_RequestBuilder builder) if (conn == NULL) return -1; + if (conn->state == HTTP_CLIENT_CONN_COMPLETE) + goto error; // Early completion due to an error + if (conn->state == HTTP_CLIENT_CONN_WAIT_HEADER) { // No body, just end headers byte_queue_write(&conn->output, "\r\n", 2); @@ -4537,7 +4545,7 @@ http_server_conn_process_events(HTTP_Server *server, HTTP_ServerConn *conn) byte_queue_write_ack(&conn->input, num); - if (byte_queue_error(&conn->output)) { + if (byte_queue_error(&conn->input)) { socket_close(&server->sockets, conn->handle); } else { check_request_buffer(server, conn); diff --git a/chttp.h b/chttp.h index acacdf7..9b567a0 100644 --- a/chttp.h +++ b/chttp.h @@ -824,6 +824,11 @@ int http_create_test_certificate(HTTP_String C, HTTP_String O, HTTP_String CN, #define HTTP_CLIENT_CAPACITY (1<<7) #endif +// Maximum number of descriptors the client will want +// to wait on. It's one per connection plus the wakeup +// self-pipe. +#define HTTP_CLIENT_POLL_CAPACITY (HTTP_CLIENT_CAPACITY+1) + #ifndef HTTP_COOKIE_JAR_CAPACITY // Maximum number of cookies that can be associated to a // single client. @@ -862,11 +867,6 @@ typedef struct { HTTP_CookieJarEntry items[HTTP_COOKIE_JAR_CAPACITY]; } HTTP_CookieJar; -// Maximum number of descriptors the client will want -// to wait on. It's one per connection plus the wakeup -// self-pipe. -#define HTTP_CLIENT_POLL_CAPACITY (HTTP_CLIENT_CAPACITY+1) - typedef enum { HTTP_CLIENT_CONN_FREE, HTTP_CLIENT_CONN_WAIT_LINE, @@ -953,7 +953,6 @@ struct HTTP_Client { // allocating the exact number of sockets we // will need. Socket socket_pool[HTTP_CLIENT_CAPACITY]; - }; // Initialize an HTTP client object. This allows one to diff --git a/examples/simple_client.c b/examples/simple_client.c index 28c3bd5..5ec5a47 100644 --- a/examples/simple_client.c +++ b/examples/simple_client.c @@ -14,6 +14,8 @@ int main(void) HTTP_RequestBuilder builder = http_client_get_builder(&client); + http_request_builder_set_trace_bytes(builder, true); + http_request_builder_url(builder, HTTP_METHOD_GET, HTTP_STR("http://coz.is") @@ -27,14 +29,14 @@ int main(void) for (;;) { - void *ptrs[HTTP_CLIENT_CAPACITY+1]; - struct pollfd polled[HTTP_CLIENT_CAPACITY+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_CAPACITY+1, + .max_polled=HTTP_CLIENT_POLL_CAPACITY, }; if (http_client_register_events(&client, ®) < 0) @@ -49,7 +51,7 @@ int main(void) HTTP_Response *response; void *user; while (http_client_next_response(&client, &response, &user)) { - // TODO + printf("Received response\n"); http_free_response(response); } } diff --git a/src/client.c b/src/client.c index 43e9a66..3abf7eb 100644 --- a/src/client.c +++ b/src/client.c @@ -1,3 +1,4 @@ + static void http_client_conn_free(HTTP_ClientConn *conn) { byte_queue_free(&conn->output); @@ -218,19 +219,31 @@ void http_request_builder_url(HTTP_RequestBuilder builder, if (conn->state != HTTP_CLIENT_CONN_WAIT_LINE) return; // Request line already written - // Allocate a copy of the URL string so the parsed URL pointers remain valid + // Allocate a copy of the URL string so the parsed + // URL pointers remain valid char *url_copy = malloc(url.len); - if (url_copy == NULL) - return; // TODO: set error + if (url_copy == NULL) { + conn->state = HTTP_CLIENT_CONN_COMPLETE; + conn->result = -1; + return; + } memcpy(url_copy, url.ptr, url.len); conn->url_buffer.ptr = url_copy; conn->url_buffer.len = url.len; // Parse the copied URL (all url.* pointers will reference url_buffer) - if (http_parse_url(conn->url_buffer.ptr, conn->url_buffer.len, &conn->url) != 1) { - free(conn->url_buffer.ptr); - return; // TODO: set error + if (http_parse_url(conn->url_buffer.ptr, conn->url_buffer.len, &conn->url) < 0) { + conn->state = HTTP_CLIENT_CONN_COMPLETE; + conn->result = -1; + return; + } + + if (!http_streq(conn->url.scheme, HTTP_STR("http")) && + !http_streq(conn->url.scheme, HTTP_STR("https"))) { + conn->state = HTTP_CLIENT_CONN_COMPLETE; + conn->result = -1; + return; } // Write method @@ -370,6 +383,9 @@ int http_request_builder_send(HTTP_RequestBuilder builder) if (conn == NULL) return -1; + if (conn->state == HTTP_CLIENT_CONN_COMPLETE) + goto error; // Early completion due to an error + if (conn->state == HTTP_CLIENT_CONN_WAIT_HEADER) { // No body, just end headers byte_queue_write(&conn->output, "\r\n", 2); diff --git a/src/client.h b/src/client.h index 31e0aca..3bc8141 100644 --- a/src/client.h +++ b/src/client.h @@ -134,7 +134,6 @@ struct HTTP_Client { // allocating the exact number of sockets we // will need. Socket socket_pool[HTTP_CLIENT_CAPACITY]; - }; // Initialize an HTTP client object. This allows one to diff --git a/src/socket.c b/src/socket.c index ea45081..44ec465 100644 --- a/src/socket.c +++ b/src/socket.c @@ -620,16 +620,9 @@ int socket_manager_wakeup(SocketManager *sm) return ret; } -static int socket_manager_register_events_nolock( +static void socket_manager_register_events_nolock( SocketManager *sm, EventRegister *reg) { - // The poll array must be able to hold descriptors - // for a socket manager at full capacity. Note that - // other than having a number of connection sockets, - // the manager also needs 2 for the listeners and - // one for the wakeup self-pipe. - if (reg->max_polled < sm->max_used+3) - return -1; reg->num_polled = 0; reg->polled[reg->num_polled].fd = sm->wait_sock; @@ -674,7 +667,7 @@ static int socket_manager_register_events_nolock( // empty list. if (s->state == SOCKET_STATE_DIED || s->state == SOCKET_STATE_ESTABLISHED_READY) { reg->num_polled = 0; - return 0; + return; } if (s->events) { @@ -685,8 +678,6 @@ static int socket_manager_register_events_nolock( reg->num_polled++; } } - - return 0; } int socket_manager_register_events(SocketManager *sm, @@ -695,11 +686,11 @@ int socket_manager_register_events(SocketManager *sm, if (mutex_lock(&sm->mutex) < 0) return -1; - int ret = socket_manager_register_events_nolock(sm, reg); + socket_manager_register_events_nolock(sm, reg); if (mutex_unlock(&sm->mutex) < 0) return -1; - return ret; + return 0; } static SocketHandle