diff --git a/chttp.c b/chttp.c index 074bb59..4b9aca1 100644 --- a/chttp.c +++ b/chttp.c @@ -40,6 +40,9 @@ typedef struct { #endif +void secure_context_global_init(void); +void secure_context_global_free(void); + int secure_context_init_as_client(SecureContext *sec); int secure_context_init_as_server(SecureContext *sec, @@ -86,6 +89,9 @@ void secure_context_free(SecureContext *sec); #include "basic.h" #endif +int socket_raw_global_init(void); +void socket_raw_global_free(void); + int set_socket_blocking(RAW_SOCKET sock, bool value); RAW_SOCKET listen_socket(HTTP_String addr, uint16_t port, bool reuse_addr, int backlog); @@ -204,6 +210,9 @@ typedef struct { void *user_data; } SocketEvent; +int socket_pool_global_init(void); +void socket_pool_global_free(void); + SocketPool *socket_pool_init(HTTP_String addr, uint16_t port, uint16_t secure_port, int max_socks, bool reuse_addr, int backlog, HTTP_String cert_file, @@ -1371,24 +1380,6 @@ int http_parse_response(char *src, int len, HTTP_Response *res) return ret; } -HTTP_String http_getqueryparam(HTTP_Request *req, HTTP_String name) -{ - // TODO - return (HTTP_String) {NULL, 0}; -} - -HTTP_String http_getbodyparam(HTTP_Request *req, HTTP_String name) -{ - // TODO - return (HTTP_String) {NULL, 0}; -} - -HTTP_String http_getcookie(HTTP_Request *req, HTTP_String name) -{ - // TODO - return (HTTP_String) {NULL, 0}; -} - //////////////////////////////////////////////////////////////////////////////////////// // src/engine.c //////////////////////////////////////////////////////////////////////////////////////// @@ -1474,12 +1465,6 @@ byte_queue_error(HTTP_ByteQueue *queue) return queue->flags & BYTE_QUEUE_ERROR; } -static void -byte_queue_setlimit(HTTP_ByteQueue *queue, unsigned int value) -{ - queue->limit = value; -} - static int byte_queue_empty(HTTP_ByteQueue *queue) { @@ -2572,6 +2557,14 @@ int http_create_test_certificate(HTTP_String C, HTTP_String O, HTTP_String CN, #ifndef HTTPS_ENABLED +void secure_context_global_init(void) +{ +} + +void secure_context_global_free(void) +{ +} + int secure_context_init_as_client(SecureContext *sec) { (void) sec; @@ -2611,6 +2604,19 @@ void secure_context_free(SecureContext *sec) #else +void secure_context_global_init(void) +{ + SSL_library_init(); + SSL_load_error_strings(); + OpenSSL_add_all_algorithms(); +} + +void secure_context_global_free(void) +{ + EVP_cleanup(); + ERR_free_strings(); +} + int secure_context_init_as_client(SecureContext *sec) { SSL_CTX *ctx = SSL_CTX_new(TLS_client_method()); @@ -2792,6 +2798,24 @@ int secure_context_add_cert(SecureContext *sec, #include "socket_raw.h" #endif +int socket_raw_global_init(void) +{ +#ifdef _WIN32 + WSADATA wsaData; + int result = WSAStartup(MAKEWORD(2, 2), &wsaData); + if (result != 0) + return 1; +#endif + return 0; +} + +void socket_raw_global_free(void) +{ +#ifdef _WIN32 + WSACleanup(); +#endif +} + int set_socket_blocking(RAW_SOCKET sock, bool value) { #ifdef _WIN32 @@ -2994,7 +3018,9 @@ void socket_connect(Socket *sock, SecureContext *sec, hints.ai_socktype = SOCK_STREAM; struct addrinfo *res = NULL; - if (getaddrinfo(pending_connect->hostname, portstr, &hints, &res) != 0) { + int ret = getaddrinfo(pending_connect->hostname, portstr, &hints, &res); + if (ret != 0) { + printf("ret=%d\n", ret); // TODO: remove pending_connect_free(pending_connect); sock->state = SOCKET_STATE_DIED; sock->events = 0; @@ -3016,6 +3042,7 @@ void socket_connect(Socket *sock, SecureContext *sec, sock->state = SOCKET_STATE_PENDING; sock->events = 0; + sock->raw = BAD_SOCKET; sock->user_data = user_data; sock->pending_connect = pending_connect; sock->sec = sec; @@ -3266,7 +3293,7 @@ void socket_update(Socket *sock) // ready for output. This means the operation is complete. int err = 0; - int len = sizeof(err); + socklen_t len = sizeof(err); if (getsockopt(sock->raw, SOL_SOCKET, SO_ERROR, (void*) &err, &len) < 0 || err != 0) { @@ -3635,12 +3662,20 @@ struct SocketPool { Socket socks[]; }; -void socket_pool_global_init(void) +int socket_pool_global_init(void) { + int ret = socket_raw_global_init(); + if (ret < 0) + return -1; + + secure_context_global_init(); + return 0; } void socket_pool_global_free(void) { + secure_context_global_free(); + socket_raw_global_free(); } SocketPool *socket_pool_init(HTTP_String addr, @@ -3698,6 +3733,9 @@ SocketPool *socket_pool_init(HTTP_String addr, #endif } + for (int i = 0; i < max_socks; i++) + pool->socks[i].state = SOCKET_STATE_FREE; + return pool; } @@ -3969,6 +4007,7 @@ int socket_pool_write(SocketPool *pool, SocketHandle handle, char *src, int len) typedef enum { CLIENT_CONNECTION_FREE, CLIENT_CONNECTION_INIT, + CLIENT_CONNECTION_INIT_ERROR, CLIENT_CONNECTION_WAIT, CLIENT_CONNECTION_DONE, } ClientConnectionState; @@ -3994,6 +4033,19 @@ struct HTTP_Client { int ready[CLIENT_MAX_CONNS]; }; +int http_global_init(void) +{ + int ret = socket_pool_global_init(); + if (ret < 0) + return -1; + return 0; +} + +void http_global_free(void) +{ + socket_pool_global_free(); +} + // Rename the memory function static void* client_memfunc(HTTP_MemoryFuncTag tag, void *ptr, int len, void *data) { (void)data; @@ -4057,6 +4109,7 @@ int http_client_get_builder(HTTP_Client *client, HTTP_RequestBuilder *builder) while (client->conns[i].state != CLIENT_CONNECTION_FREE) i++; + client->conns[i].sock = -1; client->conns[i].user_data = NULL; client->conns[i].trace = false; client->conns[i].state = CLIENT_CONNECTION_INIT; @@ -4078,6 +4131,8 @@ int http_client_wait(HTTP_Client *client, HTTP_Response **result, void **user_da case SOCKET_EVENT_DIED: { ClientConnection *conn = event.user_data; + conn->state = CLIENT_CONNECTION_DONE; + int tail = (client->ready_head + client->ready_count) % CLIENT_MAX_CONNS; client->ready[tail] = conn - client->conns; client->ready_count++; @@ -4088,6 +4143,9 @@ int http_client_wait(HTTP_Client *client, HTTP_Response **result, void **user_da { ClientConnection *conn = event.user_data; + if (conn->sock == -1) + conn->sock = event.handle; + HTTP_EngineState engine_state; engine_state = http_engine_state(&conn->eng); @@ -4147,6 +4205,8 @@ int http_client_wait(HTTP_Client *client, HTTP_Response **result, void **user_da http_engine_free(&conn->eng); conn->state = CLIENT_CONNECTION_FREE; client->num_conns--; + } else { + result2->context = client; } return 0; @@ -4205,7 +4265,7 @@ void http_request_builder_line(HTTP_RequestBuilder builder, HTTP_Method method, HTTP_URL parsed_url; int ret = http_parse_url(url.ptr, url.len, &parsed_url); if (ret != url.len) { - // TODO + conn->state = CLIENT_CONNECTION_INIT_ERROR; return; } @@ -4213,7 +4273,7 @@ void http_request_builder_line(HTTP_RequestBuilder builder, HTTP_Method method, if (http_streq(parsed_url.scheme, HTTP_STR("https"))) { secure = true; } else if (!http_streq(parsed_url.scheme, HTTP_STR("http"))) { - // TODO + conn->state = CLIENT_CONNECTION_INIT_ERROR; return; } @@ -4226,12 +4286,14 @@ void http_request_builder_line(HTTP_RequestBuilder builder, HTTP_Method method, } switch (parsed_url.authority.host.mode) { - case HTTP_HOST_MODE_IPV4: socket_pool_connect_ipv4(client->socket_pool, secure, parsed_url.authority.host.ipv4, port, conn->user_data); break; - case HTTP_HOST_MODE_IPV6: socket_pool_connect_ipv6(client->socket_pool, secure, parsed_url.authority.host.ipv6, port, conn->user_data); break; - case HTTP_HOST_MODE_NAME: socket_pool_connect (client->socket_pool, secure, parsed_url.authority.host.name, port, conn->user_data); break; + case HTTP_HOST_MODE_IPV4: ret = socket_pool_connect_ipv4(client->socket_pool, secure, parsed_url.authority.host.ipv4, port, conn); break; + case HTTP_HOST_MODE_IPV6: ret = socket_pool_connect_ipv6(client->socket_pool, secure, parsed_url.authority.host.ipv6, port, conn); break; + case HTTP_HOST_MODE_NAME: ret = socket_pool_connect (client->socket_pool, secure, parsed_url.authority.host.name, port, conn); break; + case HTTP_HOST_MODE_VOID: ret = -1; return; + } - case HTTP_HOST_MODE_VOID: - // TODO + if (ret < 0) { + conn->state = CLIENT_CONNECTION_INIT_ERROR; return; } @@ -4262,20 +4324,34 @@ void http_request_builder_body(HTTP_RequestBuilder handle, HTTP_String str) void http_request_builder_submit(HTTP_RequestBuilder handle) { + HTTP_Client *client = handle.data0; ClientConnection *conn = builder2conn(handle); if (conn == NULL) return; - if (conn->state != CLIENT_CONNECTION_INIT) + if (conn->state != CLIENT_CONNECTION_INIT && + conn->state != CLIENT_CONNECTION_INIT_ERROR) return; // TODO: invalidate the handle - http_engine_done(&conn->eng); - conn->state = CLIENT_CONNECTION_WAIT; + if (conn->state == CLIENT_CONNECTION_INIT_ERROR) { + + conn->state = CLIENT_CONNECTION_DONE; + + int tail = (client->ready_head + client->ready_count) % CLIENT_MAX_CONNS; + client->ready[tail] = conn - client->conns; + client->ready_count++; + + } else { + http_engine_done(&conn->eng); + conn->state = CLIENT_CONNECTION_WAIT; + } } -void http_response_free(HTTP_Client *client, HTTP_Response *res) +void http_response_free(HTTP_Response *res) { + HTTP_Client *client = res->context; + ClientConnection *conn = NULL; for (int i = 0, j = 0; j < client->num_conns; i++) { @@ -4752,7 +4828,7 @@ void http_router_func(HTTP_Router *router, HTTP_Method method, if (router->num_routes == router->max_routes) abort(); Route *route = &router->routes[router->num_routes++]; - // TODO: Don't ignore the method + (void) method; // TODO: Don't ignore the method route->type = ROUTE_DYNAMIC; route->endpoint = endpoint; route->func = func; diff --git a/chttp.h b/chttp.h index 50080b8..a8bc68d 100644 --- a/chttp.h +++ b/chttp.h @@ -171,6 +171,7 @@ typedef struct { } HTTP_Request; typedef struct { + void* context; int minor; int status; HTTP_String reason; @@ -186,9 +187,6 @@ int http_parse_request (char *src, int len, HTTP_Request *req); int http_parse_response (char *src, int len, HTTP_Response *res); int http_find_header (HTTP_Header *headers, int num_headers, HTTP_String name); -HTTP_String http_getqueryparam (HTTP_Request *req, HTTP_String name); -HTTP_String http_getbodyparam (HTTP_Request *req, HTTP_String name); -HTTP_String http_getcookie (HTTP_Request *req, HTTP_String name); #endif // PARSE_INCLUDED @@ -370,7 +368,7 @@ int http_create_test_certificate(HTTP_String C, HTTP_String O, HTTP_String CN, // cHTTP tries to avoid global state. What this function // does is call the global initialization functions of // its dependencies (OpenSSL and Winsock) -void http_global_init(void); +int http_global_init(void); // Free the global state of cHTTP. void http_global_free(void); @@ -429,7 +427,7 @@ void http_request_builder_submit(HTTP_RequestBuilder builder); // after the request has completed. // // TODO: allow aborting pending requests -void http_response_free(HTTP_Client *client, HTTP_Response *res); +void http_response_free(HTTP_Response *res); // Wait for the completion of one request associated to // the client. The handle of the resolved request is returned diff --git a/examples/client/000_get_request.c b/examples/client/000_get_request.c index 8f80fc5..8993506 100644 --- a/examples/client/000_get_request.c +++ b/examples/client/000_get_request.c @@ -16,7 +16,7 @@ int main(void) // Perform the request. This will block the thread // until an error occurs or the request completes. HTTP_Response *res = http_get( - HTTP_STR("http://example.com/index.html"), + HTTP_STR("http://coz.is/index.html"), headers, HTTP_COUNT(headers) ); @@ -45,7 +45,7 @@ int main(void) // When we are done reading from the response object // we must free the request's resources. - http_request_free(res); + http_response_free(res); // All done. Deinitialize the library. http_global_free(); diff --git a/examples/client/client_example.c b/examples/client/client_example.c index 4a61e39..2ee69b6 100644 --- a/examples/client/client_example.c +++ b/examples/client/client_example.c @@ -3,7 +3,8 @@ #include #include -int main(int argc, char **argv) { +int main(int argc, char **argv) +{ if (argc < 2) { printf("Usage: %s [url2 ...]\n", argv[0]); return 1; @@ -13,13 +14,12 @@ int main(int argc, char **argv) { HTTP_Client *client = http_client_init(); for (int i = 1; i < argc; i++) { - int k = i-1; HTTP_RequestBuilder builder; if (http_client_get_builder(client, &builder) < 0) { printf("request creation error\n"); return -1; } - http_request_builer_line(builder, HTTP_METHOD_GET, (HTTP_String) { argv[i], strlen(argv[i]) }); + http_request_builder_line(builder, HTTP_METHOD_GET, (HTTP_String) { argv[i], strlen(argv[i]) }); http_request_builder_submit(builder); printf("request submitted\n"); } @@ -35,7 +35,7 @@ int main(int argc, char **argv) { printf("Status: %d\n", res->status); printf("Body: %.*s\n", HTTP_UNPACK(res->body)); - http_request_free(res); + http_response_free(res); } http_client_free(client); diff --git a/src/client.c b/src/client.c index edc76da..ae27a8c 100644 --- a/src/client.c +++ b/src/client.c @@ -25,6 +25,7 @@ typedef enum { CLIENT_CONNECTION_FREE, CLIENT_CONNECTION_INIT, + CLIENT_CONNECTION_INIT_ERROR, CLIENT_CONNECTION_WAIT, CLIENT_CONNECTION_DONE, } ClientConnectionState; @@ -50,6 +51,19 @@ struct HTTP_Client { int ready[CLIENT_MAX_CONNS]; }; +int http_global_init(void) +{ + int ret = socket_pool_global_init(); + if (ret < 0) + return -1; + return 0; +} + +void http_global_free(void) +{ + socket_pool_global_free(); +} + // Rename the memory function static void* client_memfunc(HTTP_MemoryFuncTag tag, void *ptr, int len, void *data) { (void)data; @@ -113,6 +127,7 @@ int http_client_get_builder(HTTP_Client *client, HTTP_RequestBuilder *builder) while (client->conns[i].state != CLIENT_CONNECTION_FREE) i++; + client->conns[i].sock = -1; client->conns[i].user_data = NULL; client->conns[i].trace = false; client->conns[i].state = CLIENT_CONNECTION_INIT; @@ -134,6 +149,8 @@ int http_client_wait(HTTP_Client *client, HTTP_Response **result, void **user_da case SOCKET_EVENT_DIED: { ClientConnection *conn = event.user_data; + conn->state = CLIENT_CONNECTION_DONE; + int tail = (client->ready_head + client->ready_count) % CLIENT_MAX_CONNS; client->ready[tail] = conn - client->conns; client->ready_count++; @@ -144,6 +161,9 @@ int http_client_wait(HTTP_Client *client, HTTP_Response **result, void **user_da { ClientConnection *conn = event.user_data; + if (conn->sock == -1) + conn->sock = event.handle; + HTTP_EngineState engine_state; engine_state = http_engine_state(&conn->eng); @@ -203,6 +223,8 @@ int http_client_wait(HTTP_Client *client, HTTP_Response **result, void **user_da http_engine_free(&conn->eng); conn->state = CLIENT_CONNECTION_FREE; client->num_conns--; + } else { + result2->context = client; } return 0; @@ -261,7 +283,7 @@ void http_request_builder_line(HTTP_RequestBuilder builder, HTTP_Method method, HTTP_URL parsed_url; int ret = http_parse_url(url.ptr, url.len, &parsed_url); if (ret != url.len) { - // TODO + conn->state = CLIENT_CONNECTION_INIT_ERROR; return; } @@ -269,7 +291,7 @@ void http_request_builder_line(HTTP_RequestBuilder builder, HTTP_Method method, if (http_streq(parsed_url.scheme, HTTP_STR("https"))) { secure = true; } else if (!http_streq(parsed_url.scheme, HTTP_STR("http"))) { - // TODO + conn->state = CLIENT_CONNECTION_INIT_ERROR; return; } @@ -282,12 +304,14 @@ void http_request_builder_line(HTTP_RequestBuilder builder, HTTP_Method method, } switch (parsed_url.authority.host.mode) { - case HTTP_HOST_MODE_IPV4: socket_pool_connect_ipv4(client->socket_pool, secure, parsed_url.authority.host.ipv4, port, conn->user_data); break; - case HTTP_HOST_MODE_IPV6: socket_pool_connect_ipv6(client->socket_pool, secure, parsed_url.authority.host.ipv6, port, conn->user_data); break; - case HTTP_HOST_MODE_NAME: socket_pool_connect (client->socket_pool, secure, parsed_url.authority.host.name, port, conn->user_data); break; + case HTTP_HOST_MODE_IPV4: ret = socket_pool_connect_ipv4(client->socket_pool, secure, parsed_url.authority.host.ipv4, port, conn); break; + case HTTP_HOST_MODE_IPV6: ret = socket_pool_connect_ipv6(client->socket_pool, secure, parsed_url.authority.host.ipv6, port, conn); break; + case HTTP_HOST_MODE_NAME: ret = socket_pool_connect (client->socket_pool, secure, parsed_url.authority.host.name, port, conn); break; + case HTTP_HOST_MODE_VOID: ret = -1; return; + } - case HTTP_HOST_MODE_VOID: - // TODO + if (ret < 0) { + conn->state = CLIENT_CONNECTION_INIT_ERROR; return; } @@ -318,20 +342,34 @@ void http_request_builder_body(HTTP_RequestBuilder handle, HTTP_String str) void http_request_builder_submit(HTTP_RequestBuilder handle) { + HTTP_Client *client = handle.data0; ClientConnection *conn = builder2conn(handle); if (conn == NULL) return; - if (conn->state != CLIENT_CONNECTION_INIT) + if (conn->state != CLIENT_CONNECTION_INIT && + conn->state != CLIENT_CONNECTION_INIT_ERROR) return; // TODO: invalidate the handle - http_engine_done(&conn->eng); - conn->state = CLIENT_CONNECTION_WAIT; + if (conn->state == CLIENT_CONNECTION_INIT_ERROR) { + + conn->state = CLIENT_CONNECTION_DONE; + + int tail = (client->ready_head + client->ready_count) % CLIENT_MAX_CONNS; + client->ready[tail] = conn - client->conns; + client->ready_count++; + + } else { + http_engine_done(&conn->eng); + conn->state = CLIENT_CONNECTION_WAIT; + } } -void http_response_free(HTTP_Client *client, HTTP_Response *res) +void http_response_free(HTTP_Response *res) { + HTTP_Client *client = res->context; + ClientConnection *conn = NULL; for (int i = 0, j = 0; j < client->num_conns; i++) { diff --git a/src/client.h b/src/client.h index 33effc7..b0228cc 100644 --- a/src/client.h +++ b/src/client.h @@ -12,7 +12,7 @@ // cHTTP tries to avoid global state. What this function // does is call the global initialization functions of // its dependencies (OpenSSL and Winsock) -void http_global_init(void); +int http_global_init(void); // Free the global state of cHTTP. void http_global_free(void); @@ -71,7 +71,7 @@ void http_request_builder_submit(HTTP_RequestBuilder builder); // after the request has completed. // // TODO: allow aborting pending requests -void http_response_free(HTTP_Client *client, HTTP_Response *res); +void http_response_free(HTTP_Response *res); // Wait for the completion of one request associated to // the client. The handle of the resolved request is returned diff --git a/src/engine.c b/src/engine.c index f5ce571..622d700 100644 --- a/src/engine.c +++ b/src/engine.c @@ -78,12 +78,6 @@ byte_queue_error(HTTP_ByteQueue *queue) return queue->flags & BYTE_QUEUE_ERROR; } -static void -byte_queue_setlimit(HTTP_ByteQueue *queue, unsigned int value) -{ - queue->limit = value; -} - static int byte_queue_empty(HTTP_ByteQueue *queue) { diff --git a/src/parse.c b/src/parse.c index 7996b52..5ce4e6a 100644 --- a/src/parse.c +++ b/src/parse.c @@ -1020,21 +1020,3 @@ int http_parse_response(char *src, int len, HTTP_Response *res) return s.cur; return ret; } - -HTTP_String http_getqueryparam(HTTP_Request *req, HTTP_String name) -{ - // TODO - return (HTTP_String) {NULL, 0}; -} - -HTTP_String http_getbodyparam(HTTP_Request *req, HTTP_String name) -{ - // TODO - return (HTTP_String) {NULL, 0}; -} - -HTTP_String http_getcookie(HTTP_Request *req, HTTP_String name) -{ - // TODO - return (HTTP_String) {NULL, 0}; -} \ No newline at end of file diff --git a/src/parse.h b/src/parse.h index 077bac3..e1e746c 100644 --- a/src/parse.h +++ b/src/parse.h @@ -74,6 +74,7 @@ typedef struct { } HTTP_Request; typedef struct { + void* context; int minor; int status; HTTP_String reason; @@ -89,8 +90,5 @@ int http_parse_request (char *src, int len, HTTP_Request *req); int http_parse_response (char *src, int len, HTTP_Response *res); int http_find_header (HTTP_Header *headers, int num_headers, HTTP_String name); -HTTP_String http_getqueryparam (HTTP_Request *req, HTTP_String name); -HTTP_String http_getbodyparam (HTTP_Request *req, HTTP_String name); -HTTP_String http_getcookie (HTTP_Request *req, HTTP_String name); #endif // PARSE_INCLUDED \ No newline at end of file diff --git a/src/router.c b/src/router.c index a828263..eef58a6 100644 --- a/src/router.c +++ b/src/router.c @@ -79,7 +79,7 @@ void http_router_func(HTTP_Router *router, HTTP_Method method, if (router->num_routes == router->max_routes) abort(); Route *route = &router->routes[router->num_routes++]; - // TODO: Don't ignore the method + (void) method; // TODO: Don't ignore the method route->type = ROUTE_DYNAMIC; route->endpoint = endpoint; route->func = func; diff --git a/src/sec.c b/src/sec.c index 97e5b36..1faff99 100644 --- a/src/sec.c +++ b/src/sec.c @@ -4,6 +4,14 @@ #ifndef HTTPS_ENABLED +void secure_context_global_init(void) +{ +} + +void secure_context_global_free(void) +{ +} + int secure_context_init_as_client(SecureContext *sec) { (void) sec; @@ -43,6 +51,19 @@ void secure_context_free(SecureContext *sec) #else +void secure_context_global_init(void) +{ + SSL_library_init(); + SSL_load_error_strings(); + OpenSSL_add_all_algorithms(); +} + +void secure_context_global_free(void) +{ + EVP_cleanup(); + ERR_free_strings(); +} + int secure_context_init_as_client(SecureContext *sec) { SSL_CTX *ctx = SSL_CTX_new(TLS_client_method()); diff --git a/src/sec.h b/src/sec.h index bbff58c..1c2eef6 100644 --- a/src/sec.h +++ b/src/sec.h @@ -33,6 +33,9 @@ typedef struct { #endif +void secure_context_global_init(void); +void secure_context_global_free(void); + int secure_context_init_as_client(SecureContext *sec); int secure_context_init_as_server(SecureContext *sec, diff --git a/src/socket.c b/src/socket.c index 50ff831..1be1d4d 100644 --- a/src/socket.c +++ b/src/socket.c @@ -122,7 +122,9 @@ void socket_connect(Socket *sock, SecureContext *sec, hints.ai_socktype = SOCK_STREAM; struct addrinfo *res = NULL; - if (getaddrinfo(pending_connect->hostname, portstr, &hints, &res) != 0) { + int ret = getaddrinfo(pending_connect->hostname, portstr, &hints, &res); + if (ret != 0) { + printf("ret=%d\n", ret); // TODO: remove pending_connect_free(pending_connect); sock->state = SOCKET_STATE_DIED; sock->events = 0; @@ -144,6 +146,7 @@ void socket_connect(Socket *sock, SecureContext *sec, sock->state = SOCKET_STATE_PENDING; sock->events = 0; + sock->raw = BAD_SOCKET; sock->user_data = user_data; sock->pending_connect = pending_connect; sock->sec = sec; @@ -394,7 +397,7 @@ void socket_update(Socket *sock) // ready for output. This means the operation is complete. int err = 0; - int len = sizeof(err); + socklen_t len = sizeof(err); if (getsockopt(sock->raw, SOL_SOCKET, SO_ERROR, (void*) &err, &len) < 0 || err != 0) { diff --git a/src/socket_pool.c b/src/socket_pool.c index d9723f5..526c235 100644 --- a/src/socket_pool.c +++ b/src/socket_pool.c @@ -25,12 +25,20 @@ struct SocketPool { Socket socks[]; }; -void socket_pool_global_init(void) +int socket_pool_global_init(void) { + int ret = socket_raw_global_init(); + if (ret < 0) + return -1; + + secure_context_global_init(); + return 0; } void socket_pool_global_free(void) { + secure_context_global_free(); + socket_raw_global_free(); } SocketPool *socket_pool_init(HTTP_String addr, @@ -88,6 +96,9 @@ SocketPool *socket_pool_init(HTTP_String addr, #endif } + for (int i = 0; i < max_socks; i++) + pool->socks[i].state = SOCKET_STATE_FREE; + return pool; } diff --git a/src/socket_pool.h b/src/socket_pool.h index 276834e..722d52a 100644 --- a/src/socket_pool.h +++ b/src/socket_pool.h @@ -24,6 +24,9 @@ typedef struct { void *user_data; } SocketEvent; +int socket_pool_global_init(void); +void socket_pool_global_free(void); + SocketPool *socket_pool_init(HTTP_String addr, uint16_t port, uint16_t secure_port, int max_socks, bool reuse_addr, int backlog, HTTP_String cert_file, diff --git a/src/socket_raw.c b/src/socket_raw.c index 9ab344a..98fac58 100644 --- a/src/socket_raw.c +++ b/src/socket_raw.c @@ -14,6 +14,24 @@ #include "socket_raw.h" #endif +int socket_raw_global_init(void) +{ +#ifdef _WIN32 + WSADATA wsaData; + int result = WSAStartup(MAKEWORD(2, 2), &wsaData); + if (result != 0) + return 1; +#endif + return 0; +} + +void socket_raw_global_free(void) +{ +#ifdef _WIN32 + WSACleanup(); +#endif +} + int set_socket_blocking(RAW_SOCKET sock, bool value) { #ifdef _WIN32 diff --git a/src/socket_raw.h b/src/socket_raw.h index d2038df..56dd758 100644 --- a/src/socket_raw.h +++ b/src/socket_raw.h @@ -25,6 +25,9 @@ #include "basic.h" #endif +int socket_raw_global_init(void); +void socket_raw_global_free(void); + int set_socket_blocking(RAW_SOCKET sock, bool value); RAW_SOCKET listen_socket(HTTP_String addr, uint16_t port, bool reuse_addr, int backlog);