Add global state initialization functions
This commit is contained in:
@@ -40,6 +40,9 @@ typedef struct {
|
|||||||
|
|
||||||
#endif
|
#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_client(SecureContext *sec);
|
||||||
|
|
||||||
int secure_context_init_as_server(SecureContext *sec,
|
int secure_context_init_as_server(SecureContext *sec,
|
||||||
@@ -86,6 +89,9 @@ void secure_context_free(SecureContext *sec);
|
|||||||
#include "basic.h"
|
#include "basic.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
int socket_raw_global_init(void);
|
||||||
|
void socket_raw_global_free(void);
|
||||||
|
|
||||||
int set_socket_blocking(RAW_SOCKET sock, bool value);
|
int set_socket_blocking(RAW_SOCKET sock, bool value);
|
||||||
|
|
||||||
RAW_SOCKET listen_socket(HTTP_String addr, uint16_t port, bool reuse_addr, int backlog);
|
RAW_SOCKET listen_socket(HTTP_String addr, uint16_t port, bool reuse_addr, int backlog);
|
||||||
@@ -204,6 +210,9 @@ typedef struct {
|
|||||||
void *user_data;
|
void *user_data;
|
||||||
} SocketEvent;
|
} SocketEvent;
|
||||||
|
|
||||||
|
int socket_pool_global_init(void);
|
||||||
|
void socket_pool_global_free(void);
|
||||||
|
|
||||||
SocketPool *socket_pool_init(HTTP_String addr,
|
SocketPool *socket_pool_init(HTTP_String addr,
|
||||||
uint16_t port, uint16_t secure_port, int max_socks,
|
uint16_t port, uint16_t secure_port, int max_socks,
|
||||||
bool reuse_addr, int backlog, HTTP_String cert_file,
|
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;
|
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
|
// src/engine.c
|
||||||
////////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
@@ -1474,12 +1465,6 @@ byte_queue_error(HTTP_ByteQueue *queue)
|
|||||||
return queue->flags & BYTE_QUEUE_ERROR;
|
return queue->flags & BYTE_QUEUE_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
|
||||||
byte_queue_setlimit(HTTP_ByteQueue *queue, unsigned int value)
|
|
||||||
{
|
|
||||||
queue->limit = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
static int
|
||||||
byte_queue_empty(HTTP_ByteQueue *queue)
|
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
|
#ifndef HTTPS_ENABLED
|
||||||
|
|
||||||
|
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_client(SecureContext *sec)
|
||||||
{
|
{
|
||||||
(void) sec;
|
(void) sec;
|
||||||
@@ -2611,6 +2604,19 @@ void secure_context_free(SecureContext *sec)
|
|||||||
|
|
||||||
#else
|
#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)
|
int secure_context_init_as_client(SecureContext *sec)
|
||||||
{
|
{
|
||||||
SSL_CTX *ctx = SSL_CTX_new(TLS_client_method());
|
SSL_CTX *ctx = SSL_CTX_new(TLS_client_method());
|
||||||
@@ -2792,6 +2798,24 @@ int secure_context_add_cert(SecureContext *sec,
|
|||||||
#include "socket_raw.h"
|
#include "socket_raw.h"
|
||||||
#endif
|
#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)
|
int set_socket_blocking(RAW_SOCKET sock, bool value)
|
||||||
{
|
{
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
@@ -2994,7 +3018,9 @@ void socket_connect(Socket *sock, SecureContext *sec,
|
|||||||
hints.ai_socktype = SOCK_STREAM;
|
hints.ai_socktype = SOCK_STREAM;
|
||||||
|
|
||||||
struct addrinfo *res = NULL;
|
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);
|
pending_connect_free(pending_connect);
|
||||||
sock->state = SOCKET_STATE_DIED;
|
sock->state = SOCKET_STATE_DIED;
|
||||||
sock->events = 0;
|
sock->events = 0;
|
||||||
@@ -3016,6 +3042,7 @@ void socket_connect(Socket *sock, SecureContext *sec,
|
|||||||
sock->state = SOCKET_STATE_PENDING;
|
sock->state = SOCKET_STATE_PENDING;
|
||||||
sock->events = 0;
|
sock->events = 0;
|
||||||
|
|
||||||
|
sock->raw = BAD_SOCKET;
|
||||||
sock->user_data = user_data;
|
sock->user_data = user_data;
|
||||||
sock->pending_connect = pending_connect;
|
sock->pending_connect = pending_connect;
|
||||||
sock->sec = sec;
|
sock->sec = sec;
|
||||||
@@ -3266,7 +3293,7 @@ void socket_update(Socket *sock)
|
|||||||
// ready for output. This means the operation is complete.
|
// ready for output. This means the operation is complete.
|
||||||
|
|
||||||
int err = 0;
|
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) {
|
if (getsockopt(sock->raw, SOL_SOCKET, SO_ERROR, (void*) &err, &len) < 0 || err != 0) {
|
||||||
|
|
||||||
@@ -3635,12 +3662,20 @@ struct SocketPool {
|
|||||||
Socket socks[];
|
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)
|
void socket_pool_global_free(void)
|
||||||
{
|
{
|
||||||
|
secure_context_global_free();
|
||||||
|
socket_raw_global_free();
|
||||||
}
|
}
|
||||||
|
|
||||||
SocketPool *socket_pool_init(HTTP_String addr,
|
SocketPool *socket_pool_init(HTTP_String addr,
|
||||||
@@ -3698,6 +3733,9 @@ SocketPool *socket_pool_init(HTTP_String addr,
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < max_socks; i++)
|
||||||
|
pool->socks[i].state = SOCKET_STATE_FREE;
|
||||||
|
|
||||||
return pool;
|
return pool;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3969,6 +4007,7 @@ int socket_pool_write(SocketPool *pool, SocketHandle handle, char *src, int len)
|
|||||||
typedef enum {
|
typedef enum {
|
||||||
CLIENT_CONNECTION_FREE,
|
CLIENT_CONNECTION_FREE,
|
||||||
CLIENT_CONNECTION_INIT,
|
CLIENT_CONNECTION_INIT,
|
||||||
|
CLIENT_CONNECTION_INIT_ERROR,
|
||||||
CLIENT_CONNECTION_WAIT,
|
CLIENT_CONNECTION_WAIT,
|
||||||
CLIENT_CONNECTION_DONE,
|
CLIENT_CONNECTION_DONE,
|
||||||
} ClientConnectionState;
|
} ClientConnectionState;
|
||||||
@@ -3994,6 +4033,19 @@ struct HTTP_Client {
|
|||||||
int ready[CLIENT_MAX_CONNS];
|
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
|
// Rename the memory function
|
||||||
static void* client_memfunc(HTTP_MemoryFuncTag tag, void *ptr, int len, void *data) {
|
static void* client_memfunc(HTTP_MemoryFuncTag tag, void *ptr, int len, void *data) {
|
||||||
(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)
|
while (client->conns[i].state != CLIENT_CONNECTION_FREE)
|
||||||
i++;
|
i++;
|
||||||
|
|
||||||
|
client->conns[i].sock = -1;
|
||||||
client->conns[i].user_data = NULL;
|
client->conns[i].user_data = NULL;
|
||||||
client->conns[i].trace = false;
|
client->conns[i].trace = false;
|
||||||
client->conns[i].state = CLIENT_CONNECTION_INIT;
|
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:
|
case SOCKET_EVENT_DIED:
|
||||||
{
|
{
|
||||||
ClientConnection *conn = event.user_data;
|
ClientConnection *conn = event.user_data;
|
||||||
|
conn->state = CLIENT_CONNECTION_DONE;
|
||||||
|
|
||||||
int tail = (client->ready_head + client->ready_count) % CLIENT_MAX_CONNS;
|
int tail = (client->ready_head + client->ready_count) % CLIENT_MAX_CONNS;
|
||||||
client->ready[tail] = conn - client->conns;
|
client->ready[tail] = conn - client->conns;
|
||||||
client->ready_count++;
|
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;
|
ClientConnection *conn = event.user_data;
|
||||||
|
|
||||||
|
if (conn->sock == -1)
|
||||||
|
conn->sock = event.handle;
|
||||||
|
|
||||||
HTTP_EngineState engine_state;
|
HTTP_EngineState engine_state;
|
||||||
engine_state = http_engine_state(&conn->eng);
|
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);
|
http_engine_free(&conn->eng);
|
||||||
conn->state = CLIENT_CONNECTION_FREE;
|
conn->state = CLIENT_CONNECTION_FREE;
|
||||||
client->num_conns--;
|
client->num_conns--;
|
||||||
|
} else {
|
||||||
|
result2->context = client;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@@ -4205,7 +4265,7 @@ void http_request_builder_line(HTTP_RequestBuilder builder, HTTP_Method method,
|
|||||||
HTTP_URL parsed_url;
|
HTTP_URL parsed_url;
|
||||||
int ret = http_parse_url(url.ptr, url.len, &parsed_url);
|
int ret = http_parse_url(url.ptr, url.len, &parsed_url);
|
||||||
if (ret != url.len) {
|
if (ret != url.len) {
|
||||||
// TODO
|
conn->state = CLIENT_CONNECTION_INIT_ERROR;
|
||||||
return;
|
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"))) {
|
if (http_streq(parsed_url.scheme, HTTP_STR("https"))) {
|
||||||
secure = true;
|
secure = true;
|
||||||
} else if (!http_streq(parsed_url.scheme, HTTP_STR("http"))) {
|
} else if (!http_streq(parsed_url.scheme, HTTP_STR("http"))) {
|
||||||
// TODO
|
conn->state = CLIENT_CONNECTION_INIT_ERROR;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -4226,12 +4286,14 @@ void http_request_builder_line(HTTP_RequestBuilder builder, HTTP_Method method,
|
|||||||
}
|
}
|
||||||
|
|
||||||
switch (parsed_url.authority.host.mode) {
|
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_IPV4: ret = socket_pool_connect_ipv4(client->socket_pool, secure, parsed_url.authority.host.ipv4, port, conn); 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_IPV6: ret = socket_pool_connect_ipv6(client->socket_pool, secure, parsed_url.authority.host.ipv6, port, conn); 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_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:
|
if (ret < 0) {
|
||||||
// TODO
|
conn->state = CLIENT_CONNECTION_INIT_ERROR;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -4262,20 +4324,34 @@ void http_request_builder_body(HTTP_RequestBuilder handle, HTTP_String str)
|
|||||||
|
|
||||||
void http_request_builder_submit(HTTP_RequestBuilder handle)
|
void http_request_builder_submit(HTTP_RequestBuilder handle)
|
||||||
{
|
{
|
||||||
|
HTTP_Client *client = handle.data0;
|
||||||
ClientConnection *conn = builder2conn(handle);
|
ClientConnection *conn = builder2conn(handle);
|
||||||
if (conn == NULL)
|
if (conn == NULL)
|
||||||
return;
|
return;
|
||||||
if (conn->state != CLIENT_CONNECTION_INIT)
|
if (conn->state != CLIENT_CONNECTION_INIT &&
|
||||||
|
conn->state != CLIENT_CONNECTION_INIT_ERROR)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// TODO: invalidate the handle
|
// TODO: invalidate the handle
|
||||||
|
|
||||||
http_engine_done(&conn->eng);
|
if (conn->state == CLIENT_CONNECTION_INIT_ERROR) {
|
||||||
conn->state = CLIENT_CONNECTION_WAIT;
|
|
||||||
|
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;
|
ClientConnection *conn = NULL;
|
||||||
for (int i = 0, j = 0; j < client->num_conns; i++) {
|
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)
|
if (router->num_routes == router->max_routes)
|
||||||
abort();
|
abort();
|
||||||
Route *route = &router->routes[router->num_routes++];
|
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->type = ROUTE_DYNAMIC;
|
||||||
route->endpoint = endpoint;
|
route->endpoint = endpoint;
|
||||||
route->func = func;
|
route->func = func;
|
||||||
|
|||||||
@@ -171,6 +171,7 @@ typedef struct {
|
|||||||
} HTTP_Request;
|
} HTTP_Request;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
|
void* context;
|
||||||
int minor;
|
int minor;
|
||||||
int status;
|
int status;
|
||||||
HTTP_String reason;
|
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_parse_response (char *src, int len, HTTP_Response *res);
|
||||||
|
|
||||||
int http_find_header (HTTP_Header *headers, int num_headers, HTTP_String name);
|
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
|
#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
|
// cHTTP tries to avoid global state. What this function
|
||||||
// does is call the global initialization functions of
|
// does is call the global initialization functions of
|
||||||
// its dependencies (OpenSSL and Winsock)
|
// its dependencies (OpenSSL and Winsock)
|
||||||
void http_global_init(void);
|
int http_global_init(void);
|
||||||
|
|
||||||
// Free the global state of cHTTP.
|
// Free the global state of cHTTP.
|
||||||
void http_global_free(void);
|
void http_global_free(void);
|
||||||
@@ -429,7 +427,7 @@ void http_request_builder_submit(HTTP_RequestBuilder builder);
|
|||||||
// after the request has completed.
|
// after the request has completed.
|
||||||
//
|
//
|
||||||
// TODO: allow aborting pending requests
|
// 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
|
// Wait for the completion of one request associated to
|
||||||
// the client. The handle of the resolved request is returned
|
// the client. The handle of the resolved request is returned
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ int main(void)
|
|||||||
// Perform the request. This will block the thread
|
// Perform the request. This will block the thread
|
||||||
// until an error occurs or the request completes.
|
// until an error occurs or the request completes.
|
||||||
HTTP_Response *res = http_get(
|
HTTP_Response *res = http_get(
|
||||||
HTTP_STR("http://example.com/index.html"),
|
HTTP_STR("http://coz.is/index.html"),
|
||||||
headers, HTTP_COUNT(headers)
|
headers, HTTP_COUNT(headers)
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -45,7 +45,7 @@ int main(void)
|
|||||||
|
|
||||||
// When we are done reading from the response object
|
// When we are done reading from the response object
|
||||||
// we must free the request's resources.
|
// we must free the request's resources.
|
||||||
http_request_free(res);
|
http_response_free(res);
|
||||||
|
|
||||||
// All done. Deinitialize the library.
|
// All done. Deinitialize the library.
|
||||||
http_global_free();
|
http_global_free();
|
||||||
|
|||||||
@@ -3,7 +3,8 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <chttp.h>
|
#include <chttp.h>
|
||||||
|
|
||||||
int main(int argc, char **argv) {
|
int main(int argc, char **argv)
|
||||||
|
{
|
||||||
if (argc < 2) {
|
if (argc < 2) {
|
||||||
printf("Usage: %s <url1> [url2 ...]\n", argv[0]);
|
printf("Usage: %s <url1> [url2 ...]\n", argv[0]);
|
||||||
return 1;
|
return 1;
|
||||||
@@ -13,13 +14,12 @@ int main(int argc, char **argv) {
|
|||||||
HTTP_Client *client = http_client_init();
|
HTTP_Client *client = http_client_init();
|
||||||
|
|
||||||
for (int i = 1; i < argc; i++) {
|
for (int i = 1; i < argc; i++) {
|
||||||
int k = i-1;
|
|
||||||
HTTP_RequestBuilder builder;
|
HTTP_RequestBuilder builder;
|
||||||
if (http_client_get_builder(client, &builder) < 0) {
|
if (http_client_get_builder(client, &builder) < 0) {
|
||||||
printf("request creation error\n");
|
printf("request creation error\n");
|
||||||
return -1;
|
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);
|
http_request_builder_submit(builder);
|
||||||
printf("request submitted\n");
|
printf("request submitted\n");
|
||||||
}
|
}
|
||||||
@@ -35,7 +35,7 @@ int main(int argc, char **argv) {
|
|||||||
printf("Status: %d\n", res->status);
|
printf("Status: %d\n", res->status);
|
||||||
printf("Body: %.*s\n", HTTP_UNPACK(res->body));
|
printf("Body: %.*s\n", HTTP_UNPACK(res->body));
|
||||||
|
|
||||||
http_request_free(res);
|
http_response_free(res);
|
||||||
}
|
}
|
||||||
|
|
||||||
http_client_free(client);
|
http_client_free(client);
|
||||||
|
|||||||
+49
-11
@@ -25,6 +25,7 @@
|
|||||||
typedef enum {
|
typedef enum {
|
||||||
CLIENT_CONNECTION_FREE,
|
CLIENT_CONNECTION_FREE,
|
||||||
CLIENT_CONNECTION_INIT,
|
CLIENT_CONNECTION_INIT,
|
||||||
|
CLIENT_CONNECTION_INIT_ERROR,
|
||||||
CLIENT_CONNECTION_WAIT,
|
CLIENT_CONNECTION_WAIT,
|
||||||
CLIENT_CONNECTION_DONE,
|
CLIENT_CONNECTION_DONE,
|
||||||
} ClientConnectionState;
|
} ClientConnectionState;
|
||||||
@@ -50,6 +51,19 @@ struct HTTP_Client {
|
|||||||
int ready[CLIENT_MAX_CONNS];
|
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
|
// Rename the memory function
|
||||||
static void* client_memfunc(HTTP_MemoryFuncTag tag, void *ptr, int len, void *data) {
|
static void* client_memfunc(HTTP_MemoryFuncTag tag, void *ptr, int len, void *data) {
|
||||||
(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)
|
while (client->conns[i].state != CLIENT_CONNECTION_FREE)
|
||||||
i++;
|
i++;
|
||||||
|
|
||||||
|
client->conns[i].sock = -1;
|
||||||
client->conns[i].user_data = NULL;
|
client->conns[i].user_data = NULL;
|
||||||
client->conns[i].trace = false;
|
client->conns[i].trace = false;
|
||||||
client->conns[i].state = CLIENT_CONNECTION_INIT;
|
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:
|
case SOCKET_EVENT_DIED:
|
||||||
{
|
{
|
||||||
ClientConnection *conn = event.user_data;
|
ClientConnection *conn = event.user_data;
|
||||||
|
conn->state = CLIENT_CONNECTION_DONE;
|
||||||
|
|
||||||
int tail = (client->ready_head + client->ready_count) % CLIENT_MAX_CONNS;
|
int tail = (client->ready_head + client->ready_count) % CLIENT_MAX_CONNS;
|
||||||
client->ready[tail] = conn - client->conns;
|
client->ready[tail] = conn - client->conns;
|
||||||
client->ready_count++;
|
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;
|
ClientConnection *conn = event.user_data;
|
||||||
|
|
||||||
|
if (conn->sock == -1)
|
||||||
|
conn->sock = event.handle;
|
||||||
|
|
||||||
HTTP_EngineState engine_state;
|
HTTP_EngineState engine_state;
|
||||||
engine_state = http_engine_state(&conn->eng);
|
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);
|
http_engine_free(&conn->eng);
|
||||||
conn->state = CLIENT_CONNECTION_FREE;
|
conn->state = CLIENT_CONNECTION_FREE;
|
||||||
client->num_conns--;
|
client->num_conns--;
|
||||||
|
} else {
|
||||||
|
result2->context = client;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@@ -261,7 +283,7 @@ void http_request_builder_line(HTTP_RequestBuilder builder, HTTP_Method method,
|
|||||||
HTTP_URL parsed_url;
|
HTTP_URL parsed_url;
|
||||||
int ret = http_parse_url(url.ptr, url.len, &parsed_url);
|
int ret = http_parse_url(url.ptr, url.len, &parsed_url);
|
||||||
if (ret != url.len) {
|
if (ret != url.len) {
|
||||||
// TODO
|
conn->state = CLIENT_CONNECTION_INIT_ERROR;
|
||||||
return;
|
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"))) {
|
if (http_streq(parsed_url.scheme, HTTP_STR("https"))) {
|
||||||
secure = true;
|
secure = true;
|
||||||
} else if (!http_streq(parsed_url.scheme, HTTP_STR("http"))) {
|
} else if (!http_streq(parsed_url.scheme, HTTP_STR("http"))) {
|
||||||
// TODO
|
conn->state = CLIENT_CONNECTION_INIT_ERROR;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -282,12 +304,14 @@ void http_request_builder_line(HTTP_RequestBuilder builder, HTTP_Method method,
|
|||||||
}
|
}
|
||||||
|
|
||||||
switch (parsed_url.authority.host.mode) {
|
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_IPV4: ret = socket_pool_connect_ipv4(client->socket_pool, secure, parsed_url.authority.host.ipv4, port, conn); 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_IPV6: ret = socket_pool_connect_ipv6(client->socket_pool, secure, parsed_url.authority.host.ipv6, port, conn); 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_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:
|
if (ret < 0) {
|
||||||
// TODO
|
conn->state = CLIENT_CONNECTION_INIT_ERROR;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -318,20 +342,34 @@ void http_request_builder_body(HTTP_RequestBuilder handle, HTTP_String str)
|
|||||||
|
|
||||||
void http_request_builder_submit(HTTP_RequestBuilder handle)
|
void http_request_builder_submit(HTTP_RequestBuilder handle)
|
||||||
{
|
{
|
||||||
|
HTTP_Client *client = handle.data0;
|
||||||
ClientConnection *conn = builder2conn(handle);
|
ClientConnection *conn = builder2conn(handle);
|
||||||
if (conn == NULL)
|
if (conn == NULL)
|
||||||
return;
|
return;
|
||||||
if (conn->state != CLIENT_CONNECTION_INIT)
|
if (conn->state != CLIENT_CONNECTION_INIT &&
|
||||||
|
conn->state != CLIENT_CONNECTION_INIT_ERROR)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// TODO: invalidate the handle
|
// TODO: invalidate the handle
|
||||||
|
|
||||||
http_engine_done(&conn->eng);
|
if (conn->state == CLIENT_CONNECTION_INIT_ERROR) {
|
||||||
conn->state = CLIENT_CONNECTION_WAIT;
|
|
||||||
|
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;
|
ClientConnection *conn = NULL;
|
||||||
for (int i = 0, j = 0; j < client->num_conns; i++) {
|
for (int i = 0, j = 0; j < client->num_conns; i++) {
|
||||||
|
|
||||||
|
|||||||
+2
-2
@@ -12,7 +12,7 @@
|
|||||||
// cHTTP tries to avoid global state. What this function
|
// cHTTP tries to avoid global state. What this function
|
||||||
// does is call the global initialization functions of
|
// does is call the global initialization functions of
|
||||||
// its dependencies (OpenSSL and Winsock)
|
// its dependencies (OpenSSL and Winsock)
|
||||||
void http_global_init(void);
|
int http_global_init(void);
|
||||||
|
|
||||||
// Free the global state of cHTTP.
|
// Free the global state of cHTTP.
|
||||||
void http_global_free(void);
|
void http_global_free(void);
|
||||||
@@ -71,7 +71,7 @@ void http_request_builder_submit(HTTP_RequestBuilder builder);
|
|||||||
// after the request has completed.
|
// after the request has completed.
|
||||||
//
|
//
|
||||||
// TODO: allow aborting pending requests
|
// 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
|
// Wait for the completion of one request associated to
|
||||||
// the client. The handle of the resolved request is returned
|
// the client. The handle of the resolved request is returned
|
||||||
|
|||||||
@@ -78,12 +78,6 @@ byte_queue_error(HTTP_ByteQueue *queue)
|
|||||||
return queue->flags & BYTE_QUEUE_ERROR;
|
return queue->flags & BYTE_QUEUE_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
|
||||||
byte_queue_setlimit(HTTP_ByteQueue *queue, unsigned int value)
|
|
||||||
{
|
|
||||||
queue->limit = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
static int
|
||||||
byte_queue_empty(HTTP_ByteQueue *queue)
|
byte_queue_empty(HTTP_ByteQueue *queue)
|
||||||
{
|
{
|
||||||
|
|||||||
-18
@@ -1020,21 +1020,3 @@ int http_parse_response(char *src, int len, HTTP_Response *res)
|
|||||||
return s.cur;
|
return s.cur;
|
||||||
return ret;
|
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};
|
|
||||||
}
|
|
||||||
+1
-3
@@ -74,6 +74,7 @@ typedef struct {
|
|||||||
} HTTP_Request;
|
} HTTP_Request;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
|
void* context;
|
||||||
int minor;
|
int minor;
|
||||||
int status;
|
int status;
|
||||||
HTTP_String reason;
|
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_parse_response (char *src, int len, HTTP_Response *res);
|
||||||
|
|
||||||
int http_find_header (HTTP_Header *headers, int num_headers, HTTP_String name);
|
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
|
#endif // PARSE_INCLUDED
|
||||||
+1
-1
@@ -79,7 +79,7 @@ void http_router_func(HTTP_Router *router, HTTP_Method method,
|
|||||||
if (router->num_routes == router->max_routes)
|
if (router->num_routes == router->max_routes)
|
||||||
abort();
|
abort();
|
||||||
Route *route = &router->routes[router->num_routes++];
|
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->type = ROUTE_DYNAMIC;
|
||||||
route->endpoint = endpoint;
|
route->endpoint = endpoint;
|
||||||
route->func = func;
|
route->func = func;
|
||||||
|
|||||||
@@ -4,6 +4,14 @@
|
|||||||
|
|
||||||
#ifndef HTTPS_ENABLED
|
#ifndef HTTPS_ENABLED
|
||||||
|
|
||||||
|
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_client(SecureContext *sec)
|
||||||
{
|
{
|
||||||
(void) sec;
|
(void) sec;
|
||||||
@@ -43,6 +51,19 @@ void secure_context_free(SecureContext *sec)
|
|||||||
|
|
||||||
#else
|
#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)
|
int secure_context_init_as_client(SecureContext *sec)
|
||||||
{
|
{
|
||||||
SSL_CTX *ctx = SSL_CTX_new(TLS_client_method());
|
SSL_CTX *ctx = SSL_CTX_new(TLS_client_method());
|
||||||
|
|||||||
@@ -33,6 +33,9 @@ typedef struct {
|
|||||||
|
|
||||||
#endif
|
#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_client(SecureContext *sec);
|
||||||
|
|
||||||
int secure_context_init_as_server(SecureContext *sec,
|
int secure_context_init_as_server(SecureContext *sec,
|
||||||
|
|||||||
+5
-2
@@ -122,7 +122,9 @@ void socket_connect(Socket *sock, SecureContext *sec,
|
|||||||
hints.ai_socktype = SOCK_STREAM;
|
hints.ai_socktype = SOCK_STREAM;
|
||||||
|
|
||||||
struct addrinfo *res = NULL;
|
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);
|
pending_connect_free(pending_connect);
|
||||||
sock->state = SOCKET_STATE_DIED;
|
sock->state = SOCKET_STATE_DIED;
|
||||||
sock->events = 0;
|
sock->events = 0;
|
||||||
@@ -144,6 +146,7 @@ void socket_connect(Socket *sock, SecureContext *sec,
|
|||||||
sock->state = SOCKET_STATE_PENDING;
|
sock->state = SOCKET_STATE_PENDING;
|
||||||
sock->events = 0;
|
sock->events = 0;
|
||||||
|
|
||||||
|
sock->raw = BAD_SOCKET;
|
||||||
sock->user_data = user_data;
|
sock->user_data = user_data;
|
||||||
sock->pending_connect = pending_connect;
|
sock->pending_connect = pending_connect;
|
||||||
sock->sec = sec;
|
sock->sec = sec;
|
||||||
@@ -394,7 +397,7 @@ void socket_update(Socket *sock)
|
|||||||
// ready for output. This means the operation is complete.
|
// ready for output. This means the operation is complete.
|
||||||
|
|
||||||
int err = 0;
|
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) {
|
if (getsockopt(sock->raw, SOL_SOCKET, SO_ERROR, (void*) &err, &len) < 0 || err != 0) {
|
||||||
|
|
||||||
|
|||||||
+12
-1
@@ -25,12 +25,20 @@ struct SocketPool {
|
|||||||
Socket socks[];
|
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)
|
void socket_pool_global_free(void)
|
||||||
{
|
{
|
||||||
|
secure_context_global_free();
|
||||||
|
socket_raw_global_free();
|
||||||
}
|
}
|
||||||
|
|
||||||
SocketPool *socket_pool_init(HTTP_String addr,
|
SocketPool *socket_pool_init(HTTP_String addr,
|
||||||
@@ -88,6 +96,9 @@ SocketPool *socket_pool_init(HTTP_String addr,
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < max_socks; i++)
|
||||||
|
pool->socks[i].state = SOCKET_STATE_FREE;
|
||||||
|
|
||||||
return pool;
|
return pool;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -24,6 +24,9 @@ typedef struct {
|
|||||||
void *user_data;
|
void *user_data;
|
||||||
} SocketEvent;
|
} SocketEvent;
|
||||||
|
|
||||||
|
int socket_pool_global_init(void);
|
||||||
|
void socket_pool_global_free(void);
|
||||||
|
|
||||||
SocketPool *socket_pool_init(HTTP_String addr,
|
SocketPool *socket_pool_init(HTTP_String addr,
|
||||||
uint16_t port, uint16_t secure_port, int max_socks,
|
uint16_t port, uint16_t secure_port, int max_socks,
|
||||||
bool reuse_addr, int backlog, HTTP_String cert_file,
|
bool reuse_addr, int backlog, HTTP_String cert_file,
|
||||||
|
|||||||
@@ -14,6 +14,24 @@
|
|||||||
#include "socket_raw.h"
|
#include "socket_raw.h"
|
||||||
#endif
|
#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)
|
int set_socket_blocking(RAW_SOCKET sock, bool value)
|
||||||
{
|
{
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
|
|||||||
@@ -25,6 +25,9 @@
|
|||||||
#include "basic.h"
|
#include "basic.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
int socket_raw_global_init(void);
|
||||||
|
void socket_raw_global_free(void);
|
||||||
|
|
||||||
int set_socket_blocking(RAW_SOCKET sock, bool value);
|
int set_socket_blocking(RAW_SOCKET sock, bool value);
|
||||||
|
|
||||||
RAW_SOCKET listen_socket(HTTP_String addr, uint16_t port, bool reuse_addr, int backlog);
|
RAW_SOCKET listen_socket(HTTP_String addr, uint16_t port, bool reuse_addr, int backlog);
|
||||||
|
|||||||
Reference in New Issue
Block a user