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