First version of the refactor
This commit is contained in:
+99
-79
@@ -1,98 +1,118 @@
|
||||
#ifndef CLIENT_INCLUDED
|
||||
#define CLIENT_INCLUDED
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
#ifndef HTTP_AMALGAMATION
|
||||
#include "parse.h"
|
||||
#ifndef HTTP_CLIENT_CAPACITY
|
||||
// The maximum ammount of requests that can be performed
|
||||
// in parallel.
|
||||
#define HTTP_CLIENT_CAPACITY (1<<7)
|
||||
#endif
|
||||
|
||||
// Initialize the global state of cHTTP.
|
||||
//
|
||||
// cHTTP tries to avoid global state. What this function
|
||||
// does is call the global initialization functions of
|
||||
// its dependencies (OpenSSL and Winsock)
|
||||
int http_global_init(void);
|
||||
typedef enum {
|
||||
HTTP_CLIENT_CONN_FREE,
|
||||
HTTP_CLIENT_CONN_WAIT_LINE,
|
||||
HTTP_CLIENT_CONN_WAIT_HEADER,
|
||||
HTTP_CLIENT_CONN_WAIT_BODY,
|
||||
HTTP_CLIENT_CONN_FLUSHING,
|
||||
HTTP_CLIENT_CONN_BUFFERING,
|
||||
HTTP_CLIENT_CONN_COMPLETE,
|
||||
} HTTP_ClientConnState;
|
||||
|
||||
// Free the global state of cHTTP.
|
||||
void http_global_free(void);
|
||||
|
||||
// Opaque type describing an "HTTP client". Any request
|
||||
// that is started must always be associated to an HTTP
|
||||
// client object.
|
||||
typedef struct HTTP_Client HTTP_Client;
|
||||
|
||||
// Handle for a pending request. This should be considered
|
||||
// opaque. Don't read or modify its fields!
|
||||
// Fields of this struct are private
|
||||
typedef struct {
|
||||
void *data0;
|
||||
int data1;
|
||||
int data2;
|
||||
} HTTP_RequestBuilder;
|
||||
HTTP_ClientConnState state;
|
||||
ByteQueue input;
|
||||
ByteQueue output;
|
||||
} HTTP_ClientConn;
|
||||
|
||||
// Initialize a client object. If something goes wrong,
|
||||
// NULL is returned.
|
||||
HTTP_Client *http_client_init(void);
|
||||
// Fields of this struct are private
|
||||
typedef struct {
|
||||
|
||||
// Deinitialize a client object
|
||||
// Array of connections. The counter contains the
|
||||
// number of structs such that state=FREE.
|
||||
int num_conns;
|
||||
HTTP_ClientConn conns[HTTP_CLIENT_CAPACITY];
|
||||
|
||||
// Queue of indices referring to connections that
|
||||
// are in the COMPLETE state.
|
||||
int num_ready;
|
||||
int ready_head;
|
||||
int ready[HTTP_CLIENT_CAPACITY];
|
||||
|
||||
// Asynchronous TCP and TLS socket abstraction
|
||||
SocketManager sockets;
|
||||
|
||||
// The server object doesn't interact with this
|
||||
// field directly, it just initializes the socket
|
||||
// manager with a pointer to it. This allows
|
||||
// allocating the exact number of sockets we
|
||||
// will need.
|
||||
Socket socket_pool[HTTP_CLIENT_CAPACITY];
|
||||
|
||||
} HTTP_Client;
|
||||
|
||||
// Initialize an HTTP client object. This allows one to
|
||||
// perform a number of requests in parallel.
|
||||
int http_client_init(HTTP_Client *client);
|
||||
|
||||
// Release resources associated to a client object.
|
||||
void http_client_free(HTTP_Client *client);
|
||||
|
||||
// Create a request object associated to the given client.
|
||||
// On success, 0 is returned and the handle is initialized.
|
||||
// On error, -1 is returned.
|
||||
int http_client_get_builder(HTTP_Client *client, HTTP_RequestBuilder *builder);
|
||||
// When a thread is blocked waiting for client events,
|
||||
// other threads can call this function to wake it up.
|
||||
int http_client_wakeup(HTTP_Client *client);
|
||||
|
||||
void http_request_builder_user_data(HTTP_RequestBuilder builder, void *user_data);
|
||||
typedef struct {
|
||||
HTTP_Client *client;
|
||||
uint16_t index;
|
||||
uint16_t gen;
|
||||
} HTTP_RequestBuilder;
|
||||
|
||||
// Enable/disable I/O tracing for the specified request.
|
||||
// This must be done when the request is in the initialization
|
||||
// phase.
|
||||
void http_request_builder_trace(HTTP_RequestBuilder builder, bool trace);
|
||||
// Create a new request builder object. If the response
|
||||
// pointer is NULL, a brand new builder is created. If
|
||||
// response isn't NULL (and http_free_response wasn't
|
||||
// called on it yet), the connection associated to that
|
||||
// previous exchange is reused. Note that it's up to the
|
||||
// user to make sure the requests are targeting the same
|
||||
// host. Returns 0 on success, -1 on error.
|
||||
int http_client_get_builder(HTTP_Client *client,
|
||||
HTTP_Response *response, HTTP_RequestBuilder *builder);
|
||||
|
||||
// Set the method and URL of the specified request object.
|
||||
// This must be the first thing you do after http_client_request
|
||||
// is called (you may http_request_trace before, but nothing
|
||||
// else!)
|
||||
void http_request_builder_line(HTTP_RequestBuilder builder, HTTP_Method method, HTTP_String url);
|
||||
// Set the URL of the current request. This is the first
|
||||
// function of the request builder that the user must call.
|
||||
void http_request_builder_url(HTTP_RequestBuilder builder, String url);
|
||||
|
||||
// Append a header to the specified request. You must call
|
||||
// this after http_request_line and may do so multiple times.
|
||||
void http_request_builder_header(HTTP_RequestBuilder builder, HTTP_String str);
|
||||
// After the URL, the user may set zero or more headers.
|
||||
void http_request_builder_header(HTTP_RequestBuilder builder, String str);
|
||||
|
||||
// Append some data to the request's body. You must call
|
||||
// this after either http_request_line or http_request_header.
|
||||
void http_request_builder_body(HTTP_RequestBuilder builder, HTTP_String str);
|
||||
// Append bytes to the request's body. You can call this
|
||||
// any amount of times, as long as it's after having set
|
||||
// the URL.
|
||||
void http_request_builder_body(HTTP_RequestBuilder builder, String str);
|
||||
|
||||
// Mark the initialization of the request as completed and
|
||||
// perform the request.
|
||||
void http_request_builder_submit(HTTP_RequestBuilder builder);
|
||||
// Mark this request as complete. This invalidates the
|
||||
// builder.
|
||||
void http_request_builder_send(HTTP_RequestBuilder builder);
|
||||
|
||||
// Free resources associated to a request. This must be called
|
||||
// after the request has completed.
|
||||
//
|
||||
// TODO: allow aborting pending requests
|
||||
void http_response_free(HTTP_Response *res);
|
||||
// List all low-level socket events the client is
|
||||
// waiting for such that the caller can call poll()
|
||||
// with it.
|
||||
int http_client_register_events(HTTP_Client *client,
|
||||
struct pollfd *polled, int max_polled);
|
||||
|
||||
// Wait for the completion of one request associated to
|
||||
// the client. The handle of the resolved request is returned
|
||||
// through the handle output parameter. If you're not
|
||||
// interested in which request completed (like when you
|
||||
// have only one pending request), you can pass NULL.
|
||||
//
|
||||
// On error -1 is retutned, else 0 is returned and the
|
||||
// handle is initialized.
|
||||
//
|
||||
// Note that calling this function when no requests are
|
||||
// pending is considered an error.
|
||||
int http_client_wait(HTTP_Client *client, HTTP_Response **res, void **user_data);
|
||||
// The caller has waited for poll() to return and some
|
||||
// I/O events to be triggered, so now the HTTP client
|
||||
// can continue its buffering and flushing operations.
|
||||
int http_client_process_events(HTTP_Client *client,
|
||||
struct pollfd *polled, int num_polled);
|
||||
|
||||
// TODO: comment
|
||||
HTTP_Response *http_get(HTTP_String url,
|
||||
HTTP_String *headers, int num_headers);
|
||||
// After some I/O events were processes, some responses
|
||||
// may be availabe. This function returns one of the
|
||||
// buffered responses. If a request was available, true
|
||||
// is returned. If no more are avaiable, false is returned.
|
||||
// The returned response must either be freed using the
|
||||
// http_free_response function or reused by passing it
|
||||
// to http_client_get_builder.
|
||||
bool http_client_next_response(HTTP_Client *client,
|
||||
HTTP_Response **response);
|
||||
|
||||
// TODO: comment
|
||||
HTTP_Response *http_post(HTTP_String url,
|
||||
HTTP_String *headers, int num_headers,
|
||||
HTTP_String body);
|
||||
|
||||
#endif // CLIENT_INCLUDED
|
||||
// Free a response object. You can't access its fields
|
||||
// again after this.
|
||||
void http_free_response(HTTP_Response *res);
|
||||
|
||||
Reference in New Issue
Block a user