Skip to content

Instantly share code, notes, and snippets.

@kiler129
Created November 27, 2016 07:33
Show Gist options
  • Save kiler129/9502c558a3268c30602f913898a495ce to your computer and use it in GitHub Desktop.
Save kiler129/9502c558a3268c30602f913898a495ce to your computer and use it in GitHub Desktop.
diff -Naur libevent-master/http.c libevent-master-mod2/http.c
--- libevent-master/http.c 2016-11-18 11:58:08.000000000 -0600
+++ libevent-master-mod2/http.c 2016-11-27 01:30:06.726038913 -0600
@@ -192,13 +192,14 @@
static void evhttp_write_buffer(struct evhttp_connection *,
void (*)(struct evhttp_connection *, void *), void *);
static void evhttp_make_header(struct evhttp_connection *, struct evhttp_request *);
+static int evhttp_method_may_have_body_(struct evhttp_connection *, enum evhttp_cmd_type);
/* callbacks for bufferevent */
static void evhttp_read_cb(struct bufferevent *, void *);
static void evhttp_write_cb(struct bufferevent *, void *);
static void evhttp_error_cb(struct bufferevent *bufev, short what, void *arg);
-static int evhttp_find_vhost(struct evhttp *http, struct evhttp **outhttp,
- const char *hostname);
+static int evhttp_find_vhost(struct evhttp *http, struct evhttp **outhttp, const char *hostname);
+static const char * evhttp_method_(struct evhttp_connection *evcon, enum evhttp_cmd_type type, ev_uint16_t *flags);
#ifndef EVENT__HAVE_STRSEP
/* strsep replacement for platforms that lack it. Only works if
@@ -299,9 +300,11 @@
* equivalent HTTP command, or NULL if the evhttp_command_type is
* unrecognized. */
static const char *
-evhttp_method(enum evhttp_cmd_type type)
+evhttp_method_(struct evhttp_connection *evcon, enum evhttp_cmd_type type, ev_uint16_t *flags)
{
- const char *method;
+ struct evhttp_extended_method ext_method;
+ const char *method = NULL;
+ ev_uint16_t tmp_flags = 0;
switch (type) {
case EVHTTP_REQ_GET:
@@ -309,12 +312,14 @@
break;
case EVHTTP_REQ_POST:
method = "POST";
+ tmp_flags = EVHTTP_METHOD_HAS_BODY;
break;
case EVHTTP_REQ_HEAD:
method = "HEAD";
break;
case EVHTTP_REQ_PUT:
method = "PUT";
+ tmp_flags = EVHTTP_METHOD_HAS_BODY;
break;
case EVHTTP_REQ_DELETE:
method = "DELETE";
@@ -330,12 +335,51 @@
break;
case EVHTTP_REQ_PATCH:
method = "PATCH";
+ tmp_flags = EVHTTP_METHOD_HAS_BODY;
break;
default:
- method = NULL;
+ /* setup the structure to allow for the cmp.
+ *
+ * if the cmp function is set, it has the ability to
+ * modify method and flags. Other fields will be
+ * ignored.
+ *
+ * NOTE: the flags returned are OR'd with the current
+ * flags.
+ */
+ ext_method.method = NULL;
+ ext_method.type = type;
+ ext_method.flags = tmp_flags;
+
+ if (evcon->ext_method_cmp != NULL &&
+ evcon->ext_method_cmp(&ext_method) == 0) {
+
+ if (ext_method.type != type) {
+ /* XXX: when this etuns, and the method is NULL,
+ * the caller of this function just blindly adds
+ * it to the evbuffer! We need to figure out a
+ * way to propigate that error all the way down
+ * the chain.
+ *
+ * For now we just break, but it really needs
+ * to return NULL.
+ */
+ event_debug(("%s: method_cmp modified type from %u to %u, not allowd",
+ __func__, type, ext_method.type));
+ break;
+ }
+
+ method = ext_method.method;
+ tmp_flags |= ext_method.flags;
+ }
break;
}
+ event_debug(("%s: type=%04x => '%s' flags=%04x",
+ __func__, (int)type, method, tmp_flags));
+
+ if (flags != NULL)
+ *flags = tmp_flags;
return (method);
}
@@ -431,11 +475,12 @@
struct evhttp_request *req)
{
const char *method;
+ ev_uint16_t flags;
evhttp_remove_header(req->output_headers, "Proxy-Connection");
/* Generate request line */
- if (!(method = evhttp_method(req->type))) {
+ if (!(method = evhttp_method_(evcon, req->type, &flags))) {
method = "NULL";
}
@@ -444,7 +489,7 @@
method, req->uri, req->major, req->minor);
/* Add the content length on a post or put request if missing */
- if ((req->type == EVHTTP_REQ_POST || req->type == EVHTTP_REQ_PUT) &&
+ if ((flags & EVHTTP_METHOD_HAS_BODY) &&
evhttp_find_header(req->output_headers, "Content-Length") == NULL){
char size[22];
evutil_snprintf(size, sizeof(size), EV_SIZE_FMT,
@@ -1826,6 +1871,25 @@
} /* switch */
if ((int)type == EVHTTP_REQ_UNKNOWN_) {
+ /* check extended methods, we only care about the
+ * type set by the cmp function if the cmp function
+ * returns a 0 value.
+ */
+ struct evhttp_extended_method ext_method;
+
+ ext_method.method = method;
+ ext_method.type = EVHTTP_REQ_UNKNOWN_;
+
+ if (req->evcon->ext_method_cmp &&
+ req->evcon->ext_method_cmp(&ext_method) == 0) {
+ /* TODO: make sure the other fields in ext_method are
+ * not changed by the callback.
+ */
+ type = ext_method.type;
+ }
+ }
+
+ if ((int)type == EVHTTP_REQ_UNKNOWN_) {
event_debug(("%s: bad method %s on request %p from %s",
__func__, method, req, req->remote_host));
/* No error yet; we'll give a better error later when
@@ -2162,25 +2226,11 @@
}
static int
-evhttp_method_may_have_body(enum evhttp_cmd_type type)
+evhttp_method_may_have_body_(struct evhttp_connection *evcon, enum evhttp_cmd_type type)
{
- switch (type) {
- case EVHTTP_REQ_POST:
- case EVHTTP_REQ_PUT:
- case EVHTTP_REQ_PATCH:
- return 1;
- case EVHTTP_REQ_TRACE:
- return 0;
- /* XXX May any of the below methods have a body? */
- case EVHTTP_REQ_GET:
- case EVHTTP_REQ_HEAD:
- case EVHTTP_REQ_DELETE:
- case EVHTTP_REQ_OPTIONS:
- case EVHTTP_REQ_CONNECT:
- return 0;
- default:
- return 0;
- }
+ ev_uint16_t flags;
+ evhttp_method_(evcon, type, &flags);
+ return (flags & EVHTTP_METHOD_HAS_BODY) ? 1 : 0;
}
static void
@@ -2190,7 +2240,7 @@
/* If this is a request without a body, then we are done */
if (req->kind == EVHTTP_REQUEST &&
- !evhttp_method_may_have_body(req->type)) {
+ !evhttp_method_may_have_body_(evcon, req->type)) {
evhttp_connection_done(evcon);
return;
}
@@ -2353,7 +2403,9 @@
{
struct evhttp_connection *evcon = NULL;
- event_debug(("Attempting connection to %s:%d\n", address, port));
+ event_debug(("%s %s:%d\n",
+ (dnsbase?"New connection from":"Attempting connection to"),
+ address, port));
if ((evcon = mm_calloc(1, sizeof(struct evhttp_connection))) == NULL) {
event_warn("%s: calloc failed", __func__);
@@ -2453,6 +2505,12 @@
}
void
+evhttp_connection_set_extended_method_cmp(struct evhttp_connection *evcon,
+ int (*cmp)(struct evhttp_extended_method *)) {
+ evcon->ext_method_cmp = cmp;
+}
+
+void
evhttp_connection_set_base(struct evhttp_connection *evcon,
struct event_base *base)
{
@@ -2463,6 +2521,12 @@
}
void
+evhttp_set_extended_method_cmp(struct evhttp* http,
+ int (*cmp)(struct evhttp_extended_method *)) {
+ http->ext_method_cmp = cmp;
+}
+
+void
evhttp_connection_set_timeout(struct evhttp_connection *evcon,
int timeout_in_secs)
{
@@ -4278,6 +4342,7 @@
* we need to know which http server it belongs to.
*/
evcon->http_server = http;
+ evcon->ext_method_cmp = http->ext_method_cmp;
TAILQ_INSERT_TAIL(&http->connections, evcon, next);
if (evhttp_associate_new_request_with_connection(evcon) == -1)
diff -Naur libevent-master/http-internal.h libevent-master-mod2/http-internal.h
--- libevent-master/http-internal.h 2016-11-18 11:58:08.000000000 -0600
+++ libevent-master-mod2/http-internal.h 2016-11-27 01:29:57.957504958 -0600
@@ -105,6 +105,8 @@
struct event_base *base;
struct evdns_base *dns_base;
int ai_family;
+
+ int (*ext_method_cmp)(struct evhttp_extended_method *);
};
/* A callback for an http server */
@@ -172,6 +174,8 @@
void *bevcbarg;
struct event_base *base;
+
+ int (*ext_method_cmp)(struct evhttp_extended_method *);
};
/* XXX most of these functions could be static. */
diff -Naur libevent-master/include/event2/http.h libevent-master-mod2/include/event2/http.h
--- libevent-master/include/event2/http.h 2016-11-18 11:58:08.000000000 -0600
+++ libevent-master-mod2/include/event2/http.h 2016-11-27 01:30:45.776341127 -0600
@@ -73,6 +73,7 @@
struct evhttp_bound_socket;
struct evconnlistener;
struct evdns_base;
+struct evhttp_extended_method;
/**
* Create a new HTTP server.
@@ -247,6 +248,24 @@
EVENT2_EXPORT_SYMBOL
void evhttp_set_allowed_methods(struct evhttp* http, ev_uint16_t methods);
+ /**
+ Sets the callback function which allows HTTP extended methods
+ to be supported by this server.
+
+ The callback should :
+ - if method field is NULL : set method field according to type field
+ - else : set type and flags fields according to method string
+ - return 0 for success (known method / type)
+ - return -1 for error (unknown method / type)
+
+ @param http the http server on which to add support to the methods
+ @param cmp the extended method callback
+ @see evhttp_extended_method
+ */
+ EVENT2_EXPORT_SYMBOL
+ void evhttp_set_extended_method_cmp(struct evhttp* http,
+ int (*cmp)(struct evhttp_extended_method *));
+
/**
Set a callback for a specified URI
@@ -500,6 +519,24 @@
EVHTTP_REQ_PATCH = 1 << 8
};
+#define EVHTTP_REQ_MAX EVHTTP_REQ_PATCH
+
+/** structure to allow users to define their own HTTP methods
+ * @see evhttp_set_extended_method_cmp
+ * @see evhttp_connection_set_extended_method_cmp */
+
+/**
+ * @brief stucture that is passed to (and modified by) the
+ * extended method callback function
+ */
+struct evhttp_extended_method {
+ const char * method;
+ ev_uint16_t type; /* @see enum evhttp_cmd_type */
+ ev_uint16_t flags; /* Available flag : EVHTTP_METHOD_HAS_BODY */
+};
+
+#define EVHTTP_METHOD_HAS_BODY 0x0001
+
/** a request object can represent either a request or a reply */
enum evhttp_request_kind { EVHTTP_REQUEST, EVHTTP_RESPONSE };
@@ -684,6 +721,15 @@
int evhttp_request_is_owned(struct evhttp_request *req);
/**
+ * Sets extended method cmp callback for this http connection.
+ *
+ * @see evhttp_set_extended_method_cmp
+ */
+EVENT2_EXPORT_SYMBOL
+void evhttp_connection_set_extended_method_cmp(struct evhttp_connection *evcon,
+ int (*cmp)(struct evhttp_extended_method *));
+
+/**
* Returns the connection object associated with the request or NULL
*
* The user needs to either free the request explicitly or call
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment