OLD | NEW |
| (Empty) |
1 /* | |
2 * Copyright (c) 2002-2006 Niels Provos <provos@citi.umich.edu> | |
3 * All rights reserved. | |
4 * | |
5 * Redistribution and use in source and binary forms, with or without | |
6 * modification, are permitted provided that the following conditions | |
7 * are met: | |
8 * 1. Redistributions of source code must retain the above copyright | |
9 * notice, this list of conditions and the following disclaimer. | |
10 * 2. Redistributions in binary form must reproduce the above copyright | |
11 * notice, this list of conditions and the following disclaimer in the | |
12 * documentation and/or other materials provided with the distribution. | |
13 * 3. The name of the author may not be used to endorse or promote products | |
14 * derived from this software without specific prior written permission. | |
15 * | |
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR | |
17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES | |
18 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. | |
19 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, | |
20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT | |
21 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | |
22 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | |
23 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | |
25 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
26 */ | |
27 | |
28 #ifdef HAVE_CONFIG_H | |
29 #include "config.h" | |
30 #endif | |
31 | |
32 #ifdef HAVE_SYS_PARAM_H | |
33 #include <sys/param.h> | |
34 #endif | |
35 #ifdef HAVE_SYS_TYPES_H | |
36 #include <sys/types.h> | |
37 #endif | |
38 | |
39 #ifdef HAVE_SYS_TIME_H | |
40 #include <sys/time.h> | |
41 #endif | |
42 #ifdef HAVE_SYS_IOCCOM_H | |
43 #include <sys/ioccom.h> | |
44 #endif | |
45 | |
46 #ifndef WIN32 | |
47 #include <sys/resource.h> | |
48 #include <sys/socket.h> | |
49 #include <sys/stat.h> | |
50 #include <sys/wait.h> | |
51 #endif | |
52 | |
53 #include <sys/queue.h> | |
54 | |
55 #ifndef WIN32 | |
56 #include <netinet/in.h> | |
57 #include <netdb.h> | |
58 #endif | |
59 | |
60 #ifdef WIN32 | |
61 #include <winsock2.h> | |
62 #endif | |
63 | |
64 #include <assert.h> | |
65 #include <ctype.h> | |
66 #include <errno.h> | |
67 #include <stdio.h> | |
68 #include <stdlib.h> | |
69 #include <string.h> | |
70 #ifndef WIN32 | |
71 #include <syslog.h> | |
72 #endif | |
73 #include <signal.h> | |
74 #include <time.h> | |
75 #ifdef HAVE_UNISTD_H | |
76 #include <unistd.h> | |
77 #endif | |
78 #ifdef HAVE_FCNTL_H | |
79 #include <fcntl.h> | |
80 #endif | |
81 | |
82 #undef timeout_pending | |
83 #undef timeout_initialized | |
84 | |
85 #include "strlcpy-internal.h" | |
86 #include "event.h" | |
87 #include "evhttp.h" | |
88 #include "evutil.h" | |
89 #include "log.h" | |
90 #include "http-internal.h" | |
91 | |
92 #ifdef WIN32 | |
93 #define strcasecmp _stricmp | |
94 #define strncasecmp _strnicmp | |
95 #define strdup _strdup | |
96 #endif | |
97 | |
98 #ifndef HAVE_GETNAMEINFO | |
99 #define NI_MAXSERV 32 | |
100 #define NI_MAXHOST 1025 | |
101 | |
102 #ifndef NI_NUMERICHOST | |
103 #define NI_NUMERICHOST 1 | |
104 #endif | |
105 | |
106 #ifndef NI_NUMERICSERV | |
107 #define NI_NUMERICSERV 2 | |
108 #endif | |
109 | |
110 static int | |
111 fake_getnameinfo(const struct sockaddr *sa, size_t salen, char *host, | |
112 size_t hostlen, char *serv, size_t servlen, int flags) | |
113 { | |
114 struct sockaddr_in *sin = (struct sockaddr_in *)sa; | |
115 | |
116 if (serv != NULL) { | |
117 char tmpserv[16]; | |
118 evutil_snprintf(tmpserv, sizeof(tmpserv), | |
119 "%d", ntohs(sin->sin_port)); | |
120 if (strlcpy(serv, tmpserv, servlen) >= servlen) | |
121 return (-1); | |
122 } | |
123 | |
124 if (host != NULL) { | |
125 if (flags & NI_NUMERICHOST) { | |
126 if (strlcpy(host, inet_ntoa(sin->sin_addr), | |
127 hostlen) >= hostlen) | |
128 return (-1); | |
129 else | |
130 return (0); | |
131 } else { | |
132 struct hostent *hp; | |
133 hp = gethostbyaddr((char *)&sin->sin_addr, | |
134 sizeof(struct in_addr), AF_INET); | |
135 if (hp == NULL) | |
136 return (-2); | |
137 | |
138 if (strlcpy(host, hp->h_name, hostlen) >= hostlen) | |
139 return (-1); | |
140 else | |
141 return (0); | |
142 } | |
143 } | |
144 return (0); | |
145 } | |
146 | |
147 #endif | |
148 | |
149 #ifndef HAVE_GETADDRINFO | |
150 /* Apparently msvc2010 does have an addrinfo definition visible here */ | |
151 #if !defined(WIN32) || !defined(_MSC_VER) || (_MSC_VER < 1600) | |
152 struct addrinfo { | |
153 int ai_family; | |
154 int ai_socktype; | |
155 int ai_protocol; | |
156 size_t ai_addrlen; | |
157 struct sockaddr *ai_addr; | |
158 struct addrinfo *ai_next; | |
159 }; | |
160 #endif | |
161 static int | |
162 fake_getaddrinfo(const char *hostname, struct addrinfo *ai) | |
163 { | |
164 struct hostent *he = NULL; | |
165 struct sockaddr_in *sa; | |
166 if (hostname) { | |
167 he = gethostbyname(hostname); | |
168 if (!he) | |
169 return (-1); | |
170 } | |
171 ai->ai_family = he ? he->h_addrtype : AF_INET; | |
172 ai->ai_socktype = SOCK_STREAM; | |
173 ai->ai_protocol = 0; | |
174 ai->ai_addrlen = sizeof(struct sockaddr_in); | |
175 if (NULL == (ai->ai_addr = malloc(ai->ai_addrlen))) | |
176 return (-1); | |
177 sa = (struct sockaddr_in*)ai->ai_addr; | |
178 memset(sa, 0, ai->ai_addrlen); | |
179 if (he) { | |
180 sa->sin_family = he->h_addrtype; | |
181 memcpy(&sa->sin_addr, he->h_addr_list[0], he->h_length); | |
182 } else { | |
183 sa->sin_family = AF_INET; | |
184 sa->sin_addr.s_addr = INADDR_ANY; | |
185 } | |
186 ai->ai_next = NULL; | |
187 return (0); | |
188 } | |
189 static void | |
190 fake_freeaddrinfo(struct addrinfo *ai) | |
191 { | |
192 free(ai->ai_addr); | |
193 } | |
194 #endif | |
195 | |
196 #ifndef MIN | |
197 #define MIN(a,b) (((a)<(b))?(a):(b)) | |
198 #endif | |
199 | |
200 /* wrapper for setting the base from the http server */ | |
201 #define EVHTTP_BASE_SET(x, y) do { \ | |
202 if ((x)->base != NULL) event_base_set((x)->base, y); \ | |
203 } while (0) | |
204 | |
205 extern int debug; | |
206 | |
207 static int socket_connect(int fd, const char *address, unsigned short port); | |
208 static int bind_socket_ai(struct addrinfo *, int reuse); | |
209 static int bind_socket(const char *, u_short, int reuse); | |
210 static void name_from_addr(struct sockaddr *, socklen_t, char **, char **); | |
211 static int evhttp_associate_new_request_with_connection( | |
212 struct evhttp_connection *evcon); | |
213 static void evhttp_connection_start_detectclose( | |
214 struct evhttp_connection *evcon); | |
215 static void evhttp_connection_stop_detectclose( | |
216 struct evhttp_connection *evcon); | |
217 static void evhttp_request_dispatch(struct evhttp_connection* evcon); | |
218 static void evhttp_read_firstline(struct evhttp_connection *evcon, | |
219 struct evhttp_request *req); | |
220 static void evhttp_read_header(struct evhttp_connection *evcon, | |
221 struct evhttp_request *req); | |
222 static int evhttp_add_header_internal(struct evkeyvalq *headers, | |
223 const char *key, const char *value); | |
224 static int evhttp_decode_uri_internal(const char *uri, size_t length, | |
225 char *ret, int always_decode_plus); | |
226 | |
227 void evhttp_read(int, short, void *); | |
228 void evhttp_write(int, short, void *); | |
229 | |
230 #ifndef HAVE_STRSEP | |
231 /* strsep replacement for platforms that lack it. Only works if | |
232 * del is one character long. */ | |
233 static char * | |
234 strsep(char **s, const char *del) | |
235 { | |
236 char *d, *tok; | |
237 assert(strlen(del) == 1); | |
238 if (!s || !*s) | |
239 return NULL; | |
240 tok = *s; | |
241 d = strstr(tok, del); | |
242 if (d) { | |
243 *d = '\0'; | |
244 *s = d + 1; | |
245 } else | |
246 *s = NULL; | |
247 return tok; | |
248 } | |
249 #endif | |
250 | |
251 static const char * | |
252 html_replace(char ch, char *buf) | |
253 { | |
254 switch (ch) { | |
255 case '<': | |
256 return "<"; | |
257 case '>': | |
258 return ">"; | |
259 case '"': | |
260 return """; | |
261 case '\'': | |
262 return "'"; | |
263 case '&': | |
264 return "&"; | |
265 default: | |
266 break; | |
267 } | |
268 | |
269 /* Echo the character back */ | |
270 buf[0] = ch; | |
271 buf[1] = '\0'; | |
272 | |
273 return buf; | |
274 } | |
275 | |
276 /* | |
277 * Replaces <, >, ", ' and & with <, >, ", | |
278 * ' and & correspondingly. | |
279 * | |
280 * The returned string needs to be freed by the caller. | |
281 */ | |
282 | |
283 char * | |
284 evhttp_htmlescape(const char *html) | |
285 { | |
286 int i, new_size = 0, old_size = strlen(html); | |
287 char *escaped_html, *p; | |
288 char scratch_space[2]; | |
289 | |
290 for (i = 0; i < old_size; ++i) | |
291 new_size += strlen(html_replace(html[i], scratch_space)); | |
292 | |
293 p = escaped_html = malloc(new_size + 1); | |
294 if (escaped_html == NULL) | |
295 event_err(1, "%s: malloc(%d)", __func__, new_size + 1); | |
296 for (i = 0; i < old_size; ++i) { | |
297 const char *replaced = html_replace(html[i], scratch_space); | |
298 /* this is length checked */ | |
299 strcpy(p, replaced); | |
300 p += strlen(replaced); | |
301 } | |
302 | |
303 *p = '\0'; | |
304 | |
305 return (escaped_html); | |
306 } | |
307 | |
308 static const char * | |
309 evhttp_method(enum evhttp_cmd_type type) | |
310 { | |
311 const char *method; | |
312 | |
313 switch (type) { | |
314 case EVHTTP_REQ_GET: | |
315 method = "GET"; | |
316 break; | |
317 case EVHTTP_REQ_POST: | |
318 method = "POST"; | |
319 break; | |
320 case EVHTTP_REQ_HEAD: | |
321 method = "HEAD"; | |
322 break; | |
323 default: | |
324 method = NULL; | |
325 break; | |
326 } | |
327 | |
328 return (method); | |
329 } | |
330 | |
331 static void | |
332 evhttp_add_event(struct event *ev, int timeout, int default_timeout) | |
333 { | |
334 if (timeout != 0) { | |
335 struct timeval tv; | |
336 | |
337 evutil_timerclear(&tv); | |
338 tv.tv_sec = timeout != -1 ? timeout : default_timeout; | |
339 event_add(ev, &tv); | |
340 } else { | |
341 event_add(ev, NULL); | |
342 } | |
343 } | |
344 | |
345 void | |
346 evhttp_write_buffer(struct evhttp_connection *evcon, | |
347 void (*cb)(struct evhttp_connection *, void *), void *arg) | |
348 { | |
349 event_debug(("%s: preparing to write buffer\n", __func__)); | |
350 | |
351 /* Set call back */ | |
352 evcon->cb = cb; | |
353 evcon->cb_arg = arg; | |
354 | |
355 /* check if the event is already pending */ | |
356 if (event_pending(&evcon->ev, EV_WRITE|EV_TIMEOUT, NULL)) | |
357 event_del(&evcon->ev); | |
358 | |
359 event_set(&evcon->ev, evcon->fd, EV_WRITE, evhttp_write, evcon); | |
360 EVHTTP_BASE_SET(evcon, &evcon->ev); | |
361 evhttp_add_event(&evcon->ev, evcon->timeout, HTTP_WRITE_TIMEOUT); | |
362 } | |
363 | |
364 static int | |
365 evhttp_connected(struct evhttp_connection *evcon) | |
366 { | |
367 switch (evcon->state) { | |
368 case EVCON_DISCONNECTED: | |
369 case EVCON_CONNECTING: | |
370 return (0); | |
371 case EVCON_IDLE: | |
372 case EVCON_READING_FIRSTLINE: | |
373 case EVCON_READING_HEADERS: | |
374 case EVCON_READING_BODY: | |
375 case EVCON_READING_TRAILER: | |
376 case EVCON_WRITING: | |
377 default: | |
378 return (1); | |
379 } | |
380 } | |
381 | |
382 /* | |
383 * Create the headers needed for an HTTP request | |
384 */ | |
385 static void | |
386 evhttp_make_header_request(struct evhttp_connection *evcon, | |
387 struct evhttp_request *req) | |
388 { | |
389 const char *method; | |
390 | |
391 evhttp_remove_header(req->output_headers, "Proxy-Connection"); | |
392 | |
393 /* Generate request line */ | |
394 method = evhttp_method(req->type); | |
395 evbuffer_add_printf(evcon->output_buffer, "%s %s HTTP/%d.%d\r\n", | |
396 method, req->uri, req->major, req->minor); | |
397 | |
398 /* Add the content length on a post request if missing */ | |
399 if (req->type == EVHTTP_REQ_POST && | |
400 evhttp_find_header(req->output_headers, "Content-Length") == NULL){ | |
401 char size[22]; | |
402 evutil_snprintf(size, sizeof(size), "%ld", | |
403 (long)EVBUFFER_LENGTH(req->output_buffer)); | |
404 evhttp_add_header(req->output_headers, "Content-Length", size); | |
405 } | |
406 } | |
407 | |
408 static int | |
409 evhttp_is_connection_close(int flags, struct evkeyvalq* headers) | |
410 { | |
411 if (flags & EVHTTP_PROXY_REQUEST) { | |
412 /* proxy connection */ | |
413 const char *connection = evhttp_find_header(headers, "Proxy-Conn
ection"); | |
414 return (connection == NULL || strcasecmp(connection, "keep-alive
") != 0); | |
415 } else { | |
416 const char *connection = evhttp_find_header(headers, "Connection
"); | |
417 return (connection != NULL && strcasecmp(connection, "close") ==
0); | |
418 } | |
419 } | |
420 | |
421 static int | |
422 evhttp_is_connection_keepalive(struct evkeyvalq* headers) | |
423 { | |
424 const char *connection = evhttp_find_header(headers, "Connection"); | |
425 return (connection != NULL | |
426 && strncasecmp(connection, "keep-alive", 10) == 0); | |
427 } | |
428 | |
429 static void | |
430 evhttp_maybe_add_date_header(struct evkeyvalq *headers) | |
431 { | |
432 if (evhttp_find_header(headers, "Date") == NULL) { | |
433 char date[50]; | |
434 #ifndef WIN32 | |
435 struct tm cur; | |
436 #endif | |
437 struct tm *cur_p; | |
438 time_t t = time(NULL); | |
439 #ifdef WIN32 | |
440 cur_p = gmtime(&t); | |
441 #else | |
442 gmtime_r(&t, &cur); | |
443 cur_p = &cur; | |
444 #endif | |
445 if (strftime(date, sizeof(date), | |
446 "%a, %d %b %Y %H:%M:%S GMT", cur_p) != 0) { | |
447 evhttp_add_header(headers, "Date", date); | |
448 } | |
449 } | |
450 } | |
451 | |
452 static void | |
453 evhttp_maybe_add_content_length_header(struct evkeyvalq *headers, | |
454 long content_length) | |
455 { | |
456 if (evhttp_find_header(headers, "Transfer-Encoding") == NULL && | |
457 evhttp_find_header(headers, "Content-Length") == NULL) { | |
458 char len[22]; | |
459 evutil_snprintf(len, sizeof(len), "%ld", content_length); | |
460 evhttp_add_header(headers, "Content-Length", len); | |
461 } | |
462 } | |
463 | |
464 /* | |
465 * Create the headers needed for an HTTP reply | |
466 */ | |
467 | |
468 static void | |
469 evhttp_make_header_response(struct evhttp_connection *evcon, | |
470 struct evhttp_request *req) | |
471 { | |
472 int is_keepalive = evhttp_is_connection_keepalive(req->input_headers); | |
473 evbuffer_add_printf(evcon->output_buffer, "HTTP/%d.%d %d %s\r\n", | |
474 req->major, req->minor, req->response_code, | |
475 req->response_code_line); | |
476 | |
477 if (req->major == 1) { | |
478 if (req->minor == 1) | |
479 evhttp_maybe_add_date_header(req->output_headers); | |
480 | |
481 /* | |
482 * if the protocol is 1.0; and the connection was keep-alive | |
483 * we need to add a keep-alive header, too. | |
484 */ | |
485 if (req->minor == 0 && is_keepalive) | |
486 evhttp_add_header(req->output_headers, | |
487 "Connection", "keep-alive"); | |
488 | |
489 if (req->minor == 1 || is_keepalive) { | |
490 /* | |
491 * we need to add the content length if the | |
492 * user did not give it, this is required for | |
493 * persistent connections to work. | |
494 */ | |
495 evhttp_maybe_add_content_length_header( | |
496 req->output_headers, | |
497 (long)EVBUFFER_LENGTH(req->output_buffer)); | |
498 } | |
499 } | |
500 | |
501 /* Potentially add headers for unidentified content. */ | |
502 if (EVBUFFER_LENGTH(req->output_buffer)) { | |
503 if (evhttp_find_header(req->output_headers, | |
504 "Content-Type") == NULL) { | |
505 evhttp_add_header(req->output_headers, | |
506 "Content-Type", "text/html; charset=ISO-8859-1"); | |
507 } | |
508 } | |
509 | |
510 /* if the request asked for a close, we send a close, too */ | |
511 if (evhttp_is_connection_close(req->flags, req->input_headers)) { | |
512 evhttp_remove_header(req->output_headers, "Connection"); | |
513 if (!(req->flags & EVHTTP_PROXY_REQUEST)) | |
514 evhttp_add_header(req->output_headers, "Connection", "close"
); | |
515 evhttp_remove_header(req->output_headers, "Proxy-Connection"); | |
516 } | |
517 } | |
518 | |
519 void | |
520 evhttp_make_header(struct evhttp_connection *evcon, struct evhttp_request *req) | |
521 { | |
522 struct evkeyval *header; | |
523 | |
524 /* | |
525 * Depending if this is a HTTP request or response, we might need to | |
526 * add some new headers or remove existing headers. | |
527 */ | |
528 if (req->kind == EVHTTP_REQUEST) { | |
529 evhttp_make_header_request(evcon, req); | |
530 } else { | |
531 evhttp_make_header_response(evcon, req); | |
532 } | |
533 | |
534 TAILQ_FOREACH(header, req->output_headers, next) { | |
535 evbuffer_add_printf(evcon->output_buffer, "%s: %s\r\n", | |
536 header->key, header->value); | |
537 } | |
538 evbuffer_add(evcon->output_buffer, "\r\n", 2); | |
539 | |
540 if (EVBUFFER_LENGTH(req->output_buffer) > 0) { | |
541 /* | |
542 * For a request, we add the POST data, for a reply, this | |
543 * is the regular data. | |
544 */ | |
545 evbuffer_add_buffer(evcon->output_buffer, req->output_buffer); | |
546 } | |
547 } | |
548 | |
549 /* Separated host, port and file from URI */ | |
550 | |
551 int | |
552 evhttp_hostportfile(char *url, char **phost, u_short *pport, char **pfile) | |
553 { | |
554 /* XXX not threadsafe. */ | |
555 static char host[1024]; | |
556 static char file[1024]; | |
557 char *p; | |
558 const char *p2; | |
559 int len; | |
560 u_short port; | |
561 | |
562 len = strlen(HTTP_PREFIX); | |
563 if (strncasecmp(url, HTTP_PREFIX, len)) | |
564 return (-1); | |
565 | |
566 url += len; | |
567 | |
568 /* We might overrun */ | |
569 if (strlcpy(host, url, sizeof (host)) >= sizeof(host)) | |
570 return (-1); | |
571 | |
572 p = strchr(host, '/'); | |
573 if (p != NULL) { | |
574 *p = '\0'; | |
575 p2 = p + 1; | |
576 } else | |
577 p2 = NULL; | |
578 | |
579 if (pfile != NULL) { | |
580 /* Generate request file */ | |
581 if (p2 == NULL) | |
582 p2 = ""; | |
583 evutil_snprintf(file, sizeof(file), "/%s", p2); | |
584 } | |
585 | |
586 p = strchr(host, ':'); | |
587 if (p != NULL) { | |
588 *p = '\0'; | |
589 port = atoi(p + 1); | |
590 | |
591 if (port == 0) | |
592 return (-1); | |
593 } else | |
594 port = HTTP_DEFAULTPORT; | |
595 | |
596 if (phost != NULL) | |
597 *phost = host; | |
598 if (pport != NULL) | |
599 *pport = port; | |
600 if (pfile != NULL) | |
601 *pfile = file; | |
602 | |
603 return (0); | |
604 } | |
605 | |
606 static int | |
607 evhttp_connection_incoming_fail(struct evhttp_request *req, | |
608 enum evhttp_connection_error error) | |
609 { | |
610 switch (error) { | |
611 case EVCON_HTTP_TIMEOUT: | |
612 case EVCON_HTTP_EOF: | |
613 /* | |
614 * these are cases in which we probably should just | |
615 * close the connection and not send a reply. this | |
616 * case may happen when a browser keeps a persistent | |
617 * connection open and we timeout on the read. when | |
618 * the request is still being used for sending, we | |
619 * need to disassociated it from the connection here. | |
620 */ | |
621 if (!req->userdone) { | |
622 /* remove it so that it will not be freed */ | |
623 TAILQ_REMOVE(&req->evcon->requests, req, next); | |
624 /* indicate that this request no longer has a | |
625 * connection object | |
626 */ | |
627 req->evcon = NULL; | |
628 } | |
629 return (-1); | |
630 case EVCON_HTTP_INVALID_HEADER: | |
631 default: /* xxx: probably should just error on default */ | |
632 /* the callback looks at the uri to determine errors */ | |
633 if (req->uri) { | |
634 free(req->uri); | |
635 req->uri = NULL; | |
636 } | |
637 | |
638 /* | |
639 * the callback needs to send a reply, once the reply has | |
640 * been send, the connection should get freed. | |
641 */ | |
642 (*req->cb)(req, req->cb_arg); | |
643 } | |
644 | |
645 return (0); | |
646 } | |
647 | |
648 void | |
649 evhttp_connection_fail(struct evhttp_connection *evcon, | |
650 enum evhttp_connection_error error) | |
651 { | |
652 struct evhttp_request* req = TAILQ_FIRST(&evcon->requests); | |
653 void (*cb)(struct evhttp_request *, void *); | |
654 void *cb_arg; | |
655 assert(req != NULL); | |
656 | |
657 if (evcon->flags & EVHTTP_CON_INCOMING) { | |
658 /* | |
659 * for incoming requests, there are two different | |
660 * failure cases. it's either a network level error | |
661 * or an http layer error. for problems on the network | |
662 * layer like timeouts we just drop the connections. | |
663 * For HTTP problems, we might have to send back a | |
664 * reply before the connection can be freed. | |
665 */ | |
666 if (evhttp_connection_incoming_fail(req, error) == -1) | |
667 evhttp_connection_free(evcon); | |
668 return; | |
669 } | |
670 | |
671 /* save the callback for later; the cb might free our object */ | |
672 cb = req->cb; | |
673 cb_arg = req->cb_arg; | |
674 | |
675 /* do not fail all requests; the next request is going to get | |
676 * send over a new connection. when a user cancels a request, | |
677 * all other pending requests should be processed as normal | |
678 */ | |
679 TAILQ_REMOVE(&evcon->requests, req, next); | |
680 evhttp_request_free(req); | |
681 | |
682 /* reset the connection */ | |
683 evhttp_connection_reset(evcon); | |
684 | |
685 /* We are trying the next request that was queued on us */ | |
686 if (TAILQ_FIRST(&evcon->requests) != NULL) | |
687 evhttp_connection_connect(evcon); | |
688 | |
689 /* inform the user */ | |
690 if (cb != NULL) | |
691 (*cb)(NULL, cb_arg); | |
692 } | |
693 | |
694 void | |
695 evhttp_write(int fd, short what, void *arg) | |
696 { | |
697 struct evhttp_connection *evcon = arg; | |
698 int n; | |
699 | |
700 if (what == EV_TIMEOUT) { | |
701 evhttp_connection_fail(evcon, EVCON_HTTP_TIMEOUT); | |
702 return; | |
703 } | |
704 | |
705 n = evbuffer_write(evcon->output_buffer, fd); | |
706 if (n == -1) { | |
707 event_debug(("%s: evbuffer_write", __func__)); | |
708 evhttp_connection_fail(evcon, EVCON_HTTP_EOF); | |
709 return; | |
710 } | |
711 | |
712 if (n == 0) { | |
713 event_debug(("%s: write nothing", __func__)); | |
714 evhttp_connection_fail(evcon, EVCON_HTTP_EOF); | |
715 return; | |
716 } | |
717 | |
718 if (EVBUFFER_LENGTH(evcon->output_buffer) != 0) { | |
719 evhttp_add_event(&evcon->ev, | |
720 evcon->timeout, HTTP_WRITE_TIMEOUT); | |
721 return; | |
722 } | |
723 | |
724 /* Activate our call back */ | |
725 if (evcon->cb != NULL) | |
726 (*evcon->cb)(evcon, evcon->cb_arg); | |
727 } | |
728 | |
729 /** | |
730 * Advance the connection state. | |
731 * - If this is an outgoing connection, we've just processed the response; | |
732 * idle or close the connection. | |
733 * - If this is an incoming connection, we've just processed the request; | |
734 * respond. | |
735 */ | |
736 static void | |
737 evhttp_connection_done(struct evhttp_connection *evcon) | |
738 { | |
739 struct evhttp_request *req = TAILQ_FIRST(&evcon->requests); | |
740 int con_outgoing = evcon->flags & EVHTTP_CON_OUTGOING; | |
741 | |
742 if (con_outgoing) { | |
743 /* idle or close the connection */ | |
744 int need_close; | |
745 TAILQ_REMOVE(&evcon->requests, req, next); | |
746 req->evcon = NULL; | |
747 | |
748 evcon->state = EVCON_IDLE; | |
749 | |
750 need_close = | |
751 evhttp_is_connection_close(req->flags, req->input_headers)|| | |
752 evhttp_is_connection_close(req->flags, req->output_headers); | |
753 | |
754 /* check if we got asked to close the connection */ | |
755 if (need_close) | |
756 evhttp_connection_reset(evcon); | |
757 | |
758 if (TAILQ_FIRST(&evcon->requests) != NULL) { | |
759 /* | |
760 * We have more requests; reset the connection | |
761 * and deal with the next request. | |
762 */ | |
763 if (!evhttp_connected(evcon)) | |
764 evhttp_connection_connect(evcon); | |
765 else | |
766 evhttp_request_dispatch(evcon); | |
767 } else if (!need_close) { | |
768 /* | |
769 * The connection is going to be persistent, but we | |
770 * need to detect if the other side closes it. | |
771 */ | |
772 evhttp_connection_start_detectclose(evcon); | |
773 } | |
774 } else if (evcon->state != EVCON_DISCONNECTED) { | |
775 /* | |
776 * incoming connection - we need to leave the request on the | |
777 * connection so that we can reply to it. | |
778 */ | |
779 evcon->state = EVCON_WRITING; | |
780 } | |
781 | |
782 /* notify the user of the request */ | |
783 (*req->cb)(req, req->cb_arg); | |
784 | |
785 /* if this was an outgoing request, we own and it's done. so free it */ | |
786 if (con_outgoing) { | |
787 evhttp_request_free(req); | |
788 } | |
789 } | |
790 | |
791 /* | |
792 * Handles reading from a chunked request. | |
793 * return ALL_DATA_READ: | |
794 * all data has been read | |
795 * return MORE_DATA_EXPECTED: | |
796 * more data is expected | |
797 * return DATA_CORRUPTED: | |
798 * data is corrupted | |
799 * return REQUEST_CANCLED: | |
800 * request was canceled by the user calling evhttp_cancel_request | |
801 */ | |
802 | |
803 static enum message_read_status | |
804 evhttp_handle_chunked_read(struct evhttp_request *req, struct evbuffer *buf) | |
805 { | |
806 int len; | |
807 | |
808 while ((len = EVBUFFER_LENGTH(buf)) > 0) { | |
809 if (req->ntoread < 0) { | |
810 /* Read chunk size */ | |
811 ev_int64_t ntoread; | |
812 char *p = evbuffer_readline(buf); | |
813 char *endp; | |
814 int error; | |
815 if (p == NULL) | |
816 break; | |
817 /* the last chunk is on a new line? */ | |
818 if (strlen(p) == 0) { | |
819 free(p); | |
820 continue; | |
821 } | |
822 ntoread = evutil_strtoll(p, &endp, 16); | |
823 error = (*p == '\0' || | |
824 (*endp != '\0' && *endp != ' ') || | |
825 ntoread < 0); | |
826 free(p); | |
827 if (error) { | |
828 /* could not get chunk size */ | |
829 return (DATA_CORRUPTED); | |
830 } | |
831 req->ntoread = ntoread; | |
832 if (req->ntoread == 0) { | |
833 /* Last chunk */ | |
834 return (ALL_DATA_READ); | |
835 } | |
836 continue; | |
837 } | |
838 | |
839 /* don't have enough to complete a chunk; wait for more */ | |
840 if (len < req->ntoread) | |
841 return (MORE_DATA_EXPECTED); | |
842 | |
843 /* Completed chunk */ | |
844 evbuffer_add(req->input_buffer, | |
845 EVBUFFER_DATA(buf), (size_t)req->ntoread); | |
846 evbuffer_drain(buf, (size_t)req->ntoread); | |
847 req->ntoread = -1; | |
848 if (req->chunk_cb != NULL) { | |
849 (*req->chunk_cb)(req, req->cb_arg); | |
850 evbuffer_drain(req->input_buffer, | |
851 EVBUFFER_LENGTH(req->input_buffer)); | |
852 } | |
853 } | |
854 | |
855 return (MORE_DATA_EXPECTED); | |
856 } | |
857 | |
858 static void | |
859 evhttp_read_trailer(struct evhttp_connection *evcon, struct evhttp_request *req) | |
860 { | |
861 struct evbuffer *buf = evcon->input_buffer; | |
862 | |
863 switch (evhttp_parse_headers(req, buf)) { | |
864 case DATA_CORRUPTED: | |
865 evhttp_connection_fail(evcon, EVCON_HTTP_INVALID_HEADER); | |
866 break; | |
867 case ALL_DATA_READ: | |
868 event_del(&evcon->ev); | |
869 evhttp_connection_done(evcon); | |
870 break; | |
871 case MORE_DATA_EXPECTED: | |
872 default: | |
873 evhttp_add_event(&evcon->ev, evcon->timeout, | |
874 HTTP_READ_TIMEOUT); | |
875 break; | |
876 } | |
877 } | |
878 | |
879 static void | |
880 evhttp_read_body(struct evhttp_connection *evcon, struct evhttp_request *req) | |
881 { | |
882 struct evbuffer *buf = evcon->input_buffer; | |
883 | |
884 if (req->chunked) { | |
885 switch (evhttp_handle_chunked_read(req, buf)) { | |
886 case ALL_DATA_READ: | |
887 /* finished last chunk */ | |
888 evcon->state = EVCON_READING_TRAILER; | |
889 evhttp_read_trailer(evcon, req); | |
890 return; | |
891 case DATA_CORRUPTED: | |
892 /* corrupted data */ | |
893 evhttp_connection_fail(evcon, | |
894 EVCON_HTTP_INVALID_HEADER); | |
895 return; | |
896 case REQUEST_CANCELED: | |
897 /* request canceled */ | |
898 evhttp_request_free(req); | |
899 return; | |
900 case MORE_DATA_EXPECTED: | |
901 default: | |
902 break; | |
903 } | |
904 } else if (req->ntoread < 0) { | |
905 /* Read until connection close. */ | |
906 evbuffer_add_buffer(req->input_buffer, buf); | |
907 } else if (EVBUFFER_LENGTH(buf) >= req->ntoread) { | |
908 /* Completed content length */ | |
909 evbuffer_add(req->input_buffer, EVBUFFER_DATA(buf), | |
910 (size_t)req->ntoread); | |
911 evbuffer_drain(buf, (size_t)req->ntoread); | |
912 req->ntoread = 0; | |
913 evhttp_connection_done(evcon); | |
914 return; | |
915 } | |
916 /* Read more! */ | |
917 event_set(&evcon->ev, evcon->fd, EV_READ, evhttp_read, evcon); | |
918 EVHTTP_BASE_SET(evcon, &evcon->ev); | |
919 evhttp_add_event(&evcon->ev, evcon->timeout, HTTP_READ_TIMEOUT); | |
920 } | |
921 | |
922 /* | |
923 * Reads data into a buffer structure until no more data | |
924 * can be read on the file descriptor or we have read all | |
925 * the data that we wanted to read. | |
926 * Execute callback when done. | |
927 */ | |
928 | |
929 void | |
930 evhttp_read(int fd, short what, void *arg) | |
931 { | |
932 struct evhttp_connection *evcon = arg; | |
933 struct evhttp_request *req = TAILQ_FIRST(&evcon->requests); | |
934 struct evbuffer *buf = evcon->input_buffer; | |
935 int n, len; | |
936 | |
937 if (what == EV_TIMEOUT) { | |
938 evhttp_connection_fail(evcon, EVCON_HTTP_TIMEOUT); | |
939 return; | |
940 } | |
941 n = evbuffer_read(buf, fd, -1); | |
942 len = EVBUFFER_LENGTH(buf); | |
943 event_debug(("%s: got %d on %d\n", __func__, n, fd)); | |
944 | |
945 if (n == -1) { | |
946 if (errno != EINTR && errno != EAGAIN) { | |
947 event_debug(("%s: evbuffer_read", __func__)); | |
948 evhttp_connection_fail(evcon, EVCON_HTTP_EOF); | |
949 } else { | |
950 evhttp_add_event(&evcon->ev, evcon->timeout, | |
951 HTTP_READ_TIMEOUT); | |
952 } | |
953 return; | |
954 } else if (n == 0) { | |
955 /* Connection closed */ | |
956 evcon->state = EVCON_DISCONNECTED; | |
957 evhttp_connection_done(evcon); | |
958 return; | |
959 } | |
960 | |
961 switch (evcon->state) { | |
962 case EVCON_READING_FIRSTLINE: | |
963 evhttp_read_firstline(evcon, req); | |
964 break; | |
965 case EVCON_READING_HEADERS: | |
966 evhttp_read_header(evcon, req); | |
967 break; | |
968 case EVCON_READING_BODY: | |
969 evhttp_read_body(evcon, req); | |
970 break; | |
971 case EVCON_READING_TRAILER: | |
972 evhttp_read_trailer(evcon, req); | |
973 break; | |
974 case EVCON_DISCONNECTED: | |
975 case EVCON_CONNECTING: | |
976 case EVCON_IDLE: | |
977 case EVCON_WRITING: | |
978 default: | |
979 event_errx(1, "%s: illegal connection state %d", | |
980 __func__, evcon->state); | |
981 } | |
982 } | |
983 | |
984 static void | |
985 evhttp_write_connectioncb(struct evhttp_connection *evcon, void *arg) | |
986 { | |
987 /* This is after writing the request to the server */ | |
988 struct evhttp_request *req = TAILQ_FIRST(&evcon->requests); | |
989 assert(req != NULL); | |
990 | |
991 assert(evcon->state == EVCON_WRITING); | |
992 | |
993 /* We are done writing our header and are now expecting the response */ | |
994 req->kind = EVHTTP_RESPONSE; | |
995 | |
996 evhttp_start_read(evcon); | |
997 } | |
998 | |
999 /* | |
1000 * Clean up a connection object | |
1001 */ | |
1002 | |
1003 void | |
1004 evhttp_connection_free(struct evhttp_connection *evcon) | |
1005 { | |
1006 struct evhttp_request *req; | |
1007 | |
1008 /* notify interested parties that this connection is going down */ | |
1009 if (evcon->fd != -1) { | |
1010 if (evhttp_connected(evcon) && evcon->closecb != NULL) | |
1011 (*evcon->closecb)(evcon, evcon->closecb_arg); | |
1012 } | |
1013 | |
1014 /* remove all requests that might be queued on this | |
1015 * connection. for server connections, this should be empty. | |
1016 * because it gets dequeued either in evhttp_connection_done or | |
1017 * evhttp_connection_fail. | |
1018 */ | |
1019 while ((req = TAILQ_FIRST(&evcon->requests)) != NULL) { | |
1020 TAILQ_REMOVE(&evcon->requests, req, next); | |
1021 evhttp_request_free(req); | |
1022 } | |
1023 | |
1024 if (evcon->http_server != NULL) { | |
1025 struct evhttp *http = evcon->http_server; | |
1026 TAILQ_REMOVE(&http->connections, evcon, next); | |
1027 } | |
1028 | |
1029 if (event_initialized(&evcon->close_ev)) | |
1030 event_del(&evcon->close_ev); | |
1031 | |
1032 if (event_initialized(&evcon->ev)) | |
1033 event_del(&evcon->ev); | |
1034 | |
1035 if (evcon->fd != -1) | |
1036 EVUTIL_CLOSESOCKET(evcon->fd); | |
1037 | |
1038 if (evcon->bind_address != NULL) | |
1039 free(evcon->bind_address); | |
1040 | |
1041 if (evcon->address != NULL) | |
1042 free(evcon->address); | |
1043 | |
1044 if (evcon->input_buffer != NULL) | |
1045 evbuffer_free(evcon->input_buffer); | |
1046 | |
1047 if (evcon->output_buffer != NULL) | |
1048 evbuffer_free(evcon->output_buffer); | |
1049 | |
1050 free(evcon); | |
1051 } | |
1052 | |
1053 void | |
1054 evhttp_connection_set_local_address(struct evhttp_connection *evcon, | |
1055 const char *address) | |
1056 { | |
1057 assert(evcon->state == EVCON_DISCONNECTED); | |
1058 if (evcon->bind_address) | |
1059 free(evcon->bind_address); | |
1060 if ((evcon->bind_address = strdup(address)) == NULL) | |
1061 event_err(1, "%s: strdup", __func__); | |
1062 } | |
1063 | |
1064 void | |
1065 evhttp_connection_set_local_port(struct evhttp_connection *evcon, | |
1066 unsigned short port) | |
1067 { | |
1068 assert(evcon->state == EVCON_DISCONNECTED); | |
1069 evcon->bind_port = port; | |
1070 } | |
1071 | |
1072 static void | |
1073 evhttp_request_dispatch(struct evhttp_connection* evcon) | |
1074 { | |
1075 struct evhttp_request *req = TAILQ_FIRST(&evcon->requests); | |
1076 | |
1077 /* this should not usually happy but it's possible */ | |
1078 if (req == NULL) | |
1079 return; | |
1080 | |
1081 /* delete possible close detection events */ | |
1082 evhttp_connection_stop_detectclose(evcon); | |
1083 | |
1084 /* we assume that the connection is connected already */ | |
1085 assert(evcon->state == EVCON_IDLE); | |
1086 | |
1087 evcon->state = EVCON_WRITING; | |
1088 | |
1089 /* Create the header from the store arguments */ | |
1090 evhttp_make_header(evcon, req); | |
1091 | |
1092 evhttp_write_buffer(evcon, evhttp_write_connectioncb, NULL); | |
1093 } | |
1094 | |
1095 /* Reset our connection state */ | |
1096 void | |
1097 evhttp_connection_reset(struct evhttp_connection *evcon) | |
1098 { | |
1099 if (event_initialized(&evcon->ev)) | |
1100 event_del(&evcon->ev); | |
1101 | |
1102 if (evcon->fd != -1) { | |
1103 /* inform interested parties about connection close */ | |
1104 if (evhttp_connected(evcon) && evcon->closecb != NULL) | |
1105 (*evcon->closecb)(evcon, evcon->closecb_arg); | |
1106 | |
1107 EVUTIL_CLOSESOCKET(evcon->fd); | |
1108 evcon->fd = -1; | |
1109 } | |
1110 evcon->state = EVCON_DISCONNECTED; | |
1111 | |
1112 evbuffer_drain(evcon->input_buffer, | |
1113 EVBUFFER_LENGTH(evcon->input_buffer)); | |
1114 evbuffer_drain(evcon->output_buffer, | |
1115 EVBUFFER_LENGTH(evcon->output_buffer)); | |
1116 } | |
1117 | |
1118 static void | |
1119 evhttp_detect_close_cb(int fd, short what, void *arg) | |
1120 { | |
1121 struct evhttp_connection *evcon = arg; | |
1122 evhttp_connection_reset(evcon); | |
1123 } | |
1124 | |
1125 static void | |
1126 evhttp_connection_start_detectclose(struct evhttp_connection *evcon) | |
1127 { | |
1128 evcon->flags |= EVHTTP_CON_CLOSEDETECT; | |
1129 | |
1130 if (event_initialized(&evcon->close_ev)) | |
1131 event_del(&evcon->close_ev); | |
1132 event_set(&evcon->close_ev, evcon->fd, EV_READ, | |
1133 evhttp_detect_close_cb, evcon); | |
1134 EVHTTP_BASE_SET(evcon, &evcon->close_ev); | |
1135 event_add(&evcon->close_ev, NULL); | |
1136 } | |
1137 | |
1138 static void | |
1139 evhttp_connection_stop_detectclose(struct evhttp_connection *evcon) | |
1140 { | |
1141 evcon->flags &= ~EVHTTP_CON_CLOSEDETECT; | |
1142 event_del(&evcon->close_ev); | |
1143 } | |
1144 | |
1145 static void | |
1146 evhttp_connection_retry(int fd, short what, void *arg) | |
1147 { | |
1148 struct evhttp_connection *evcon = arg; | |
1149 | |
1150 evcon->state = EVCON_DISCONNECTED; | |
1151 evhttp_connection_connect(evcon); | |
1152 } | |
1153 | |
1154 /* | |
1155 * Call back for asynchronous connection attempt. | |
1156 */ | |
1157 | |
1158 static void | |
1159 evhttp_connectioncb(int fd, short what, void *arg) | |
1160 { | |
1161 struct evhttp_connection *evcon = arg; | |
1162 int error; | |
1163 socklen_t errsz = sizeof(error); | |
1164 | |
1165 if (what == EV_TIMEOUT) { | |
1166 event_debug(("%s: connection timeout for \"%s:%d\" on %d", | |
1167 __func__, evcon->address, evcon->port, evcon->fd)); | |
1168 goto cleanup; | |
1169 } | |
1170 | |
1171 /* Check if the connection completed */ | |
1172 if (getsockopt(evcon->fd, SOL_SOCKET, SO_ERROR, (void*)&error, | |
1173 &errsz) == -1) { | |
1174 event_debug(("%s: getsockopt for \"%s:%d\" on %d", | |
1175 __func__, evcon->address, evcon->port, evcon->fd)); | |
1176 goto cleanup; | |
1177 } | |
1178 | |
1179 if (error) { | |
1180 event_debug(("%s: connect failed for \"%s:%d\" on %d: %s", | |
1181 __func__, evcon->address, evcon->port, evcon->fd, | |
1182 strerror(error))); | |
1183 goto cleanup; | |
1184 } | |
1185 | |
1186 /* We are connected to the server now */ | |
1187 event_debug(("%s: connected to \"%s:%d\" on %d\n", | |
1188 __func__, evcon->address, evcon->port, evcon->fd)); | |
1189 | |
1190 /* Reset the retry count as we were successful in connecting */ | |
1191 evcon->retry_cnt = 0; | |
1192 evcon->state = EVCON_IDLE; | |
1193 | |
1194 /* try to start requests that have queued up on this connection */ | |
1195 evhttp_request_dispatch(evcon); | |
1196 return; | |
1197 | |
1198 cleanup: | |
1199 if (evcon->retry_max < 0 || evcon->retry_cnt < evcon->retry_max) { | |
1200 evtimer_set(&evcon->ev, evhttp_connection_retry, evcon); | |
1201 EVHTTP_BASE_SET(evcon, &evcon->ev); | |
1202 evhttp_add_event(&evcon->ev, MIN(3600, 2 << evcon->retry_cnt), | |
1203 HTTP_CONNECT_TIMEOUT); | |
1204 evcon->retry_cnt++; | |
1205 return; | |
1206 } | |
1207 evhttp_connection_reset(evcon); | |
1208 | |
1209 /* for now, we just signal all requests by executing their callbacks */ | |
1210 while (TAILQ_FIRST(&evcon->requests) != NULL) { | |
1211 struct evhttp_request *request = TAILQ_FIRST(&evcon->requests); | |
1212 TAILQ_REMOVE(&evcon->requests, request, next); | |
1213 request->evcon = NULL; | |
1214 | |
1215 /* we might want to set an error here */ | |
1216 request->cb(request, request->cb_arg); | |
1217 evhttp_request_free(request); | |
1218 } | |
1219 } | |
1220 | |
1221 /* | |
1222 * Check if we got a valid response code. | |
1223 */ | |
1224 | |
1225 static int | |
1226 evhttp_valid_response_code(int code) | |
1227 { | |
1228 if (code == 0) | |
1229 return (0); | |
1230 | |
1231 return (1); | |
1232 } | |
1233 | |
1234 /* Parses the status line of a web server */ | |
1235 | |
1236 static int | |
1237 evhttp_parse_response_line(struct evhttp_request *req, char *line) | |
1238 { | |
1239 char *protocol; | |
1240 char *number; | |
1241 const char *readable = ""; | |
1242 | |
1243 protocol = strsep(&line, " "); | |
1244 if (line == NULL) | |
1245 return (-1); | |
1246 number = strsep(&line, " "); | |
1247 if (line != NULL) | |
1248 readable = line; | |
1249 | |
1250 if (strcmp(protocol, "HTTP/1.0") == 0) { | |
1251 req->major = 1; | |
1252 req->minor = 0; | |
1253 } else if (strcmp(protocol, "HTTP/1.1") == 0) { | |
1254 req->major = 1; | |
1255 req->minor = 1; | |
1256 } else { | |
1257 event_debug(("%s: bad protocol \"%s\"", | |
1258 __func__, protocol)); | |
1259 return (-1); | |
1260 } | |
1261 | |
1262 req->response_code = atoi(number); | |
1263 if (!evhttp_valid_response_code(req->response_code)) { | |
1264 event_debug(("%s: bad response code \"%s\"", | |
1265 __func__, number)); | |
1266 return (-1); | |
1267 } | |
1268 | |
1269 if ((req->response_code_line = strdup(readable)) == NULL) | |
1270 event_err(1, "%s: strdup", __func__); | |
1271 | |
1272 return (0); | |
1273 } | |
1274 | |
1275 /* Parse the first line of a HTTP request */ | |
1276 | |
1277 static int | |
1278 evhttp_parse_request_line(struct evhttp_request *req, char *line) | |
1279 { | |
1280 char *method; | |
1281 char *uri; | |
1282 char *version; | |
1283 | |
1284 /* Parse the request line */ | |
1285 method = strsep(&line, " "); | |
1286 if (line == NULL) | |
1287 return (-1); | |
1288 uri = strsep(&line, " "); | |
1289 if (line == NULL) | |
1290 return (-1); | |
1291 version = strsep(&line, " "); | |
1292 if (line != NULL) | |
1293 return (-1); | |
1294 | |
1295 /* First line */ | |
1296 if (strcmp(method, "GET") == 0) { | |
1297 req->type = EVHTTP_REQ_GET; | |
1298 } else if (strcmp(method, "POST") == 0) { | |
1299 req->type = EVHTTP_REQ_POST; | |
1300 } else if (strcmp(method, "HEAD") == 0) { | |
1301 req->type = EVHTTP_REQ_HEAD; | |
1302 } else { | |
1303 event_debug(("%s: bad method %s on request %p from %s", | |
1304 __func__, method, req, req->remote_host)); | |
1305 return (-1); | |
1306 } | |
1307 | |
1308 if (strcmp(version, "HTTP/1.0") == 0) { | |
1309 req->major = 1; | |
1310 req->minor = 0; | |
1311 } else if (strcmp(version, "HTTP/1.1") == 0) { | |
1312 req->major = 1; | |
1313 req->minor = 1; | |
1314 } else { | |
1315 event_debug(("%s: bad version %s on request %p from %s", | |
1316 __func__, version, req, req->remote_host)); | |
1317 return (-1); | |
1318 } | |
1319 | |
1320 if ((req->uri = strdup(uri)) == NULL) { | |
1321 event_debug(("%s: strdup", __func__)); | |
1322 return (-1); | |
1323 } | |
1324 | |
1325 /* determine if it's a proxy request */ | |
1326 if (strlen(req->uri) > 0 && req->uri[0] != '/') | |
1327 req->flags |= EVHTTP_PROXY_REQUEST; | |
1328 | |
1329 return (0); | |
1330 } | |
1331 | |
1332 const char * | |
1333 evhttp_find_header(const struct evkeyvalq *headers, const char *key) | |
1334 { | |
1335 struct evkeyval *header; | |
1336 | |
1337 TAILQ_FOREACH(header, headers, next) { | |
1338 if (strcasecmp(header->key, key) == 0) | |
1339 return (header->value); | |
1340 } | |
1341 | |
1342 return (NULL); | |
1343 } | |
1344 | |
1345 void | |
1346 evhttp_clear_headers(struct evkeyvalq *headers) | |
1347 { | |
1348 struct evkeyval *header; | |
1349 | |
1350 for (header = TAILQ_FIRST(headers); | |
1351 header != NULL; | |
1352 header = TAILQ_FIRST(headers)) { | |
1353 TAILQ_REMOVE(headers, header, next); | |
1354 free(header->key); | |
1355 free(header->value); | |
1356 free(header); | |
1357 } | |
1358 } | |
1359 | |
1360 /* | |
1361 * Returns 0, if the header was successfully removed. | |
1362 * Returns -1, if the header could not be found. | |
1363 */ | |
1364 | |
1365 int | |
1366 evhttp_remove_header(struct evkeyvalq *headers, const char *key) | |
1367 { | |
1368 struct evkeyval *header; | |
1369 | |
1370 TAILQ_FOREACH(header, headers, next) { | |
1371 if (strcasecmp(header->key, key) == 0) | |
1372 break; | |
1373 } | |
1374 | |
1375 if (header == NULL) | |
1376 return (-1); | |
1377 | |
1378 /* Free and remove the header that we found */ | |
1379 TAILQ_REMOVE(headers, header, next); | |
1380 free(header->key); | |
1381 free(header->value); | |
1382 free(header); | |
1383 | |
1384 return (0); | |
1385 } | |
1386 | |
1387 static int | |
1388 evhttp_header_is_valid_value(const char *value) | |
1389 { | |
1390 const char *p = value; | |
1391 | |
1392 while ((p = strpbrk(p, "\r\n")) != NULL) { | |
1393 /* we really expect only one new line */ | |
1394 p += strspn(p, "\r\n"); | |
1395 /* we expect a space or tab for continuation */ | |
1396 if (*p != ' ' && *p != '\t') | |
1397 return (0); | |
1398 } | |
1399 return (1); | |
1400 } | |
1401 | |
1402 int | |
1403 evhttp_add_header(struct evkeyvalq *headers, | |
1404 const char *key, const char *value) | |
1405 { | |
1406 event_debug(("%s: key: %s val: %s\n", __func__, key, value)); | |
1407 | |
1408 if (strchr(key, '\r') != NULL || strchr(key, '\n') != NULL) { | |
1409 /* drop illegal headers */ | |
1410 event_debug(("%s: dropping illegal header key\n", __func__)); | |
1411 return (-1); | |
1412 } | |
1413 | |
1414 if (!evhttp_header_is_valid_value(value)) { | |
1415 event_debug(("%s: dropping illegal header value\n", __func__)); | |
1416 return (-1); | |
1417 } | |
1418 | |
1419 return (evhttp_add_header_internal(headers, key, value)); | |
1420 } | |
1421 | |
1422 static int | |
1423 evhttp_add_header_internal(struct evkeyvalq *headers, | |
1424 const char *key, const char *value) | |
1425 { | |
1426 struct evkeyval *header = calloc(1, sizeof(struct evkeyval)); | |
1427 if (header == NULL) { | |
1428 event_warn("%s: calloc", __func__); | |
1429 return (-1); | |
1430 } | |
1431 if ((header->key = strdup(key)) == NULL) { | |
1432 free(header); | |
1433 event_warn("%s: strdup", __func__); | |
1434 return (-1); | |
1435 } | |
1436 if ((header->value = strdup(value)) == NULL) { | |
1437 free(header->key); | |
1438 free(header); | |
1439 event_warn("%s: strdup", __func__); | |
1440 return (-1); | |
1441 } | |
1442 | |
1443 TAILQ_INSERT_TAIL(headers, header, next); | |
1444 | |
1445 return (0); | |
1446 } | |
1447 | |
1448 /* | |
1449 * Parses header lines from a request or a response into the specified | |
1450 * request object given an event buffer. | |
1451 * | |
1452 * Returns | |
1453 * DATA_CORRUPTED on error | |
1454 * MORE_DATA_EXPECTED when we need to read more headers | |
1455 * ALL_DATA_READ when all headers have been read. | |
1456 */ | |
1457 | |
1458 enum message_read_status | |
1459 evhttp_parse_firstline(struct evhttp_request *req, struct evbuffer *buffer) | |
1460 { | |
1461 char *line; | |
1462 enum message_read_status status = ALL_DATA_READ; | |
1463 | |
1464 line = evbuffer_readline(buffer); | |
1465 if (line == NULL) | |
1466 return (MORE_DATA_EXPECTED); | |
1467 | |
1468 switch (req->kind) { | |
1469 case EVHTTP_REQUEST: | |
1470 if (evhttp_parse_request_line(req, line) == -1) | |
1471 status = DATA_CORRUPTED; | |
1472 break; | |
1473 case EVHTTP_RESPONSE: | |
1474 if (evhttp_parse_response_line(req, line) == -1) | |
1475 status = DATA_CORRUPTED; | |
1476 break; | |
1477 default: | |
1478 status = DATA_CORRUPTED; | |
1479 } | |
1480 | |
1481 free(line); | |
1482 return (status); | |
1483 } | |
1484 | |
1485 static int | |
1486 evhttp_append_to_last_header(struct evkeyvalq *headers, const char *line) | |
1487 { | |
1488 struct evkeyval *header = TAILQ_LAST(headers, evkeyvalq); | |
1489 char *newval; | |
1490 size_t old_len, line_len; | |
1491 | |
1492 if (header == NULL) | |
1493 return (-1); | |
1494 | |
1495 old_len = strlen(header->value); | |
1496 line_len = strlen(line); | |
1497 | |
1498 newval = realloc(header->value, old_len + line_len + 1); | |
1499 if (newval == NULL) | |
1500 return (-1); | |
1501 | |
1502 memcpy(newval + old_len, line, line_len + 1); | |
1503 header->value = newval; | |
1504 | |
1505 return (0); | |
1506 } | |
1507 | |
1508 enum message_read_status | |
1509 evhttp_parse_headers(struct evhttp_request *req, struct evbuffer* buffer) | |
1510 { | |
1511 char *line; | |
1512 enum message_read_status status = MORE_DATA_EXPECTED; | |
1513 | |
1514 struct evkeyvalq* headers = req->input_headers; | |
1515 while ((line = evbuffer_readline(buffer)) | |
1516 != NULL) { | |
1517 char *skey, *svalue; | |
1518 | |
1519 if (*line == '\0') { /* Last header - Done */ | |
1520 status = ALL_DATA_READ; | |
1521 free(line); | |
1522 break; | |
1523 } | |
1524 | |
1525 /* Check if this is a continuation line */ | |
1526 if (*line == ' ' || *line == '\t') { | |
1527 if (evhttp_append_to_last_header(headers, line) == -1) | |
1528 goto error; | |
1529 free(line); | |
1530 continue; | |
1531 } | |
1532 | |
1533 /* Processing of header lines */ | |
1534 svalue = line; | |
1535 skey = strsep(&svalue, ":"); | |
1536 if (svalue == NULL) | |
1537 goto error; | |
1538 | |
1539 svalue += strspn(svalue, " "); | |
1540 | |
1541 if (evhttp_add_header(headers, skey, svalue) == -1) | |
1542 goto error; | |
1543 | |
1544 free(line); | |
1545 } | |
1546 | |
1547 return (status); | |
1548 | |
1549 error: | |
1550 free(line); | |
1551 return (DATA_CORRUPTED); | |
1552 } | |
1553 | |
1554 static int | |
1555 evhttp_get_body_length(struct evhttp_request *req) | |
1556 { | |
1557 struct evkeyvalq *headers = req->input_headers; | |
1558 const char *content_length; | |
1559 const char *connection; | |
1560 | |
1561 content_length = evhttp_find_header(headers, "Content-Length"); | |
1562 connection = evhttp_find_header(headers, "Connection"); | |
1563 | |
1564 if (content_length == NULL && connection == NULL) | |
1565 req->ntoread = -1; | |
1566 else if (content_length == NULL && | |
1567 strcasecmp(connection, "Close") != 0) { | |
1568 /* Bad combination, we don't know when it will end */ | |
1569 event_warnx("%s: we got no content length, but the " | |
1570 "server wants to keep the connection open: %s.", | |
1571 __func__, connection); | |
1572 return (-1); | |
1573 } else if (content_length == NULL) { | |
1574 req->ntoread = -1; | |
1575 } else { | |
1576 char *endp; | |
1577 ev_int64_t ntoread = evutil_strtoll(content_length, &endp, 10); | |
1578 if (*content_length == '\0' || *endp != '\0' || ntoread < 0) { | |
1579 event_debug(("%s: illegal content length: %s", | |
1580 __func__, content_length)); | |
1581 return (-1); | |
1582 } | |
1583 req->ntoread = ntoread; | |
1584 } | |
1585 | |
1586 event_debug(("%s: bytes to read: %lld (in buffer %ld)\n", | |
1587 __func__, req->ntoread, | |
1588 EVBUFFER_LENGTH(req->evcon->input_buffer))); | |
1589 | |
1590 return (0); | |
1591 } | |
1592 | |
1593 static void | |
1594 evhttp_get_body(struct evhttp_connection *evcon, struct evhttp_request *req) | |
1595 { | |
1596 const char *xfer_enc; | |
1597 | |
1598 /* If this is a request without a body, then we are done */ | |
1599 if (req->kind == EVHTTP_REQUEST && req->type != EVHTTP_REQ_POST) { | |
1600 evhttp_connection_done(evcon); | |
1601 return; | |
1602 } | |
1603 evcon->state = EVCON_READING_BODY; | |
1604 xfer_enc = evhttp_find_header(req->input_headers, "Transfer-Encoding"); | |
1605 if (xfer_enc != NULL && strcasecmp(xfer_enc, "chunked") == 0) { | |
1606 req->chunked = 1; | |
1607 req->ntoread = -1; | |
1608 } else { | |
1609 if (evhttp_get_body_length(req) == -1) { | |
1610 evhttp_connection_fail(evcon, | |
1611 EVCON_HTTP_INVALID_HEADER); | |
1612 return; | |
1613 } | |
1614 } | |
1615 evhttp_read_body(evcon, req); | |
1616 } | |
1617 | |
1618 static void | |
1619 evhttp_read_firstline(struct evhttp_connection *evcon, | |
1620 struct evhttp_request *req) | |
1621 { | |
1622 enum message_read_status res; | |
1623 | |
1624 res = evhttp_parse_firstline(req, evcon->input_buffer); | |
1625 if (res == DATA_CORRUPTED) { | |
1626 /* Error while reading, terminate */ | |
1627 event_debug(("%s: bad header lines on %d\n", | |
1628 __func__, evcon->fd)); | |
1629 evhttp_connection_fail(evcon, EVCON_HTTP_INVALID_HEADER); | |
1630 return; | |
1631 } else if (res == MORE_DATA_EXPECTED) { | |
1632 /* Need more header lines */ | |
1633 evhttp_add_event(&evcon->ev, | |
1634 evcon->timeout, HTTP_READ_TIMEOUT); | |
1635 return; | |
1636 } | |
1637 | |
1638 evcon->state = EVCON_READING_HEADERS; | |
1639 evhttp_read_header(evcon, req); | |
1640 } | |
1641 | |
1642 static void | |
1643 evhttp_read_header(struct evhttp_connection *evcon, struct evhttp_request *req) | |
1644 { | |
1645 enum message_read_status res; | |
1646 int fd = evcon->fd; | |
1647 | |
1648 res = evhttp_parse_headers(req, evcon->input_buffer); | |
1649 if (res == DATA_CORRUPTED) { | |
1650 /* Error while reading, terminate */ | |
1651 event_debug(("%s: bad header lines on %d\n", __func__, fd)); | |
1652 evhttp_connection_fail(evcon, EVCON_HTTP_INVALID_HEADER); | |
1653 return; | |
1654 } else if (res == MORE_DATA_EXPECTED) { | |
1655 /* Need more header lines */ | |
1656 evhttp_add_event(&evcon->ev, | |
1657 evcon->timeout, HTTP_READ_TIMEOUT); | |
1658 return; | |
1659 } | |
1660 | |
1661 /* Done reading headers, do the real work */ | |
1662 switch (req->kind) { | |
1663 case EVHTTP_REQUEST: | |
1664 event_debug(("%s: checking for post data on %d\n", | |
1665 __func__, fd)); | |
1666 evhttp_get_body(evcon, req); | |
1667 break; | |
1668 | |
1669 case EVHTTP_RESPONSE: | |
1670 if (req->response_code == HTTP_NOCONTENT || | |
1671 req->response_code == HTTP_NOTMODIFIED || | |
1672 (req->response_code >= 100 && req->response_code < 200)) { | |
1673 event_debug(("%s: skipping body for code %d\n", | |
1674 __func__, req->response_code)); | |
1675 evhttp_connection_done(evcon); | |
1676 } else { | |
1677 event_debug(("%s: start of read body for %s on %d\n", | |
1678 __func__, req->remote_host, fd)); | |
1679 evhttp_get_body(evcon, req); | |
1680 } | |
1681 break; | |
1682 | |
1683 default: | |
1684 event_warnx("%s: bad header on %d", __func__, fd); | |
1685 evhttp_connection_fail(evcon, EVCON_HTTP_INVALID_HEADER); | |
1686 break; | |
1687 } | |
1688 } | |
1689 | |
1690 /* | |
1691 * Creates a TCP connection to the specified port and executes a callback | |
1692 * when finished. Failure or sucess is indicate by the passed connection | |
1693 * object. | |
1694 * | |
1695 * Although this interface accepts a hostname, it is intended to take | |
1696 * only numeric hostnames so that non-blocking DNS resolution can | |
1697 * happen elsewhere. | |
1698 */ | |
1699 | |
1700 struct evhttp_connection * | |
1701 evhttp_connection_new(const char *address, unsigned short port) | |
1702 { | |
1703 struct evhttp_connection *evcon = NULL; | |
1704 | |
1705 event_debug(("Attempting connection to %s:%d\n", address, port)); | |
1706 | |
1707 if ((evcon = calloc(1, sizeof(struct evhttp_connection))) == NULL) { | |
1708 event_warn("%s: calloc failed", __func__); | |
1709 goto error; | |
1710 } | |
1711 | |
1712 evcon->fd = -1; | |
1713 evcon->port = port; | |
1714 | |
1715 evcon->timeout = -1; | |
1716 evcon->retry_cnt = evcon->retry_max = 0; | |
1717 | |
1718 if ((evcon->address = strdup(address)) == NULL) { | |
1719 event_warn("%s: strdup failed", __func__); | |
1720 goto error; | |
1721 } | |
1722 | |
1723 if ((evcon->input_buffer = evbuffer_new()) == NULL) { | |
1724 event_warn("%s: evbuffer_new failed", __func__); | |
1725 goto error; | |
1726 } | |
1727 | |
1728 if ((evcon->output_buffer = evbuffer_new()) == NULL) { | |
1729 event_warn("%s: evbuffer_new failed", __func__); | |
1730 goto error; | |
1731 } | |
1732 | |
1733 evcon->state = EVCON_DISCONNECTED; | |
1734 TAILQ_INIT(&evcon->requests); | |
1735 | |
1736 return (evcon); | |
1737 | |
1738 error: | |
1739 if (evcon != NULL) | |
1740 evhttp_connection_free(evcon); | |
1741 return (NULL); | |
1742 } | |
1743 | |
1744 void evhttp_connection_set_base(struct evhttp_connection *evcon, | |
1745 struct event_base *base) | |
1746 { | |
1747 assert(evcon->base == NULL); | |
1748 assert(evcon->state == EVCON_DISCONNECTED); | |
1749 evcon->base = base; | |
1750 } | |
1751 | |
1752 void | |
1753 evhttp_connection_set_timeout(struct evhttp_connection *evcon, | |
1754 int timeout_in_secs) | |
1755 { | |
1756 evcon->timeout = timeout_in_secs; | |
1757 } | |
1758 | |
1759 void | |
1760 evhttp_connection_set_retries(struct evhttp_connection *evcon, | |
1761 int retry_max) | |
1762 { | |
1763 evcon->retry_max = retry_max; | |
1764 } | |
1765 | |
1766 void | |
1767 evhttp_connection_set_closecb(struct evhttp_connection *evcon, | |
1768 void (*cb)(struct evhttp_connection *, void *), void *cbarg) | |
1769 { | |
1770 evcon->closecb = cb; | |
1771 evcon->closecb_arg = cbarg; | |
1772 } | |
1773 | |
1774 void | |
1775 evhttp_connection_get_peer(struct evhttp_connection *evcon, | |
1776 char **address, u_short *port) | |
1777 { | |
1778 *address = evcon->address; | |
1779 *port = evcon->port; | |
1780 } | |
1781 | |
1782 int | |
1783 evhttp_connection_connect(struct evhttp_connection *evcon) | |
1784 { | |
1785 if (evcon->state == EVCON_CONNECTING) | |
1786 return (0); | |
1787 | |
1788 evhttp_connection_reset(evcon); | |
1789 | |
1790 assert(!(evcon->flags & EVHTTP_CON_INCOMING)); | |
1791 evcon->flags |= EVHTTP_CON_OUTGOING; | |
1792 | |
1793 evcon->fd = bind_socket( | |
1794 evcon->bind_address, evcon->bind_port, 0 /*reuse*/); | |
1795 if (evcon->fd == -1) { | |
1796 event_debug(("%s: failed to bind to \"%s\"", | |
1797 __func__, evcon->bind_address)); | |
1798 return (-1); | |
1799 } | |
1800 | |
1801 if (socket_connect(evcon->fd, evcon->address, evcon->port) == -1) { | |
1802 EVUTIL_CLOSESOCKET(evcon->fd); evcon->fd = -1; | |
1803 return (-1); | |
1804 } | |
1805 | |
1806 /* Set up a callback for successful connection setup */ | |
1807 event_set(&evcon->ev, evcon->fd, EV_WRITE, evhttp_connectioncb, evcon); | |
1808 EVHTTP_BASE_SET(evcon, &evcon->ev); | |
1809 evhttp_add_event(&evcon->ev, evcon->timeout, HTTP_CONNECT_TIMEOUT); | |
1810 | |
1811 evcon->state = EVCON_CONNECTING; | |
1812 | |
1813 return (0); | |
1814 } | |
1815 | |
1816 /* | |
1817 * Starts an HTTP request on the provided evhttp_connection object. | |
1818 * If the connection object is not connected to the web server already, | |
1819 * this will start the connection. | |
1820 */ | |
1821 | |
1822 int | |
1823 evhttp_make_request(struct evhttp_connection *evcon, | |
1824 struct evhttp_request *req, | |
1825 enum evhttp_cmd_type type, const char *uri) | |
1826 { | |
1827 /* We are making a request */ | |
1828 req->kind = EVHTTP_REQUEST; | |
1829 req->type = type; | |
1830 if (req->uri != NULL) | |
1831 free(req->uri); | |
1832 if ((req->uri = strdup(uri)) == NULL) | |
1833 event_err(1, "%s: strdup", __func__); | |
1834 | |
1835 /* Set the protocol version if it is not supplied */ | |
1836 if (!req->major && !req->minor) { | |
1837 req->major = 1; | |
1838 req->minor = 1; | |
1839 } | |
1840 | |
1841 assert(req->evcon == NULL); | |
1842 req->evcon = evcon; | |
1843 assert(!(req->flags & EVHTTP_REQ_OWN_CONNECTION)); | |
1844 | |
1845 TAILQ_INSERT_TAIL(&evcon->requests, req, next); | |
1846 | |
1847 /* If the connection object is not connected; make it so */ | |
1848 if (!evhttp_connected(evcon)) | |
1849 return (evhttp_connection_connect(evcon)); | |
1850 | |
1851 /* | |
1852 * If it's connected already and we are the first in the queue, | |
1853 * then we can dispatch this request immediately. Otherwise, it | |
1854 * will be dispatched once the pending requests are completed. | |
1855 */ | |
1856 if (TAILQ_FIRST(&evcon->requests) == req) | |
1857 evhttp_request_dispatch(evcon); | |
1858 | |
1859 return (0); | |
1860 } | |
1861 | |
1862 /* | |
1863 * Reads data from file descriptor into request structure | |
1864 * Request structure needs to be set up correctly. | |
1865 */ | |
1866 | |
1867 void | |
1868 evhttp_start_read(struct evhttp_connection *evcon) | |
1869 { | |
1870 /* Set up an event to read the headers */ | |
1871 if (event_initialized(&evcon->ev)) | |
1872 event_del(&evcon->ev); | |
1873 event_set(&evcon->ev, evcon->fd, EV_READ, evhttp_read, evcon); | |
1874 EVHTTP_BASE_SET(evcon, &evcon->ev); | |
1875 | |
1876 evhttp_add_event(&evcon->ev, evcon->timeout, HTTP_READ_TIMEOUT); | |
1877 evcon->state = EVCON_READING_FIRSTLINE; | |
1878 } | |
1879 | |
1880 static void | |
1881 evhttp_send_done(struct evhttp_connection *evcon, void *arg) | |
1882 { | |
1883 int need_close; | |
1884 struct evhttp_request *req = TAILQ_FIRST(&evcon->requests); | |
1885 TAILQ_REMOVE(&evcon->requests, req, next); | |
1886 | |
1887 /* delete possible close detection events */ | |
1888 evhttp_connection_stop_detectclose(evcon); | |
1889 | |
1890 need_close = | |
1891 (req->minor == 0 && | |
1892 !evhttp_is_connection_keepalive(req->input_headers))|| | |
1893 evhttp_is_connection_close(req->flags, req->input_headers) || | |
1894 evhttp_is_connection_close(req->flags, req->output_headers); | |
1895 | |
1896 assert(req->flags & EVHTTP_REQ_OWN_CONNECTION); | |
1897 evhttp_request_free(req); | |
1898 | |
1899 if (need_close) { | |
1900 evhttp_connection_free(evcon); | |
1901 return; | |
1902 } | |
1903 | |
1904 /* we have a persistent connection; try to accept another request. */ | |
1905 if (evhttp_associate_new_request_with_connection(evcon) == -1) | |
1906 evhttp_connection_free(evcon); | |
1907 } | |
1908 | |
1909 /* | |
1910 * Returns an error page. | |
1911 */ | |
1912 | |
1913 void | |
1914 evhttp_send_error(struct evhttp_request *req, int error, const char *reason) | |
1915 { | |
1916 #define ERR_FORMAT "<HTML><HEAD>\n" \ | |
1917 "<TITLE>%d %s</TITLE>\n" \ | |
1918 "</HEAD><BODY>\n" \ | |
1919 "<H1>Method Not Implemented</H1>\n" \ | |
1920 "Invalid method in request<P>\n" \ | |
1921 "</BODY></HTML>\n" | |
1922 | |
1923 struct evbuffer *buf = evbuffer_new(); | |
1924 | |
1925 /* close the connection on error */ | |
1926 evhttp_add_header(req->output_headers, "Connection", "close"); | |
1927 | |
1928 evhttp_response_code(req, error, reason); | |
1929 | |
1930 evbuffer_add_printf(buf, ERR_FORMAT, error, reason); | |
1931 | |
1932 evhttp_send_page(req, buf); | |
1933 | |
1934 evbuffer_free(buf); | |
1935 #undef ERR_FORMAT | |
1936 } | |
1937 | |
1938 /* Requires that headers and response code are already set up */ | |
1939 | |
1940 static inline void | |
1941 evhttp_send(struct evhttp_request *req, struct evbuffer *databuf) | |
1942 { | |
1943 struct evhttp_connection *evcon = req->evcon; | |
1944 | |
1945 if (evcon == NULL) { | |
1946 evhttp_request_free(req); | |
1947 return; | |
1948 } | |
1949 | |
1950 assert(TAILQ_FIRST(&evcon->requests) == req); | |
1951 | |
1952 /* we expect no more calls form the user on this request */ | |
1953 req->userdone = 1; | |
1954 | |
1955 /* xxx: not sure if we really should expose the data buffer this way */ | |
1956 if (databuf != NULL) | |
1957 evbuffer_add_buffer(req->output_buffer, databuf); | |
1958 | |
1959 /* Adds headers to the response */ | |
1960 evhttp_make_header(evcon, req); | |
1961 | |
1962 evhttp_write_buffer(evcon, evhttp_send_done, NULL); | |
1963 } | |
1964 | |
1965 void | |
1966 evhttp_send_reply(struct evhttp_request *req, int code, const char *reason, | |
1967 struct evbuffer *databuf) | |
1968 { | |
1969 evhttp_response_code(req, code, reason); | |
1970 | |
1971 evhttp_send(req, databuf); | |
1972 } | |
1973 | |
1974 void | |
1975 evhttp_send_reply_start(struct evhttp_request *req, int code, | |
1976 const char *reason) | |
1977 { | |
1978 evhttp_response_code(req, code, reason); | |
1979 if (req->major == 1 && req->minor == 1) { | |
1980 /* use chunked encoding for HTTP/1.1 */ | |
1981 evhttp_add_header(req->output_headers, "Transfer-Encoding", | |
1982 "chunked"); | |
1983 req->chunked = 1; | |
1984 } | |
1985 evhttp_make_header(req->evcon, req); | |
1986 evhttp_write_buffer(req->evcon, NULL, NULL); | |
1987 } | |
1988 | |
1989 void | |
1990 evhttp_send_reply_chunk(struct evhttp_request *req, struct evbuffer *databuf) | |
1991 { | |
1992 struct evhttp_connection *evcon = req->evcon; | |
1993 | |
1994 if (evcon == NULL) | |
1995 return; | |
1996 | |
1997 if (req->chunked) { | |
1998 evbuffer_add_printf(evcon->output_buffer, "%x\r\n", | |
1999 (unsigned)EVBUFFER_LENGTH(databuf)); | |
2000 } | |
2001 evbuffer_add_buffer(evcon->output_buffer, databuf); | |
2002 if (req->chunked) { | |
2003 evbuffer_add(evcon->output_buffer, "\r\n", 2); | |
2004 } | |
2005 evhttp_write_buffer(evcon, NULL, NULL); | |
2006 } | |
2007 | |
2008 void | |
2009 evhttp_send_reply_end(struct evhttp_request *req) | |
2010 { | |
2011 struct evhttp_connection *evcon = req->evcon; | |
2012 | |
2013 if (evcon == NULL) { | |
2014 evhttp_request_free(req); | |
2015 return; | |
2016 } | |
2017 | |
2018 /* we expect no more calls form the user on this request */ | |
2019 req->userdone = 1; | |
2020 | |
2021 if (req->chunked) { | |
2022 evbuffer_add(req->evcon->output_buffer, "0\r\n\r\n", 5); | |
2023 evhttp_write_buffer(req->evcon, evhttp_send_done, NULL); | |
2024 req->chunked = 0; | |
2025 } else if (!event_pending(&evcon->ev, EV_WRITE|EV_TIMEOUT, NULL)) { | |
2026 /* let the connection know that we are done with the request */ | |
2027 evhttp_send_done(evcon, NULL); | |
2028 } else { | |
2029 /* make the callback execute after all data has been written */ | |
2030 evcon->cb = evhttp_send_done; | |
2031 evcon->cb_arg = NULL; | |
2032 } | |
2033 } | |
2034 | |
2035 void | |
2036 evhttp_response_code(struct evhttp_request *req, int code, const char *reason) | |
2037 { | |
2038 req->kind = EVHTTP_RESPONSE; | |
2039 req->response_code = code; | |
2040 if (req->response_code_line != NULL) | |
2041 free(req->response_code_line); | |
2042 req->response_code_line = strdup(reason); | |
2043 } | |
2044 | |
2045 void | |
2046 evhttp_send_page(struct evhttp_request *req, struct evbuffer *databuf) | |
2047 { | |
2048 if (!req->major || !req->minor) { | |
2049 req->major = 1; | |
2050 req->minor = 1; | |
2051 } | |
2052 | |
2053 if (req->kind != EVHTTP_RESPONSE) | |
2054 evhttp_response_code(req, 200, "OK"); | |
2055 | |
2056 evhttp_clear_headers(req->output_headers); | |
2057 evhttp_add_header(req->output_headers, "Content-Type", "text/html"); | |
2058 evhttp_add_header(req->output_headers, "Connection", "close"); | |
2059 | |
2060 evhttp_send(req, databuf); | |
2061 } | |
2062 | |
2063 static const char uri_chars[256] = { | |
2064 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | |
2065 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | |
2066 0, 1, 0, 0, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, | |
2067 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 0, 0, | |
2068 /* 64 */ | |
2069 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, | |
2070 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, | |
2071 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, | |
2072 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0, | |
2073 /* 128 */ | |
2074 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | |
2075 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | |
2076 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | |
2077 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | |
2078 /* 192 */ | |
2079 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | |
2080 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | |
2081 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | |
2082 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | |
2083 }; | |
2084 | |
2085 /* | |
2086 * Helper functions to encode/decode a URI. | |
2087 * The returned string must be freed by the caller. | |
2088 */ | |
2089 char * | |
2090 evhttp_encode_uri(const char *uri) | |
2091 { | |
2092 struct evbuffer *buf = evbuffer_new(); | |
2093 char *p; | |
2094 | |
2095 for (p = (char *)uri; *p != '\0'; p++) { | |
2096 if (uri_chars[(u_char)(*p)]) { | |
2097 evbuffer_add(buf, p, 1); | |
2098 } else { | |
2099 evbuffer_add_printf(buf, "%%%02X", (u_char)(*p)); | |
2100 } | |
2101 } | |
2102 evbuffer_add(buf, "", 1); | |
2103 p = strdup((char *)EVBUFFER_DATA(buf)); | |
2104 evbuffer_free(buf); | |
2105 | |
2106 return (p); | |
2107 } | |
2108 | |
2109 /* | |
2110 * @param always_decode_plus: when true we transform plus to space even | |
2111 * if we have not seen a ?. | |
2112 */ | |
2113 static int | |
2114 evhttp_decode_uri_internal( | |
2115 const char *uri, size_t length, char *ret, int always_decode_plus) | |
2116 { | |
2117 char c; | |
2118 int i, j, in_query = always_decode_plus; | |
2119 | |
2120 for (i = j = 0; uri[i] != '\0'; i++) { | |
2121 c = uri[i]; | |
2122 if (c == '?') { | |
2123 in_query = 1; | |
2124 } else if (c == '+' && in_query) { | |
2125 c = ' '; | |
2126 } else if (c == '%' && isxdigit((unsigned char)uri[i+1]) && | |
2127 isxdigit((unsigned char)uri[i+2])) { | |
2128 char tmp[] = { uri[i+1], uri[i+2], '\0' }; | |
2129 c = (char)strtol(tmp, NULL, 16); | |
2130 i += 2; | |
2131 } | |
2132 ret[j++] = c; | |
2133 } | |
2134 ret[j] = '\0'; | |
2135 | |
2136 return (j); | |
2137 } | |
2138 | |
2139 char * | |
2140 evhttp_decode_uri(const char *uri) | |
2141 { | |
2142 char *ret; | |
2143 | |
2144 if ((ret = malloc(strlen(uri) + 1)) == NULL) | |
2145 event_err(1, "%s: malloc(%lu)", __func__, | |
2146 (unsigned long)(strlen(uri) + 1)); | |
2147 | |
2148 evhttp_decode_uri_internal(uri, strlen(uri), | |
2149 ret, 0 /*always_decode_plus*/); | |
2150 | |
2151 return (ret); | |
2152 } | |
2153 | |
2154 /* | |
2155 * Helper function to parse out arguments in a query. | |
2156 * The arguments are separated by key and value. | |
2157 */ | |
2158 | |
2159 void | |
2160 evhttp_parse_query(const char *uri, struct evkeyvalq *headers) | |
2161 { | |
2162 char *line; | |
2163 char *argument; | |
2164 char *p; | |
2165 | |
2166 TAILQ_INIT(headers); | |
2167 | |
2168 /* No arguments - we are done */ | |
2169 if (strchr(uri, '?') == NULL) | |
2170 return; | |
2171 | |
2172 if ((line = strdup(uri)) == NULL) | |
2173 event_err(1, "%s: strdup", __func__); | |
2174 | |
2175 | |
2176 argument = line; | |
2177 | |
2178 /* We already know that there has to be a ? */ | |
2179 strsep(&argument, "?"); | |
2180 | |
2181 p = argument; | |
2182 while (p != NULL && *p != '\0') { | |
2183 char *key, *value, *decoded_value; | |
2184 argument = strsep(&p, "&"); | |
2185 | |
2186 value = argument; | |
2187 key = strsep(&value, "="); | |
2188 if (value == NULL) | |
2189 goto error; | |
2190 | |
2191 if ((decoded_value = malloc(strlen(value) + 1)) == NULL) | |
2192 event_err(1, "%s: malloc", __func__); | |
2193 | |
2194 evhttp_decode_uri_internal(value, strlen(value), | |
2195 decoded_value, 1 /*always_decode_plus*/); | |
2196 event_debug(("Query Param: %s -> %s\n", key, decoded_value)); | |
2197 evhttp_add_header_internal(headers, key, decoded_value); | |
2198 free(decoded_value); | |
2199 } | |
2200 | |
2201 error: | |
2202 free(line); | |
2203 } | |
2204 | |
2205 static struct evhttp_cb * | |
2206 evhttp_dispatch_callback(struct httpcbq *callbacks, struct evhttp_request *req) | |
2207 { | |
2208 struct evhttp_cb *cb; | |
2209 size_t offset = 0; | |
2210 | |
2211 /* Test for different URLs */ | |
2212 char *p = strchr(req->uri, '?'); | |
2213 if (p != NULL) | |
2214 offset = (size_t)(p - req->uri); | |
2215 | |
2216 TAILQ_FOREACH(cb, callbacks, next) { | |
2217 int res = 0; | |
2218 if (p == NULL) { | |
2219 res = strcmp(cb->what, req->uri) == 0; | |
2220 } else { | |
2221 res = ((strncmp(cb->what, req->uri, offset) == 0) && | |
2222 (cb->what[offset] == '\0')); | |
2223 } | |
2224 | |
2225 if (res) | |
2226 return (cb); | |
2227 } | |
2228 | |
2229 return (NULL); | |
2230 } | |
2231 | |
2232 static void | |
2233 evhttp_handle_request(struct evhttp_request *req, void *arg) | |
2234 { | |
2235 struct evhttp *http = arg; | |
2236 struct evhttp_cb *cb = NULL; | |
2237 | |
2238 event_debug(("%s: req->uri=%s", __func__, req->uri)); | |
2239 if (req->uri == NULL) { | |
2240 event_debug(("%s: bad request", __func__)); | |
2241 if (req->evcon->state == EVCON_DISCONNECTED) { | |
2242 evhttp_connection_fail(req->evcon, EVCON_HTTP_EOF); | |
2243 } else { | |
2244 event_debug(("%s: sending error", __func__)); | |
2245 evhttp_send_error(req, HTTP_BADREQUEST, "Bad Request"); | |
2246 } | |
2247 return; | |
2248 } | |
2249 | |
2250 if ((cb = evhttp_dispatch_callback(&http->callbacks, req)) != NULL) { | |
2251 (*cb->cb)(req, cb->cbarg); | |
2252 return; | |
2253 } | |
2254 | |
2255 /* Generic call back */ | |
2256 if (http->gencb) { | |
2257 (*http->gencb)(req, http->gencbarg); | |
2258 return; | |
2259 } else { | |
2260 /* We need to send a 404 here */ | |
2261 #define ERR_FORMAT "<html><head>" \ | |
2262 "<title>404 Not Found</title>" \ | |
2263 "</head><body>" \ | |
2264 "<h1>Not Found</h1>" \ | |
2265 "<p>The requested URL %s was not found on this server.</p>"\ | |
2266 "</body></html>\n" | |
2267 | |
2268 char *escaped_html = evhttp_htmlescape(req->uri); | |
2269 struct evbuffer *buf = evbuffer_new(); | |
2270 | |
2271 evhttp_response_code(req, HTTP_NOTFOUND, "Not Found"); | |
2272 | |
2273 evbuffer_add_printf(buf, ERR_FORMAT, escaped_html); | |
2274 | |
2275 free(escaped_html); | |
2276 | |
2277 evhttp_send_page(req, buf); | |
2278 | |
2279 evbuffer_free(buf); | |
2280 #undef ERR_FORMAT | |
2281 } | |
2282 } | |
2283 | |
2284 static void | |
2285 accept_socket(int fd, short what, void *arg) | |
2286 { | |
2287 struct evhttp *http = arg; | |
2288 struct sockaddr_storage ss; | |
2289 socklen_t addrlen = sizeof(ss); | |
2290 int nfd; | |
2291 | |
2292 if ((nfd = accept(fd, (struct sockaddr *)&ss, &addrlen)) == -1) { | |
2293 if (errno != EAGAIN && errno != EINTR) | |
2294 event_warn("%s: bad accept", __func__); | |
2295 return; | |
2296 } | |
2297 if (evutil_make_socket_nonblocking(nfd) < 0) | |
2298 return; | |
2299 | |
2300 evhttp_get_request(http, nfd, (struct sockaddr *)&ss, addrlen); | |
2301 } | |
2302 | |
2303 int | |
2304 evhttp_bind_socket(struct evhttp *http, const char *address, u_short port) | |
2305 { | |
2306 int fd; | |
2307 int res; | |
2308 | |
2309 if ((fd = bind_socket(address, port, 1 /*reuse*/)) == -1) | |
2310 return (-1); | |
2311 | |
2312 if (listen(fd, 128) == -1) { | |
2313 event_warn("%s: listen", __func__); | |
2314 EVUTIL_CLOSESOCKET(fd); | |
2315 return (-1); | |
2316 } | |
2317 | |
2318 res = evhttp_accept_socket(http, fd); | |
2319 | |
2320 if (res != -1) | |
2321 event_debug(("Bound to port %d - Awaiting connections ... ", | |
2322 port)); | |
2323 | |
2324 return (res); | |
2325 } | |
2326 | |
2327 int | |
2328 evhttp_accept_socket(struct evhttp *http, int fd) | |
2329 { | |
2330 struct evhttp_bound_socket *bound; | |
2331 struct event *ev; | |
2332 int res; | |
2333 | |
2334 bound = malloc(sizeof(struct evhttp_bound_socket)); | |
2335 if (bound == NULL) | |
2336 return (-1); | |
2337 | |
2338 ev = &bound->bind_ev; | |
2339 | |
2340 /* Schedule the socket for accepting */ | |
2341 event_set(ev, fd, EV_READ | EV_PERSIST, accept_socket, http); | |
2342 EVHTTP_BASE_SET(http, ev); | |
2343 | |
2344 res = event_add(ev, NULL); | |
2345 | |
2346 if (res == -1) { | |
2347 free(bound); | |
2348 return (-1); | |
2349 } | |
2350 | |
2351 TAILQ_INSERT_TAIL(&http->sockets, bound, next); | |
2352 | |
2353 return (0); | |
2354 } | |
2355 | |
2356 static struct evhttp* | |
2357 evhttp_new_object(void) | |
2358 { | |
2359 struct evhttp *http = NULL; | |
2360 | |
2361 if ((http = calloc(1, sizeof(struct evhttp))) == NULL) { | |
2362 event_warn("%s: calloc", __func__); | |
2363 return (NULL); | |
2364 } | |
2365 | |
2366 http->timeout = -1; | |
2367 | |
2368 TAILQ_INIT(&http->sockets); | |
2369 TAILQ_INIT(&http->callbacks); | |
2370 TAILQ_INIT(&http->connections); | |
2371 | |
2372 return (http); | |
2373 } | |
2374 | |
2375 struct evhttp * | |
2376 evhttp_new(struct event_base *base) | |
2377 { | |
2378 struct evhttp *http = evhttp_new_object(); | |
2379 | |
2380 http->base = base; | |
2381 | |
2382 return (http); | |
2383 } | |
2384 | |
2385 /* | |
2386 * Start a web server on the specified address and port. | |
2387 */ | |
2388 | |
2389 struct evhttp * | |
2390 evhttp_start(const char *address, u_short port) | |
2391 { | |
2392 struct evhttp *http = evhttp_new_object(); | |
2393 | |
2394 if (evhttp_bind_socket(http, address, port) == -1) { | |
2395 free(http); | |
2396 return (NULL); | |
2397 } | |
2398 | |
2399 return (http); | |
2400 } | |
2401 | |
2402 void | |
2403 evhttp_free(struct evhttp* http) | |
2404 { | |
2405 struct evhttp_cb *http_cb; | |
2406 struct evhttp_connection *evcon; | |
2407 struct evhttp_bound_socket *bound; | |
2408 int fd; | |
2409 | |
2410 /* Remove the accepting part */ | |
2411 while ((bound = TAILQ_FIRST(&http->sockets)) != NULL) { | |
2412 TAILQ_REMOVE(&http->sockets, bound, next); | |
2413 | |
2414 fd = bound->bind_ev.ev_fd; | |
2415 event_del(&bound->bind_ev); | |
2416 EVUTIL_CLOSESOCKET(fd); | |
2417 | |
2418 free(bound); | |
2419 } | |
2420 | |
2421 while ((evcon = TAILQ_FIRST(&http->connections)) != NULL) { | |
2422 /* evhttp_connection_free removes the connection */ | |
2423 evhttp_connection_free(evcon); | |
2424 } | |
2425 | |
2426 while ((http_cb = TAILQ_FIRST(&http->callbacks)) != NULL) { | |
2427 TAILQ_REMOVE(&http->callbacks, http_cb, next); | |
2428 free(http_cb->what); | |
2429 free(http_cb); | |
2430 } | |
2431 | |
2432 free(http); | |
2433 } | |
2434 | |
2435 void | |
2436 evhttp_set_timeout(struct evhttp* http, int timeout_in_secs) | |
2437 { | |
2438 http->timeout = timeout_in_secs; | |
2439 } | |
2440 | |
2441 void | |
2442 evhttp_set_cb(struct evhttp *http, const char *uri, | |
2443 void (*cb)(struct evhttp_request *, void *), void *cbarg) | |
2444 { | |
2445 struct evhttp_cb *http_cb; | |
2446 | |
2447 if ((http_cb = calloc(1, sizeof(struct evhttp_cb))) == NULL) | |
2448 event_err(1, "%s: calloc", __func__); | |
2449 | |
2450 http_cb->what = strdup(uri); | |
2451 http_cb->cb = cb; | |
2452 http_cb->cbarg = cbarg; | |
2453 | |
2454 TAILQ_INSERT_TAIL(&http->callbacks, http_cb, next); | |
2455 } | |
2456 | |
2457 int | |
2458 evhttp_del_cb(struct evhttp *http, const char *uri) | |
2459 { | |
2460 struct evhttp_cb *http_cb; | |
2461 | |
2462 TAILQ_FOREACH(http_cb, &http->callbacks, next) { | |
2463 if (strcmp(http_cb->what, uri) == 0) | |
2464 break; | |
2465 } | |
2466 if (http_cb == NULL) | |
2467 return (-1); | |
2468 | |
2469 TAILQ_REMOVE(&http->callbacks, http_cb, next); | |
2470 free(http_cb->what); | |
2471 free(http_cb); | |
2472 | |
2473 return (0); | |
2474 } | |
2475 | |
2476 void | |
2477 evhttp_set_gencb(struct evhttp *http, | |
2478 void (*cb)(struct evhttp_request *, void *), void *cbarg) | |
2479 { | |
2480 http->gencb = cb; | |
2481 http->gencbarg = cbarg; | |
2482 } | |
2483 | |
2484 /* | |
2485 * Request related functions | |
2486 */ | |
2487 | |
2488 struct evhttp_request * | |
2489 evhttp_request_new(void (*cb)(struct evhttp_request *, void *), void *arg) | |
2490 { | |
2491 struct evhttp_request *req = NULL; | |
2492 | |
2493 /* Allocate request structure */ | |
2494 if ((req = calloc(1, sizeof(struct evhttp_request))) == NULL) { | |
2495 event_warn("%s: calloc", __func__); | |
2496 goto error; | |
2497 } | |
2498 | |
2499 req->kind = EVHTTP_RESPONSE; | |
2500 req->input_headers = calloc(1, sizeof(struct evkeyvalq)); | |
2501 if (req->input_headers == NULL) { | |
2502 event_warn("%s: calloc", __func__); | |
2503 goto error; | |
2504 } | |
2505 TAILQ_INIT(req->input_headers); | |
2506 | |
2507 req->output_headers = calloc(1, sizeof(struct evkeyvalq)); | |
2508 if (req->output_headers == NULL) { | |
2509 event_warn("%s: calloc", __func__); | |
2510 goto error; | |
2511 } | |
2512 TAILQ_INIT(req->output_headers); | |
2513 | |
2514 if ((req->input_buffer = evbuffer_new()) == NULL) { | |
2515 event_warn("%s: evbuffer_new", __func__); | |
2516 goto error; | |
2517 } | |
2518 | |
2519 if ((req->output_buffer = evbuffer_new()) == NULL) { | |
2520 event_warn("%s: evbuffer_new", __func__); | |
2521 goto error; | |
2522 } | |
2523 | |
2524 req->cb = cb; | |
2525 req->cb_arg = arg; | |
2526 | |
2527 return (req); | |
2528 | |
2529 error: | |
2530 if (req != NULL) | |
2531 evhttp_request_free(req); | |
2532 return (NULL); | |
2533 } | |
2534 | |
2535 void | |
2536 evhttp_request_free(struct evhttp_request *req) | |
2537 { | |
2538 if (req->remote_host != NULL) | |
2539 free(req->remote_host); | |
2540 if (req->uri != NULL) | |
2541 free(req->uri); | |
2542 if (req->response_code_line != NULL) | |
2543 free(req->response_code_line); | |
2544 | |
2545 evhttp_clear_headers(req->input_headers); | |
2546 free(req->input_headers); | |
2547 | |
2548 evhttp_clear_headers(req->output_headers); | |
2549 free(req->output_headers); | |
2550 | |
2551 if (req->input_buffer != NULL) | |
2552 evbuffer_free(req->input_buffer); | |
2553 | |
2554 if (req->output_buffer != NULL) | |
2555 evbuffer_free(req->output_buffer); | |
2556 | |
2557 free(req); | |
2558 } | |
2559 | |
2560 struct evhttp_connection * | |
2561 evhttp_request_get_connection(struct evhttp_request *req) | |
2562 { | |
2563 return req->evcon; | |
2564 } | |
2565 | |
2566 | |
2567 void | |
2568 evhttp_request_set_chunked_cb(struct evhttp_request *req, | |
2569 void (*cb)(struct evhttp_request *, void *)) | |
2570 { | |
2571 req->chunk_cb = cb; | |
2572 } | |
2573 | |
2574 /* | |
2575 * Allows for inspection of the request URI | |
2576 */ | |
2577 | |
2578 const char * | |
2579 evhttp_request_uri(struct evhttp_request *req) { | |
2580 if (req->uri == NULL) | |
2581 event_debug(("%s: request %p has no uri\n", __func__, req)); | |
2582 return (req->uri); | |
2583 } | |
2584 | |
2585 /* | |
2586 * Takes a file descriptor to read a request from. | |
2587 * The callback is executed once the whole request has been read. | |
2588 */ | |
2589 | |
2590 static struct evhttp_connection* | |
2591 evhttp_get_request_connection( | |
2592 struct evhttp* http, | |
2593 int fd, struct sockaddr *sa, socklen_t salen) | |
2594 { | |
2595 struct evhttp_connection *evcon; | |
2596 char *hostname = NULL, *portname = NULL; | |
2597 | |
2598 name_from_addr(sa, salen, &hostname, &portname); | |
2599 if (hostname == NULL || portname == NULL) { | |
2600 if (hostname) free(hostname); | |
2601 if (portname) free(portname); | |
2602 return (NULL); | |
2603 } | |
2604 | |
2605 event_debug(("%s: new request from %s:%s on %d\n", | |
2606 __func__, hostname, portname, fd)); | |
2607 | |
2608 /* we need a connection object to put the http request on */ | |
2609 evcon = evhttp_connection_new(hostname, atoi(portname)); | |
2610 free(hostname); | |
2611 free(portname); | |
2612 if (evcon == NULL) | |
2613 return (NULL); | |
2614 | |
2615 /* associate the base if we have one*/ | |
2616 evhttp_connection_set_base(evcon, http->base); | |
2617 | |
2618 evcon->flags |= EVHTTP_CON_INCOMING; | |
2619 evcon->state = EVCON_READING_FIRSTLINE; | |
2620 | |
2621 evcon->fd = fd; | |
2622 | |
2623 return (evcon); | |
2624 } | |
2625 | |
2626 static int | |
2627 evhttp_associate_new_request_with_connection(struct evhttp_connection *evcon) | |
2628 { | |
2629 struct evhttp *http = evcon->http_server; | |
2630 struct evhttp_request *req; | |
2631 if ((req = evhttp_request_new(evhttp_handle_request, http)) == NULL) | |
2632 return (-1); | |
2633 | |
2634 req->evcon = evcon; /* the request ends up owning the connection */ | |
2635 req->flags |= EVHTTP_REQ_OWN_CONNECTION; | |
2636 | |
2637 TAILQ_INSERT_TAIL(&evcon->requests, req, next); | |
2638 | |
2639 req->kind = EVHTTP_REQUEST; | |
2640 | |
2641 if ((req->remote_host = strdup(evcon->address)) == NULL) | |
2642 event_err(1, "%s: strdup", __func__); | |
2643 req->remote_port = evcon->port; | |
2644 | |
2645 evhttp_start_read(evcon); | |
2646 | |
2647 return (0); | |
2648 } | |
2649 | |
2650 void | |
2651 evhttp_get_request(struct evhttp *http, int fd, | |
2652 struct sockaddr *sa, socklen_t salen) | |
2653 { | |
2654 struct evhttp_connection *evcon; | |
2655 | |
2656 evcon = evhttp_get_request_connection(http, fd, sa, salen); | |
2657 if (evcon == NULL) | |
2658 return; | |
2659 | |
2660 /* the timeout can be used by the server to close idle connections */ | |
2661 if (http->timeout != -1) | |
2662 evhttp_connection_set_timeout(evcon, http->timeout); | |
2663 | |
2664 /* | |
2665 * if we want to accept more than one request on a connection, | |
2666 * we need to know which http server it belongs to. | |
2667 */ | |
2668 evcon->http_server = http; | |
2669 TAILQ_INSERT_TAIL(&http->connections, evcon, next); | |
2670 | |
2671 if (evhttp_associate_new_request_with_connection(evcon) == -1) | |
2672 evhttp_connection_free(evcon); | |
2673 } | |
2674 | |
2675 | |
2676 /* | |
2677 * Network helper functions that we do not want to export to the rest of | |
2678 * the world. | |
2679 */ | |
2680 #if 0 /* Unused */ | |
2681 static struct addrinfo * | |
2682 addr_from_name(char *address) | |
2683 { | |
2684 #ifdef HAVE_GETADDRINFO | |
2685 struct addrinfo ai, *aitop; | |
2686 int ai_result; | |
2687 | |
2688 memset(&ai, 0, sizeof(ai)); | |
2689 ai.ai_family = AF_INET; | |
2690 ai.ai_socktype = SOCK_RAW; | |
2691 ai.ai_flags = 0; | |
2692 if ((ai_result = getaddrinfo(address, NULL, &ai, &aitop)) != 0) { | |
2693 if ( ai_result == EAI_SYSTEM ) | |
2694 event_warn("getaddrinfo"); | |
2695 else | |
2696 event_warnx("getaddrinfo: %s", gai_strerror(ai_result)); | |
2697 } | |
2698 | |
2699 return (aitop); | |
2700 #else | |
2701 assert(0); | |
2702 return NULL; /* XXXXX Use gethostbyname, if this function is ever used.
*/ | |
2703 #endif | |
2704 } | |
2705 #endif | |
2706 | |
2707 static void | |
2708 name_from_addr(struct sockaddr *sa, socklen_t salen, | |
2709 char **phost, char **pport) | |
2710 { | |
2711 char ntop[NI_MAXHOST]; | |
2712 char strport[NI_MAXSERV]; | |
2713 int ni_result; | |
2714 | |
2715 #ifdef HAVE_GETNAMEINFO | |
2716 ni_result = getnameinfo(sa, salen, | |
2717 ntop, sizeof(ntop), strport, sizeof(strport), | |
2718 NI_NUMERICHOST|NI_NUMERICSERV); | |
2719 | |
2720 if (ni_result != 0) { | |
2721 if (ni_result == EAI_SYSTEM) | |
2722 event_err(1, "getnameinfo failed"); | |
2723 else | |
2724 event_errx(1, "getnameinfo failed: %s", gai_strerror(ni_
result)); | |
2725 return; | |
2726 } | |
2727 #else | |
2728 ni_result = fake_getnameinfo(sa, salen, | |
2729 ntop, sizeof(ntop), strport, sizeof(strport), | |
2730 NI_NUMERICHOST|NI_NUMERICSERV); | |
2731 if (ni_result != 0) | |
2732 return; | |
2733 #endif | |
2734 *phost = strdup(ntop); | |
2735 *pport = strdup(strport); | |
2736 } | |
2737 | |
2738 /* Create a non-blocking socket and bind it */ | |
2739 /* todo: rename this function */ | |
2740 static int | |
2741 bind_socket_ai(struct addrinfo *ai, int reuse) | |
2742 { | |
2743 int fd, on = 1, r; | |
2744 int serrno; | |
2745 | |
2746 /* Create listen socket */ | |
2747 fd = socket(AF_INET, SOCK_STREAM, 0); | |
2748 if (fd == -1) { | |
2749 event_warn("socket"); | |
2750 return (-1); | |
2751 } | |
2752 | |
2753 if (evutil_make_socket_nonblocking(fd) < 0) | |
2754 goto out; | |
2755 | |
2756 #ifndef WIN32 | |
2757 if (fcntl(fd, F_SETFD, 1) == -1) { | |
2758 event_warn("fcntl(F_SETFD)"); | |
2759 goto out; | |
2760 } | |
2761 #endif | |
2762 | |
2763 setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, (void *)&on, sizeof(on)); | |
2764 if (reuse) { | |
2765 setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, | |
2766 (void *)&on, sizeof(on)); | |
2767 } | |
2768 | |
2769 if (ai != NULL) { | |
2770 r = bind(fd, ai->ai_addr, ai->ai_addrlen); | |
2771 if (r == -1) | |
2772 goto out; | |
2773 } | |
2774 | |
2775 return (fd); | |
2776 | |
2777 out: | |
2778 serrno = EVUTIL_SOCKET_ERROR(); | |
2779 EVUTIL_CLOSESOCKET(fd); | |
2780 EVUTIL_SET_SOCKET_ERROR(serrno); | |
2781 return (-1); | |
2782 } | |
2783 | |
2784 static struct addrinfo * | |
2785 make_addrinfo(const char *address, u_short port) | |
2786 { | |
2787 struct addrinfo *aitop = NULL; | |
2788 | |
2789 #ifdef HAVE_GETADDRINFO | |
2790 struct addrinfo ai; | |
2791 char strport[NI_MAXSERV]; | |
2792 int ai_result; | |
2793 | |
2794 memset(&ai, 0, sizeof(ai)); | |
2795 ai.ai_family = AF_INET; | |
2796 ai.ai_socktype = SOCK_STREAM; | |
2797 ai.ai_flags = AI_PASSIVE; /* turn NULL host name into INADDR_ANY */ | |
2798 evutil_snprintf(strport, sizeof(strport), "%d", port); | |
2799 if ((ai_result = getaddrinfo(address, strport, &ai, &aitop)) != 0) { | |
2800 if ( ai_result == EAI_SYSTEM ) | |
2801 event_warn("getaddrinfo"); | |
2802 else | |
2803 event_warnx("getaddrinfo: %s", gai_strerror(ai_result)); | |
2804 return (NULL); | |
2805 } | |
2806 #else | |
2807 static int cur; | |
2808 static struct addrinfo ai[2]; /* We will be returning the address of som
e of this memory so it has to last even after this call. */ | |
2809 if (++cur == 2) cur = 0; /* allow calling this function twice */ | |
2810 | |
2811 if (fake_getaddrinfo(address, &ai[cur]) < 0) { | |
2812 event_warn("fake_getaddrinfo"); | |
2813 return (NULL); | |
2814 } | |
2815 aitop = &ai[cur]; | |
2816 ((struct sockaddr_in *) aitop->ai_addr)->sin_port = htons(port); | |
2817 #endif | |
2818 | |
2819 return (aitop); | |
2820 } | |
2821 | |
2822 static int | |
2823 bind_socket(const char *address, u_short port, int reuse) | |
2824 { | |
2825 int fd; | |
2826 struct addrinfo *aitop = NULL; | |
2827 | |
2828 /* just create an unbound socket */ | |
2829 if (address == NULL && port == 0) | |
2830 return bind_socket_ai(NULL, 0); | |
2831 | |
2832 aitop = make_addrinfo(address, port); | |
2833 | |
2834 if (aitop == NULL) | |
2835 return (-1); | |
2836 | |
2837 fd = bind_socket_ai(aitop, reuse); | |
2838 | |
2839 #ifdef HAVE_GETADDRINFO | |
2840 freeaddrinfo(aitop); | |
2841 #else | |
2842 fake_freeaddrinfo(aitop); | |
2843 #endif | |
2844 | |
2845 return (fd); | |
2846 } | |
2847 | |
2848 static int | |
2849 socket_connect(int fd, const char *address, unsigned short port) | |
2850 { | |
2851 struct addrinfo *ai = make_addrinfo(address, port); | |
2852 int res = -1; | |
2853 | |
2854 if (ai == NULL) { | |
2855 event_debug(("%s: make_addrinfo: \"%s:%d\"", | |
2856 __func__, address, port)); | |
2857 return (-1); | |
2858 } | |
2859 | |
2860 if (connect(fd, ai->ai_addr, ai->ai_addrlen) == -1) { | |
2861 #ifdef WIN32 | |
2862 int tmp_error = WSAGetLastError(); | |
2863 if (tmp_error != WSAEWOULDBLOCK && tmp_error != WSAEINVAL && | |
2864 tmp_error != WSAEINPROGRESS) { | |
2865 goto out; | |
2866 } | |
2867 #else | |
2868 if (errno != EINPROGRESS) { | |
2869 goto out; | |
2870 } | |
2871 #endif | |
2872 } | |
2873 | |
2874 /* everything is fine */ | |
2875 res = 0; | |
2876 | |
2877 out: | |
2878 #ifdef HAVE_GETADDRINFO | |
2879 freeaddrinfo(ai); | |
2880 #else | |
2881 fake_freeaddrinfo(ai); | |
2882 #endif | |
2883 | |
2884 return (res); | |
2885 } | |
OLD | NEW |