From 49b2e92d1add1b3746cc71124c1939b6a3288f94 Mon Sep 17 00:00:00 2001 From: Vsevolod Stakhov Date: Thu, 9 Jan 2014 14:44:29 +0000 Subject: [PATCH] Reorganize HTTP library. --- src/http.c | 143 +++++++++++++++++++++++++---------------------------- src/http.h | 74 +++++++++++++-------------- 2 files changed, 105 insertions(+), 112 deletions(-) diff --git a/src/http.c b/src/http.c index 4d036428b..6c37d069e 100644 --- a/src/http.c +++ b/src/http.c @@ -25,7 +25,7 @@ #include "http.h" #include "utlist.h" -struct rspamd_http_server_private { +struct rspamd_http_connection_private { GString *buf; gboolean new_header; struct rspamd_http_header *header; @@ -35,7 +35,7 @@ struct rspamd_http_server_private { struct timeval tv; struct timeval *ptv; gboolean in_body; - struct rspamd_http_request *req; + struct rspamd_http_message *req; }; #define HTTP_ERROR http_error_quark () @@ -46,7 +46,7 @@ http_error_quark (void) } static inline void -rspamd_http_check_date (struct rspamd_http_server_private *priv) +rspamd_http_check_date (struct rspamd_http_connection_private *priv) { if (g_ascii_strcasecmp (priv->header->name->str, "date") == 0) { priv->req->date = rspamd_http_parse_date (priv->header->value->str, @@ -57,10 +57,10 @@ rspamd_http_check_date (struct rspamd_http_server_private *priv) static gint rspamd_http_on_url (http_parser* parser, const gchar *at, size_t length) { - struct rspamd_http_server *serv = (struct rspamd_http_server *)parser->data; - struct rspamd_http_server_private *priv; + struct rspamd_http_connection *conn = (struct rspamd_http_connection *)parser->data; + struct rspamd_http_connection_private *priv; - priv = serv->priv; + priv = conn->priv; g_string_append_len (priv->req->url, at, length); @@ -70,10 +70,10 @@ rspamd_http_on_url (http_parser* parser, const gchar *at, size_t length) static gint rspamd_http_on_header_field (http_parser* parser, const gchar *at, size_t length) { - struct rspamd_http_server *serv = (struct rspamd_http_server *)parser->data; - struct rspamd_http_server_private *priv; + struct rspamd_http_connection *conn = (struct rspamd_http_connection *)parser->data; + struct rspamd_http_connection_private *priv; - priv = serv->priv; + priv = conn->priv; if (priv->header == NULL) { priv->header = g_slice_alloc (sizeof (struct rspamd_http_header)); @@ -97,10 +97,10 @@ rspamd_http_on_header_field (http_parser* parser, const gchar *at, size_t length static gint rspamd_http_on_header_value (http_parser* parser, const gchar *at, size_t length) { - struct rspamd_http_server *serv = (struct rspamd_http_server *)parser->data; - struct rspamd_http_server_private *priv; + struct rspamd_http_connection *conn = (struct rspamd_http_connection *)parser->data; + struct rspamd_http_connection_private *priv; - priv = serv->priv; + priv = conn->priv; if (priv->header == NULL) { /* Should not happen */ @@ -116,10 +116,10 @@ rspamd_http_on_header_value (http_parser* parser, const gchar *at, size_t length static int rspamd_http_on_headers_complete (http_parser* parser) { - struct rspamd_http_server *serv = (struct rspamd_http_server *)parser->data; - struct rspamd_http_server_private *priv; + struct rspamd_http_connection *conn = (struct rspamd_http_connection *)parser->data; + struct rspamd_http_connection_private *priv; - priv = serv->priv; + priv = conn->priv; if (priv->header != NULL) { LL_PREPEND (priv->req->headers, priv->header); @@ -129,7 +129,7 @@ rspamd_http_on_headers_complete (http_parser* parser) priv->in_body = TRUE; if (parser->content_length != 0 && parser->content_length != ULLONG_MAX) { - priv->req->body = g_string_sized_new (parser->content_length); + priv->req->body = g_string_sized_new (parser->content_length + 1); } else { priv->req->body = g_string_sized_new (BUFSIZ); @@ -141,10 +141,15 @@ rspamd_http_on_headers_complete (http_parser* parser) static int rspamd_http_on_body (http_parser* parser, const gchar *at, size_t length) { - struct rspamd_http_server *serv = (struct rspamd_http_server *)parser->data; + struct rspamd_http_connection *conn = (struct rspamd_http_connection *)parser->data; + struct rspamd_http_connection_private *priv; - if (serv->opts & RSPAMD_HTTP_BODY_PARTIAL) { - return (serv->body_handler (serv, serv->priv->req, at, length)); + priv = conn->priv; + + g_string_append_len (priv->req->body, at, length); + + if (conn->opts & RSPAMD_HTTP_BODY_PARTIAL) { + return (conn->body_handler (conn, priv->req, at, length)); } return 0; @@ -153,17 +158,17 @@ rspamd_http_on_body (http_parser* parser, const gchar *at, size_t length) static int rspamd_http_on_message_complete (http_parser* parser) { - struct rspamd_http_server *serv = (struct rspamd_http_server *)parser->data; - struct rspamd_http_server_private *priv; + struct rspamd_http_connection *conn = (struct rspamd_http_connection *)parser->data; + struct rspamd_http_connection_private *priv; int ret; - priv = serv->priv; + priv = conn->priv; - if (serv->opts & RSPAMD_HTTP_BODY_PARTIAL) { - ret = serv->body_handler (serv, priv->req, NULL, 0); + if (conn->opts & RSPAMD_HTTP_BODY_PARTIAL) { + ret = conn->body_handler (conn, priv->req, NULL, 0); } else { - ret = serv->body_handler (serv, priv->req, priv->req->body->str, priv->req->body->len); + ret = conn->body_handler (conn, priv->req, priv->req->body->str, priv->req->body->len); } return ret; @@ -172,62 +177,48 @@ rspamd_http_on_message_complete (http_parser* parser) static void rspamd_http_event_handler (int fd, short what, gpointer ud) { - struct rspamd_http_server *serv = (struct rspamd_http_server *)ud; - struct rspamd_http_server_private *priv; + struct rspamd_http_connection *conn = (struct rspamd_http_connection *)ud; + struct rspamd_http_connection_private *priv; GString *buf; - gchar *start; gssize r; - gint64 remain; GError *err; - priv = serv->priv; - if (priv->in_body) { - buf = priv->req->body; - } - else { - priv->buf->len = 0; - buf = priv->buf; - } + priv = conn->priv; + buf = priv->buf; - remain = buf->allocated_len - buf->len; - if (remain <= 0) { - /* Expand string */ - g_string_set_size (buf, buf->allocated_len * 2); - remain = buf->allocated_len - buf->len; - } - start = buf->str + buf->len; - r = read (fd, start, remain); + r = read (fd, buf->str, buf->allocated_len); if (r == -1) { err = g_error_new (HTTP_ERROR, errno, "IO read error: %s", strerror (errno)); - serv->error_handler (serv, err); + conn->error_handler (conn, err); g_error_free (err); } else { - buf->len += r; - if (http_parser_execute (&priv->parser, &priv->parser_cb, start, r) != (size_t)r) { + buf->len = r; + if (http_parser_execute (&priv->parser, &priv->parser_cb, buf->str, r) != (size_t)r) { err = g_error_new (HTTP_ERROR, priv->parser.http_errno, "HTTP parser error: %s", http_errno_description (priv->parser.http_errno)); - serv->error_handler (serv, err); + conn->error_handler (conn, err); g_error_free (err); } + /* TODO: handle EOF */ } } -struct rspamd_http_server* -rspamd_http_server_new (rspamd_http_body_handler body_handler, +struct rspamd_http_connection* +rspamd_http_connection_new (rspamd_http_body_handler body_handler, rspamd_http_error_handler error_handler, enum rspamd_http_options opts) { - struct rspamd_http_server *new; - struct rspamd_http_server_private *priv; + struct rspamd_http_connection *new; + struct rspamd_http_connection_private *priv; - new = g_slice_alloc0 (sizeof (struct rspamd_http_server)); + new = g_slice_alloc0 (sizeof (struct rspamd_http_connection)); new->opts = opts; new->body_handler = body_handler; new->error_handler = error_handler; new->fd = -1; /* Init priv */ - priv = g_slice_alloc0 (sizeof (struct rspamd_http_server_private)); + priv = g_slice_alloc0 (sizeof (struct rspamd_http_connection_private)); http_parser_init (&priv->parser, HTTP_REQUEST); priv->parser.data = new; priv->parser_cb.on_url = rspamd_http_on_url; @@ -243,13 +234,13 @@ rspamd_http_server_new (rspamd_http_body_handler body_handler, } void -rspamd_http_server_reset (struct rspamd_http_server *server) +rspamd_http_connection_reset (struct rspamd_http_connection *conn) { - struct rspamd_http_server_private *priv; - struct rspamd_http_request *req; + struct rspamd_http_connection_private *priv; + struct rspamd_http_message *req; struct rspamd_http_header *hdr, *tmp_hdr; - priv = server->priv; + priv = conn->priv; req = priv->req; /* Clear request */ @@ -261,7 +252,7 @@ rspamd_http_server_reset (struct rspamd_http_server *server) } g_string_free (req->body, TRUE); g_string_free (req->url, TRUE); - g_slice_free1 (sizeof (struct rspamd_http_request), req); + g_slice_free1 (sizeof (struct rspamd_http_message), req); priv->req = NULL; } @@ -272,33 +263,33 @@ rspamd_http_server_reset (struct rspamd_http_server *server) priv->buf = NULL; } - /* Clear server itself */ - if (server->fd != -1) { - close (server->fd); + /* Clear conn itself */ + if (conn->fd != -1) { + close (conn->fd); } } void -rspamd_http_server_free (struct rspamd_http_server *server) +rspamd_http_connection_free (struct rspamd_http_connection *conn) { - struct rspamd_http_server_private *priv; + struct rspamd_http_connection_private *priv; - priv = server->priv; - rspamd_http_server_reset (server); - g_slice_free1 (sizeof (struct rspamd_http_server_private), priv); - g_slice_free1 (sizeof (struct rspamd_http_server), server); + priv = conn->priv; + rspamd_http_connection_reset (conn); + g_slice_free1 (sizeof (struct rspamd_http_connection_private), priv); + g_slice_free1 (sizeof (struct rspamd_http_connection), conn); } void -rspamd_http_server_handle_request (struct rspamd_http_server *server, +rspamd_http_connection_handle_request (struct rspamd_http_connection *conn, gpointer ud, gint fd, struct timeval *timeout, struct event_base *base) { - struct rspamd_http_server_private *priv = server->priv; - struct rspamd_http_request *req; + struct rspamd_http_connection_private *priv = conn->priv; + struct rspamd_http_message *req; - server->fd = fd; - server->ud = ud; - req = g_slice_alloc (sizeof (struct rspamd_http_request)); + conn->fd = fd; + conn->ud = ud; + req = g_slice_alloc (sizeof (struct rspamd_http_message)); req->url = g_string_sized_new (32); req->headers = NULL; req->date = 0; @@ -316,7 +307,7 @@ rspamd_http_server_handle_request (struct rspamd_http_server *server, priv->in_body = FALSE; priv->new_header = TRUE; - event_set (&priv->ev, fd, EV_READ | EV_PERSIST, rspamd_http_event_handler, server); + event_set (&priv->ev, fd, EV_READ | EV_PERSIST, rspamd_http_event_handler, conn); event_base_set (base, &priv->ev); event_add (&priv->ev, priv->ptv); } diff --git a/src/http.h b/src/http.h index 8506097a5..fe9c8d643 100644 --- a/src/http.h +++ b/src/http.h @@ -27,13 +27,18 @@ /** * @file http.h * - * This is an interface for HTTP client and server. This code uses HTTP parser written + * This is an interface for HTTP client and conn. This code uses HTTP parser written * by Joyent Inc based on nginx code. */ #include "config.h" #include "http_parser.h" +enum rspamd_http_message_type { + RSPAMD_HTTP_REQUEST, + RSPAMD_HTTP_REPLY +}; + /** * HTTP header structure */ @@ -44,48 +49,44 @@ struct rspamd_http_header { }; /** - * HTTP request structure, used for requests + * HTTP message structure, used for requests and replies */ -struct rspamd_http_request { +struct rspamd_http_message { GString *url; struct rspamd_http_header *headers; GString *body; + enum rspamd_http_message_type type; time_t date; gint code; }; -struct rspamd_http_reply { - struct rspamd_http_header *headers; - GString *body; - gint code; -}; /** - * Options for HTTP client and server + * Options for HTTP connection */ enum rspamd_http_options { RSPAMD_HTTP_BODY_PARTIAL = 0x1//!< RSPAMD_HTTP_BODY_PARTIAL }; -struct rspamd_http_server_private; -struct rspamd_http_server; +struct rspamd_http_connection_private; +struct rspamd_http_connection; -typedef gboolean (*rspamd_http_body_handler) (struct rspamd_http_server *srv, - struct rspamd_http_request *req, +typedef gboolean (*rspamd_http_body_handler) (struct rspamd_http_connection *srv, + struct rspamd_http_message *req, const gchar *chunk, gsize len); -typedef void (*rspamd_http_error_handler) (struct rspamd_http_server *srv, GError *err); +typedef void (*rspamd_http_error_handler) (struct rspamd_http_connection *srv, GError *err); -typedef void (*rspamd_http_reply_handler) (struct rspamd_http_server *srv, - struct rspamd_http_reply *reply, GError *err); +typedef void (*rspamd_http_reply_handler) (struct rspamd_http_connection *srv, + struct rspamd_http_message *reply, GError *err); /** - * HTTP server structure + * HTTP conn structure */ -struct rspamd_http_server { +struct rspamd_http_connection { gint fd; - struct rspamd_http_server_private *priv; + struct rspamd_http_connection_private *priv; enum rspamd_http_options opts; rspamd_http_body_handler body_handler; rspamd_http_error_handler error_handler; @@ -93,51 +94,52 @@ struct rspamd_http_server { }; /** - * Create new http server + * Create new http conn * @param handler handler for body * @param opts options - * @return new server structure + * @return new conn structure */ -struct rspamd_http_server* rspamd_http_server_new (rspamd_http_body_handler body_handler, +struct rspamd_http_connection* rspamd_http_connection_new (rspamd_http_body_handler body_handler, rspamd_http_error_handler error_handler, enum rspamd_http_options opts); /** * Handle a request using socket fd and user data ud - * @param server server structure + * @param conn conn structure * @param ud opaque user data * @param fd fd to read/write */ -void rspamd_http_server_handle_request (struct rspamd_http_server *server, gpointer ud, gint fd, +void rspamd_http_connection_handle_request (struct rspamd_http_connection *conn, gpointer ud, gint fd, struct timeval *timeout, struct event_base *base); /** - * Send reply using initialised server - * @param server server structure + * Send reply using initialised conn + * @param conn conn structure * @param reply HTTP reply * @return TRUE if request can be sent */ -gboolean rspamd_http_server_write_reply (struct rspamd_http_server *server, struct rspamd_http_reply *reply, +gboolean rspamd_http_connection_write_reply (struct rspamd_http_connection *conn, + struct rspamd_http_message *reply, rspamd_http_reply_handler *handler); /** - * Free server structure - * @param server + * Free conn structure + * @param conn */ -void rspamd_http_server_free (struct rspamd_http_server *server); +void rspamd_http_connection_free (struct rspamd_http_connection *conn); /** - * Reset server for a new request - * @param server + * Reset conn for a new request + * @param conn */ -void rspamd_http_server_reset (struct rspamd_http_server *server); +void rspamd_http_connection_reset (struct rspamd_http_connection *conn); /** * Create new HTTP reply * @param code code to pass * @return new reply object */ -struct rspamd_http_reply * rspamd_http_new_reply (gint code); +struct rspamd_http_message* rspamd_http_new_message (enum rspamd_http_message_type); /** * Append a header to reply @@ -145,13 +147,13 @@ struct rspamd_http_reply * rspamd_http_new_reply (gint code); * @param name * @param value */ -void rspamd_http_reply_add_header (struct rspamd_http_reply *rep, const gchar *name, const gchar *value); +void rspamd_http_message_add_header (struct rspamd_http_message *rep, const gchar *name, const gchar *value); /** * Free HTTP reply * @param rep */ -void rspamd_http_reply_free (struct rspamd_http_reply *rep); +void rspamd_http_message_free (struct rspamd_http_message *msg); /** * Parse HTTP date header and return it as time_t -- 2.39.5