3 * Copyright (c) 2002-2006 Niels Provos <provos@citi.umich.edu>
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * 3. The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33 #ifdef HAVE_SYS_PARAM_H
34 #include <sys/param.h>
36 #ifdef HAVE_SYS_TYPES_H
37 #include <sys/types.h>
40 #ifdef HAVE_SYS_TIME_H
43 #ifdef HAVE_SYS_IOCCOM_H
44 #include <sys/ioccom.h>
48 #include <sys/resource.h>
49 #include <sys/socket.h>
54 #include <sys/queue.h>
57 #include <netinet/in.h>
83 #undef timeout_pending
84 #undef timeout_initialized
86 #include "strlcpy-internal.h"
91 #include "http-internal.h"
94 #define strcasecmp _stricmp
95 #define strncasecmp _strnicmp
96 #define strdup _strdup
99 #ifndef HAVE_GETNAMEINFO
100 #define NI_MAXSERV 32
101 #define NI_MAXHOST 1025
103 #define NI_NUMERICHOST 1
104 #define NI_NUMERICSERV 2
107 fake_getnameinfo(const struct sockaddr
*sa
, size_t salen
, char *host
,
108 size_t hostlen
, char *serv
, size_t servlen
, int flags
)
110 struct sockaddr_in
*sin
= (struct sockaddr_in
*)sa
;
114 evutil_snprintf(tmpserv
, sizeof(tmpserv
),
115 "%d", ntohs(sin
->sin_port
));
116 if (strlcpy(serv
, tmpserv
, servlen
) >= servlen
)
121 if (flags
& NI_NUMERICHOST
) {
122 if (strlcpy(host
, inet_ntoa(sin
->sin_addr
),
129 hp
= gethostbyaddr((char *)&sin
->sin_addr
,
130 sizeof(struct in_addr
), AF_INET
);
134 if (strlcpy(host
, hp
->h_name
, hostlen
) >= hostlen
)
145 #ifndef HAVE_GETADDRINFO
151 struct sockaddr
*ai_addr
;
152 struct addrinfo
*ai_next
;
155 fake_getaddrinfo(const char *hostname
, struct addrinfo
*ai
)
157 struct hostent
*he
= NULL
;
158 struct sockaddr_in
*sa
;
160 he
= gethostbyname(hostname
);
164 ai
->ai_family
= he
? he
->h_addrtype
: AF_INET
;
165 ai
->ai_socktype
= SOCK_STREAM
;
167 ai
->ai_addrlen
= sizeof(struct sockaddr_in
);
168 if (NULL
== (ai
->ai_addr
= malloc(ai
->ai_addrlen
)))
170 sa
= (struct sockaddr_in
*)ai
->ai_addr
;
171 memset(sa
, 0, ai
->ai_addrlen
);
173 sa
->sin_family
= he
->h_addrtype
;
174 memcpy(&sa
->sin_addr
, he
->h_addr_list
[0], he
->h_length
);
176 sa
->sin_family
= AF_INET
;
177 sa
->sin_addr
.s_addr
= INADDR_ANY
;
183 fake_freeaddrinfo(struct addrinfo
*ai
)
190 #define MIN(a,b) (((a)<(b))?(a):(b))
193 /* wrapper for setting the base from the http server */
194 #define EVHTTP_BASE_SET(x, y) do { \
195 if ((x)->base != NULL) event_base_set((x)->base, y); \
200 static int socket_connect(int fd
, const char *address
, unsigned short port
);
201 static int bind_socket_ai(struct addrinfo
*, int reuse
);
202 static int bind_socket(const char *, u_short
, int reuse
);
203 static void name_from_addr(struct sockaddr
*, socklen_t
, char **, char **);
204 static int evhttp_associate_new_request_with_connection(
205 struct evhttp_connection
*evcon
);
206 static void evhttp_connection_start_detectclose(
207 struct evhttp_connection
*evcon
);
208 static void evhttp_connection_stop_detectclose(
209 struct evhttp_connection
*evcon
);
210 static void evhttp_request_dispatch(struct evhttp_connection
* evcon
);
211 static void evhttp_read_firstline(struct evhttp_connection
*evcon
,
212 struct evhttp_request
*req
);
213 static void evhttp_read_header(struct evhttp_connection
*evcon
,
214 struct evhttp_request
*req
);
215 static int evhttp_add_header_internal(struct evkeyvalq
*headers
,
216 const char *key
, const char *value
);
217 static int evhttp_decode_uri_internal(const char *uri
, size_t length
,
218 char *ret
, int always_decode_plus
);
220 void evhttp_read(int, short, void *);
221 void evhttp_write(int, short, void *);
224 /* strsep replacement for platforms that lack it. Only works if
225 * del is one character long. */
227 strsep(char **s
, const char *del
)
230 assert(strlen(del
) == 1);
234 d
= strstr(tok
, del
);
245 html_replace(char ch
, char *buf
)
262 /* Echo the character back */
270 * Replaces <, >, ", ' and & with <, >, ",
271 * ' and & correspondingly.
273 * The returned string needs to be freed by the caller.
277 evhttp_htmlescape(const char *html
)
279 int i
, new_size
= 0, old_size
= strlen(html
);
280 char *escaped_html
, *p
;
281 char scratch_space
[2];
283 for (i
= 0; i
< old_size
; ++i
)
284 new_size
+= strlen(html_replace(html
[i
], scratch_space
));
286 p
= escaped_html
= malloc(new_size
+ 1);
287 if (escaped_html
== NULL
)
288 event_err(1, "%s: malloc(%d)", __func__
, new_size
+ 1);
289 for (i
= 0; i
< old_size
; ++i
) {
290 const char *replaced
= html_replace(html
[i
], scratch_space
);
291 /* this is length checked */
293 p
+= strlen(replaced
);
298 return (escaped_html
);
302 evhttp_method(enum evhttp_cmd_type type
)
310 case EVHTTP_REQ_POST
:
313 case EVHTTP_REQ_HEAD
:
325 evhttp_add_event(struct event
*ev
, int timeout
, int default_timeout
)
330 evutil_timerclear(&tv
);
331 tv
.tv_sec
= timeout
!= -1 ? timeout
: default_timeout
;
339 evhttp_write_buffer(struct evhttp_connection
*evcon
,
340 void (*cb
)(struct evhttp_connection
*, void *), void *arg
)
342 event_debug(("%s: preparing to write buffer\n", __func__
));
348 /* check if the event is already pending */
349 if (event_pending(&evcon
->ev
, EV_WRITE
|EV_TIMEOUT
, NULL
))
350 event_del(&evcon
->ev
);
352 event_set(&evcon
->ev
, evcon
->fd
, EV_WRITE
, evhttp_write
, evcon
);
353 EVHTTP_BASE_SET(evcon
, &evcon
->ev
);
354 evhttp_add_event(&evcon
->ev
, evcon
->timeout
, HTTP_WRITE_TIMEOUT
);
358 evhttp_connected(struct evhttp_connection
*evcon
)
360 switch (evcon
->state
) {
361 case EVCON_DISCONNECTED
:
362 case EVCON_CONNECTING
:
365 case EVCON_READING_FIRSTLINE
:
366 case EVCON_READING_HEADERS
:
367 case EVCON_READING_BODY
:
368 case EVCON_READING_TRAILER
:
376 * Create the headers needed for an HTTP request
379 evhttp_make_header_request(struct evhttp_connection
*evcon
,
380 struct evhttp_request
*req
)
384 evhttp_remove_header(req
->output_headers
, "Proxy-Connection");
386 /* Generate request line */
387 method
= evhttp_method(req
->type
);
388 evbuffer_add_printf(evcon
->output_buffer
, "%s %s HTTP/%d.%d\r\n",
389 method
, req
->uri
, req
->major
, req
->minor
);
391 /* Add the content length on a post request if missing */
392 if (req
->type
== EVHTTP_REQ_POST
&&
393 evhttp_find_header(req
->output_headers
, "Content-Length") == NULL
){
395 evutil_snprintf(size
, sizeof(size
), "%ld",
396 (long)EVBUFFER_LENGTH(req
->output_buffer
));
397 evhttp_add_header(req
->output_headers
, "Content-Length", size
);
402 evhttp_is_connection_close(int flags
, struct evkeyvalq
* headers
)
404 if (flags
& EVHTTP_PROXY_REQUEST
) {
405 /* proxy connection */
406 const char *connection
= evhttp_find_header(headers
, "Proxy-Connection");
407 return (connection
== NULL
|| strcasecmp(connection
, "keep-alive") != 0);
409 const char *connection
= evhttp_find_header(headers
, "Connection");
410 return (connection
!= NULL
&& strcasecmp(connection
, "close") == 0);
415 evhttp_is_connection_keepalive(struct evkeyvalq
* headers
)
417 const char *connection
= evhttp_find_header(headers
, "Connection");
418 return (connection
!= NULL
419 && strncasecmp(connection
, "keep-alive", 10) == 0);
423 evhttp_maybe_add_date_header(struct evkeyvalq
*headers
)
425 if (evhttp_find_header(headers
, "Date") == NULL
) {
431 time_t t
= time(NULL
);
438 if (strftime(date
, sizeof(date
),
439 "%a, %d %b %Y %H:%M:%S GMT", cur_p
) != 0) {
440 evhttp_add_header(headers
, "Date", date
);
446 evhttp_maybe_add_content_length_header(struct evkeyvalq
*headers
,
449 if (evhttp_find_header(headers
, "Transfer-Encoding") == NULL
&&
450 evhttp_find_header(headers
, "Content-Length") == NULL
) {
452 evutil_snprintf(len
, sizeof(len
), "%ld", content_length
);
453 evhttp_add_header(headers
, "Content-Length", len
);
458 * Create the headers needed for an HTTP reply
462 evhttp_make_header_response(struct evhttp_connection
*evcon
,
463 struct evhttp_request
*req
)
465 int is_keepalive
= evhttp_is_connection_keepalive(req
->input_headers
);
466 evbuffer_add_printf(evcon
->output_buffer
, "HTTP/%d.%d %d %s\r\n",
467 req
->major
, req
->minor
, req
->response_code
,
468 req
->response_code_line
);
470 if (req
->major
== 1) {
472 evhttp_maybe_add_date_header(req
->output_headers
);
475 * if the protocol is 1.0; and the connection was keep-alive
476 * we need to add a keep-alive header, too.
478 if (req
->minor
== 0 && is_keepalive
)
479 evhttp_add_header(req
->output_headers
,
480 "Connection", "keep-alive");
482 if (req
->minor
== 1 || is_keepalive
) {
484 * we need to add the content length if the
485 * user did not give it, this is required for
486 * persistent connections to work.
488 evhttp_maybe_add_content_length_header(
490 (long)EVBUFFER_LENGTH(req
->output_buffer
));
494 /* Potentially add headers for unidentified content. */
495 if (EVBUFFER_LENGTH(req
->output_buffer
)) {
496 if (evhttp_find_header(req
->output_headers
,
497 "Content-Type") == NULL
) {
498 evhttp_add_header(req
->output_headers
,
499 "Content-Type", "text/html; charset=ISO-8859-1");
503 /* if the request asked for a close, we send a close, too */
504 if (evhttp_is_connection_close(req
->flags
, req
->input_headers
)) {
505 evhttp_remove_header(req
->output_headers
, "Connection");
506 if (!(req
->flags
& EVHTTP_PROXY_REQUEST
))
507 evhttp_add_header(req
->output_headers
, "Connection", "close");
508 evhttp_remove_header(req
->output_headers
, "Proxy-Connection");
513 evhttp_make_header(struct evhttp_connection
*evcon
, struct evhttp_request
*req
)
515 struct evkeyval
*header
;
518 * Depending if this is a HTTP request or response, we might need to
519 * add some new headers or remove existing headers.
521 if (req
->kind
== EVHTTP_REQUEST
) {
522 evhttp_make_header_request(evcon
, req
);
524 evhttp_make_header_response(evcon
, req
);
527 TAILQ_FOREACH(header
, req
->output_headers
, next
) {
528 evbuffer_add_printf(evcon
->output_buffer
, "%s: %s\r\n",
529 header
->key
, header
->value
);
531 evbuffer_add(evcon
->output_buffer
, "\r\n", 2);
533 if (EVBUFFER_LENGTH(req
->output_buffer
) > 0) {
535 * For a request, we add the POST data, for a reply, this
536 * is the regular data.
538 evbuffer_add_buffer(evcon
->output_buffer
, req
->output_buffer
);
542 /* Separated host, port and file from URI */
545 evhttp_hostportfile(char *url
, char **phost
, u_short
*pport
, char **pfile
)
547 /* XXX not threadsafe. */
548 static char host
[1024];
549 static char file
[1024];
555 len
= strlen(HTTP_PREFIX
);
556 if (strncasecmp(url
, HTTP_PREFIX
, len
))
561 /* We might overrun */
562 if (strlcpy(host
, url
, sizeof (host
)) >= sizeof(host
))
565 p
= strchr(host
, '/');
573 /* Generate request file */
576 evutil_snprintf(file
, sizeof(file
), "/%s", p2
);
579 p
= strchr(host
, ':');
587 port
= HTTP_DEFAULTPORT
;
600 evhttp_connection_incoming_fail(struct evhttp_request
*req
,
601 enum evhttp_connection_error error
)
604 case EVCON_HTTP_TIMEOUT
:
607 * these are cases in which we probably should just
608 * close the connection and not send a reply. this
609 * case may happen when a browser keeps a persistent
610 * connection open and we timeout on the read.
613 case EVCON_HTTP_INVALID_HEADER
:
614 default: /* xxx: probably should just error on default */
615 /* the callback looks at the uri to determine errors */
622 * the callback needs to send a reply, once the reply has
623 * been send, the connection should get freed.
625 (*req
->cb
)(req
, req
->cb_arg
);
632 evhttp_connection_fail(struct evhttp_connection
*evcon
,
633 enum evhttp_connection_error error
)
635 struct evhttp_request
* req
= TAILQ_FIRST(&evcon
->requests
);
636 void (*cb
)(struct evhttp_request
*, void *);
640 if (evcon
->flags
& EVHTTP_CON_INCOMING
) {
642 * for incoming requests, there are two different
643 * failure cases. it's either a network level error
644 * or an http layer error. for problems on the network
645 * layer like timeouts we just drop the connections.
646 * For HTTP problems, we might have to send back a
647 * reply before the connection can be freed.
649 if (evhttp_connection_incoming_fail(req
, error
) == -1)
650 evhttp_connection_free(evcon
);
654 /* save the callback for later; the cb might free our object */
656 cb_arg
= req
->cb_arg
;
658 TAILQ_REMOVE(&evcon
->requests
, req
, next
);
659 evhttp_request_free(req
);
661 /* xxx: maybe we should fail all requests??? */
663 /* reset the connection */
664 evhttp_connection_reset(evcon
);
666 /* We are trying the next request that was queued on us */
667 if (TAILQ_FIRST(&evcon
->requests
) != NULL
)
668 evhttp_connection_connect(evcon
);
670 /* inform the user */
676 evhttp_write(int fd
, short what
, void *arg
)
678 struct evhttp_connection
*evcon
= arg
;
681 if (what
== EV_TIMEOUT
) {
682 evhttp_connection_fail(evcon
, EVCON_HTTP_TIMEOUT
);
686 n
= evbuffer_write(evcon
->output_buffer
, fd
);
688 event_debug(("%s: evbuffer_write", __func__
));
689 evhttp_connection_fail(evcon
, EVCON_HTTP_EOF
);
694 event_debug(("%s: write nothing", __func__
));
695 evhttp_connection_fail(evcon
, EVCON_HTTP_EOF
);
699 if (EVBUFFER_LENGTH(evcon
->output_buffer
) != 0) {
700 evhttp_add_event(&evcon
->ev
,
701 evcon
->timeout
, HTTP_WRITE_TIMEOUT
);
705 /* Activate our call back */
706 if (evcon
->cb
!= NULL
)
707 (*evcon
->cb
)(evcon
, evcon
->cb_arg
);
711 * Advance the connection state.
712 * - If this is an outgoing connection, we've just processed the response;
713 * idle or close the connection.
714 * - If this is an incoming connection, we've just processed the request;
718 evhttp_connection_done(struct evhttp_connection
*evcon
)
720 struct evhttp_request
*req
= TAILQ_FIRST(&evcon
->requests
);
721 int con_outgoing
= evcon
->flags
& EVHTTP_CON_OUTGOING
;
724 /* idle or close the connection */
726 TAILQ_REMOVE(&evcon
->requests
, req
, next
);
729 evcon
->state
= EVCON_IDLE
;
732 evhttp_is_connection_close(req
->flags
, req
->input_headers
)||
733 evhttp_is_connection_close(req
->flags
, req
->output_headers
);
735 /* check if we got asked to close the connection */
737 evhttp_connection_reset(evcon
);
739 if (TAILQ_FIRST(&evcon
->requests
) != NULL
) {
741 * We have more requests; reset the connection
742 * and deal with the next request.
744 if (!evhttp_connected(evcon
))
745 evhttp_connection_connect(evcon
);
747 evhttp_request_dispatch(evcon
);
748 } else if (!need_close
) {
750 * The connection is going to be persistent, but we
751 * need to detect if the other side closes it.
753 evhttp_connection_start_detectclose(evcon
);
757 * incoming connection - we need to leave the request on the
758 * connection so that we can reply to it.
760 evcon
->state
= EVCON_WRITING
;
763 /* notify the user of the request */
764 (*req
->cb
)(req
, req
->cb_arg
);
766 /* if this was an outgoing request, we own and it's done. so free it */
768 evhttp_request_free(req
);
773 * Handles reading from a chunked request.
774 * return ALL_DATA_READ:
775 * all data has been read
776 * return MORE_DATA_EXPECTED:
777 * more data is expected
778 * return DATA_CORRUPTED:
780 * return REQUEST_CANCLED:
781 * request was canceled by the user calling evhttp_cancel_request
784 static enum message_read_status
785 evhttp_handle_chunked_read(struct evhttp_request
*req
, struct evbuffer
*buf
)
789 while ((len
= EVBUFFER_LENGTH(buf
)) > 0) {
790 if (req
->ntoread
< 0) {
791 /* Read chunk size */
793 char *p
= evbuffer_readline(buf
);
798 /* the last chunk is on a new line? */
799 if (strlen(p
) == 0) {
803 ntoread
= evutil_strtoll(p
, &endp
, 16);
804 error
= (*p
== '\0' ||
805 (*endp
!= '\0' && *endp
!= ' ') ||
809 /* could not get chunk size */
810 return (DATA_CORRUPTED
);
812 req
->ntoread
= ntoread
;
813 if (req
->ntoread
== 0) {
815 return (ALL_DATA_READ
);
820 /* don't have enough to complete a chunk; wait for more */
821 if (len
< req
->ntoread
)
822 return (MORE_DATA_EXPECTED
);
824 /* Completed chunk */
825 evbuffer_add(req
->input_buffer
,
826 EVBUFFER_DATA(buf
), (size_t)req
->ntoread
);
827 evbuffer_drain(buf
, (size_t)req
->ntoread
);
829 if (req
->chunk_cb
!= NULL
) {
830 (*req
->chunk_cb
)(req
, req
->cb_arg
);
831 evbuffer_drain(req
->input_buffer
,
832 EVBUFFER_LENGTH(req
->input_buffer
));
836 return (MORE_DATA_EXPECTED
);
840 evhttp_read_trailer(struct evhttp_connection
*evcon
, struct evhttp_request
*req
)
842 struct evbuffer
*buf
= evcon
->input_buffer
;
844 switch (evhttp_parse_headers(req
, buf
)) {
846 evhttp_connection_fail(evcon
, EVCON_HTTP_INVALID_HEADER
);
849 event_del(&evcon
->ev
);
850 evhttp_connection_done(evcon
);
852 case MORE_DATA_EXPECTED
:
854 evhttp_add_event(&evcon
->ev
, evcon
->timeout
,
861 evhttp_read_body(struct evhttp_connection
*evcon
, struct evhttp_request
*req
)
863 struct evbuffer
*buf
= evcon
->input_buffer
;
866 switch (evhttp_handle_chunked_read(req
, buf
)) {
868 /* finished last chunk */
869 evcon
->state
= EVCON_READING_TRAILER
;
870 evhttp_read_trailer(evcon
, req
);
874 evhttp_connection_fail(evcon
,
875 EVCON_HTTP_INVALID_HEADER
);
877 case REQUEST_CANCELED
:
878 /* request canceled */
879 evhttp_request_free(req
);
881 case MORE_DATA_EXPECTED
:
885 } else if (req
->ntoread
< 0) {
886 /* Read until connection close. */
887 evbuffer_add_buffer(req
->input_buffer
, buf
);
888 } else if (EVBUFFER_LENGTH(buf
) >= req
->ntoread
) {
889 /* Completed content length */
890 evbuffer_add(req
->input_buffer
, EVBUFFER_DATA(buf
),
891 (size_t)req
->ntoread
);
892 evbuffer_drain(buf
, (size_t)req
->ntoread
);
894 evhttp_connection_done(evcon
);
898 event_set(&evcon
->ev
, evcon
->fd
, EV_READ
, evhttp_read
, evcon
);
899 EVHTTP_BASE_SET(evcon
, &evcon
->ev
);
900 evhttp_add_event(&evcon
->ev
, evcon
->timeout
, HTTP_READ_TIMEOUT
);
904 * Reads data into a buffer structure until no more data
905 * can be read on the file descriptor or we have read all
906 * the data that we wanted to read.
907 * Execute callback when done.
911 evhttp_read(int fd
, short what
, void *arg
)
913 struct evhttp_connection
*evcon
= arg
;
914 struct evhttp_request
*req
= TAILQ_FIRST(&evcon
->requests
);
915 struct evbuffer
*buf
= evcon
->input_buffer
;
918 if (what
== EV_TIMEOUT
) {
919 evhttp_connection_fail(evcon
, EVCON_HTTP_TIMEOUT
);
922 n
= evbuffer_read(buf
, fd
, -1);
923 len
= EVBUFFER_LENGTH(buf
);
924 event_debug(("%s: got %d on %d\n", __func__
, n
, fd
));
927 if (errno
!= EINTR
&& errno
!= EAGAIN
) {
928 event_debug(("%s: evbuffer_read", __func__
));
929 evhttp_connection_fail(evcon
, EVCON_HTTP_EOF
);
931 evhttp_add_event(&evcon
->ev
, evcon
->timeout
,
936 /* Connection closed */
937 evhttp_connection_done(evcon
);
941 switch (evcon
->state
) {
942 case EVCON_READING_FIRSTLINE
:
943 evhttp_read_firstline(evcon
, req
);
945 case EVCON_READING_HEADERS
:
946 evhttp_read_header(evcon
, req
);
948 case EVCON_READING_BODY
:
949 evhttp_read_body(evcon
, req
);
951 case EVCON_READING_TRAILER
:
952 evhttp_read_trailer(evcon
, req
);
954 case EVCON_DISCONNECTED
:
955 case EVCON_CONNECTING
:
959 event_errx(1, "%s: illegal connection state %d",
960 __func__
, evcon
->state
);
965 evhttp_write_connectioncb(struct evhttp_connection
*evcon
, void *arg
)
967 /* This is after writing the request to the server */
968 struct evhttp_request
*req
= TAILQ_FIRST(&evcon
->requests
);
971 assert(evcon
->state
== EVCON_WRITING
);
973 /* We are done writing our header and are now expecting the response */
974 req
->kind
= EVHTTP_RESPONSE
;
976 evhttp_start_read(evcon
);
980 * Clean up a connection object
984 evhttp_connection_free(struct evhttp_connection
*evcon
)
986 struct evhttp_request
*req
;
988 /* notify interested parties that this connection is going down */
989 if (evcon
->fd
!= -1) {
990 if (evhttp_connected(evcon
) && evcon
->closecb
!= NULL
)
991 (*evcon
->closecb
)(evcon
, evcon
->closecb_arg
);
994 /* remove all requests that might be queued on this connection */
995 while ((req
= TAILQ_FIRST(&evcon
->requests
)) != NULL
) {
996 TAILQ_REMOVE(&evcon
->requests
, req
, next
);
997 evhttp_request_free(req
);
1000 if (evcon
->http_server
!= NULL
) {
1001 struct evhttp
*http
= evcon
->http_server
;
1002 TAILQ_REMOVE(&http
->connections
, evcon
, next
);
1005 if (event_initialized(&evcon
->close_ev
))
1006 event_del(&evcon
->close_ev
);
1008 if (event_initialized(&evcon
->ev
))
1009 event_del(&evcon
->ev
);
1011 if (evcon
->fd
!= -1)
1012 EVUTIL_CLOSESOCKET(evcon
->fd
);
1014 if (evcon
->bind_address
!= NULL
)
1015 free(evcon
->bind_address
);
1017 if (evcon
->address
!= NULL
)
1018 free(evcon
->address
);
1020 if (evcon
->input_buffer
!= NULL
)
1021 evbuffer_free(evcon
->input_buffer
);
1023 if (evcon
->output_buffer
!= NULL
)
1024 evbuffer_free(evcon
->output_buffer
);
1030 evhttp_connection_set_local_address(struct evhttp_connection
*evcon
,
1031 const char *address
)
1033 assert(evcon
->state
== EVCON_DISCONNECTED
);
1034 if (evcon
->bind_address
)
1035 free(evcon
->bind_address
);
1036 if ((evcon
->bind_address
= strdup(address
)) == NULL
)
1037 event_err(1, "%s: strdup", __func__
);
1041 evhttp_connection_set_local_port(struct evhttp_connection
*evcon
,
1042 unsigned short port
)
1044 assert(evcon
->state
== EVCON_DISCONNECTED
);
1045 evcon
->bind_port
= port
;
1049 evhttp_request_dispatch(struct evhttp_connection
* evcon
)
1051 struct evhttp_request
*req
= TAILQ_FIRST(&evcon
->requests
);
1053 /* this should not usually happy but it's possible */
1057 /* delete possible close detection events */
1058 evhttp_connection_stop_detectclose(evcon
);
1060 /* we assume that the connection is connected already */
1061 assert(evcon
->state
== EVCON_IDLE
);
1063 evcon
->state
= EVCON_WRITING
;
1065 /* Create the header from the store arguments */
1066 evhttp_make_header(evcon
, req
);
1068 evhttp_write_buffer(evcon
, evhttp_write_connectioncb
, NULL
);
1071 /* Reset our connection state */
1073 evhttp_connection_reset(struct evhttp_connection
*evcon
)
1075 if (event_initialized(&evcon
->ev
))
1076 event_del(&evcon
->ev
);
1078 if (evcon
->fd
!= -1) {
1079 /* inform interested parties about connection close */
1080 if (evhttp_connected(evcon
) && evcon
->closecb
!= NULL
)
1081 (*evcon
->closecb
)(evcon
, evcon
->closecb_arg
);
1083 EVUTIL_CLOSESOCKET(evcon
->fd
);
1086 evcon
->state
= EVCON_DISCONNECTED
;
1088 evbuffer_drain(evcon
->input_buffer
,
1089 EVBUFFER_LENGTH(evcon
->input_buffer
));
1090 evbuffer_drain(evcon
->output_buffer
,
1091 EVBUFFER_LENGTH(evcon
->output_buffer
));
1095 evhttp_detect_close_cb(int fd
, short what
, void *arg
)
1097 struct evhttp_connection
*evcon
= arg
;
1098 evhttp_connection_reset(evcon
);
1102 evhttp_connection_start_detectclose(struct evhttp_connection
*evcon
)
1104 evcon
->flags
|= EVHTTP_CON_CLOSEDETECT
;
1106 if (event_initialized(&evcon
->close_ev
))
1107 event_del(&evcon
->close_ev
);
1108 event_set(&evcon
->close_ev
, evcon
->fd
, EV_READ
,
1109 evhttp_detect_close_cb
, evcon
);
1110 EVHTTP_BASE_SET(evcon
, &evcon
->close_ev
);
1111 event_add(&evcon
->close_ev
, NULL
);
1115 evhttp_connection_stop_detectclose(struct evhttp_connection
*evcon
)
1117 evcon
->flags
&= ~EVHTTP_CON_CLOSEDETECT
;
1118 event_del(&evcon
->close_ev
);
1122 evhttp_connection_retry(int fd
, short what
, void *arg
)
1124 struct evhttp_connection
*evcon
= arg
;
1126 evcon
->state
= EVCON_DISCONNECTED
;
1127 evhttp_connection_connect(evcon
);
1131 * Call back for asynchronous connection attempt.
1135 evhttp_connectioncb(int fd
, short what
, void *arg
)
1137 struct evhttp_connection
*evcon
= arg
;
1139 socklen_t errsz
= sizeof(error
);
1141 if (what
== EV_TIMEOUT
) {
1142 event_debug(("%s: connection timeout for \"%s:%d\" on %d",
1143 __func__
, evcon
->address
, evcon
->port
, evcon
->fd
));
1147 /* Check if the connection completed */
1148 if (getsockopt(evcon
->fd
, SOL_SOCKET
, SO_ERROR
, (void*)&error
,
1150 event_debug(("%s: getsockopt for \"%s:%d\" on %d",
1151 __func__
, evcon
->address
, evcon
->port
, evcon
->fd
));
1156 event_debug(("%s: connect failed for \"%s:%d\" on %d: %s",
1157 __func__
, evcon
->address
, evcon
->port
, evcon
->fd
,
1162 /* We are connected to the server now */
1163 event_debug(("%s: connected to \"%s:%d\" on %d\n",
1164 __func__
, evcon
->address
, evcon
->port
, evcon
->fd
));
1166 /* Reset the retry count as we were successful in connecting */
1167 evcon
->retry_cnt
= 0;
1168 evcon
->state
= EVCON_IDLE
;
1170 /* try to start requests that have queued up on this connection */
1171 evhttp_request_dispatch(evcon
);
1175 if (evcon
->retry_max
< 0 || evcon
->retry_cnt
< evcon
->retry_max
) {
1176 evtimer_set(&evcon
->ev
, evhttp_connection_retry
, evcon
);
1177 EVHTTP_BASE_SET(evcon
, &evcon
->ev
);
1178 evhttp_add_event(&evcon
->ev
, MIN(3600, 2 << evcon
->retry_cnt
),
1179 HTTP_CONNECT_TIMEOUT
);
1183 evhttp_connection_reset(evcon
);
1185 /* for now, we just signal all requests by executing their callbacks */
1186 while (TAILQ_FIRST(&evcon
->requests
) != NULL
) {
1187 struct evhttp_request
*request
= TAILQ_FIRST(&evcon
->requests
);
1188 TAILQ_REMOVE(&evcon
->requests
, request
, next
);
1189 request
->evcon
= NULL
;
1191 /* we might want to set an error here */
1192 request
->cb(request
, request
->cb_arg
);
1193 evhttp_request_free(request
);
1198 * Check if we got a valid response code.
1202 evhttp_valid_response_code(int code
)
1210 /* Parses the status line of a web server */
1213 evhttp_parse_response_line(struct evhttp_request
*req
, char *line
)
1219 protocol
= strsep(&line
, " ");
1222 number
= strsep(&line
, " ");
1227 if (strcmp(protocol
, "HTTP/1.0") == 0) {
1230 } else if (strcmp(protocol
, "HTTP/1.1") == 0) {
1234 event_debug(("%s: bad protocol \"%s\"",
1235 __func__
, protocol
));
1239 req
->response_code
= atoi(number
);
1240 if (!evhttp_valid_response_code(req
->response_code
)) {
1241 event_debug(("%s: bad response code \"%s\"",
1246 if ((req
->response_code_line
= strdup(readable
)) == NULL
)
1247 event_err(1, "%s: strdup", __func__
);
1252 /* Parse the first line of a HTTP request */
1255 evhttp_parse_request_line(struct evhttp_request
*req
, char *line
)
1261 /* Parse the request line */
1262 method
= strsep(&line
, " ");
1265 uri
= strsep(&line
, " ");
1268 version
= strsep(&line
, " ");
1273 if (strcmp(method
, "GET") == 0) {
1274 req
->type
= EVHTTP_REQ_GET
;
1275 } else if (strcmp(method
, "POST") == 0) {
1276 req
->type
= EVHTTP_REQ_POST
;
1277 } else if (strcmp(method
, "HEAD") == 0) {
1278 req
->type
= EVHTTP_REQ_HEAD
;
1280 event_debug(("%s: bad method %s on request %p from %s",
1281 __func__
, method
, req
, req
->remote_host
));
1285 if (strcmp(version
, "HTTP/1.0") == 0) {
1288 } else if (strcmp(version
, "HTTP/1.1") == 0) {
1292 event_debug(("%s: bad version %s on request %p from %s",
1293 __func__
, version
, req
, req
->remote_host
));
1297 if ((req
->uri
= strdup(uri
)) == NULL
) {
1298 event_debug(("%s: evhttp_decode_uri", __func__
));
1302 /* determine if it's a proxy request */
1303 if (strlen(req
->uri
) > 0 && req
->uri
[0] != '/')
1304 req
->flags
|= EVHTTP_PROXY_REQUEST
;
1310 evhttp_find_header(const struct evkeyvalq
*headers
, const char *key
)
1312 struct evkeyval
*header
;
1314 TAILQ_FOREACH(header
, headers
, next
) {
1315 if (strcasecmp(header
->key
, key
) == 0)
1316 return (header
->value
);
1323 evhttp_clear_headers(struct evkeyvalq
*headers
)
1325 struct evkeyval
*header
;
1327 for (header
= TAILQ_FIRST(headers
);
1329 header
= TAILQ_FIRST(headers
)) {
1330 TAILQ_REMOVE(headers
, header
, next
);
1332 free(header
->value
);
1338 * Returns 0, if the header was successfully removed.
1339 * Returns -1, if the header could not be found.
1343 evhttp_remove_header(struct evkeyvalq
*headers
, const char *key
)
1345 struct evkeyval
*header
;
1347 TAILQ_FOREACH(header
, headers
, next
) {
1348 if (strcasecmp(header
->key
, key
) == 0)
1355 /* Free and remove the header that we found */
1356 TAILQ_REMOVE(headers
, header
, next
);
1358 free(header
->value
);
1365 evhttp_header_is_valid_value(const char *value
)
1367 const char *p
= value
;
1369 while ((p
= strpbrk(p
, "\r\n")) != NULL
) {
1370 /* we really expect only one new line */
1371 p
+= strspn(p
, "\r\n");
1372 /* we expect a space or tab for continuation */
1373 if (*p
!= ' ' && *p
!= '\t')
1380 evhttp_add_header(struct evkeyvalq
*headers
,
1381 const char *key
, const char *value
)
1383 event_debug(("%s: key: %s val: %s\n", __func__
, key
, value
));
1385 if (strchr(key
, '\r') != NULL
|| strchr(key
, '\n') != NULL
) {
1386 /* drop illegal headers */
1387 event_debug(("%s: dropping illegal header key\n", __func__
));
1391 if (!evhttp_header_is_valid_value(value
)) {
1392 event_debug(("%s: dropping illegal header value\n", __func__
));
1396 return (evhttp_add_header_internal(headers
, key
, value
));
1400 evhttp_add_header_internal(struct evkeyvalq
*headers
,
1401 const char *key
, const char *value
)
1403 struct evkeyval
*header
= calloc(1, sizeof(struct evkeyval
));
1404 if (header
== NULL
) {
1405 event_warn("%s: calloc", __func__
);
1408 if ((header
->key
= strdup(key
)) == NULL
) {
1410 event_warn("%s: strdup", __func__
);
1413 if ((header
->value
= strdup(value
)) == NULL
) {
1416 event_warn("%s: strdup", __func__
);
1420 TAILQ_INSERT_TAIL(headers
, header
, next
);
1426 * Parses header lines from a request or a response into the specified
1427 * request object given an event buffer.
1430 * DATA_CORRUPTED on error
1431 * MORE_DATA_EXPECTED when we need to read more headers
1432 * ALL_DATA_READ when all headers have been read.
1435 enum message_read_status
1436 evhttp_parse_firstline(struct evhttp_request
*req
, struct evbuffer
*buffer
)
1439 enum message_read_status status
= ALL_DATA_READ
;
1441 line
= evbuffer_readline(buffer
);
1443 return (MORE_DATA_EXPECTED
);
1445 switch (req
->kind
) {
1446 case EVHTTP_REQUEST
:
1447 if (evhttp_parse_request_line(req
, line
) == -1)
1448 status
= DATA_CORRUPTED
;
1450 case EVHTTP_RESPONSE
:
1451 if (evhttp_parse_response_line(req
, line
) == -1)
1452 status
= DATA_CORRUPTED
;
1455 status
= DATA_CORRUPTED
;
1463 evhttp_append_to_last_header(struct evkeyvalq
*headers
, const char *line
)
1465 struct evkeyval
*header
= TAILQ_LAST(headers
, evkeyvalq
);
1467 size_t old_len
, line_len
;
1472 old_len
= strlen(header
->value
);
1473 line_len
= strlen(line
);
1475 newval
= realloc(header
->value
, old_len
+ line_len
+ 1);
1479 memcpy(newval
+ old_len
, line
, line_len
+ 1);
1480 header
->value
= newval
;
1485 enum message_read_status
1486 evhttp_parse_headers(struct evhttp_request
*req
, struct evbuffer
* buffer
)
1489 enum message_read_status status
= MORE_DATA_EXPECTED
;
1491 struct evkeyvalq
* headers
= req
->input_headers
;
1492 while ((line
= evbuffer_readline(buffer
))
1494 char *skey
, *svalue
;
1496 if (*line
== '\0') { /* Last header - Done */
1497 status
= ALL_DATA_READ
;
1502 /* Check if this is a continuation line */
1503 if (*line
== ' ' || *line
== '\t') {
1504 if (evhttp_append_to_last_header(headers
, line
) == -1)
1510 /* Processing of header lines */
1512 skey
= strsep(&svalue
, ":");
1516 svalue
+= strspn(svalue
, " ");
1518 if (evhttp_add_header(headers
, skey
, svalue
) == -1)
1528 return (DATA_CORRUPTED
);
1532 evhttp_get_body_length(struct evhttp_request
*req
)
1534 struct evkeyvalq
*headers
= req
->input_headers
;
1535 const char *content_length
;
1536 const char *connection
;
1538 content_length
= evhttp_find_header(headers
, "Content-Length");
1539 connection
= evhttp_find_header(headers
, "Connection");
1541 if (content_length
== NULL
&& connection
== NULL
)
1543 else if (content_length
== NULL
&&
1544 strcasecmp(connection
, "Close") != 0) {
1545 /* Bad combination, we don't know when it will end */
1546 event_warnx("%s: we got no content length, but the "
1547 "server wants to keep the connection open: %s.",
1548 __func__
, connection
);
1550 } else if (content_length
== NULL
) {
1554 ev_int64_t ntoread
= evutil_strtoll(content_length
, &endp
, 10);
1555 if (*content_length
== '\0' || *endp
!= '\0' || ntoread
< 0) {
1556 event_debug(("%s: illegal content length: %s",
1557 __func__
, content_length
));
1560 req
->ntoread
= ntoread
;
1563 event_debug(("%s: bytes to read: %lld (in buffer %ld)\n",
1564 __func__
, req
->ntoread
,
1565 EVBUFFER_LENGTH(req
->evcon
->input_buffer
)));
1571 evhttp_get_body(struct evhttp_connection
*evcon
, struct evhttp_request
*req
)
1573 const char *xfer_enc
;
1575 /* If this is a request without a body, then we are done */
1576 if (req
->kind
== EVHTTP_REQUEST
&& req
->type
!= EVHTTP_REQ_POST
) {
1577 evhttp_connection_done(evcon
);
1580 evcon
->state
= EVCON_READING_BODY
;
1581 xfer_enc
= evhttp_find_header(req
->input_headers
, "Transfer-Encoding");
1582 if (xfer_enc
!= NULL
&& strcasecmp(xfer_enc
, "chunked") == 0) {
1586 if (evhttp_get_body_length(req
) == -1) {
1587 evhttp_connection_fail(evcon
,
1588 EVCON_HTTP_INVALID_HEADER
);
1592 evhttp_read_body(evcon
, req
);
1596 evhttp_read_firstline(struct evhttp_connection
*evcon
,
1597 struct evhttp_request
*req
)
1599 enum message_read_status res
;
1601 res
= evhttp_parse_firstline(req
, evcon
->input_buffer
);
1602 if (res
== DATA_CORRUPTED
) {
1603 /* Error while reading, terminate */
1604 event_debug(("%s: bad header lines on %d\n",
1605 __func__
, evcon
->fd
));
1606 evhttp_connection_fail(evcon
, EVCON_HTTP_INVALID_HEADER
);
1608 } else if (res
== MORE_DATA_EXPECTED
) {
1609 /* Need more header lines */
1610 evhttp_add_event(&evcon
->ev
,
1611 evcon
->timeout
, HTTP_READ_TIMEOUT
);
1615 evcon
->state
= EVCON_READING_HEADERS
;
1616 evhttp_read_header(evcon
, req
);
1620 evhttp_read_header(struct evhttp_connection
*evcon
, struct evhttp_request
*req
)
1622 enum message_read_status res
;
1625 res
= evhttp_parse_headers(req
, evcon
->input_buffer
);
1626 if (res
== DATA_CORRUPTED
) {
1627 /* Error while reading, terminate */
1628 event_debug(("%s: bad header lines on %d\n", __func__
, fd
));
1629 evhttp_connection_fail(evcon
, EVCON_HTTP_INVALID_HEADER
);
1631 } else if (res
== MORE_DATA_EXPECTED
) {
1632 /* Need more header lines */
1633 evhttp_add_event(&evcon
->ev
,
1634 evcon
->timeout
, HTTP_READ_TIMEOUT
);
1638 /* Done reading headers, do the real work */
1639 switch (req
->kind
) {
1640 case EVHTTP_REQUEST
:
1641 event_debug(("%s: checking for post data on %d\n",
1643 evhttp_get_body(evcon
, req
);
1646 case EVHTTP_RESPONSE
:
1647 if (req
->response_code
== HTTP_NOCONTENT
||
1648 req
->response_code
== HTTP_NOTMODIFIED
||
1649 (req
->response_code
>= 100 && req
->response_code
< 200)) {
1650 event_debug(("%s: skipping body for code %d\n",
1651 __func__
, req
->response_code
));
1652 evhttp_connection_done(evcon
);
1654 event_debug(("%s: start of read body for %s on %d\n",
1655 __func__
, req
->remote_host
, fd
));
1656 evhttp_get_body(evcon
, req
);
1661 event_warnx("%s: bad header on %d", __func__
, fd
);
1662 evhttp_connection_fail(evcon
, EVCON_HTTP_INVALID_HEADER
);
1668 * Creates a TCP connection to the specified port and executes a callback
1669 * when finished. Failure or sucess is indicate by the passed connection
1672 * Although this interface accepts a hostname, it is intended to take
1673 * only numeric hostnames so that non-blocking DNS resolution can
1677 struct evhttp_connection
*
1678 evhttp_connection_new(const char *address
, unsigned short port
)
1680 struct evhttp_connection
*evcon
= NULL
;
1682 event_debug(("Attempting connection to %s:%d\n", address
, port
));
1684 if ((evcon
= calloc(1, sizeof(struct evhttp_connection
))) == NULL
) {
1685 event_warn("%s: calloc failed", __func__
);
1692 evcon
->timeout
= -1;
1693 evcon
->retry_cnt
= evcon
->retry_max
= 0;
1695 if ((evcon
->address
= strdup(address
)) == NULL
) {
1696 event_warn("%s: strdup failed", __func__
);
1700 if ((evcon
->input_buffer
= evbuffer_new()) == NULL
) {
1701 event_warn("%s: evbuffer_new failed", __func__
);
1705 if ((evcon
->output_buffer
= evbuffer_new()) == NULL
) {
1706 event_warn("%s: evbuffer_new failed", __func__
);
1710 evcon
->state
= EVCON_DISCONNECTED
;
1711 TAILQ_INIT(&evcon
->requests
);
1717 evhttp_connection_free(evcon
);
1721 void evhttp_connection_set_base(struct evhttp_connection
*evcon
,
1722 struct event_base
*base
)
1724 assert(evcon
->base
== NULL
);
1725 assert(evcon
->state
== EVCON_DISCONNECTED
);
1730 evhttp_connection_set_timeout(struct evhttp_connection
*evcon
,
1731 int timeout_in_secs
)
1733 evcon
->timeout
= timeout_in_secs
;
1737 evhttp_connection_set_retries(struct evhttp_connection
*evcon
,
1740 evcon
->retry_max
= retry_max
;
1744 evhttp_connection_set_closecb(struct evhttp_connection
*evcon
,
1745 void (*cb
)(struct evhttp_connection
*, void *), void *cbarg
)
1747 evcon
->closecb
= cb
;
1748 evcon
->closecb_arg
= cbarg
;
1752 evhttp_connection_get_peer(struct evhttp_connection
*evcon
,
1753 char **address
, u_short
*port
)
1755 *address
= evcon
->address
;
1756 *port
= evcon
->port
;
1760 evhttp_connection_connect(struct evhttp_connection
*evcon
)
1762 if (evcon
->state
== EVCON_CONNECTING
)
1765 evhttp_connection_reset(evcon
);
1767 assert(!(evcon
->flags
& EVHTTP_CON_INCOMING
));
1768 evcon
->flags
|= EVHTTP_CON_OUTGOING
;
1770 evcon
->fd
= bind_socket(
1771 evcon
->bind_address
, evcon
->bind_port
, 0 /*reuse*/);
1772 if (evcon
->fd
== -1) {
1773 event_debug(("%s: failed to bind to \"%s\"",
1774 __func__
, evcon
->bind_address
));
1778 if (socket_connect(evcon
->fd
, evcon
->address
, evcon
->port
) == -1) {
1779 EVUTIL_CLOSESOCKET(evcon
->fd
); evcon
->fd
= -1;
1783 /* Set up a callback for successful connection setup */
1784 event_set(&evcon
->ev
, evcon
->fd
, EV_WRITE
, evhttp_connectioncb
, evcon
);
1785 EVHTTP_BASE_SET(evcon
, &evcon
->ev
);
1786 evhttp_add_event(&evcon
->ev
, evcon
->timeout
, HTTP_CONNECT_TIMEOUT
);
1788 evcon
->state
= EVCON_CONNECTING
;
1794 * Starts an HTTP request on the provided evhttp_connection object.
1795 * If the connection object is not connected to the web server already,
1796 * this will start the connection.
1800 evhttp_make_request(struct evhttp_connection
*evcon
,
1801 struct evhttp_request
*req
,
1802 enum evhttp_cmd_type type
, const char *uri
)
1804 /* We are making a request */
1805 req
->kind
= EVHTTP_REQUEST
;
1807 if (req
->uri
!= NULL
)
1809 if ((req
->uri
= strdup(uri
)) == NULL
)
1810 event_err(1, "%s: strdup", __func__
);
1812 /* Set the protocol version if it is not supplied */
1813 if (!req
->major
&& !req
->minor
) {
1818 assert(req
->evcon
== NULL
);
1820 assert(!(req
->flags
& EVHTTP_REQ_OWN_CONNECTION
));
1822 TAILQ_INSERT_TAIL(&evcon
->requests
, req
, next
);
1824 /* If the connection object is not connected; make it so */
1825 if (!evhttp_connected(evcon
))
1826 return (evhttp_connection_connect(evcon
));
1829 * If it's connected already and we are the first in the queue,
1830 * then we can dispatch this request immediately. Otherwise, it
1831 * will be dispatched once the pending requests are completed.
1833 if (TAILQ_FIRST(&evcon
->requests
) == req
)
1834 evhttp_request_dispatch(evcon
);
1840 * Reads data from file descriptor into request structure
1841 * Request structure needs to be set up correctly.
1845 evhttp_start_read(struct evhttp_connection
*evcon
)
1847 /* Set up an event to read the headers */
1848 if (event_initialized(&evcon
->ev
))
1849 event_del(&evcon
->ev
);
1850 event_set(&evcon
->ev
, evcon
->fd
, EV_READ
, evhttp_read
, evcon
);
1851 EVHTTP_BASE_SET(evcon
, &evcon
->ev
);
1853 evhttp_add_event(&evcon
->ev
, evcon
->timeout
, HTTP_READ_TIMEOUT
);
1854 evcon
->state
= EVCON_READING_FIRSTLINE
;
1858 evhttp_send_done(struct evhttp_connection
*evcon
, void *arg
)
1861 struct evhttp_request
*req
= TAILQ_FIRST(&evcon
->requests
);
1862 TAILQ_REMOVE(&evcon
->requests
, req
, next
);
1864 /* delete possible close detection events */
1865 evhttp_connection_stop_detectclose(evcon
);
1869 !evhttp_is_connection_keepalive(req
->input_headers
))||
1870 evhttp_is_connection_close(req
->flags
, req
->input_headers
) ||
1871 evhttp_is_connection_close(req
->flags
, req
->output_headers
);
1873 assert(req
->flags
& EVHTTP_REQ_OWN_CONNECTION
);
1874 evhttp_request_free(req
);
1877 evhttp_connection_free(evcon
);
1881 /* we have a persistent connection; try to accept another request. */
1882 if (evhttp_associate_new_request_with_connection(evcon
) == -1)
1883 evhttp_connection_free(evcon
);
1887 * Returns an error page.
1891 evhttp_send_error(struct evhttp_request
*req
, int error
, const char *reason
)
1893 #define ERR_FORMAT "<HTML><HEAD>\n" \
1894 "<TITLE>%d %s</TITLE>\n" \
1896 "<H1>Method Not Implemented</H1>\n" \
1897 "Invalid method in request<P>\n" \
1900 struct evbuffer
*buf
= evbuffer_new();
1902 /* close the connection on error */
1903 evhttp_add_header(req
->output_headers
, "Connection", "close");
1905 evhttp_response_code(req
, error
, reason
);
1907 evbuffer_add_printf(buf
, ERR_FORMAT
, error
, reason
);
1909 evhttp_send_page(req
, buf
);
1915 /* Requires that headers and response code are already set up */
1918 evhttp_send(struct evhttp_request
*req
, struct evbuffer
*databuf
)
1920 struct evhttp_connection
*evcon
= req
->evcon
;
1922 assert(TAILQ_FIRST(&evcon
->requests
) == req
);
1924 /* xxx: not sure if we really should expose the data buffer this way */
1925 if (databuf
!= NULL
)
1926 evbuffer_add_buffer(req
->output_buffer
, databuf
);
1928 /* Adds headers to the response */
1929 evhttp_make_header(evcon
, req
);
1931 evhttp_write_buffer(evcon
, evhttp_send_done
, NULL
);
1935 evhttp_send_reply(struct evhttp_request
*req
, int code
, const char *reason
,
1936 struct evbuffer
*databuf
)
1938 evhttp_response_code(req
, code
, reason
);
1940 evhttp_send(req
, databuf
);
1944 evhttp_send_reply_start(struct evhttp_request
*req
, int code
,
1947 evhttp_response_code(req
, code
, reason
);
1948 if (req
->major
== 1 && req
->minor
== 1) {
1949 /* use chunked encoding for HTTP/1.1 */
1950 evhttp_add_header(req
->output_headers
, "Transfer-Encoding",
1954 evhttp_make_header(req
->evcon
, req
);
1955 evhttp_write_buffer(req
->evcon
, NULL
, NULL
);
1959 evhttp_send_reply_chunk(struct evhttp_request
*req
, struct evbuffer
*databuf
)
1962 evbuffer_add_printf(req
->evcon
->output_buffer
, "%x\r\n",
1963 (unsigned)EVBUFFER_LENGTH(databuf
));
1965 evbuffer_add_buffer(req
->evcon
->output_buffer
, databuf
);
1967 evbuffer_add(req
->evcon
->output_buffer
, "\r\n", 2);
1969 evhttp_write_buffer(req
->evcon
, NULL
, NULL
);
1973 evhttp_send_reply_end(struct evhttp_request
*req
)
1975 struct evhttp_connection
*evcon
= req
->evcon
;
1978 evbuffer_add(req
->evcon
->output_buffer
, "0\r\n\r\n", 5);
1979 evhttp_write_buffer(req
->evcon
, evhttp_send_done
, NULL
);
1981 } else if (!event_pending(&evcon
->ev
, EV_WRITE
|EV_TIMEOUT
, NULL
)) {
1982 /* let the connection know that we are done with the request */
1983 evhttp_send_done(evcon
, NULL
);
1985 /* make the callback execute after all data has been written */
1986 evcon
->cb
= evhttp_send_done
;
1987 evcon
->cb_arg
= NULL
;
1992 evhttp_response_code(struct evhttp_request
*req
, int code
, const char *reason
)
1994 req
->kind
= EVHTTP_RESPONSE
;
1995 req
->response_code
= code
;
1996 if (req
->response_code_line
!= NULL
)
1997 free(req
->response_code_line
);
1998 req
->response_code_line
= strdup(reason
);
2002 evhttp_send_page(struct evhttp_request
*req
, struct evbuffer
*databuf
)
2004 if (!req
->major
|| !req
->minor
) {
2009 if (req
->kind
!= EVHTTP_RESPONSE
)
2010 evhttp_response_code(req
, 200, "OK");
2012 evhttp_clear_headers(req
->output_headers
);
2013 evhttp_add_header(req
->output_headers
, "Content-Type", "text/html");
2014 evhttp_add_header(req
->output_headers
, "Connection", "close");
2016 evhttp_send(req
, databuf
);
2019 static const char uri_chars
[256] = {
2020 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2021 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2022 0, 1, 0, 0, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1,
2023 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 0, 0,
2025 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
2026 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1,
2027 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
2028 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 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 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 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2042 * Helper functions to encode/decode a URI.
2043 * The returned string must be freed by the caller.
2046 evhttp_encode_uri(const char *uri
)
2048 struct evbuffer
*buf
= evbuffer_new();
2051 for (p
= (char *)uri
; *p
!= '\0'; p
++) {
2052 if (uri_chars
[(u_char
)(*p
)]) {
2053 evbuffer_add(buf
, p
, 1);
2055 evbuffer_add_printf(buf
, "%%%02X", (u_char
)(*p
));
2058 evbuffer_add(buf
, "", 1);
2059 p
= strdup((char *)EVBUFFER_DATA(buf
));
2066 * @param always_decode_plus: when true we transform plus to space even
2067 * if we have not seen a ?.
2070 evhttp_decode_uri_internal(
2071 const char *uri
, size_t length
, char *ret
, int always_decode_plus
)
2074 int i
, j
, in_query
= always_decode_plus
;
2076 for (i
= j
= 0; uri
[i
] != '\0'; i
++) {
2080 } else if (c
== '+' && in_query
) {
2082 } else if (c
== '%' && isxdigit((unsigned char)uri
[i
+1]) &&
2083 isxdigit((unsigned char)uri
[i
+2])) {
2084 char tmp
[] = { uri
[i
+1], uri
[i
+2], '\0' };
2085 c
= (char)strtol(tmp
, NULL
, 16);
2096 evhttp_decode_uri(const char *uri
)
2100 if ((ret
= malloc(strlen(uri
) + 1)) == NULL
)
2101 event_err(1, "%s: malloc(%lu)", __func__
,
2102 (unsigned long)(strlen(uri
) + 1));
2104 evhttp_decode_uri_internal(uri
, strlen(uri
),
2105 ret
, 0 /*always_decode_plus*/);
2111 * Helper function to parse out arguments in a query.
2112 * The arguments are separated by key and value.
2116 evhttp_parse_query(const char *uri
, struct evkeyvalq
*headers
)
2122 TAILQ_INIT(headers
);
2124 /* No arguments - we are done */
2125 if (strchr(uri
, '?') == NULL
)
2128 if ((line
= strdup(uri
)) == NULL
)
2129 event_err(1, "%s: strdup", __func__
);
2134 /* We already know that there has to be a ? */
2135 strsep(&argument
, "?");
2138 while (p
!= NULL
&& *p
!= '\0') {
2139 char *key
, *value
, *decoded_value
;
2140 argument
= strsep(&p
, "&");
2143 key
= strsep(&value
, "=");
2147 if ((decoded_value
= malloc(strlen(value
) + 1)) == NULL
)
2148 event_err(1, "%s: malloc", __func__
);
2150 evhttp_decode_uri_internal(value
, strlen(value
),
2151 decoded_value
, 1 /*always_decode_plus*/);
2152 event_debug(("Query Param: %s -> %s\n", key
, decoded_value
));
2153 evhttp_add_header_internal(headers
, key
, decoded_value
);
2154 free(decoded_value
);
2161 static struct evhttp_cb
*
2162 evhttp_dispatch_callback(struct httpcbq
*callbacks
, struct evhttp_request
*req
)
2164 struct evhttp_cb
*cb
;
2167 /* Test for different URLs */
2168 char *p
= strchr(req
->uri
, '?');
2170 offset
= (size_t)(p
- req
->uri
);
2172 TAILQ_FOREACH(cb
, callbacks
, next
) {
2175 res
= strcmp(cb
->what
, req
->uri
) == 0;
2177 res
= ((strncmp(cb
->what
, req
->uri
, offset
) == 0) &&
2178 (cb
->what
[offset
] == '\0'));
2189 evhttp_handle_request(struct evhttp_request
*req
, void *arg
)
2191 struct evhttp
*http
= arg
;
2192 struct evhttp_cb
*cb
= NULL
;
2194 if (req
->uri
== NULL
) {
2195 evhttp_send_error(req
, HTTP_BADREQUEST
, "Bad Request");
2199 if ((cb
= evhttp_dispatch_callback(&http
->callbacks
, req
)) != NULL
) {
2200 (*cb
->cb
)(req
, cb
->cbarg
);
2204 /* Generic call back */
2206 (*http
->gencb
)(req
, http
->gencbarg
);
2209 /* We need to send a 404 here */
2210 #define ERR_FORMAT "<html><head>" \
2211 "<title>404 Not Found</title>" \
2213 "<h1>Not Found</h1>" \
2214 "<p>The requested URL %s was not found on this server.</p>"\
2217 char *escaped_html
= evhttp_htmlescape(req
->uri
);
2218 struct evbuffer
*buf
= evbuffer_new();
2220 evhttp_response_code(req
, HTTP_NOTFOUND
, "Not Found");
2222 evbuffer_add_printf(buf
, ERR_FORMAT
, escaped_html
);
2226 evhttp_send_page(req
, buf
);
2234 accept_socket(int fd
, short what
, void *arg
)
2236 struct evhttp
*http
= arg
;
2237 struct sockaddr_storage ss
;
2238 socklen_t addrlen
= sizeof(ss
);
2241 if ((nfd
= accept(fd
, (struct sockaddr
*)&ss
, &addrlen
)) == -1) {
2242 if (errno
!= EAGAIN
&& errno
!= EINTR
)
2243 event_warn("%s: bad accept", __func__
);
2246 if (evutil_make_socket_nonblocking(nfd
) < 0)
2249 evhttp_get_request(http
, nfd
, (struct sockaddr
*)&ss
, addrlen
);
2253 evhttp_bind_socket(struct evhttp
*http
, const char *address
, u_short port
)
2258 if ((fd
= bind_socket(address
, port
, 1 /*reuse*/)) == -1)
2261 if (listen(fd
, 128) == -1) {
2262 event_warn("%s: listen", __func__
);
2263 EVUTIL_CLOSESOCKET(fd
);
2267 res
= evhttp_accept_socket(http
, fd
);
2270 event_debug(("Bound to port %d - Awaiting connections ... ",
2277 evhttp_accept_socket(struct evhttp
*http
, int fd
)
2279 struct evhttp_bound_socket
*bound
;
2283 bound
= malloc(sizeof(struct evhttp_bound_socket
));
2287 ev
= &bound
->bind_ev
;
2289 /* Schedule the socket for accepting */
2290 event_set(ev
, fd
, EV_READ
| EV_PERSIST
, accept_socket
, http
);
2291 EVHTTP_BASE_SET(http
, ev
);
2293 res
= event_add(ev
, NULL
);
2300 TAILQ_INSERT_TAIL(&http
->sockets
, bound
, next
);
2305 static struct evhttp
*
2306 evhttp_new_object(void)
2308 struct evhttp
*http
= NULL
;
2310 if ((http
= calloc(1, sizeof(struct evhttp
))) == NULL
) {
2311 event_warn("%s: calloc", __func__
);
2317 TAILQ_INIT(&http
->sockets
);
2318 TAILQ_INIT(&http
->callbacks
);
2319 TAILQ_INIT(&http
->connections
);
2325 evhttp_new(struct event_base
*base
)
2327 struct evhttp
*http
= evhttp_new_object();
2335 * Start a web server on the specified address and port.
2339 evhttp_start(const char *address
, u_short port
)
2341 struct evhttp
*http
= evhttp_new_object();
2343 if (evhttp_bind_socket(http
, address
, port
) == -1) {
2352 evhttp_free(struct evhttp
* http
)
2354 struct evhttp_cb
*http_cb
;
2355 struct evhttp_connection
*evcon
;
2356 struct evhttp_bound_socket
*bound
;
2359 /* Remove the accepting part */
2360 while ((bound
= TAILQ_FIRST(&http
->sockets
)) != NULL
) {
2361 TAILQ_REMOVE(&http
->sockets
, bound
, next
);
2363 fd
= bound
->bind_ev
.ev_fd
;
2364 event_del(&bound
->bind_ev
);
2365 EVUTIL_CLOSESOCKET(fd
);
2370 while ((evcon
= TAILQ_FIRST(&http
->connections
)) != NULL
) {
2371 /* evhttp_connection_free removes the connection */
2372 evhttp_connection_free(evcon
);
2375 while ((http_cb
= TAILQ_FIRST(&http
->callbacks
)) != NULL
) {
2376 TAILQ_REMOVE(&http
->callbacks
, http_cb
, next
);
2377 free(http_cb
->what
);
2385 evhttp_set_timeout(struct evhttp
* http
, int timeout_in_secs
)
2387 http
->timeout
= timeout_in_secs
;
2391 evhttp_set_cb(struct evhttp
*http
, const char *uri
,
2392 void (*cb
)(struct evhttp_request
*, void *), void *cbarg
)
2394 struct evhttp_cb
*http_cb
;
2396 if ((http_cb
= calloc(1, sizeof(struct evhttp_cb
))) == NULL
)
2397 event_err(1, "%s: calloc", __func__
);
2399 http_cb
->what
= strdup(uri
);
2401 http_cb
->cbarg
= cbarg
;
2403 TAILQ_INSERT_TAIL(&http
->callbacks
, http_cb
, next
);
2407 evhttp_del_cb(struct evhttp
*http
, const char *uri
)
2409 struct evhttp_cb
*http_cb
;
2411 TAILQ_FOREACH(http_cb
, &http
->callbacks
, next
) {
2412 if (strcmp(http_cb
->what
, uri
) == 0)
2415 if (http_cb
== NULL
)
2418 TAILQ_REMOVE(&http
->callbacks
, http_cb
, next
);
2419 free(http_cb
->what
);
2426 evhttp_set_gencb(struct evhttp
*http
,
2427 void (*cb
)(struct evhttp_request
*, void *), void *cbarg
)
2430 http
->gencbarg
= cbarg
;
2434 * Request related functions
2437 struct evhttp_request
*
2438 evhttp_request_new(void (*cb
)(struct evhttp_request
*, void *), void *arg
)
2440 struct evhttp_request
*req
= NULL
;
2442 /* Allocate request structure */
2443 if ((req
= calloc(1, sizeof(struct evhttp_request
))) == NULL
) {
2444 event_warn("%s: calloc", __func__
);
2448 req
->kind
= EVHTTP_RESPONSE
;
2449 req
->input_headers
= calloc(1, sizeof(struct evkeyvalq
));
2450 if (req
->input_headers
== NULL
) {
2451 event_warn("%s: calloc", __func__
);
2454 TAILQ_INIT(req
->input_headers
);
2456 req
->output_headers
= calloc(1, sizeof(struct evkeyvalq
));
2457 if (req
->output_headers
== NULL
) {
2458 event_warn("%s: calloc", __func__
);
2461 TAILQ_INIT(req
->output_headers
);
2463 if ((req
->input_buffer
= evbuffer_new()) == NULL
) {
2464 event_warn("%s: evbuffer_new", __func__
);
2468 if ((req
->output_buffer
= evbuffer_new()) == NULL
) {
2469 event_warn("%s: evbuffer_new", __func__
);
2480 evhttp_request_free(req
);
2485 evhttp_request_free(struct evhttp_request
*req
)
2487 if (req
->remote_host
!= NULL
)
2488 free(req
->remote_host
);
2489 if (req
->uri
!= NULL
)
2491 if (req
->response_code_line
!= NULL
)
2492 free(req
->response_code_line
);
2494 evhttp_clear_headers(req
->input_headers
);
2495 free(req
->input_headers
);
2497 evhttp_clear_headers(req
->output_headers
);
2498 free(req
->output_headers
);
2500 if (req
->input_buffer
!= NULL
)
2501 evbuffer_free(req
->input_buffer
);
2503 if (req
->output_buffer
!= NULL
)
2504 evbuffer_free(req
->output_buffer
);
2510 evhttp_request_set_chunked_cb(struct evhttp_request
*req
,
2511 void (*cb
)(struct evhttp_request
*, void *))
2517 * Allows for inspection of the request URI
2521 evhttp_request_uri(struct evhttp_request
*req
) {
2522 if (req
->uri
== NULL
)
2523 event_debug(("%s: request %p has no uri\n", __func__
, req
));
2528 * Takes a file descriptor to read a request from.
2529 * The callback is executed once the whole request has been read.
2532 static struct evhttp_connection
*
2533 evhttp_get_request_connection(
2534 struct evhttp
* http
,
2535 int fd
, struct sockaddr
*sa
, socklen_t salen
)
2537 struct evhttp_connection
*evcon
;
2538 char *hostname
= NULL
, *portname
= NULL
;
2540 name_from_addr(sa
, salen
, &hostname
, &portname
);
2541 if (hostname
== NULL
|| portname
== NULL
) {
2542 if (hostname
) free(hostname
);
2543 if (portname
) free(portname
);
2547 event_debug(("%s: new request from %s:%s on %d\n",
2548 __func__
, hostname
, portname
, fd
));
2550 /* we need a connection object to put the http request on */
2551 evcon
= evhttp_connection_new(hostname
, atoi(portname
));
2557 /* associate the base if we have one*/
2558 evhttp_connection_set_base(evcon
, http
->base
);
2560 evcon
->flags
|= EVHTTP_CON_INCOMING
;
2561 evcon
->state
= EVCON_READING_FIRSTLINE
;
2569 evhttp_associate_new_request_with_connection(struct evhttp_connection
*evcon
)
2571 struct evhttp
*http
= evcon
->http_server
;
2572 struct evhttp_request
*req
;
2573 if ((req
= evhttp_request_new(evhttp_handle_request
, http
)) == NULL
)
2576 req
->evcon
= evcon
; /* the request ends up owning the connection */
2577 req
->flags
|= EVHTTP_REQ_OWN_CONNECTION
;
2579 TAILQ_INSERT_TAIL(&evcon
->requests
, req
, next
);
2581 req
->kind
= EVHTTP_REQUEST
;
2583 if ((req
->remote_host
= strdup(evcon
->address
)) == NULL
)
2584 event_err(1, "%s: strdup", __func__
);
2585 req
->remote_port
= evcon
->port
;
2587 evhttp_start_read(evcon
);
2593 evhttp_get_request(struct evhttp
*http
, int fd
,
2594 struct sockaddr
*sa
, socklen_t salen
)
2596 struct evhttp_connection
*evcon
;
2598 evcon
= evhttp_get_request_connection(http
, fd
, sa
, salen
);
2602 /* the timeout can be used by the server to close idle connections */
2603 if (http
->timeout
!= -1)
2604 evhttp_connection_set_timeout(evcon
, http
->timeout
);
2607 * if we want to accept more than one request on a connection,
2608 * we need to know which http server it belongs to.
2610 evcon
->http_server
= http
;
2611 TAILQ_INSERT_TAIL(&http
->connections
, evcon
, next
);
2613 if (evhttp_associate_new_request_with_connection(evcon
) == -1)
2614 evhttp_connection_free(evcon
);
2619 * Network helper functions that we do not want to export to the rest of
2623 static struct addrinfo
*
2624 addr_from_name(char *address
)
2626 #ifdef HAVE_GETADDRINFO
2627 struct addrinfo ai
, *aitop
;
2630 memset(&ai
, 0, sizeof(ai
));
2631 ai
.ai_family
= AF_INET
;
2632 ai
.ai_socktype
= SOCK_RAW
;
2634 if ((ai_result
= getaddrinfo(address
, NULL
, &ai
, &aitop
)) != 0) {
2635 if ( ai_result
== EAI_SYSTEM
)
2636 event_warn("getaddrinfo");
2638 event_warnx("getaddrinfo: %s", gai_strerror(ai_result
));
2644 return NULL
; /* XXXXX Use gethostbyname, if this function is ever used. */
2650 name_from_addr(struct sockaddr
*sa
, socklen_t salen
,
2651 char **phost
, char **pport
)
2653 char ntop
[NI_MAXHOST
];
2654 char strport
[NI_MAXSERV
];
2657 #ifdef HAVE_GETNAMEINFO
2658 ni_result
= getnameinfo(sa
, salen
,
2659 ntop
, sizeof(ntop
), strport
, sizeof(strport
),
2660 NI_NUMERICHOST
|NI_NUMERICSERV
);
2662 if (ni_result
!= 0) {
2663 if (ni_result
== EAI_SYSTEM
)
2664 event_err(1, "getnameinfo failed");
2666 event_errx(1, "getnameinfo failed: %s", gai_strerror(ni_result
));
2670 ni_result
= fake_getnameinfo(sa
, salen
,
2671 ntop
, sizeof(ntop
), strport
, sizeof(strport
),
2672 NI_NUMERICHOST
|NI_NUMERICSERV
);
2676 *phost
= strdup(ntop
);
2677 *pport
= strdup(strport
);
2680 /* Create a non-blocking socket and bind it */
2681 /* todo: rename this function */
2683 bind_socket_ai(struct addrinfo
*ai
, int reuse
)
2688 /* Create listen socket */
2689 fd
= socket(AF_INET
, SOCK_STREAM
, 0);
2691 event_warn("socket");
2695 if (evutil_make_socket_nonblocking(fd
) < 0)
2699 if (fcntl(fd
, F_SETFD
, 1) == -1) {
2700 event_warn("fcntl(F_SETFD)");
2705 setsockopt(fd
, SOL_SOCKET
, SO_KEEPALIVE
, (void *)&on
, sizeof(on
));
2707 setsockopt(fd
, SOL_SOCKET
, SO_REUSEADDR
,
2708 (void *)&on
, sizeof(on
));
2712 r
= bind(fd
, ai
->ai_addr
, ai
->ai_addrlen
);
2720 serrno
= EVUTIL_SOCKET_ERROR();
2721 EVUTIL_CLOSESOCKET(fd
);
2722 EVUTIL_SET_SOCKET_ERROR(serrno
);
2726 static struct addrinfo
*
2727 make_addrinfo(const char *address
, u_short port
)
2729 struct addrinfo
*aitop
= NULL
;
2731 #ifdef HAVE_GETADDRINFO
2733 char strport
[NI_MAXSERV
];
2736 memset(&ai
, 0, sizeof(ai
));
2737 ai
.ai_family
= AF_INET
;
2738 ai
.ai_socktype
= SOCK_STREAM
;
2739 ai
.ai_flags
= AI_PASSIVE
; /* turn NULL host name into INADDR_ANY */
2740 evutil_snprintf(strport
, sizeof(strport
), "%d", port
);
2741 if ((ai_result
= getaddrinfo(address
, strport
, &ai
, &aitop
)) != 0) {
2742 if ( ai_result
== EAI_SYSTEM
)
2743 event_warn("getaddrinfo");
2745 event_warnx("getaddrinfo: %s", gai_strerror(ai_result
));
2750 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. */
2751 if (++cur
== 2) cur
= 0; /* allow calling this function twice */
2753 if (fake_getaddrinfo(address
, &ai
[cur
]) < 0) {
2754 event_warn("fake_getaddrinfo");
2758 ((struct sockaddr_in
*) aitop
->ai_addr
)->sin_port
= htons(port
);
2765 bind_socket(const char *address
, u_short port
, int reuse
)
2768 struct addrinfo
*aitop
= NULL
;
2770 /* just create an unbound socket */
2771 if (address
== NULL
&& port
== 0)
2772 return bind_socket_ai(NULL
, 0);
2774 aitop
= make_addrinfo(address
, port
);
2779 fd
= bind_socket_ai(aitop
, reuse
);
2781 #ifdef HAVE_GETADDRINFO
2782 freeaddrinfo(aitop
);
2784 fake_freeaddrinfo(aitop
);
2791 socket_connect(int fd
, const char *address
, unsigned short port
)
2793 struct addrinfo
*ai
= make_addrinfo(address
, port
);
2797 event_debug(("%s: make_addrinfo: \"%s:%d\"",
2798 __func__
, address
, port
));
2802 if (connect(fd
, ai
->ai_addr
, ai
->ai_addrlen
) == -1) {
2804 int tmp_error
= WSAGetLastError();
2805 if (tmp_error
!= WSAEWOULDBLOCK
&& tmp_error
!= WSAEINVAL
&&
2806 tmp_error
!= WSAEINPROGRESS
) {
2810 if (errno
!= EINPROGRESS
) {
2816 /* everything is fine */
2820 #ifdef HAVE_GETADDRINFO
2823 fake_freeaddrinfo(ai
);