2 * Copyright (c) 2002-2006 Niels Provos <provos@citi.umich.edu>
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
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.
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.
32 #ifdef HAVE_SYS_PARAM_H
33 #include <sys/param.h>
35 #ifdef HAVE_SYS_TYPES_H
36 #include <sys/types.h>
39 #ifdef HAVE_SYS_TIME_H
42 #ifdef HAVE_SYS_IOCCOM_H
43 #include <sys/ioccom.h>
47 #include <sys/resource.h>
48 #include <sys/socket.h>
53 #include <sys/queue.h>
56 #include <netinet/in.h>
82 #undef timeout_pending
83 #undef timeout_initialized
85 #include "strlcpy-internal.h"
90 #include "http-internal.h"
93 #define strcasecmp _stricmp
94 #define strncasecmp _strnicmp
95 #define strdup _strdup
98 #ifndef HAVE_GETNAMEINFO
100 #define NI_MAXHOST 1025
102 #define NI_NUMERICHOST 1
103 #define NI_NUMERICSERV 2
106 fake_getnameinfo(const struct sockaddr
*sa
, size_t salen
, char *host
,
107 size_t hostlen
, char *serv
, size_t servlen
, int flags
)
109 struct sockaddr_in
*sin
= (struct sockaddr_in
*)sa
;
113 evutil_snprintf(tmpserv
, sizeof(tmpserv
),
114 "%d", ntohs(sin
->sin_port
));
115 if (strlcpy(serv
, tmpserv
, servlen
) >= servlen
)
120 if (flags
& NI_NUMERICHOST
) {
121 if (strlcpy(host
, inet_ntoa(sin
->sin_addr
),
128 hp
= gethostbyaddr((char *)&sin
->sin_addr
,
129 sizeof(struct in_addr
), AF_INET
);
133 if (strlcpy(host
, hp
->h_name
, hostlen
) >= hostlen
)
144 #ifndef HAVE_GETADDRINFO
150 struct sockaddr
*ai_addr
;
151 struct addrinfo
*ai_next
;
154 fake_getaddrinfo(const char *hostname
, struct addrinfo
*ai
)
156 struct hostent
*he
= NULL
;
157 struct sockaddr_in
*sa
;
159 he
= gethostbyname(hostname
);
163 ai
->ai_family
= he
? he
->h_addrtype
: AF_INET
;
164 ai
->ai_socktype
= SOCK_STREAM
;
166 ai
->ai_addrlen
= sizeof(struct sockaddr_in
);
167 if (NULL
== (ai
->ai_addr
= malloc(ai
->ai_addrlen
)))
169 sa
= (struct sockaddr_in
*)ai
->ai_addr
;
170 memset(sa
, 0, ai
->ai_addrlen
);
172 sa
->sin_family
= he
->h_addrtype
;
173 memcpy(&sa
->sin_addr
, he
->h_addr_list
[0], he
->h_length
);
175 sa
->sin_family
= AF_INET
;
176 sa
->sin_addr
.s_addr
= INADDR_ANY
;
182 fake_freeaddrinfo(struct addrinfo
*ai
)
189 #define MIN(a,b) (((a)<(b))?(a):(b))
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); \
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
);
219 void evhttp_read(int, short, void *);
220 void evhttp_write(int, short, void *);
223 /* strsep replacement for platforms that lack it. Only works if
224 * del is one character long. */
226 strsep(char **s
, const char *del
)
229 assert(strlen(del
) == 1);
233 d
= strstr(tok
, del
);
244 html_replace(char ch
, char *buf
)
261 /* Echo the character back */
269 * Replaces <, >, ", ' and & with <, >, ",
270 * ' and & correspondingly.
272 * The returned string needs to be freed by the caller.
276 evhttp_htmlescape(const char *html
)
278 int i
, new_size
= 0, old_size
= strlen(html
);
279 char *escaped_html
, *p
;
280 char scratch_space
[2];
282 for (i
= 0; i
< old_size
; ++i
)
283 new_size
+= strlen(html_replace(html
[i
], scratch_space
));
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 */
292 p
+= strlen(replaced
);
297 return (escaped_html
);
301 evhttp_method(enum evhttp_cmd_type type
)
309 case EVHTTP_REQ_POST
:
312 case EVHTTP_REQ_HEAD
:
324 evhttp_add_event(struct event
*ev
, int timeout
, int default_timeout
)
329 evutil_timerclear(&tv
);
330 tv
.tv_sec
= timeout
!= -1 ? timeout
: default_timeout
;
338 evhttp_write_buffer(struct evhttp_connection
*evcon
,
339 void (*cb
)(struct evhttp_connection
*, void *), void *arg
)
341 event_debug(("%s: preparing to write buffer\n", __func__
));
347 /* check if the event is already pending */
348 if (event_pending(&evcon
->ev
, EV_WRITE
|EV_TIMEOUT
, NULL
))
349 event_del(&evcon
->ev
);
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
);
357 evhttp_connected(struct evhttp_connection
*evcon
)
359 switch (evcon
->state
) {
360 case EVCON_DISCONNECTED
:
361 case EVCON_CONNECTING
:
364 case EVCON_READING_FIRSTLINE
:
365 case EVCON_READING_HEADERS
:
366 case EVCON_READING_BODY
:
367 case EVCON_READING_TRAILER
:
375 * Create the headers needed for an HTTP request
378 evhttp_make_header_request(struct evhttp_connection
*evcon
,
379 struct evhttp_request
*req
)
383 evhttp_remove_header(req
->output_headers
, "Proxy-Connection");
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
);
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
){
394 evutil_snprintf(size
, sizeof(size
), "%ld",
395 (long)EVBUFFER_LENGTH(req
->output_buffer
));
396 evhttp_add_header(req
->output_headers
, "Content-Length", size
);
401 evhttp_is_connection_close(int flags
, struct evkeyvalq
* headers
)
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);
408 const char *connection
= evhttp_find_header(headers
, "Connection");
409 return (connection
!= NULL
&& strcasecmp(connection
, "close") == 0);
414 evhttp_is_connection_keepalive(struct evkeyvalq
* headers
)
416 const char *connection
= evhttp_find_header(headers
, "Connection");
417 return (connection
!= NULL
418 && strncasecmp(connection
, "keep-alive", 10) == 0);
422 evhttp_maybe_add_date_header(struct evkeyvalq
*headers
)
424 if (evhttp_find_header(headers
, "Date") == NULL
) {
430 time_t t
= time(NULL
);
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
);
445 evhttp_maybe_add_content_length_header(struct evkeyvalq
*headers
,
448 if (evhttp_find_header(headers
, "Transfer-Encoding") == NULL
&&
449 evhttp_find_header(headers
, "Content-Length") == NULL
) {
451 evutil_snprintf(len
, sizeof(len
), "%ld", content_length
);
452 evhttp_add_header(headers
, "Content-Length", len
);
457 * Create the headers needed for an HTTP reply
461 evhttp_make_header_response(struct evhttp_connection
*evcon
,
462 struct evhttp_request
*req
)
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
);
469 if (req
->major
== 1) {
471 evhttp_maybe_add_date_header(req
->output_headers
);
474 * if the protocol is 1.0; and the connection was keep-alive
475 * we need to add a keep-alive header, too.
477 if (req
->minor
== 0 && is_keepalive
)
478 evhttp_add_header(req
->output_headers
,
479 "Connection", "keep-alive");
481 if (req
->minor
== 1 || is_keepalive
) {
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.
487 evhttp_maybe_add_content_length_header(
489 (long)EVBUFFER_LENGTH(req
->output_buffer
));
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");
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");
512 evhttp_make_header(struct evhttp_connection
*evcon
, struct evhttp_request
*req
)
514 struct evkeyval
*header
;
517 * Depending if this is a HTTP request or response, we might need to
518 * add some new headers or remove existing headers.
520 if (req
->kind
== EVHTTP_REQUEST
) {
521 evhttp_make_header_request(evcon
, req
);
523 evhttp_make_header_response(evcon
, req
);
526 TAILQ_FOREACH(header
, req
->output_headers
, next
) {
527 evbuffer_add_printf(evcon
->output_buffer
, "%s: %s\r\n",
528 header
->key
, header
->value
);
530 evbuffer_add(evcon
->output_buffer
, "\r\n", 2);
532 if (EVBUFFER_LENGTH(req
->output_buffer
) > 0) {
534 * For a request, we add the POST data, for a reply, this
535 * is the regular data.
537 evbuffer_add_buffer(evcon
->output_buffer
, req
->output_buffer
);
541 /* Separated host, port and file from URI */
544 evhttp_hostportfile(char *url
, char **phost
, u_short
*pport
, char **pfile
)
546 /* XXX not threadsafe. */
547 static char host
[1024];
548 static char file
[1024];
554 len
= strlen(HTTP_PREFIX
);
555 if (strncasecmp(url
, HTTP_PREFIX
, len
))
560 /* We might overrun */
561 if (strlcpy(host
, url
, sizeof (host
)) >= sizeof(host
))
564 p
= strchr(host
, '/');
572 /* Generate request file */
575 evutil_snprintf(file
, sizeof(file
), "/%s", p2
);
578 p
= strchr(host
, ':');
586 port
= HTTP_DEFAULTPORT
;
599 evhttp_connection_incoming_fail(struct evhttp_request
*req
,
600 enum evhttp_connection_error error
)
603 case EVCON_HTTP_TIMEOUT
:
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.
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 */
621 * the callback needs to send a reply, once the reply has
622 * been send, the connection should get freed.
624 (*req
->cb
)(req
, req
->cb_arg
);
631 evhttp_connection_fail(struct evhttp_connection
*evcon
,
632 enum evhttp_connection_error error
)
634 struct evhttp_request
* req
= TAILQ_FIRST(&evcon
->requests
);
635 void (*cb
)(struct evhttp_request
*, void *);
639 if (evcon
->flags
& EVHTTP_CON_INCOMING
) {
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.
648 if (evhttp_connection_incoming_fail(req
, error
) == -1)
649 evhttp_connection_free(evcon
);
653 /* save the callback for later; the cb might free our object */
655 cb_arg
= req
->cb_arg
;
657 TAILQ_REMOVE(&evcon
->requests
, req
, next
);
658 evhttp_request_free(req
);
660 /* xxx: maybe we should fail all requests??? */
662 /* reset the connection */
663 evhttp_connection_reset(evcon
);
665 /* We are trying the next request that was queued on us */
666 if (TAILQ_FIRST(&evcon
->requests
) != NULL
)
667 evhttp_connection_connect(evcon
);
669 /* inform the user */
675 evhttp_write(int fd
, short what
, void *arg
)
677 struct evhttp_connection
*evcon
= arg
;
680 if (what
== EV_TIMEOUT
) {
681 evhttp_connection_fail(evcon
, EVCON_HTTP_TIMEOUT
);
685 n
= evbuffer_write(evcon
->output_buffer
, fd
);
687 event_debug(("%s: evbuffer_write", __func__
));
688 evhttp_connection_fail(evcon
, EVCON_HTTP_EOF
);
693 event_debug(("%s: write nothing", __func__
));
694 evhttp_connection_fail(evcon
, EVCON_HTTP_EOF
);
698 if (EVBUFFER_LENGTH(evcon
->output_buffer
) != 0) {
699 evhttp_add_event(&evcon
->ev
,
700 evcon
->timeout
, HTTP_WRITE_TIMEOUT
);
704 /* Activate our call back */
705 if (evcon
->cb
!= NULL
)
706 (*evcon
->cb
)(evcon
, evcon
->cb_arg
);
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;
717 evhttp_connection_done(struct evhttp_connection
*evcon
)
719 struct evhttp_request
*req
= TAILQ_FIRST(&evcon
->requests
);
720 int con_outgoing
= evcon
->flags
& EVHTTP_CON_OUTGOING
;
723 /* idle or close the connection */
725 TAILQ_REMOVE(&evcon
->requests
, req
, next
);
728 evcon
->state
= EVCON_IDLE
;
731 evhttp_is_connection_close(req
->flags
, req
->input_headers
)||
732 evhttp_is_connection_close(req
->flags
, req
->output_headers
);
734 /* check if we got asked to close the connection */
736 evhttp_connection_reset(evcon
);
738 if (TAILQ_FIRST(&evcon
->requests
) != NULL
) {
740 * We have more requests; reset the connection
741 * and deal with the next request.
743 if (!evhttp_connected(evcon
))
744 evhttp_connection_connect(evcon
);
746 evhttp_request_dispatch(evcon
);
747 } else if (!need_close
) {
749 * The connection is going to be persistent, but we
750 * need to detect if the other side closes it.
752 evhttp_connection_start_detectclose(evcon
);
756 * incoming connection - we need to leave the request on the
757 * connection so that we can reply to it.
759 evcon
->state
= EVCON_WRITING
;
762 /* notify the user of the request */
763 (*req
->cb
)(req
, req
->cb_arg
);
765 /* if this was an outgoing request, we own and it's done. so free it */
767 evhttp_request_free(req
);
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:
779 * return REQUEST_CANCLED:
780 * request was canceled by the user calling evhttp_cancel_request
783 static enum message_read_status
784 evhttp_handle_chunked_read(struct evhttp_request
*req
, struct evbuffer
*buf
)
788 while ((len
= EVBUFFER_LENGTH(buf
)) > 0) {
789 if (req
->ntoread
< 0) {
790 /* Read chunk size */
792 char *p
= evbuffer_readline(buf
);
797 /* the last chunk is on a new line? */
798 if (strlen(p
) == 0) {
802 ntoread
= evutil_strtoll(p
, &endp
, 16);
803 error
= (*p
== '\0' ||
804 (*endp
!= '\0' && *endp
!= ' ') ||
808 /* could not get chunk size */
809 return (DATA_CORRUPTED
);
811 req
->ntoread
= ntoread
;
812 if (req
->ntoread
== 0) {
814 return (ALL_DATA_READ
);
819 /* don't have enough to complete a chunk; wait for more */
820 if (len
< req
->ntoread
)
821 return (MORE_DATA_EXPECTED
);
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
);
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
));
835 return (MORE_DATA_EXPECTED
);
839 evhttp_read_trailer(struct evhttp_connection
*evcon
, struct evhttp_request
*req
)
841 struct evbuffer
*buf
= evcon
->input_buffer
;
843 switch (evhttp_parse_headers(req
, buf
)) {
845 evhttp_connection_fail(evcon
, EVCON_HTTP_INVALID_HEADER
);
848 event_del(&evcon
->ev
);
849 evhttp_connection_done(evcon
);
851 case MORE_DATA_EXPECTED
:
853 evhttp_add_event(&evcon
->ev
, evcon
->timeout
,
860 evhttp_read_body(struct evhttp_connection
*evcon
, struct evhttp_request
*req
)
862 struct evbuffer
*buf
= evcon
->input_buffer
;
865 switch (evhttp_handle_chunked_read(req
, buf
)) {
867 /* finished last chunk */
868 evcon
->state
= EVCON_READING_TRAILER
;
869 evhttp_read_trailer(evcon
, req
);
873 evhttp_connection_fail(evcon
,
874 EVCON_HTTP_INVALID_HEADER
);
876 case REQUEST_CANCELED
:
877 /* request canceled */
878 evhttp_request_free(req
);
880 case MORE_DATA_EXPECTED
:
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
);
893 evhttp_connection_done(evcon
);
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
);
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.
910 evhttp_read(int fd
, short what
, void *arg
)
912 struct evhttp_connection
*evcon
= arg
;
913 struct evhttp_request
*req
= TAILQ_FIRST(&evcon
->requests
);
914 struct evbuffer
*buf
= evcon
->input_buffer
;
917 if (what
== EV_TIMEOUT
) {
918 evhttp_connection_fail(evcon
, EVCON_HTTP_TIMEOUT
);
921 n
= evbuffer_read(buf
, fd
, -1);
922 len
= EVBUFFER_LENGTH(buf
);
923 event_debug(("%s: got %d on %d\n", __func__
, n
, fd
));
926 if (errno
!= EINTR
&& errno
!= EAGAIN
) {
927 event_debug(("%s: evbuffer_read", __func__
));
928 evhttp_connection_fail(evcon
, EVCON_HTTP_EOF
);
930 evhttp_add_event(&evcon
->ev
, evcon
->timeout
,
935 /* Connection closed */
936 evhttp_connection_done(evcon
);
940 switch (evcon
->state
) {
941 case EVCON_READING_FIRSTLINE
:
942 evhttp_read_firstline(evcon
, req
);
944 case EVCON_READING_HEADERS
:
945 evhttp_read_header(evcon
, req
);
947 case EVCON_READING_BODY
:
948 evhttp_read_body(evcon
, req
);
950 case EVCON_READING_TRAILER
:
951 evhttp_read_trailer(evcon
, req
);
953 case EVCON_DISCONNECTED
:
954 case EVCON_CONNECTING
:
958 event_errx(1, "%s: illegal connection state %d",
959 __func__
, evcon
->state
);
964 evhttp_write_connectioncb(struct evhttp_connection
*evcon
, void *arg
)
966 /* This is after writing the request to the server */
967 struct evhttp_request
*req
= TAILQ_FIRST(&evcon
->requests
);
970 assert(evcon
->state
== EVCON_WRITING
);
972 /* We are done writing our header and are now expecting the response */
973 req
->kind
= EVHTTP_RESPONSE
;
975 evhttp_start_read(evcon
);
979 * Clean up a connection object
983 evhttp_connection_free(struct evhttp_connection
*evcon
)
985 struct evhttp_request
*req
;
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
);
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
);
999 if (evcon
->http_server
!= NULL
) {
1000 struct evhttp
*http
= evcon
->http_server
;
1001 TAILQ_REMOVE(&http
->connections
, evcon
, next
);
1004 if (event_initialized(&evcon
->close_ev
))
1005 event_del(&evcon
->close_ev
);
1007 if (event_initialized(&evcon
->ev
))
1008 event_del(&evcon
->ev
);
1010 if (evcon
->fd
!= -1)
1011 EVUTIL_CLOSESOCKET(evcon
->fd
);
1013 if (evcon
->bind_address
!= NULL
)
1014 free(evcon
->bind_address
);
1016 if (evcon
->address
!= NULL
)
1017 free(evcon
->address
);
1019 if (evcon
->input_buffer
!= NULL
)
1020 evbuffer_free(evcon
->input_buffer
);
1022 if (evcon
->output_buffer
!= NULL
)
1023 evbuffer_free(evcon
->output_buffer
);
1029 evhttp_connection_set_local_address(struct evhttp_connection
*evcon
,
1030 const char *address
)
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__
);
1040 evhttp_connection_set_local_port(struct evhttp_connection
*evcon
,
1041 unsigned short port
)
1043 assert(evcon
->state
== EVCON_DISCONNECTED
);
1044 evcon
->bind_port
= port
;
1048 evhttp_request_dispatch(struct evhttp_connection
* evcon
)
1050 struct evhttp_request
*req
= TAILQ_FIRST(&evcon
->requests
);
1052 /* this should not usually happy but it's possible */
1056 /* delete possible close detection events */
1057 evhttp_connection_stop_detectclose(evcon
);
1059 /* we assume that the connection is connected already */
1060 assert(evcon
->state
== EVCON_IDLE
);
1062 evcon
->state
= EVCON_WRITING
;
1064 /* Create the header from the store arguments */
1065 evhttp_make_header(evcon
, req
);
1067 evhttp_write_buffer(evcon
, evhttp_write_connectioncb
, NULL
);
1070 /* Reset our connection state */
1072 evhttp_connection_reset(struct evhttp_connection
*evcon
)
1074 if (event_initialized(&evcon
->ev
))
1075 event_del(&evcon
->ev
);
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
);
1082 EVUTIL_CLOSESOCKET(evcon
->fd
);
1085 evcon
->state
= EVCON_DISCONNECTED
;
1087 evbuffer_drain(evcon
->input_buffer
,
1088 EVBUFFER_LENGTH(evcon
->input_buffer
));
1089 evbuffer_drain(evcon
->output_buffer
,
1090 EVBUFFER_LENGTH(evcon
->output_buffer
));
1094 evhttp_detect_close_cb(int fd
, short what
, void *arg
)
1096 struct evhttp_connection
*evcon
= arg
;
1097 evhttp_connection_reset(evcon
);
1101 evhttp_connection_start_detectclose(struct evhttp_connection
*evcon
)
1103 evcon
->flags
|= EVHTTP_CON_CLOSEDETECT
;
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
);
1114 evhttp_connection_stop_detectclose(struct evhttp_connection
*evcon
)
1116 evcon
->flags
&= ~EVHTTP_CON_CLOSEDETECT
;
1117 event_del(&evcon
->close_ev
);
1121 evhttp_connection_retry(int fd
, short what
, void *arg
)
1123 struct evhttp_connection
*evcon
= arg
;
1125 evcon
->state
= EVCON_DISCONNECTED
;
1126 evhttp_connection_connect(evcon
);
1130 * Call back for asynchronous connection attempt.
1134 evhttp_connectioncb(int fd
, short what
, void *arg
)
1136 struct evhttp_connection
*evcon
= arg
;
1138 socklen_t errsz
= sizeof(error
);
1140 if (what
== EV_TIMEOUT
) {
1141 event_debug(("%s: connection timeout for \"%s:%d\" on %d",
1142 __func__
, evcon
->address
, evcon
->port
, evcon
->fd
));
1146 /* Check if the connection completed */
1147 if (getsockopt(evcon
->fd
, SOL_SOCKET
, SO_ERROR
, (void*)&error
,
1149 event_debug(("%s: getsockopt for \"%s:%d\" on %d",
1150 __func__
, evcon
->address
, evcon
->port
, evcon
->fd
));
1155 event_debug(("%s: connect failed for \"%s:%d\" on %d: %s",
1156 __func__
, evcon
->address
, evcon
->port
, evcon
->fd
,
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
));
1165 /* Reset the retry count as we were successful in connecting */
1166 evcon
->retry_cnt
= 0;
1167 evcon
->state
= EVCON_IDLE
;
1169 /* try to start requests that have queued up on this connection */
1170 evhttp_request_dispatch(evcon
);
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
);
1182 evhttp_connection_reset(evcon
);
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
;
1190 /* we might want to set an error here */
1191 request
->cb(request
, request
->cb_arg
);
1192 evhttp_request_free(request
);
1197 * Check if we got a valid response code.
1201 evhttp_valid_response_code(int code
)
1209 /* Parses the status line of a web server */
1212 evhttp_parse_response_line(struct evhttp_request
*req
, char *line
)
1218 protocol
= strsep(&line
, " ");
1221 number
= strsep(&line
, " ");
1226 if (strcmp(protocol
, "HTTP/1.0") == 0) {
1229 } else if (strcmp(protocol
, "HTTP/1.1") == 0) {
1233 event_debug(("%s: bad protocol \"%s\"",
1234 __func__
, protocol
));
1238 req
->response_code
= atoi(number
);
1239 if (!evhttp_valid_response_code(req
->response_code
)) {
1240 event_debug(("%s: bad response code \"%s\"",
1245 if ((req
->response_code_line
= strdup(readable
)) == NULL
)
1246 event_err(1, "%s: strdup", __func__
);
1251 /* Parse the first line of a HTTP request */
1254 evhttp_parse_request_line(struct evhttp_request
*req
, char *line
)
1260 /* Parse the request line */
1261 method
= strsep(&line
, " ");
1264 uri
= strsep(&line
, " ");
1267 version
= strsep(&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
;
1279 event_debug(("%s: bad method %s on request %p from %s",
1280 __func__
, method
, req
, req
->remote_host
));
1284 if (strcmp(version
, "HTTP/1.0") == 0) {
1287 } else if (strcmp(version
, "HTTP/1.1") == 0) {
1291 event_debug(("%s: bad version %s on request %p from %s",
1292 __func__
, version
, req
, req
->remote_host
));
1296 if ((req
->uri
= strdup(uri
)) == NULL
) {
1297 event_debug(("%s: evhttp_decode_uri", __func__
));
1301 /* determine if it's a proxy request */
1302 if (strlen(req
->uri
) > 0 && req
->uri
[0] != '/')
1303 req
->flags
|= EVHTTP_PROXY_REQUEST
;
1309 evhttp_find_header(const struct evkeyvalq
*headers
, const char *key
)
1311 struct evkeyval
*header
;
1313 TAILQ_FOREACH(header
, headers
, next
) {
1314 if (strcasecmp(header
->key
, key
) == 0)
1315 return (header
->value
);
1322 evhttp_clear_headers(struct evkeyvalq
*headers
)
1324 struct evkeyval
*header
;
1326 for (header
= TAILQ_FIRST(headers
);
1328 header
= TAILQ_FIRST(headers
)) {
1329 TAILQ_REMOVE(headers
, header
, next
);
1331 free(header
->value
);
1337 * Returns 0, if the header was successfully removed.
1338 * Returns -1, if the header could not be found.
1342 evhttp_remove_header(struct evkeyvalq
*headers
, const char *key
)
1344 struct evkeyval
*header
;
1346 TAILQ_FOREACH(header
, headers
, next
) {
1347 if (strcasecmp(header
->key
, key
) == 0)
1354 /* Free and remove the header that we found */
1355 TAILQ_REMOVE(headers
, header
, next
);
1357 free(header
->value
);
1364 evhttp_header_is_valid_value(const char *value
)
1366 const char *p
= value
;
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')
1379 evhttp_add_header(struct evkeyvalq
*headers
,
1380 const char *key
, const char *value
)
1382 event_debug(("%s: key: %s val: %s\n", __func__
, key
, value
));
1384 if (strchr(key
, '\r') != NULL
|| strchr(key
, '\n') != NULL
) {
1385 /* drop illegal headers */
1386 event_debug(("%s: dropping illegal header key\n", __func__
));
1390 if (!evhttp_header_is_valid_value(value
)) {
1391 event_debug(("%s: dropping illegal header value\n", __func__
));
1395 return (evhttp_add_header_internal(headers
, key
, value
));
1399 evhttp_add_header_internal(struct evkeyvalq
*headers
,
1400 const char *key
, const char *value
)
1402 struct evkeyval
*header
= calloc(1, sizeof(struct evkeyval
));
1403 if (header
== NULL
) {
1404 event_warn("%s: calloc", __func__
);
1407 if ((header
->key
= strdup(key
)) == NULL
) {
1409 event_warn("%s: strdup", __func__
);
1412 if ((header
->value
= strdup(value
)) == NULL
) {
1415 event_warn("%s: strdup", __func__
);
1419 TAILQ_INSERT_TAIL(headers
, header
, next
);
1425 * Parses header lines from a request or a response into the specified
1426 * request object given an event buffer.
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.
1434 enum message_read_status
1435 evhttp_parse_firstline(struct evhttp_request
*req
, struct evbuffer
*buffer
)
1438 enum message_read_status status
= ALL_DATA_READ
;
1440 line
= evbuffer_readline(buffer
);
1442 return (MORE_DATA_EXPECTED
);
1444 switch (req
->kind
) {
1445 case EVHTTP_REQUEST
:
1446 if (evhttp_parse_request_line(req
, line
) == -1)
1447 status
= DATA_CORRUPTED
;
1449 case EVHTTP_RESPONSE
:
1450 if (evhttp_parse_response_line(req
, line
) == -1)
1451 status
= DATA_CORRUPTED
;
1454 status
= DATA_CORRUPTED
;
1462 evhttp_append_to_last_header(struct evkeyvalq
*headers
, const char *line
)
1464 struct evkeyval
*header
= TAILQ_LAST(headers
, evkeyvalq
);
1466 size_t old_len
, line_len
;
1471 old_len
= strlen(header
->value
);
1472 line_len
= strlen(line
);
1474 newval
= realloc(header
->value
, old_len
+ line_len
+ 1);
1478 memcpy(newval
+ old_len
, line
, line_len
+ 1);
1479 header
->value
= newval
;
1484 enum message_read_status
1485 evhttp_parse_headers(struct evhttp_request
*req
, struct evbuffer
* buffer
)
1488 enum message_read_status status
= MORE_DATA_EXPECTED
;
1490 struct evkeyvalq
* headers
= req
->input_headers
;
1491 while ((line
= evbuffer_readline(buffer
))
1493 char *skey
, *svalue
;
1495 if (*line
== '\0') { /* Last header - Done */
1496 status
= ALL_DATA_READ
;
1501 /* Check if this is a continuation line */
1502 if (*line
== ' ' || *line
== '\t') {
1503 if (evhttp_append_to_last_header(headers
, line
) == -1)
1509 /* Processing of header lines */
1511 skey
= strsep(&svalue
, ":");
1515 svalue
+= strspn(svalue
, " ");
1517 if (evhttp_add_header(headers
, skey
, svalue
) == -1)
1527 return (DATA_CORRUPTED
);
1531 evhttp_get_body_length(struct evhttp_request
*req
)
1533 struct evkeyvalq
*headers
= req
->input_headers
;
1534 const char *content_length
;
1535 const char *connection
;
1537 content_length
= evhttp_find_header(headers
, "Content-Length");
1538 connection
= evhttp_find_header(headers
, "Connection");
1540 if (content_length
== NULL
&& connection
== NULL
)
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
);
1549 } else if (content_length
== NULL
) {
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
));
1559 req
->ntoread
= ntoread
;
1562 event_debug(("%s: bytes to read: %lld (in buffer %ld)\n",
1563 __func__
, req
->ntoread
,
1564 EVBUFFER_LENGTH(req
->evcon
->input_buffer
)));
1570 evhttp_get_body(struct evhttp_connection
*evcon
, struct evhttp_request
*req
)
1572 const char *xfer_enc
;
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
);
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) {
1585 if (evhttp_get_body_length(req
) == -1) {
1586 evhttp_connection_fail(evcon
,
1587 EVCON_HTTP_INVALID_HEADER
);
1591 evhttp_read_body(evcon
, req
);
1595 evhttp_read_firstline(struct evhttp_connection
*evcon
,
1596 struct evhttp_request
*req
)
1598 enum message_read_status res
;
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
);
1607 } else if (res
== MORE_DATA_EXPECTED
) {
1608 /* Need more header lines */
1609 evhttp_add_event(&evcon
->ev
,
1610 evcon
->timeout
, HTTP_READ_TIMEOUT
);
1614 evcon
->state
= EVCON_READING_HEADERS
;
1615 evhttp_read_header(evcon
, req
);
1619 evhttp_read_header(struct evhttp_connection
*evcon
, struct evhttp_request
*req
)
1621 enum message_read_status res
;
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
);
1630 } else if (res
== MORE_DATA_EXPECTED
) {
1631 /* Need more header lines */
1632 evhttp_add_event(&evcon
->ev
,
1633 evcon
->timeout
, HTTP_READ_TIMEOUT
);
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",
1642 evhttp_get_body(evcon
, req
);
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
);
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
);
1660 event_warnx("%s: bad header on %d", __func__
, fd
);
1661 evhttp_connection_fail(evcon
, EVCON_HTTP_INVALID_HEADER
);
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
1671 * Although this interface accepts a hostname, it is intended to take
1672 * only numeric hostnames so that non-blocking DNS resolution can
1676 struct evhttp_connection
*
1677 evhttp_connection_new(const char *address
, unsigned short port
)
1679 struct evhttp_connection
*evcon
= NULL
;
1681 event_debug(("Attempting connection to %s:%d\n", address
, port
));
1683 if ((evcon
= calloc(1, sizeof(struct evhttp_connection
))) == NULL
) {
1684 event_warn("%s: calloc failed", __func__
);
1691 evcon
->timeout
= -1;
1692 evcon
->retry_cnt
= evcon
->retry_max
= 0;
1694 if ((evcon
->address
= strdup(address
)) == NULL
) {
1695 event_warn("%s: strdup failed", __func__
);
1699 if ((evcon
->input_buffer
= evbuffer_new()) == NULL
) {
1700 event_warn("%s: evbuffer_new failed", __func__
);
1704 if ((evcon
->output_buffer
= evbuffer_new()) == NULL
) {
1705 event_warn("%s: evbuffer_new failed", __func__
);
1709 evcon
->state
= EVCON_DISCONNECTED
;
1710 TAILQ_INIT(&evcon
->requests
);
1716 evhttp_connection_free(evcon
);
1720 void evhttp_connection_set_base(struct evhttp_connection
*evcon
,
1721 struct event_base
*base
)
1723 assert(evcon
->base
== NULL
);
1724 assert(evcon
->state
== EVCON_DISCONNECTED
);
1729 evhttp_connection_set_timeout(struct evhttp_connection
*evcon
,
1730 int timeout_in_secs
)
1732 evcon
->timeout
= timeout_in_secs
;
1736 evhttp_connection_set_retries(struct evhttp_connection
*evcon
,
1739 evcon
->retry_max
= retry_max
;
1743 evhttp_connection_set_closecb(struct evhttp_connection
*evcon
,
1744 void (*cb
)(struct evhttp_connection
*, void *), void *cbarg
)
1746 evcon
->closecb
= cb
;
1747 evcon
->closecb_arg
= cbarg
;
1751 evhttp_connection_get_peer(struct evhttp_connection
*evcon
,
1752 char **address
, u_short
*port
)
1754 *address
= evcon
->address
;
1755 *port
= evcon
->port
;
1759 evhttp_connection_connect(struct evhttp_connection
*evcon
)
1761 if (evcon
->state
== EVCON_CONNECTING
)
1764 evhttp_connection_reset(evcon
);
1766 assert(!(evcon
->flags
& EVHTTP_CON_INCOMING
));
1767 evcon
->flags
|= EVHTTP_CON_OUTGOING
;
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
));
1777 if (socket_connect(evcon
->fd
, evcon
->address
, evcon
->port
) == -1) {
1778 EVUTIL_CLOSESOCKET(evcon
->fd
); evcon
->fd
= -1;
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
);
1787 evcon
->state
= EVCON_CONNECTING
;
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.
1799 evhttp_make_request(struct evhttp_connection
*evcon
,
1800 struct evhttp_request
*req
,
1801 enum evhttp_cmd_type type
, const char *uri
)
1803 /* We are making a request */
1804 req
->kind
= EVHTTP_REQUEST
;
1806 if (req
->uri
!= NULL
)
1808 if ((req
->uri
= strdup(uri
)) == NULL
)
1809 event_err(1, "%s: strdup", __func__
);
1811 /* Set the protocol version if it is not supplied */
1812 if (!req
->major
&& !req
->minor
) {
1817 assert(req
->evcon
== NULL
);
1819 assert(!(req
->flags
& EVHTTP_REQ_OWN_CONNECTION
));
1821 TAILQ_INSERT_TAIL(&evcon
->requests
, req
, next
);
1823 /* If the connection object is not connected; make it so */
1824 if (!evhttp_connected(evcon
))
1825 return (evhttp_connection_connect(evcon
));
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.
1832 if (TAILQ_FIRST(&evcon
->requests
) == req
)
1833 evhttp_request_dispatch(evcon
);
1839 * Reads data from file descriptor into request structure
1840 * Request structure needs to be set up correctly.
1844 evhttp_start_read(struct evhttp_connection
*evcon
)
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
);
1852 evhttp_add_event(&evcon
->ev
, evcon
->timeout
, HTTP_READ_TIMEOUT
);
1853 evcon
->state
= EVCON_READING_FIRSTLINE
;
1857 evhttp_send_done(struct evhttp_connection
*evcon
, void *arg
)
1860 struct evhttp_request
*req
= TAILQ_FIRST(&evcon
->requests
);
1861 TAILQ_REMOVE(&evcon
->requests
, req
, next
);
1863 /* delete possible close detection events */
1864 evhttp_connection_stop_detectclose(evcon
);
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
);
1872 assert(req
->flags
& EVHTTP_REQ_OWN_CONNECTION
);
1873 evhttp_request_free(req
);
1876 evhttp_connection_free(evcon
);
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
);
1886 * Returns an error page.
1890 evhttp_send_error(struct evhttp_request
*req
, int error
, const char *reason
)
1892 #define ERR_FORMAT "<HTML><HEAD>\n" \
1893 "<TITLE>%d %s</TITLE>\n" \
1895 "<H1>Method Not Implemented</H1>\n" \
1896 "Invalid method in request<P>\n" \
1899 struct evbuffer
*buf
= evbuffer_new();
1901 /* close the connection on error */
1902 evhttp_add_header(req
->output_headers
, "Connection", "close");
1904 evhttp_response_code(req
, error
, reason
);
1906 evbuffer_add_printf(buf
, ERR_FORMAT
, error
, reason
);
1908 evhttp_send_page(req
, buf
);
1914 /* Requires that headers and response code are already set up */
1917 evhttp_send(struct evhttp_request
*req
, struct evbuffer
*databuf
)
1919 struct evhttp_connection
*evcon
= req
->evcon
;
1921 assert(TAILQ_FIRST(&evcon
->requests
) == req
);
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
);
1927 /* Adds headers to the response */
1928 evhttp_make_header(evcon
, req
);
1930 evhttp_write_buffer(evcon
, evhttp_send_done
, NULL
);
1934 evhttp_send_reply(struct evhttp_request
*req
, int code
, const char *reason
,
1935 struct evbuffer
*databuf
)
1937 evhttp_response_code(req
, code
, reason
);
1939 evhttp_send(req
, databuf
);
1943 evhttp_send_reply_start(struct evhttp_request
*req
, int code
,
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",
1953 evhttp_make_header(req
->evcon
, req
);
1954 evhttp_write_buffer(req
->evcon
, NULL
, NULL
);
1958 evhttp_send_reply_chunk(struct evhttp_request
*req
, struct evbuffer
*databuf
)
1961 evbuffer_add_printf(req
->evcon
->output_buffer
, "%x\r\n",
1962 (unsigned)EVBUFFER_LENGTH(databuf
));
1964 evbuffer_add_buffer(req
->evcon
->output_buffer
, databuf
);
1966 evbuffer_add(req
->evcon
->output_buffer
, "\r\n", 2);
1968 evhttp_write_buffer(req
->evcon
, NULL
, NULL
);
1972 evhttp_send_reply_end(struct evhttp_request
*req
)
1974 struct evhttp_connection
*evcon
= req
->evcon
;
1977 evbuffer_add(req
->evcon
->output_buffer
, "0\r\n\r\n", 5);
1978 evhttp_write_buffer(req
->evcon
, evhttp_send_done
, NULL
);
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
);
1984 /* make the callback execute after all data has been written */
1985 evcon
->cb
= evhttp_send_done
;
1986 evcon
->cb_arg
= NULL
;
1991 evhttp_response_code(struct evhttp_request
*req
, int code
, const char *reason
)
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
);
2001 evhttp_send_page(struct evhttp_request
*req
, struct evbuffer
*databuf
)
2003 if (!req
->major
|| !req
->minor
) {
2008 if (req
->kind
!= EVHTTP_RESPONSE
)
2009 evhttp_response_code(req
, 200, "OK");
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");
2015 evhttp_send(req
, databuf
);
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,
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,
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,
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,
2041 * Helper functions to encode/decode a URI.
2042 * The returned string must be freed by the caller.
2045 evhttp_encode_uri(const char *uri
)
2047 struct evbuffer
*buf
= evbuffer_new();
2050 for (p
= (char *)uri
; *p
!= '\0'; p
++) {
2051 if (uri_chars
[(u_char
)(*p
)]) {
2052 evbuffer_add(buf
, p
, 1);
2054 evbuffer_add_printf(buf
, "%%%02X", (u_char
)(*p
));
2057 evbuffer_add(buf
, "", 1);
2058 p
= strdup((char *)EVBUFFER_DATA(buf
));
2065 * @param always_decode_plus: when true we transform plus to space even
2066 * if we have not seen a ?.
2069 evhttp_decode_uri_internal(
2070 const char *uri
, size_t length
, char *ret
, int always_decode_plus
)
2073 int i
, j
, in_query
= always_decode_plus
;
2075 for (i
= j
= 0; uri
[i
] != '\0'; i
++) {
2079 } else if (c
== '+' && in_query
) {
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);
2095 evhttp_decode_uri(const char *uri
)
2099 if ((ret
= malloc(strlen(uri
) + 1)) == NULL
)
2100 event_err(1, "%s: malloc(%lu)", __func__
,
2101 (unsigned long)(strlen(uri
) + 1));
2103 evhttp_decode_uri_internal(uri
, strlen(uri
),
2104 ret
, 0 /*always_decode_plus*/);
2110 * Helper function to parse out arguments in a query.
2111 * The arguments are separated by key and value.
2115 evhttp_parse_query(const char *uri
, struct evkeyvalq
*headers
)
2121 TAILQ_INIT(headers
);
2123 /* No arguments - we are done */
2124 if (strchr(uri
, '?') == NULL
)
2127 if ((line
= strdup(uri
)) == NULL
)
2128 event_err(1, "%s: strdup", __func__
);
2133 /* We already know that there has to be a ? */
2134 strsep(&argument
, "?");
2137 while (p
!= NULL
&& *p
!= '\0') {
2138 char *key
, *value
, *decoded_value
;
2139 argument
= strsep(&p
, "&");
2142 key
= strsep(&value
, "=");
2146 if ((decoded_value
= malloc(strlen(value
) + 1)) == NULL
)
2147 event_err(1, "%s: malloc", __func__
);
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
);
2160 static struct evhttp_cb
*
2161 evhttp_dispatch_callback(struct httpcbq
*callbacks
, struct evhttp_request
*req
)
2163 struct evhttp_cb
*cb
;
2166 /* Test for different URLs */
2167 char *p
= strchr(req
->uri
, '?');
2169 offset
= (size_t)(p
- req
->uri
);
2171 TAILQ_FOREACH(cb
, callbacks
, next
) {
2174 res
= strcmp(cb
->what
, req
->uri
) == 0;
2176 res
= ((strncmp(cb
->what
, req
->uri
, offset
) == 0) &&
2177 (cb
->what
[offset
] == '\0'));
2188 evhttp_handle_request(struct evhttp_request
*req
, void *arg
)
2190 struct evhttp
*http
= arg
;
2191 struct evhttp_cb
*cb
= NULL
;
2193 if (req
->uri
== NULL
) {
2194 evhttp_send_error(req
, HTTP_BADREQUEST
, "Bad Request");
2198 if ((cb
= evhttp_dispatch_callback(&http
->callbacks
, req
)) != NULL
) {
2199 (*cb
->cb
)(req
, cb
->cbarg
);
2203 /* Generic call back */
2205 (*http
->gencb
)(req
, http
->gencbarg
);
2208 /* We need to send a 404 here */
2209 #define ERR_FORMAT "<html><head>" \
2210 "<title>404 Not Found</title>" \
2212 "<h1>Not Found</h1>" \
2213 "<p>The requested URL %s was not found on this server.</p>"\
2216 char *escaped_html
= evhttp_htmlescape(req
->uri
);
2217 struct evbuffer
*buf
= evbuffer_new();
2219 evhttp_response_code(req
, HTTP_NOTFOUND
, "Not Found");
2221 evbuffer_add_printf(buf
, ERR_FORMAT
, escaped_html
);
2225 evhttp_send_page(req
, buf
);
2233 accept_socket(int fd
, short what
, void *arg
)
2235 struct evhttp
*http
= arg
;
2236 struct sockaddr_storage ss
;
2237 socklen_t addrlen
= sizeof(ss
);
2240 if ((nfd
= accept(fd
, (struct sockaddr
*)&ss
, &addrlen
)) == -1) {
2241 if (errno
!= EAGAIN
&& errno
!= EINTR
)
2242 event_warn("%s: bad accept", __func__
);
2245 if (evutil_make_socket_nonblocking(nfd
) < 0)
2248 evhttp_get_request(http
, nfd
, (struct sockaddr
*)&ss
, addrlen
);
2252 evhttp_bind_socket(struct evhttp
*http
, const char *address
, u_short port
)
2257 if ((fd
= bind_socket(address
, port
, 1 /*reuse*/)) == -1)
2260 if (listen(fd
, 128) == -1) {
2261 event_warn("%s: listen", __func__
);
2262 EVUTIL_CLOSESOCKET(fd
);
2266 res
= evhttp_accept_socket(http
, fd
);
2269 event_debug(("Bound to port %d - Awaiting connections ... ",
2276 evhttp_accept_socket(struct evhttp
*http
, int fd
)
2278 struct evhttp_bound_socket
*bound
;
2282 bound
= malloc(sizeof(struct evhttp_bound_socket
));
2286 ev
= &bound
->bind_ev
;
2288 /* Schedule the socket for accepting */
2289 event_set(ev
, fd
, EV_READ
| EV_PERSIST
, accept_socket
, http
);
2290 EVHTTP_BASE_SET(http
, ev
);
2292 res
= event_add(ev
, NULL
);
2299 TAILQ_INSERT_TAIL(&http
->sockets
, bound
, next
);
2304 static struct evhttp
*
2305 evhttp_new_object(void)
2307 struct evhttp
*http
= NULL
;
2309 if ((http
= calloc(1, sizeof(struct evhttp
))) == NULL
) {
2310 event_warn("%s: calloc", __func__
);
2316 TAILQ_INIT(&http
->sockets
);
2317 TAILQ_INIT(&http
->callbacks
);
2318 TAILQ_INIT(&http
->connections
);
2324 evhttp_new(struct event_base
*base
)
2326 struct evhttp
*http
= evhttp_new_object();
2334 * Start a web server on the specified address and port.
2338 evhttp_start(const char *address
, u_short port
)
2340 struct evhttp
*http
= evhttp_new_object();
2342 if (evhttp_bind_socket(http
, address
, port
) == -1) {
2351 evhttp_free(struct evhttp
* http
)
2353 struct evhttp_cb
*http_cb
;
2354 struct evhttp_connection
*evcon
;
2355 struct evhttp_bound_socket
*bound
;
2358 /* Remove the accepting part */
2359 while ((bound
= TAILQ_FIRST(&http
->sockets
)) != NULL
) {
2360 TAILQ_REMOVE(&http
->sockets
, bound
, next
);
2362 fd
= bound
->bind_ev
.ev_fd
;
2363 event_del(&bound
->bind_ev
);
2364 EVUTIL_CLOSESOCKET(fd
);
2369 while ((evcon
= TAILQ_FIRST(&http
->connections
)) != NULL
) {
2370 /* evhttp_connection_free removes the connection */
2371 evhttp_connection_free(evcon
);
2374 while ((http_cb
= TAILQ_FIRST(&http
->callbacks
)) != NULL
) {
2375 TAILQ_REMOVE(&http
->callbacks
, http_cb
, next
);
2376 free(http_cb
->what
);
2384 evhttp_set_timeout(struct evhttp
* http
, int timeout_in_secs
)
2386 http
->timeout
= timeout_in_secs
;
2390 evhttp_set_cb(struct evhttp
*http
, const char *uri
,
2391 void (*cb
)(struct evhttp_request
*, void *), void *cbarg
)
2393 struct evhttp_cb
*http_cb
;
2395 if ((http_cb
= calloc(1, sizeof(struct evhttp_cb
))) == NULL
)
2396 event_err(1, "%s: calloc", __func__
);
2398 http_cb
->what
= strdup(uri
);
2400 http_cb
->cbarg
= cbarg
;
2402 TAILQ_INSERT_TAIL(&http
->callbacks
, http_cb
, next
);
2406 evhttp_del_cb(struct evhttp
*http
, const char *uri
)
2408 struct evhttp_cb
*http_cb
;
2410 TAILQ_FOREACH(http_cb
, &http
->callbacks
, next
) {
2411 if (strcmp(http_cb
->what
, uri
) == 0)
2414 if (http_cb
== NULL
)
2417 TAILQ_REMOVE(&http
->callbacks
, http_cb
, next
);
2418 free(http_cb
->what
);
2425 evhttp_set_gencb(struct evhttp
*http
,
2426 void (*cb
)(struct evhttp_request
*, void *), void *cbarg
)
2429 http
->gencbarg
= cbarg
;
2433 * Request related functions
2436 struct evhttp_request
*
2437 evhttp_request_new(void (*cb
)(struct evhttp_request
*, void *), void *arg
)
2439 struct evhttp_request
*req
= NULL
;
2441 /* Allocate request structure */
2442 if ((req
= calloc(1, sizeof(struct evhttp_request
))) == NULL
) {
2443 event_warn("%s: calloc", __func__
);
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__
);
2453 TAILQ_INIT(req
->input_headers
);
2455 req
->output_headers
= calloc(1, sizeof(struct evkeyvalq
));
2456 if (req
->output_headers
== NULL
) {
2457 event_warn("%s: calloc", __func__
);
2460 TAILQ_INIT(req
->output_headers
);
2462 if ((req
->input_buffer
= evbuffer_new()) == NULL
) {
2463 event_warn("%s: evbuffer_new", __func__
);
2467 if ((req
->output_buffer
= evbuffer_new()) == NULL
) {
2468 event_warn("%s: evbuffer_new", __func__
);
2479 evhttp_request_free(req
);
2484 evhttp_request_free(struct evhttp_request
*req
)
2486 if (req
->remote_host
!= NULL
)
2487 free(req
->remote_host
);
2488 if (req
->uri
!= NULL
)
2490 if (req
->response_code_line
!= NULL
)
2491 free(req
->response_code_line
);
2493 evhttp_clear_headers(req
->input_headers
);
2494 free(req
->input_headers
);
2496 evhttp_clear_headers(req
->output_headers
);
2497 free(req
->output_headers
);
2499 if (req
->input_buffer
!= NULL
)
2500 evbuffer_free(req
->input_buffer
);
2502 if (req
->output_buffer
!= NULL
)
2503 evbuffer_free(req
->output_buffer
);
2509 evhttp_request_set_chunked_cb(struct evhttp_request
*req
,
2510 void (*cb
)(struct evhttp_request
*, void *))
2516 * Allows for inspection of the request URI
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
));
2527 * Takes a file descriptor to read a request from.
2528 * The callback is executed once the whole request has been read.
2531 static struct evhttp_connection
*
2532 evhttp_get_request_connection(
2533 struct evhttp
* http
,
2534 int fd
, struct sockaddr
*sa
, socklen_t salen
)
2536 struct evhttp_connection
*evcon
;
2537 char *hostname
= NULL
, *portname
= NULL
;
2539 name_from_addr(sa
, salen
, &hostname
, &portname
);
2540 if (hostname
== NULL
|| portname
== NULL
) {
2541 if (hostname
) free(hostname
);
2542 if (portname
) free(portname
);
2546 event_debug(("%s: new request from %s:%s on %d\n",
2547 __func__
, hostname
, portname
, fd
));
2549 /* we need a connection object to put the http request on */
2550 evcon
= evhttp_connection_new(hostname
, atoi(portname
));
2556 /* associate the base if we have one*/
2557 evhttp_connection_set_base(evcon
, http
->base
);
2559 evcon
->flags
|= EVHTTP_CON_INCOMING
;
2560 evcon
->state
= EVCON_READING_FIRSTLINE
;
2568 evhttp_associate_new_request_with_connection(struct evhttp_connection
*evcon
)
2570 struct evhttp
*http
= evcon
->http_server
;
2571 struct evhttp_request
*req
;
2572 if ((req
= evhttp_request_new(evhttp_handle_request
, http
)) == NULL
)
2575 req
->evcon
= evcon
; /* the request ends up owning the connection */
2576 req
->flags
|= EVHTTP_REQ_OWN_CONNECTION
;
2578 TAILQ_INSERT_TAIL(&evcon
->requests
, req
, next
);
2580 req
->kind
= EVHTTP_REQUEST
;
2582 if ((req
->remote_host
= strdup(evcon
->address
)) == NULL
)
2583 event_err(1, "%s: strdup", __func__
);
2584 req
->remote_port
= evcon
->port
;
2586 evhttp_start_read(evcon
);
2592 evhttp_get_request(struct evhttp
*http
, int fd
,
2593 struct sockaddr
*sa
, socklen_t salen
)
2595 struct evhttp_connection
*evcon
;
2597 evcon
= evhttp_get_request_connection(http
, fd
, sa
, salen
);
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
);
2606 * if we want to accept more than one request on a connection,
2607 * we need to know which http server it belongs to.
2609 evcon
->http_server
= http
;
2610 TAILQ_INSERT_TAIL(&http
->connections
, evcon
, next
);
2612 if (evhttp_associate_new_request_with_connection(evcon
) == -1)
2613 evhttp_connection_free(evcon
);
2618 * Network helper functions that we do not want to export to the rest of
2622 static struct addrinfo
*
2623 addr_from_name(char *address
)
2625 #ifdef HAVE_GETADDRINFO
2626 struct addrinfo ai
, *aitop
;
2629 memset(&ai
, 0, sizeof(ai
));
2630 ai
.ai_family
= AF_INET
;
2631 ai
.ai_socktype
= SOCK_RAW
;
2633 if ((ai_result
= getaddrinfo(address
, NULL
, &ai
, &aitop
)) != 0) {
2634 if ( ai_result
== EAI_SYSTEM
)
2635 event_warn("getaddrinfo");
2637 event_warnx("getaddrinfo: %s", gai_strerror(ai_result
));
2643 return NULL
; /* XXXXX Use gethostbyname, if this function is ever used. */
2649 name_from_addr(struct sockaddr
*sa
, socklen_t salen
,
2650 char **phost
, char **pport
)
2652 char ntop
[NI_MAXHOST
];
2653 char strport
[NI_MAXSERV
];
2656 #ifdef HAVE_GETNAMEINFO
2657 ni_result
= getnameinfo(sa
, salen
,
2658 ntop
, sizeof(ntop
), strport
, sizeof(strport
),
2659 NI_NUMERICHOST
|NI_NUMERICSERV
);
2661 if (ni_result
!= 0) {
2662 if (ni_result
== EAI_SYSTEM
)
2663 event_err(1, "getnameinfo failed");
2665 event_errx(1, "getnameinfo failed: %s", gai_strerror(ni_result
));
2669 ni_result
= fake_getnameinfo(sa
, salen
,
2670 ntop
, sizeof(ntop
), strport
, sizeof(strport
),
2671 NI_NUMERICHOST
|NI_NUMERICSERV
);
2675 *phost
= strdup(ntop
);
2676 *pport
= strdup(strport
);
2679 /* Create a non-blocking socket and bind it */
2680 /* todo: rename this function */
2682 bind_socket_ai(struct addrinfo
*ai
, int reuse
)
2687 /* Create listen socket */
2688 fd
= socket(AF_INET
, SOCK_STREAM
, 0);
2690 event_warn("socket");
2694 if (evutil_make_socket_nonblocking(fd
) < 0)
2698 if (fcntl(fd
, F_SETFD
, 1) == -1) {
2699 event_warn("fcntl(F_SETFD)");
2704 setsockopt(fd
, SOL_SOCKET
, SO_KEEPALIVE
, (void *)&on
, sizeof(on
));
2706 setsockopt(fd
, SOL_SOCKET
, SO_REUSEADDR
,
2707 (void *)&on
, sizeof(on
));
2711 r
= bind(fd
, ai
->ai_addr
, ai
->ai_addrlen
);
2719 serrno
= EVUTIL_SOCKET_ERROR();
2720 EVUTIL_CLOSESOCKET(fd
);
2721 EVUTIL_SET_SOCKET_ERROR(serrno
);
2725 static struct addrinfo
*
2726 make_addrinfo(const char *address
, u_short port
)
2728 struct addrinfo
*aitop
= NULL
;
2730 #ifdef HAVE_GETADDRINFO
2732 char strport
[NI_MAXSERV
];
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");
2744 event_warnx("getaddrinfo: %s", gai_strerror(ai_result
));
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 */
2752 if (fake_getaddrinfo(address
, &ai
[cur
]) < 0) {
2753 event_warn("fake_getaddrinfo");
2757 ((struct sockaddr_in
*) aitop
->ai_addr
)->sin_port
= htons(port
);
2764 bind_socket(const char *address
, u_short port
, int reuse
)
2767 struct addrinfo
*aitop
= NULL
;
2769 /* just create an unbound socket */
2770 if (address
== NULL
&& port
== 0)
2771 return bind_socket_ai(NULL
, 0);
2773 aitop
= make_addrinfo(address
, port
);
2778 fd
= bind_socket_ai(aitop
, reuse
);
2780 #ifdef HAVE_GETADDRINFO
2781 freeaddrinfo(aitop
);
2783 fake_freeaddrinfo(aitop
);
2790 socket_connect(int fd
, const char *address
, unsigned short port
)
2792 struct addrinfo
*ai
= make_addrinfo(address
, port
);
2796 event_debug(("%s: make_addrinfo: \"%s:%d\"",
2797 __func__
, address
, port
));
2801 if (connect(fd
, ai
->ai_addr
, ai
->ai_addrlen
) == -1) {
2803 int tmp_error
= WSAGetLastError();
2804 if (tmp_error
!= WSAEWOULDBLOCK
&& tmp_error
!= WSAEINVAL
&&
2805 tmp_error
!= WSAEINPROGRESS
) {
2809 if (errno
!= EINPROGRESS
) {
2815 /* everything is fine */
2819 #ifdef HAVE_GETADDRINFO
2822 fake_freeaddrinfo(ai
);