Created
November 27, 2016 07:33
-
-
Save kiler129/9502c558a3268c30602f913898a495ce to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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