summaryrefslogtreecommitdiffstats
path: root/meta-linaro/recipes-extra/libevent/files/libevent-1.4.14.fb-changes.diff
diff options
context:
space:
mode:
Diffstat (limited to 'meta-linaro/recipes-extra/libevent/files/libevent-1.4.14.fb-changes.diff')
-rw-r--r--meta-linaro/recipes-extra/libevent/files/libevent-1.4.14.fb-changes.diff611
1 files changed, 611 insertions, 0 deletions
diff --git a/meta-linaro/recipes-extra/libevent/files/libevent-1.4.14.fb-changes.diff b/meta-linaro/recipes-extra/libevent/files/libevent-1.4.14.fb-changes.diff
new file mode 100644
index 0000000..0f29aac
--- /dev/null
+++ b/meta-linaro/recipes-extra/libevent/files/libevent-1.4.14.fb-changes.diff
@@ -0,0 +1,611 @@
1diff --git a/event.c b/event.c
2index 74ba5c4..06984b8 100644
3--- a/event.c
4+++ b/event.c
5@@ -138,10 +138,12 @@ detect_monotonic(void)
6 static int
7 gettime(struct event_base *base, struct timeval *tp)
8 {
9+/*
10 if (base->tv_cache.tv_sec) {
11 *tp = base->tv_cache;
12 return (0);
13 }
14+*/
15
16 #if defined(HAVE_CLOCK_GETTIME) && defined(CLOCK_MONOTONIC)
17 if (use_monotonic) {
18@@ -481,7 +483,7 @@ event_base_loop(struct event_base *base, int flags)
19 int res, done;
20
21 /* clear time cache */
22- base->tv_cache.tv_sec = 0;
23+ /* base->tv_cache.tv_sec = 0; */
24
25 if (base->sig.ev_signal_added)
26 evsignal_base = base;
27@@ -533,13 +535,13 @@ event_base_loop(struct event_base *base, int flags)
28 gettime(base, &base->event_tv);
29
30 /* clear time cache */
31- base->tv_cache.tv_sec = 0;
32+ /* base->tv_cache.tv_sec = 0; */
33
34 res = evsel->dispatch(base, evbase, tv_p);
35
36 if (res == -1)
37 return (-1);
38- gettime(base, &base->tv_cache);
39+ /* gettime(base, &base->tv_cache); */
40
41 timeout_process(base);
42
43@@ -552,7 +554,7 @@ event_base_loop(struct event_base *base, int flags)
44 }
45
46 /* clear time cache */
47- base->tv_cache.tv_sec = 0;
48+ /* base->tv_cache.tv_sec = 0; */
49
50 event_debug(("%s: asked to terminate loop.", __func__));
51 return (0);
52diff --git a/evhttp.h b/evhttp.h
53index 7ddf720..13c8b79 100644
54--- a/evhttp.h
55+++ b/evhttp.h
56@@ -81,12 +81,50 @@ struct evhttp *evhttp_new(struct event_base *base);
57 * @param http a pointer to an evhttp object
58 * @param address a string containing the IP address to listen(2) on
59 * @param port the port number to listen on
60- * @return a newly allocated evhttp struct
61+ * @return 0 on success, -1 on error
62 * @see evhttp_free()
63 */
64 int evhttp_bind_socket(struct evhttp *http, const char *address, u_short port);
65
66 /**
67+ * Binds an HTTP server on the specified address and port, using backlog.
68+ *
69+ * Can be called multiple times to bind the same http server
70+ * to multiple different ports.
71+ *
72+ * @param http a pointer to an evhttp object
73+ * @param address a string containing the IP address to listen(2) on
74+ * @param port the port number to listen on
75+ * @param backlog the backlog value for listen(2)
76+ * @return 0 on success, -1 on error
77+ * @see evhttp_free()
78+ */
79+int evhttp_bind_socket_backlog(struct evhttp *http, const char *address, u_short port, int backlog);
80+
81+/**
82+ * Like evhttp_bind_socket(), but returns the socket file descriptor.
83+ *
84+ * @param http a pointer to an evhttp object
85+ * @param address a string containing the IP address to listen(2) on
86+ * @param port the port number to listen on
87+ * @return Socket file descriptor on success, -1 on failure
88+ * @see evhttp_bind_socket()
89+ */
90+int evhttp_bind_socket_with_fd(struct evhttp *http, const char *address, u_short port);
91+
92+/**
93+ * Like evhttp_bind_socket(), but returns the socket file descriptor.
94+ *
95+ * @param http a pointer to an evhttp object
96+ * @param address a string containing the IP address to listen(2) on
97+ * @param port the port number to listen on
98+ * @param backlog the backlog value for listen(2)
99+ * @return Socket file descriptor on success, -1 on failure
100+ * @see evhttp_bind_socket()
101+ */
102+int evhttp_bind_socket_backlog_fd(struct evhttp *http, const char *address, u_short port, int backlog);
103+
104+/**
105 * Makes an HTTP server accept connections on the specified socket
106 *
107 * This may be useful to create a socket and then fork multiple instances
108@@ -105,6 +143,21 @@ int evhttp_bind_socket(struct evhttp *http, const char *address, u_short port);
109 int evhttp_accept_socket(struct evhttp *http, int fd);
110
111 /**
112+ * Makes an HTTP server stop accepting connections on the specified socket
113+ *
114+ * This may be useful when a socket has been sent via file descriptor passing
115+ * and is no longer needed by the current process.
116+ *
117+ * This function does not close the socket.
118+ *
119+ * @param http a pointer to an evhttp object
120+ * @param fd a socket fd that is currently accepting connections
121+ * @return 0 on success, -1 on failure.
122+ * @see evhttp_accept_socket()
123+ */
124+int evhttp_del_accept_socket(struct evhttp *http, int fd);
125+
126+/**
127 * Free the previously created HTTP server.
128 *
129 * Works only if no requests are currently being served.
130@@ -134,6 +187,28 @@ void evhttp_set_gencb(struct evhttp *,
131 */
132 void evhttp_set_timeout(struct evhttp *, int timeout_in_secs);
133
134+/**
135+ * Limit the number of simultaneous connections via this http instance.
136+ *
137+ * @param http an evhttp object
138+ * @param nlimit the maximum number of connections, zero is unlimited
139+ */
140+int evhttp_set_connection_limit(struct evhttp *http, int nlimit);
141+
142+/**
143+ * Return the maximum number of connections allowed for this instance.
144+ *
145+ * @param http an evhttp object
146+ */
147+int evhttp_get_connection_limit(struct evhttp *http);
148+
149+/**
150+ * Return the number of connections in this instance.
151+ *
152+ * @param http an evhttp object
153+ */
154+int evhttp_get_connection_count(struct evhttp *http);
155+
156 /* Request/Response functionality */
157
158 /**
159@@ -157,6 +232,19 @@ void evhttp_send_error(struct evhttp_request *req, int error,
160 void evhttp_send_reply(struct evhttp_request *req, int code,
161 const char *reason, struct evbuffer *databuf);
162
163+/**
164+ * Send an HTML reply synchronously as much as possible by calling _begin().
165+ * Great for a worker thread to send the reply immediately without queuing up
166+ * events back to the loop. Call _end() to send the rest of the packet from
167+ * event loop.
168+ *
169+ * When _begin() returns needs to be fed into _end() as the 1st parameter
170+ * "nwritten".
171+ */
172+int evhttp_send_reply_sync_begin(struct evhttp_request *req, int code,
173+ const char *reason, struct evbuffer *databuf);
174+void evhttp_send_reply_sync_end(int nwritten, struct evhttp_request *req);
175+
176 /* Low-level response interface, for streaming/chunked replies */
177 void evhttp_send_reply_start(struct evhttp_request *, int, const char *);
178 void evhttp_send_reply_chunk(struct evhttp_request *, struct evbuffer *);
179@@ -210,6 +298,7 @@ struct {
180
181 enum evhttp_request_kind kind;
182 enum evhttp_cmd_type type;
183+ char *ext_method; /* webdav methods, for example */
184
185 char *uri; /* uri after HTTP request was parsed */
186
187@@ -224,6 +313,8 @@ struct {
188 int chunked:1, /* a chunked request */
189 userdone:1; /* the user has sent all data */
190
191+ int referenced;
192+
193 struct evbuffer *output_buffer; /* outgoing post or data */
194
195 /* Callback */
196diff --git a/http-internal.h b/http-internal.h
197index 9cd03cd..3f60f54 100644
198--- a/http-internal.h
199+++ b/http-internal.h
200@@ -116,6 +116,9 @@ struct evhttp {
201 TAILQ_HEAD(httpcbq, evhttp_cb) callbacks;
202 struct evconq connections;
203
204+ int connection_count;
205+ int connection_limit;
206+
207 int timeout;
208
209 void (*gencb)(struct evhttp_request *req, void *);
210diff --git a/http.c b/http.c
211index efcec40..e10d114 100644
212--- a/http.c
213+++ b/http.c
214@@ -219,6 +219,13 @@ static int evhttp_decode_uri_internal(const char *uri, size_t length,
215 void evhttp_read(int, short, void *);
216 void evhttp_write(int, short, void *);
217
218+
219+void evhttp_server_drop_connection(struct evhttp_connection *evcon);
220+void evhttp_server_add_connection(struct evhttp *http,
221+ struct evhttp_connection *evcon);
222+void evhttp_pause(struct evhttp *http);
223+void evhttp_resume(struct evhttp *http);
224+
225 #ifndef HAVE_STRSEP
226 /* strsep replacement for platforms that lack it. Only works if
227 * del is one character long. */
228@@ -478,7 +485,6 @@ evhttp_make_header_response(struct evhttp_connection *evcon,
229 evhttp_add_header(req->output_headers,
230 "Connection", "keep-alive");
231
232- if (req->minor == 1 || is_keepalive) {
233 /*
234 * we need to add the content length if the
235 * user did not give it, this is required for
236@@ -488,7 +494,6 @@ evhttp_make_header_response(struct evhttp_connection *evcon,
237 req->output_headers,
238 (long)EVBUFFER_LENGTH(req->output_buffer));
239 }
240- }
241
242 /* Potentially add headers for unidentified content. */
243 if (EVBUFFER_LENGTH(req->output_buffer)) {
244@@ -687,14 +692,14 @@ void
245 evhttp_write(int fd, short what, void *arg)
246 {
247 struct evhttp_connection *evcon = arg;
248- int n;
249
250 if (what == EV_TIMEOUT) {
251 evhttp_connection_fail(evcon, EVCON_HTTP_TIMEOUT);
252 return;
253 }
254
255- n = evbuffer_write(evcon->output_buffer, fd);
256+ if (EVBUFFER_LENGTH(evcon->output_buffer) != 0) {
257+ int n = evbuffer_write(evcon->output_buffer, fd);
258 if (n == -1) {
259 event_debug(("%s: evbuffer_write", __func__));
260 evhttp_connection_fail(evcon, EVCON_HTTP_EOF);
261@@ -706,6 +711,7 @@ evhttp_write(int fd, short what, void *arg)
262 evhttp_connection_fail(evcon, EVCON_HTTP_EOF);
263 return;
264 }
265+ }
266
267 if (EVBUFFER_LENGTH(evcon->output_buffer) != 0) {
268 evhttp_add_event(&evcon->ev,
269@@ -1012,11 +1018,9 @@ evhttp_connection_free(struct evhttp_connection *evcon)
270 TAILQ_REMOVE(&evcon->requests, req, next);
271 evhttp_request_free(req);
272 }
273-
274- if (evcon->http_server != NULL) {
275- struct evhttp *http = evcon->http_server;
276- TAILQ_REMOVE(&http->connections, evcon, next);
277- }
278+
279+ if (evcon->http_server != NULL)
280+ evhttp_server_drop_connection(evcon);
281
282 if (event_initialized(&evcon->close_ev))
283 event_del(&evcon->close_ev);
284@@ -1101,10 +1105,16 @@ evhttp_connection_reset(struct evhttp_connection *evcon)
285 }
286 evcon->state = EVCON_DISCONNECTED;
287
288- evbuffer_drain(evcon->input_buffer,
289- EVBUFFER_LENGTH(evcon->input_buffer));
290- evbuffer_drain(evcon->output_buffer,
291- EVBUFFER_LENGTH(evcon->output_buffer));
292+ /*
293+ * These can grow quite large if processing a large photo or video
294+ * upload/download. Instead of keeping the buffers around, just
295+ * free and allocate new.
296+ */
297+ evbuffer_free(evcon->input_buffer);
298+ evcon->input_buffer = evbuffer_new();
299+
300+ evbuffer_free(evcon->output_buffer);
301+ evcon->output_buffer = evbuffer_new();
302 }
303
304 static void
305@@ -1278,19 +1288,52 @@ evhttp_parse_request_line(struct evhttp_request *req, char *line)
306 if (line == NULL)
307 return (-1);
308 uri = strsep(&line, " ");
309- if (line == NULL)
310- return (-1);
311+ if (line == NULL) {
312+ version = "HTTP/1.0";
313+ } else {
314 version = strsep(&line, " ");
315 if (line != NULL)
316 return (-1);
317+ }
318
319 /* First line */
320+ req->ext_method = NULL;
321 if (strcmp(method, "GET") == 0) {
322 req->type = EVHTTP_REQ_GET;
323 } else if (strcmp(method, "POST") == 0) {
324 req->type = EVHTTP_REQ_POST;
325 } else if (strcmp(method, "HEAD") == 0) {
326 req->type = EVHTTP_REQ_HEAD;
327+ } else if (strcmp(method, "OPTIONS") == 0) {
328+ req->type = EVHTTP_REQ_POST;
329+ req->ext_method = "OPTIONS";
330+ } else if (strcmp(method, "REPORT") == 0) {
331+ req->type = EVHTTP_REQ_POST;
332+ req->ext_method = "REPORT";
333+ } else if (strcmp(method, "PROPFIND") == 0) {
334+ req->type = EVHTTP_REQ_POST;
335+ req->ext_method = "PROPFIND";
336+ } else if (strcmp(method, "PROPPATH") == 0) {
337+ req->type = EVHTTP_REQ_POST;
338+ req->ext_method = "PROPPATH";
339+ } else if (strcmp(method, "MKCOL") == 0) {
340+ req->type = EVHTTP_REQ_POST;
341+ req->ext_method = "MKCOL";
342+ } else if (strcmp(method, "MKCALENDAR") == 0) {
343+ req->type = EVHTTP_REQ_POST;
344+ req->ext_method = "MKCALENDAR";
345+ } else if (strcmp(method, "PUT") == 0) {
346+ req->type = EVHTTP_REQ_POST;
347+ req->ext_method = "PUT";
348+ } else if (strcmp(method, "DELETE") == 0) {
349+ req->type = EVHTTP_REQ_POST;
350+ req->ext_method = "DELETE";
351+ } else if (strcmp(method, "LOCK") == 0) {
352+ req->type = EVHTTP_REQ_POST;
353+ req->ext_method = "LOCK";
354+ } else if (strcmp(method, "UNLOCK") == 0) {
355+ req->type = EVHTTP_REQ_POST;
356+ req->ext_method = "UNLOCK";
357 } else {
358 event_debug(("%s: bad method %s on request %p from %s",
359 __func__, method, req, req->remote_host));
360@@ -1963,10 +2006,44 @@ evhttp_send_reply(struct evhttp_request *req, int code, const char *reason,
361 evhttp_send(req, databuf);
362 }
363
364+int
365+evhttp_send_reply_sync_begin(struct evhttp_request *req, int code,
366+ const char *reason, struct evbuffer *databuf) {
367+ evhttp_response_code(req, code, reason);
368+ struct evhttp_connection *evcon = req->evcon;
369+
370+ assert(TAILQ_FIRST(&evcon->requests) == req);
371+
372+ /* xxx: not sure if we really should expose the data buffer this way */
373+ if (databuf != NULL)
374+ evbuffer_add_buffer(req->output_buffer, databuf);
375+
376+ /* Adds headers to the response */
377+ evhttp_make_header(evcon, req);
378+
379+ return evbuffer_write(evcon->output_buffer, evcon->fd);
380+}
381+
382+void
383+evhttp_send_reply_sync_end(int nwritten, struct evhttp_request *req) {
384+ struct evhttp_connection *evcon = req->evcon;
385+
386+ if (nwritten <= 0) {
387+ evhttp_connection_fail(evcon, EVCON_HTTP_EOF);
388+ } else if (EVBUFFER_LENGTH(evcon->output_buffer) == 0) {
389+ evhttp_send_done(evcon, NULL);
390+ } else {
391+ evhttp_write_buffer(evcon, evhttp_send_done, NULL);
392+ }
393+}
394+
395+
396 void
397 evhttp_send_reply_start(struct evhttp_request *req, int code,
398 const char *reason)
399 {
400+ req->referenced = 1;
401+
402 evhttp_response_code(req, code, reason);
403 if (req->major == 1 && req->minor == 1) {
404 /* use chunked encoding for HTTP/1.1 */
405@@ -1986,6 +2063,8 @@ evhttp_send_reply_chunk(struct evhttp_request *req, struct evbuffer *databuf)
406 if (evcon == NULL)
407 return;
408
409+ if (req->referenced < 0) return;
410+
411 if (req->chunked) {
412 evbuffer_add_printf(evcon->output_buffer, "%x\r\n",
413 (unsigned)EVBUFFER_LENGTH(databuf));
414@@ -2007,7 +2086,14 @@ evhttp_send_reply_end(struct evhttp_request *req)
415 return;
416 }
417
418- /* we expect no more calls form the user on this request */
419+ if (req->referenced < 0) {
420+ req->referenced = 0;
421+ evhttp_request_free(req);
422+ return;
423+ }
424+ req->referenced = 0;
425+
426+ /* we expect no more calls form the user on this request */
427 req->userdone = 1;
428
429 if (req->chunked) {
430@@ -2293,7 +2379,8 @@ accept_socket(int fd, short what, void *arg)
431 }
432
433 int
434-evhttp_bind_socket(struct evhttp *http, const char *address, u_short port)
435+evhttp_bind_socket_backlog_fd(struct evhttp *http, const char *address,
436+ u_short port, int backlog)
437 {
438 int fd;
439 int res;
440@@ -2301,7 +2388,7 @@ evhttp_bind_socket(struct evhttp *http, const char *address, u_short port)
441 if ((fd = bind_socket(address, port, 1 /*reuse*/)) == -1)
442 return (-1);
443
444- if (listen(fd, 128) == -1) {
445+ if (listen(fd, backlog) == -1) {
446 event_warn("%s: listen", __func__);
447 EVUTIL_CLOSESOCKET(fd);
448 return (-1);
449@@ -2309,13 +2396,42 @@ evhttp_bind_socket(struct evhttp *http, const char *address, u_short port)
450
451 res = evhttp_accept_socket(http, fd);
452
453- if (res != -1)
454+ if (res != -1) {
455 event_debug(("Bound to port %d - Awaiting connections ... ",
456 port));
457+ return (fd);
458+ }
459
460 return (res);
461 }
462
463+static int
464+mask_fd(int fd)
465+{
466+ return fd > 0 ? 0 : fd;
467+}
468+
469+int
470+evhttp_bind_socket(struct evhttp *http, const char *address, u_short port)
471+{
472+ return mask_fd(evhttp_bind_socket_backlog_fd(http, address, port, 128));
473+}
474+
475+int
476+evhttp_bind_socket_with_fd(struct evhttp *http, const char *address,
477+ u_short port)
478+{
479+ return evhttp_bind_socket_backlog_fd(http, address, port, 128);
480+}
481+
482+int
483+evhttp_bind_socket_backlog(struct evhttp *http, const char *address,
484+ u_short port, int backlog)
485+{
486+ return mask_fd(
487+ evhttp_bind_socket_backlog_fd(http, address, port, backlog));
488+}
489+
490 int
491 evhttp_accept_socket(struct evhttp *http, int fd)
492 {
493@@ -2345,6 +2461,25 @@ evhttp_accept_socket(struct evhttp *http, int fd)
494 return (0);
495 }
496
497+int
498+evhttp_del_accept_socket(struct evhttp *http, int fd)
499+{
500+ struct evhttp_bound_socket *bound;
501+ TAILQ_FOREACH(bound, &http->sockets, next) {
502+ if (bound->bind_ev.ev_fd == fd)
503+ break;
504+ }
505+
506+ if (bound == NULL)
507+ return (-1);
508+
509+ TAILQ_REMOVE(&http->sockets, bound, next);
510+ event_del(&bound->bind_ev);
511+ free(bound);
512+
513+ return (0);
514+}
515+
516 static struct evhttp*
517 evhttp_new_object(void)
518 {
519@@ -2527,6 +2662,11 @@ evhttp_request_new(void (*cb)(struct evhttp_request *, void *), void *arg)
520 void
521 evhttp_request_free(struct evhttp_request *req)
522 {
523+ if (req->referenced) {
524+ req->referenced = -1;
525+ return;
526+ }
527+
528 if (req->remote_host != NULL)
529 free(req->remote_host);
530 if (req->uri != NULL)
531@@ -2657,13 +2797,78 @@ evhttp_get_request(struct evhttp *http, int fd,
532 * if we want to accept more than one request on a connection,
533 * we need to know which http server it belongs to.
534 */
535- evcon->http_server = http;
536- TAILQ_INSERT_TAIL(&http->connections, evcon, next);
537+
538+ evhttp_server_add_connection(http, evcon);
539
540 if (evhttp_associate_new_request_with_connection(evcon) == -1)
541 evhttp_connection_free(evcon);
542 }
543
544+void
545+evhttp_pause(struct evhttp *http)
546+{
547+ struct evhttp_bound_socket *bound;
548+ TAILQ_FOREACH(bound, &http->sockets, next) {
549+ event_del(&bound->bind_ev);
550+ }
551+}
552+
553+void
554+evhttp_resume(struct evhttp *http)
555+{
556+ struct evhttp_bound_socket *bound;
557+ TAILQ_FOREACH(bound, &http->sockets, next) {
558+ event_add(&bound->bind_ev, 0);
559+ }
560+}
561+
562+int
563+evhttp_get_connection_limit(struct evhttp *http)
564+{
565+ return http->connection_limit;
566+}
567+
568+int
569+evhttp_set_connection_limit(struct evhttp *http, int nlimit)
570+{
571+ int olimit = http->connection_limit;
572+ http->connection_limit = nlimit;
573+ return olimit;
574+}
575+
576+int
577+evhttp_get_connection_count(struct evhttp *http)
578+{
579+ return http != NULL ? http->connection_count : 0;
580+}
581+
582+void
583+evhttp_server_add_connection(struct evhttp *http,
584+ struct evhttp_connection *evcon)
585+{
586+ evcon->http_server = http;
587+ TAILQ_INSERT_TAIL(&http->connections, evcon, next);
588+
589+ http->connection_count++;
590+ if (http->connection_limit > 0
591+ && http->connection_count >= http->connection_limit)
592+ {
593+ evhttp_pause(http);
594+ }
595+}
596+
597+void
598+evhttp_server_drop_connection(struct evhttp_connection *evcon)
599+{
600+ struct evhttp *http = evcon->http_server;
601+ TAILQ_REMOVE(&http->connections, evcon, next);
602+ http->connection_count--;
603+ if (http->connection_limit > 0
604+ && http->connection_count < http->connection_limit)
605+ {
606+ evhttp_resume(http);
607+ }
608+}
609
610 /*
611 * Network helper functions that we do not want to export to the rest of