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