Browse Source

Unify http code for client and server.

tags/0.6.7
Vsevolod Stakhov 10 years ago
parent
commit
9845dc6efa
3 changed files with 521 additions and 290 deletions
  1. 1
    1
      src/cfg_utils.c
  2. 475
    260
      src/http.c
  3. 45
    29
      src/http.h

+ 1
- 1
src/cfg_utils.c View File

@@ -125,7 +125,7 @@ parse_host_port_priority_strv (memory_pool_t *pool, gchar **tokens,
}
}
else if (default_port != 0) {
rspamd_snprintf (portbuf, sizeof (portbuf), "%u", default_port);
rspamd_snprintf (portbuf, sizeof (portbuf), "%ud", default_port);
cur_port = portbuf;
}
else {

+ 475
- 260
src/http.c View File

@@ -24,6 +24,7 @@
#include "config.h"
#include "http.h"
#include "utlist.h"
#include "printf.h"

struct rspamd_http_connection_private {
GString *buf;
@@ -34,8 +35,11 @@ struct rspamd_http_connection_private {
struct event ev;
struct timeval tv;
struct timeval *ptv;
gboolean in_body;
struct rspamd_http_message *req;
struct rspamd_http_message *msg;
struct iovec *out;
guint outlen;
gsize wr_pos;
gsize wr_total;
};

#define HTTP_ERROR http_error_quark ()
@@ -45,274 +49,31 @@ http_error_quark (void)
return g_quark_from_static_string ("http-error-quark");
}

static inline void
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,
priv->header->value->len);
}
}

static gint
rspamd_http_on_url (http_parser* parser, const gchar *at, size_t length)
{
struct rspamd_http_connection *conn = (struct rspamd_http_connection *)parser->data;
struct rspamd_http_connection_private *priv;

priv = conn->priv;

g_string_append_len (priv->req->url, at, length);

return 0;
}

static gint
rspamd_http_on_header_field (http_parser* parser, const gchar *at, size_t length)
{
struct rspamd_http_connection *conn = (struct rspamd_http_connection *)parser->data;
struct rspamd_http_connection_private *priv;

priv = conn->priv;

if (priv->header == NULL) {
priv->header = g_slice_alloc (sizeof (struct rspamd_http_header));
priv->header->name = g_string_sized_new (32);
priv->header->value = g_string_sized_new (32);
}
else if (priv->new_header) {
LL_PREPEND (priv->req->headers, priv->header);
rspamd_http_check_date (priv);
priv->header = g_slice_alloc (sizeof (struct rspamd_http_header));
priv->header->name = g_string_sized_new (32);
priv->header->value = g_string_sized_new (32);
}

priv->new_header = FALSE;
g_string_append_len (priv->header->name, at, length);

return 0;
}

static gint
rspamd_http_on_header_value (http_parser* parser, const gchar *at, size_t length)
{
struct rspamd_http_connection *conn = (struct rspamd_http_connection *)parser->data;
struct rspamd_http_connection_private *priv;

priv = conn->priv;

if (priv->header == NULL) {
/* Should not happen */
return -1;
}

priv->new_header = TRUE;
g_string_append_len (priv->header->value, at, length);

return 0;
}

static int
rspamd_http_on_headers_complete (http_parser* parser)
{
struct rspamd_http_connection *conn = (struct rspamd_http_connection *)parser->data;
struct rspamd_http_connection_private *priv;

priv = conn->priv;

if (priv->header != NULL) {
LL_PREPEND (priv->req->headers, priv->header);
rspamd_http_check_date (priv);
priv->header = NULL;
}

priv->in_body = TRUE;
if (parser->content_length != 0 && parser->content_length != ULLONG_MAX) {
priv->req->body = g_string_sized_new (parser->content_length + 1);
}
else {
priv->req->body = g_string_sized_new (BUFSIZ);
}

return 0;
}

static int
rspamd_http_on_body (http_parser* parser, const gchar *at, size_t length)
{
struct rspamd_http_connection *conn = (struct rspamd_http_connection *)parser->data;
struct rspamd_http_connection_private *priv;

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;
}

static int
rspamd_http_on_message_complete (http_parser* parser)
{
struct rspamd_http_connection *conn = (struct rspamd_http_connection *)parser->data;
struct rspamd_http_connection_private *priv;
int ret;

priv = conn->priv;

if (conn->opts & RSPAMD_HTTP_BODY_PARTIAL) {
ret = conn->body_handler (conn, priv->req, NULL, 0);
}
else {
ret = conn->body_handler (conn, priv->req, priv->req->body->str, priv->req->body->len);
}

return ret;
}

static void
rspamd_http_event_handler (int fd, short what, gpointer ud)
static const gchar *
rspamd_http_code_to_str (gint code)
{
struct rspamd_http_connection *conn = (struct rspamd_http_connection *)ud;
struct rspamd_http_connection_private *priv;
GString *buf;
gssize r;
GError *err;

priv = conn->priv;
buf = priv->buf;

r = read (fd, buf->str, buf->allocated_len);
if (r == -1) {
err = g_error_new (HTTP_ERROR, errno, "IO read error: %s", strerror (errno));
conn->error_handler (conn, err);
g_error_free (err);
}
else {
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));
conn->error_handler (conn, err);
g_error_free (err);
}
/* TODO: handle EOF */
if (code == 200) {
return "OK";
}
}

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_connection *new;
struct rspamd_http_connection_private *priv;

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_connection_private));
http_parser_init (&priv->parser, HTTP_REQUEST);
priv->parser.data = new;
priv->parser_cb.on_url = rspamd_http_on_url;
priv->parser_cb.on_header_field = rspamd_http_on_header_field;
priv->parser_cb.on_header_value = rspamd_http_on_header_value;
priv->parser_cb.on_headers_complete = rspamd_http_on_headers_complete;
priv->parser_cb.on_body = rspamd_http_on_body;
priv->parser_cb.on_message_complete = rspamd_http_on_message_complete;

new->priv = priv;

return new;
}

void
rspamd_http_connection_reset (struct rspamd_http_connection *conn)
{
struct rspamd_http_connection_private *priv;
struct rspamd_http_message *req;
struct rspamd_http_header *hdr, *tmp_hdr;

priv = conn->priv;
req = priv->req;

/* Clear request */
if (req != NULL) {
LL_FOREACH_SAFE(req->headers, hdr, tmp_hdr) {
g_string_free (hdr->name, TRUE);
g_string_free (hdr->value, TRUE);
g_slice_free1 (sizeof (struct rspamd_http_header), hdr);
}
g_string_free (req->body, TRUE);
g_string_free (req->url, TRUE);
g_slice_free1 (sizeof (struct rspamd_http_message), req);
priv->req = NULL;
else if (code == 404) {
return "Not found";
}

/* Clear priv */
event_del (&priv->ev);
if (priv->buf != NULL) {
g_string_free (priv->buf, TRUE);
priv->buf = NULL;
else if (code == 403 || code == 401) {
return "Not authorized";
}

/* Clear conn itself */
if (conn->fd != -1) {
close (conn->fd);
else if (code >= 400 && code < 500) {
return "Bad request";
}
}

void
rspamd_http_connection_free (struct rspamd_http_connection *conn)
{
struct rspamd_http_connection_private *priv;

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_connection_handle_request (struct rspamd_http_connection *conn,
gpointer ud, gint fd, struct timeval *timeout, struct event_base *base)
{
struct rspamd_http_connection_private *priv = conn->priv;
struct rspamd_http_message *req;

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;
priv->req = req;

if (timeout == NULL) {
priv->ptv = NULL;
else if (code >= 300 && code < 400) {
return "See Other";
}
else {
memcpy (&priv->tv, timeout, sizeof (struct timeval));
priv->ptv = &priv->tv;
else if (code >= 500 && code < 600) {
return "Internal server error";
}
priv->header = NULL;
priv->buf = g_string_sized_new (BUFSIZ);
priv->in_body = FALSE;
priv->new_header = TRUE;

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);
return "Unknown error";
}


/*
* Obtained from nginx
* Copyright (C) Igor Sysoev
@@ -580,3 +341,457 @@ rspamd_http_parse_date (const gchar *header, gsize len)

return (time_t) time;
}

static inline void
rspamd_http_check_date (struct rspamd_http_connection_private *priv)
{
if (g_ascii_strcasecmp (priv->header->name->str, "date") == 0) {
priv->msg->date = rspamd_http_parse_date (priv->header->value->str,
priv->header->value->len);
}
}

static gint
rspamd_http_on_url (http_parser* parser, const gchar *at, size_t length)
{
struct rspamd_http_connection *conn = (struct rspamd_http_connection *)parser->data;
struct rspamd_http_connection_private *priv;

priv = conn->priv;

g_string_append_len (priv->msg->url, at, length);

return 0;
}

static gint
rspamd_http_on_header_field (http_parser* parser, const gchar *at, size_t length)
{
struct rspamd_http_connection *conn = (struct rspamd_http_connection *)parser->data;
struct rspamd_http_connection_private *priv;

priv = conn->priv;

if (priv->header == NULL) {
priv->header = g_slice_alloc (sizeof (struct rspamd_http_header));
priv->header->name = g_string_sized_new (32);
priv->header->value = g_string_sized_new (32);
}
else if (priv->new_header) {
LL_PREPEND (priv->msg->headers, priv->header);
rspamd_http_check_date (priv);
priv->header = g_slice_alloc (sizeof (struct rspamd_http_header));
priv->header->name = g_string_sized_new (32);
priv->header->value = g_string_sized_new (32);
}

priv->new_header = FALSE;
g_string_append_len (priv->header->name, at, length);

return 0;
}

static gint
rspamd_http_on_header_value (http_parser* parser, const gchar *at, size_t length)
{
struct rspamd_http_connection *conn = (struct rspamd_http_connection *)parser->data;
struct rspamd_http_connection_private *priv;

priv = conn->priv;

if (priv->header == NULL) {
/* Should not happen */
return -1;
}

priv->new_header = TRUE;
g_string_append_len (priv->header->value, at, length);

return 0;
}

static int
rspamd_http_on_headers_complete (http_parser* parser)
{
struct rspamd_http_connection *conn = (struct rspamd_http_connection *)parser->data;
struct rspamd_http_connection_private *priv;

priv = conn->priv;

if (priv->header != NULL) {
LL_PREPEND (priv->msg->headers, priv->header);
rspamd_http_check_date (priv);
priv->header = NULL;
}

if (parser->content_length != 0 && parser->content_length != ULLONG_MAX) {
priv->msg->body = g_string_sized_new (parser->content_length + 1);
}
else {
priv->msg->body = g_string_sized_new (BUFSIZ);
}

return 0;
}

static int
rspamd_http_on_body (http_parser* parser, const gchar *at, size_t length)
{
struct rspamd_http_connection *conn = (struct rspamd_http_connection *)parser->data;
struct rspamd_http_connection_private *priv;

priv = conn->priv;

g_string_append_len (priv->msg->body, at, length);

if (conn->opts & RSPAMD_HTTP_BODY_PARTIAL) {
return (conn->body_handler (conn, priv->msg, at, length));
}

return 0;
}

static int
rspamd_http_on_message_complete (http_parser* parser)
{
struct rspamd_http_connection *conn = (struct rspamd_http_connection *)parser->data;
struct rspamd_http_connection_private *priv;
int ret;

priv = conn->priv;

if (conn->body_handler != NULL) {
if (conn->opts & RSPAMD_HTTP_BODY_PARTIAL) {
ret = conn->body_handler (conn, priv->msg, NULL, 0);
}
else {
ret = conn->body_handler (conn, priv->msg, priv->msg->body->str, priv->msg->body->len);
}
}
conn->finish_handler (conn, priv->msg);

return ret;
}

static void
rspamd_http_write_helper (struct rspamd_http_connection *conn)
{
struct rspamd_http_connection_private *priv;
struct iovec *start;
guint niov, i;
gsize remain;
gssize r;
GError *err;

priv = conn->priv;

if (priv->wr_pos == priv->wr_total) {
conn->finish_handler (conn, priv->msg);
return;
}

start = &priv->out[0];
niov = priv->outlen;
remain = priv->wr_pos;
for (i = 0; i < priv->outlen && remain > 0; i ++) {
/* Find out the first iov required */
start = &priv->out[i];
if (start->iov_len <= remain) {
remain -= start->iov_len;
start = &priv->out[i + 1];
niov --;
}
else {
start->iov_base = (void *)((char *)start->iov_base + remain);
start->iov_len -= remain;
remain = 0;
}
}

r = writev (conn->fd, start, MIN (IOV_MAX, niov));

if (r == -1) {
err = g_error_new (HTTP_ERROR, errno, "IO write error: %s", strerror (errno));
conn->error_handler (conn, err);
g_error_free (err);
}
else {
priv->wr_pos += r;
}

if (priv->wr_pos >= priv->wr_total) {
conn->finish_handler (conn, priv->msg);
}
}

static void
rspamd_http_event_handler (int fd, short what, gpointer ud)
{
struct rspamd_http_connection *conn = (struct rspamd_http_connection *)ud;
struct rspamd_http_connection_private *priv;
GString *buf;
gssize r;
GError *err;

priv = conn->priv;
buf = priv->buf;

if (what == EV_READ) {
r = read (fd, buf->str, buf->allocated_len);
if (r == -1) {
err = g_error_new (HTTP_ERROR, errno, "IO read error: %s", strerror (errno));
conn->error_handler (conn, err);
g_error_free (err);
}
else {
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));
conn->error_handler (conn, err);
g_error_free (err);
}
}
}
else if (what == EV_TIMEOUT) {
err = g_error_new (HTTP_ERROR, ETIMEDOUT,
"IO timeout");
conn->error_handler (conn, err);
g_error_free (err);
}
else if (what == EV_WRITE) {
rspamd_http_write_helper (conn);
}
}

struct rspamd_http_connection*
rspamd_http_connection_new (rspamd_http_body_handler body_handler,
rspamd_http_error_handler error_handler,
rspamd_http_finish_handler finish_handler,
enum rspamd_http_options opts,
enum rspamd_http_connection_type type)
{
struct rspamd_http_connection *new;
struct rspamd_http_connection_private *priv;

if (error_handler == NULL || finish_handler == NULL) {
return NULL;
}

new = g_slice_alloc0 (sizeof (struct rspamd_http_connection));
new->opts = opts;
new->type = type;
new->body_handler = body_handler;
new->error_handler = error_handler;
new->finish_handler = finish_handler;
new->fd = -1;

/* Init priv */
priv = g_slice_alloc0 (sizeof (struct rspamd_http_connection_private));
http_parser_init (&priv->parser, type == RSPAMD_HTTP_SERVER ? HTTP_REQUEST : HTTP_RESPONSE);
priv->parser.data = new;
priv->parser_cb.on_url = rspamd_http_on_url;
priv->parser_cb.on_header_field = rspamd_http_on_header_field;
priv->parser_cb.on_header_value = rspamd_http_on_header_value;
priv->parser_cb.on_headers_complete = rspamd_http_on_headers_complete;
priv->parser_cb.on_body = rspamd_http_on_body;
priv->parser_cb.on_message_complete = rspamd_http_on_message_complete;

new->priv = priv;

return new;
}

void
rspamd_http_connection_reset (struct rspamd_http_connection *conn)
{
struct rspamd_http_connection_private *priv;
struct rspamd_http_message *msg;

priv = conn->priv;
msg = priv->msg;

/* Clear request */
if (msg != NULL) {
rspamd_http_message_free (msg);
priv->msg = NULL;
}

/* Clear priv */
event_del (&priv->ev);
if (priv->buf != NULL) {
g_string_free (priv->buf, TRUE);
priv->buf = NULL;
}
if (priv->out != NULL) {
g_slice_free1 (sizeof (struct iovec) * priv->outlen, priv->out);
priv->out = NULL;
}

/* Clear conn itself */
if (conn->fd != -1) {
close (conn->fd);
}
}

void
rspamd_http_connection_free (struct rspamd_http_connection *conn)
{
struct rspamd_http_connection_private *priv;

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_connection_read_message (struct rspamd_http_connection *conn,
gpointer ud, gint fd, struct timeval *timeout, struct event_base *base)
{
struct rspamd_http_connection_private *priv = conn->priv;
struct rspamd_http_message *req;

conn->fd = fd;
conn->ud = ud;
req = rspamd_http_new_message (conn->type == RSPAMD_HTTP_SERVER ? HTTP_REQUEST : HTTP_RESPONSE);
priv->msg = req;

if (timeout == NULL) {
priv->ptv = NULL;
}
else {
memcpy (&priv->tv, timeout, sizeof (struct timeval));
priv->ptv = &priv->tv;
}
priv->header = NULL;
priv->buf = g_string_sized_new (BUFSIZ);
priv->new_header = TRUE;

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);
}

void
rspamd_http_connection_write_message (struct rspamd_http_connection *conn,
struct rspamd_http_message *msg, const gchar *host,
gpointer ud, gint fd, struct timeval *timeout, struct event_base *base)
{
struct rspamd_http_connection_private *priv = conn->priv;
struct rspamd_http_header *hdr;
gint i;

conn->fd = fd;
conn->ud = ud;
priv->msg = msg;

if (timeout == NULL) {
priv->ptv = NULL;
}
else {
memcpy (&priv->tv, timeout, sizeof (struct timeval));
priv->ptv = &priv->tv;
}
priv->header = NULL;
priv->buf = g_string_sized_new (64);

if (conn->type == RSPAMD_HTTP_SERVER) {
/* Format reply */
rspamd_printf_gstring (priv->buf, "HTTP/1.1 %d %s\r\n"
"Connection: close\r\n"
"Content-Length: %z\r\n",
msg->code, rspamd_http_code_to_str (msg->code),
msg->body->len);
}
else {
/* Format request */
if (host != NULL) {
rspamd_printf_gstring (priv->buf, "%s %v HTTP/1.1\r\n"
"Connection: close\r\n"
"Host: %s\r\n"
"Content-Length: %z\r\n",
http_method_str (msg->method), msg->url, host, msg->body->len);
}
else {
/* Fallback to HTTP/1.0 */
rspamd_printf_gstring (priv->buf, "%s %v HTTP/1.0\r\n"
"Content-Length: %z\r\n",
http_method_str (msg->method), msg->url, msg->body->len);
}
}

/* Allocate iov */
priv->outlen = 3;
priv->wr_total = msg->body->len + priv->buf->len + 2;
LL_FOREACH (msg->headers, hdr) {
/* <name><: ><value><\r\n> */
priv->wr_total += hdr->name->len + hdr->value->len + 4;
priv->outlen += 4;
}
priv->out = g_slice_alloc (sizeof (struct iovec) * priv->outlen);
priv->wr_pos = 0;

/* Now set up all iov */
priv->out[0].iov_base = priv->buf->str;
priv->out[0].iov_len = priv->buf->len;
i = 1;
LL_FOREACH (msg->headers, hdr) {
priv->out[i].iov_base = hdr->name->str;
priv->out[i++].iov_len = hdr->name->len;
priv->out[i].iov_base = ": ";
priv->out[i++].iov_len = 2;
priv->out[i].iov_base = hdr->value->str;
priv->out[i++].iov_len = hdr->value->len;
priv->out[i].iov_base = "\r\n";
priv->out[i++].iov_len = 2;
}
priv->out[i].iov_base = "\r\n";
priv->out[i++].iov_len = 2;
priv->out[i].iov_base = msg->body->str;
priv->out[i++].iov_len = msg->body->len;

event_set (&priv->ev, fd, EV_WRITE, rspamd_http_event_handler, conn);
event_base_set (base, &priv->ev);
event_add (&priv->ev, priv->ptv);
}

struct rspamd_http_message*
rspamd_http_new_message (enum http_parser_type type)
{
struct rspamd_http_message *new;

new = g_slice_alloc (sizeof (struct rspamd_http_message));
if (type == HTTP_REQUEST) {
new->url = g_string_sized_new (32);
}
else {
new->url = NULL;
new->code = 200;
}
new->headers = NULL;
new->date = 0;
new->body = NULL;
new->type = type;

return new;
}

void
rspamd_http_message_free (struct rspamd_http_message *msg)
{
struct rspamd_http_header *hdr, *tmp_hdr;

LL_FOREACH_SAFE (msg->headers, hdr, tmp_hdr) {
g_string_free (hdr->name, TRUE);
g_string_free (hdr->value, TRUE);
g_slice_free1 (sizeof (struct rspamd_http_header), hdr);
}
if (msg->body != NULL) {
g_string_free (msg->body, TRUE);
}
if (msg->url != NULL) {
g_string_free (msg->url, TRUE);
}
g_slice_free1 (sizeof (struct rspamd_http_message), msg);
}

+ 45
- 29
src/http.h View File

@@ -34,9 +34,9 @@
#include "config.h"
#include "http_parser.h"

enum rspamd_http_message_type {
RSPAMD_HTTP_REQUEST,
RSPAMD_HTTP_REPLY
enum rspamd_http_connection_type {
RSPAMD_HTTP_SERVER,
RSPAMD_HTTP_CLIENT
};

/**
@@ -55,9 +55,10 @@ struct rspamd_http_message {
GString *url;
struct rspamd_http_header *headers;
GString *body;
enum rspamd_http_message_type type;
enum http_parser_type type;
time_t date;
gint code;
enum http_method method;
};


@@ -71,65 +72,80 @@ enum rspamd_http_options {
struct rspamd_http_connection_private;
struct rspamd_http_connection;

typedef gboolean (*rspamd_http_body_handler) (struct rspamd_http_connection *srv,
struct rspamd_http_message *req,
typedef gboolean (*rspamd_http_body_handler) (struct rspamd_http_connection *conn,
struct rspamd_http_message *msg,
const gchar *chunk,
gsize len);

typedef void (*rspamd_http_error_handler) (struct rspamd_http_connection *srv, GError *err);
typedef void (*rspamd_http_error_handler) (struct rspamd_http_connection *conn, GError *err);

typedef void (*rspamd_http_reply_handler) (struct rspamd_http_connection *srv,
struct rspamd_http_message *reply, GError *err);
typedef void (*rspamd_http_finish_handler) (struct rspamd_http_connection *conn,
struct rspamd_http_message *msg);

/**
* HTTP conn structure
* HTTP connection structure
*/
struct rspamd_http_connection {
gint fd;
struct rspamd_http_connection_private *priv;
enum rspamd_http_options opts;
rspamd_http_body_handler body_handler;
rspamd_http_error_handler error_handler;
rspamd_http_finish_handler finish_handler;
gpointer ud;
enum rspamd_http_options opts;
enum rspamd_http_connection_type type;
gint fd;
};

/**
* Create new http conn
* Create new http connection
* @param handler handler for body
* @param opts options
* @return new conn structure
* @return new connection structure
*/
struct rspamd_http_connection* rspamd_http_connection_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);
rspamd_http_finish_handler finish_handler,
enum rspamd_http_options opts,
enum rspamd_http_connection_type type);

/**
* Handle a request using socket fd and user data ud
* @param conn conn structure
* @param conn connection structure
* @param ud opaque user data
* @param fd fd to read/write
*/
void rspamd_http_connection_handle_request (struct rspamd_http_connection *conn, gpointer ud, gint fd,
struct timeval *timeout, struct event_base *base);
void rspamd_http_connection_read_message (
struct rspamd_http_connection *conn,
gpointer ud,
gint fd,
struct timeval *timeout,
struct event_base *base);

/**
* Send reply using initialised conn
* @param conn conn structure
* @param reply HTTP reply
* @return TRUE if request can be sent
* Send reply using initialised connection
* @param conn connection structure
* @param msg HTTP message
* @param ud opaque user data
* @param fd fd to read/write
*/
gboolean rspamd_http_connection_write_reply (struct rspamd_http_connection *conn,
struct rspamd_http_message *reply,
rspamd_http_reply_handler *handler);
void rspamd_http_connection_write_message (
struct rspamd_http_connection *conn,
struct rspamd_http_message *msg,
const gchar *host,
gpointer ud,
gint fd,
struct timeval *timeout,
struct event_base *base);

/**
* Free conn structure
* Free connection structure
* @param conn
*/
void rspamd_http_connection_free (struct rspamd_http_connection *conn);

/**
* Reset conn for a new request
* Reset connection for a new request
* @param conn
*/
void rspamd_http_connection_reset (struct rspamd_http_connection *conn);
@@ -139,7 +155,7 @@ void rspamd_http_connection_reset (struct rspamd_http_connection *conn);
* @param code code to pass
* @return new reply object
*/
struct rspamd_http_message* rspamd_http_new_message (enum rspamd_http_message_type);
struct rspamd_http_message* rspamd_http_new_message (enum http_parser_type type);

/**
* Append a header to reply

Loading…
Cancel
Save