aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorVsevolod Stakhov <vsevolod@highsecure.ru>2014-01-09 14:44:29 +0000
committerVsevolod Stakhov <vsevolod@highsecure.ru>2014-01-09 14:44:29 +0000
commit49b2e92d1add1b3746cc71124c1939b6a3288f94 (patch)
tree33f248096ee4abc78a534b762de0b6b5936529a5
parent4e4ae88f0e2093f0a354e396169694d40eb08d6d (diff)
downloadrspamd-49b2e92d1add1b3746cc71124c1939b6a3288f94.tar.gz
rspamd-49b2e92d1add1b3746cc71124c1939b6a3288f94.zip
Reorganize HTTP library.
-rw-r--r--src/http.c143
-rw-r--r--src/http.h74
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