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>
55 #ifndef HAVE_TAILQFOREACH
56 #include <event-internal.h>
60 #include <netinet/in.h>
86 #undef timeout_pending
87 #undef timeout_initialized
89 #include "strlcpy-internal.h"
94 #include "http-internal.h"
97 #define strcasecmp _stricmp
98 #define strncasecmp _strnicmp
99 #define strdup _strdup
102 #ifndef HAVE_GETNAMEINFO
103 #define NI_MAXSERV 32
104 #define NI_MAXHOST 1025
106 #define NI_NUMERICHOST 1
107 #define NI_NUMERICSERV 2
110 fake_getnameinfo(
const struct sockaddr *sa,
size_t salen,
char *host,
111 size_t hostlen,
char *serv,
size_t servlen,
int flags)
113 struct sockaddr_in *sin = (
struct sockaddr_in *)sa;
117 evutil_snprintf(tmpserv,
sizeof(tmpserv),
118 "%d", ntohs(sin->sin_port));
119 if (strlcpy(serv, tmpserv, servlen) >= servlen)
124 if (flags & NI_NUMERICHOST) {
125 if (strlcpy(host, inet_ntoa(sin->sin_addr),
132 hp = gethostbyaddr((
char *)&sin->sin_addr,
133 sizeof(
struct in_addr), AF_INET);
137 if (strlcpy(host, hp->h_name, hostlen) >= hostlen)
148 #ifndef HAVE_GETADDRINFO
154 struct sockaddr *ai_addr;
158 fake_getaddrinfo(
const char *hostname,
struct addrinfo *ai)
160 struct hostent *he = NULL;
161 struct sockaddr_in *sa;
163 he = gethostbyname(hostname);
167 ai->ai_family = he ? he->h_addrtype : AF_INET;
168 ai->ai_socktype = SOCK_STREAM;
170 ai->ai_addrlen =
sizeof(
struct sockaddr_in);
171 if (NULL == (ai->ai_addr = malloc(ai->ai_addrlen)))
173 sa = (
struct sockaddr_in*)ai->ai_addr;
174 memset(sa, 0, ai->ai_addrlen);
176 sa->sin_family = he->h_addrtype;
177 memcpy(&sa->sin_addr, he->h_addr_list[0], he->h_length);
179 sa->sin_family = AF_INET;
180 sa->sin_addr.s_addr = INADDR_ANY;
186 fake_freeaddrinfo(
struct addrinfo *ai)
193 #define MIN(a,b) (((a)<(b))?(a):(b))
197 #define EVHTTP_BASE_SET(x, y) do { \
198 if ((x)->base != NULL) event_base_set((x)->base, y); \
203 static int socket_connect(
int fd,
const char *address,
unsigned short port);
204 static int bind_socket_ai(
struct addrinfo *,
int reuse);
205 static int bind_socket(
const char *, u_short,
int reuse);
206 static void name_from_addr(
struct sockaddr *, socklen_t,
char **,
char **);
207 static int evhttp_associate_new_request_with_connection(
209 static void evhttp_connection_start_detectclose(
211 static void evhttp_connection_stop_detectclose(
218 static int evhttp_add_header_internal(
struct evkeyvalq *headers,
219 const char *key,
const char *value);
220 static int evhttp_decode_uri_internal(
const char *uri,
size_t length,
221 char *
ret,
int always_decode_plus);
223 void evhttp_read(
int,
short,
void *);
224 void evhttp_write(
int,
short,
void *);
230 strsep(
char **s,
const char *del)
233 assert(strlen(del) == 1);
237 d = strstr(tok, del);
248 html_replace(
char ch,
char *
buf)
282 int i, new_size = 0, old_size = strlen(html);
283 char *escaped_html, *p;
284 char scratch_space[2];
286 for (i = 0; i < old_size; ++
i)
287 new_size += strlen(html_replace(html[i], scratch_space));
289 p = escaped_html = malloc(new_size + 1);
290 if (escaped_html == NULL)
291 event_err(1,
"%s: malloc(%d)", __func__, new_size + 1);
292 for (i = 0; i < old_size; ++
i) {
293 const char *replaced = html_replace(html[i], scratch_space);
296 p += strlen(replaced);
301 return (escaped_html);
305 evhttp_method(
enum evhttp_cmd_type
type)
313 case EVHTTP_REQ_POST:
316 case EVHTTP_REQ_HEAD:
328 evhttp_add_event(
struct event *ev,
int timeout,
int default_timeout)
333 evutil_timerclear(&tv);
334 tv.tv_sec = timeout != -1 ? timeout : default_timeout;
345 event_debug((
"%s: preparing to write buffer\n", __func__));
352 if (event_pending(&evcon->ev, EV_WRITE|EV_TIMEOUT, NULL))
353 event_del(&evcon->ev);
355 event_set(&evcon->ev, evcon->fd, EV_WRITE, evhttp_write, evcon);
356 EVHTTP_BASE_SET(evcon, &evcon->ev);
357 evhttp_add_event(&evcon->ev, evcon->timeout, HTTP_WRITE_TIMEOUT);
363 switch (evcon->state) {
364 case EVCON_DISCONNECTED:
365 case EVCON_CONNECTING:
368 case EVCON_READING_FIRSTLINE:
369 case EVCON_READING_HEADERS:
370 case EVCON_READING_BODY:
371 case EVCON_READING_TRAILER:
387 evhttp_remove_header(req->output_headers,
"Proxy-Connection");
390 method = evhttp_method(req->type);
391 evbuffer_add_printf(evcon->output_buffer,
"%s %s HTTP/%d.%d\r\n",
392 method, req->uri, req->major, req->minor);
395 if (req->type == EVHTTP_REQ_POST &&
396 evhttp_find_header(req->output_headers,
"Content-Length") == NULL){
398 evutil_snprintf(size,
sizeof(size),
"%ld",
399 (
long)EVBUFFER_LENGTH(req->output_buffer));
400 evhttp_add_header(req->output_headers,
"Content-Length", size);
405 evhttp_is_connection_close(
int flags,
struct evkeyvalq* headers)
407 if (flags & EVHTTP_PROXY_REQUEST) {
409 const char *connection = evhttp_find_header(headers,
"Proxy-Connection");
410 return (connection == NULL || strcasecmp(connection,
"keep-alive") != 0);
412 const char *connection = evhttp_find_header(headers,
"Connection");
413 return (connection != NULL && strcasecmp(connection,
"close") == 0);
418 evhttp_is_connection_keepalive(
struct evkeyvalq* headers)
420 const char *connection = evhttp_find_header(headers,
"Connection");
421 return (connection != NULL
422 && strncasecmp(connection,
"keep-alive", 10) == 0);
426 evhttp_maybe_add_date_header(
struct evkeyvalq *headers)
428 if (evhttp_find_header(headers,
"Date") == NULL) {
434 time_t t = time(NULL);
441 if (strftime(date,
sizeof(date),
442 "%a, %d %b %Y %H:%M:%S GMT", cur_p) != 0) {
443 evhttp_add_header(headers,
"Date", date);
449 evhttp_maybe_add_content_length_header(
struct evkeyvalq *headers,
452 if (evhttp_find_header(headers,
"Transfer-Encoding") == NULL &&
453 evhttp_find_header(headers,
"Content-Length") == NULL) {
455 evutil_snprintf(len,
sizeof(len),
"%ld", content_length);
456 evhttp_add_header(headers,
"Content-Length", len);
468 int is_keepalive = evhttp_is_connection_keepalive(req->input_headers);
469 evbuffer_add_printf(evcon->output_buffer,
"HTTP/%d.%d %d %s\r\n",
470 req->major, req->minor, req->response_code,
471 req->response_code_line);
473 if (req->major == 1) {
475 evhttp_maybe_add_date_header(req->output_headers);
481 if (req->minor == 0 && is_keepalive)
482 evhttp_add_header(req->output_headers,
483 "Connection",
"keep-alive");
485 if (req->minor == 1 || is_keepalive) {
491 evhttp_maybe_add_content_length_header(
493 (
long)EVBUFFER_LENGTH(req->output_buffer));
498 if (EVBUFFER_LENGTH(req->output_buffer)) {
499 if (evhttp_find_header(req->output_headers,
500 "Content-Type") == NULL) {
501 evhttp_add_header(req->output_headers,
502 "Content-Type",
"text/html; charset=ISO-8859-1");
507 if (evhttp_is_connection_close(req->flags, req->input_headers)) {
508 evhttp_remove_header(req->output_headers,
"Connection");
509 if (!(req->flags & EVHTTP_PROXY_REQUEST))
510 evhttp_add_header(req->output_headers,
"Connection",
"close");
511 evhttp_remove_header(req->output_headers,
"Proxy-Connection");
524 if (req->kind == EVHTTP_REQUEST) {
525 evhttp_make_header_request(evcon, req);
527 evhttp_make_header_response(evcon, req);
530 TAILQ_FOREACH(header, req->output_headers, next) {
531 evbuffer_add_printf(evcon->output_buffer,
"%s: %s\r\n",
532 header->key, header->value);
534 evbuffer_add(evcon->output_buffer,
"\r\n", 2);
536 if (EVBUFFER_LENGTH(req->output_buffer) > 0) {
541 evbuffer_add_buffer(evcon->output_buffer, req->output_buffer);
548 evhttp_hostportfile(
char *url,
char **phost, u_short *pport,
char **pfile)
551 static char host[1024];
552 static char file[1024];
558 len = strlen(HTTP_PREFIX);
559 if (strncasecmp(url, HTTP_PREFIX, len))
565 if (strlcpy(host, url,
sizeof (host)) >=
sizeof(host))
568 p = strchr(host,
'/');
579 evutil_snprintf(file,
sizeof(file),
"/%s", p2);
582 p = strchr(host,
':');
590 port = HTTP_DEFAULTPORT;
604 enum evhttp_connection_error error)
607 case EVCON_HTTP_TIMEOUT:
616 case EVCON_HTTP_INVALID_HEADER:
628 (*req->cb)(req, req->cb_arg);
636 enum evhttp_connection_error error)
643 if (evcon->flags & EVHTTP_CON_INCOMING) {
652 if (evhttp_connection_incoming_fail(req, error) == -1)
659 cb_arg = req->cb_arg;
661 TAILQ_REMOVE(&evcon->requests, req, next);
667 evhttp_connection_reset(evcon);
670 if (TAILQ_FIRST(&evcon->requests) != NULL)
671 evhttp_connection_connect(evcon);
679 evhttp_write(
int fd,
short what,
void *arg)
684 if (what == EV_TIMEOUT) {
685 evhttp_connection_fail(evcon, EVCON_HTTP_TIMEOUT);
689 n = evbuffer_write(evcon->output_buffer, fd);
691 event_debug((
"%s: evbuffer_write", __func__));
692 evhttp_connection_fail(evcon, EVCON_HTTP_EOF);
697 event_debug((
"%s: write nothing", __func__));
698 evhttp_connection_fail(evcon, EVCON_HTTP_EOF);
702 if (EVBUFFER_LENGTH(evcon->output_buffer) != 0) {
703 evhttp_add_event(&evcon->ev,
704 evcon->timeout, HTTP_WRITE_TIMEOUT);
709 if (evcon->cb != NULL)
710 (*evcon->cb)(evcon, evcon->cb_arg);
724 int con_outgoing = evcon->flags & EVHTTP_CON_OUTGOING;
729 TAILQ_REMOVE(&evcon->requests, req, next);
732 evcon->state = EVCON_IDLE;
735 evhttp_is_connection_close(req->flags, req->input_headers)||
736 evhttp_is_connection_close(req->flags, req->output_headers);
740 evhttp_connection_reset(evcon);
742 if (TAILQ_FIRST(&evcon->requests) != NULL) {
747 if (!evhttp_connected(evcon))
748 evhttp_connection_connect(evcon);
750 evhttp_request_dispatch(evcon);
751 }
else if (!need_close) {
756 evhttp_connection_start_detectclose(evcon);
763 evcon->state = EVCON_WRITING;
767 (*req->cb)(req, req->cb_arg);
787 static enum message_read_status
792 while ((len = EVBUFFER_LENGTH(buf)) > 0) {
793 if (req->ntoread < 0) {
796 char *p = evbuffer_readline(buf);
802 if (strlen(p) == 0) {
806 ntoread = evutil_strtoll(p, &endp, 16);
807 error = (*p ==
'\0' ||
808 (*endp !=
'\0' && *endp !=
' ') ||
813 return (DATA_CORRUPTED);
815 req->ntoread = ntoread;
816 if (req->ntoread == 0) {
818 return (ALL_DATA_READ);
824 if (len < req->ntoread)
825 return (MORE_DATA_EXPECTED);
828 evbuffer_add(req->input_buffer,
829 EVBUFFER_DATA(buf), (
size_t)req->ntoread);
830 evbuffer_drain(buf, (
size_t)req->ntoread);
832 if (req->chunk_cb != NULL) {
833 (*req->chunk_cb)(req, req->cb_arg);
834 evbuffer_drain(req->input_buffer,
835 EVBUFFER_LENGTH(req->input_buffer));
839 return (MORE_DATA_EXPECTED);
845 struct evbuffer *buf = evcon->input_buffer;
847 switch (evhttp_parse_headers(req, buf)) {
849 evhttp_connection_fail(evcon, EVCON_HTTP_INVALID_HEADER);
852 event_del(&evcon->ev);
853 evhttp_connection_done(evcon);
855 case MORE_DATA_EXPECTED:
857 evhttp_add_event(&evcon->ev, evcon->timeout,
866 struct evbuffer *buf = evcon->input_buffer;
869 switch (evhttp_handle_chunked_read(req, buf)) {
872 evcon->state = EVCON_READING_TRAILER;
873 evhttp_read_trailer(evcon, req);
877 evhttp_connection_fail(evcon,
878 EVCON_HTTP_INVALID_HEADER);
880 case REQUEST_CANCELED:
884 case MORE_DATA_EXPECTED:
888 }
else if (req->ntoread < 0) {
890 evbuffer_add_buffer(req->input_buffer, buf);
891 }
else if (EVBUFFER_LENGTH(buf) >= req->ntoread) {
893 evbuffer_add(req->input_buffer, EVBUFFER_DATA(buf),
894 (
size_t)req->ntoread);
895 evbuffer_drain(buf, (
size_t)req->ntoread);
897 evhttp_connection_done(evcon);
901 event_set(&evcon->ev, evcon->fd, EV_READ, evhttp_read, evcon);
902 EVHTTP_BASE_SET(evcon, &evcon->ev);
903 evhttp_add_event(&evcon->ev, evcon->timeout, HTTP_READ_TIMEOUT);
914 evhttp_read(
int fd,
short what,
void *arg)
918 struct evbuffer *buf = evcon->input_buffer;
921 if (what == EV_TIMEOUT) {
922 evhttp_connection_fail(evcon, EVCON_HTTP_TIMEOUT);
925 n = evbuffer_read(buf, fd, -1);
926 len = EVBUFFER_LENGTH(buf);
927 event_debug((
"%s: got %d on %d\n", __func__, n, fd));
930 if (errno != EINTR && errno != EAGAIN) {
931 event_debug((
"%s: evbuffer_read", __func__));
932 evhttp_connection_fail(evcon, EVCON_HTTP_EOF);
934 evhttp_add_event(&evcon->ev, evcon->timeout,
940 evhttp_connection_done(evcon);
944 switch (evcon->state) {
945 case EVCON_READING_FIRSTLINE:
946 evhttp_read_firstline(evcon, req);
948 case EVCON_READING_HEADERS:
949 evhttp_read_header(evcon, req);
951 case EVCON_READING_BODY:
952 evhttp_read_body(evcon, req);
954 case EVCON_READING_TRAILER:
955 evhttp_read_trailer(evcon, req);
957 case EVCON_DISCONNECTED:
958 case EVCON_CONNECTING:
962 event_errx(1,
"%s: illegal connection state %d",
963 __func__, evcon->state);
974 assert(evcon->state == EVCON_WRITING);
977 req->kind = EVHTTP_RESPONSE;
979 evhttp_start_read(evcon);
992 if (evcon->fd != -1) {
993 if (evhttp_connected(evcon) && evcon->closecb != NULL)
994 (*evcon->closecb)(evcon, evcon->closecb_arg);
998 while ((req = TAILQ_FIRST(&evcon->requests)) != NULL) {
999 TAILQ_REMOVE(&evcon->requests, req, next);
1003 if (evcon->http_server != NULL) {
1004 struct evhttp *http = evcon->http_server;
1005 TAILQ_REMOVE(&http->connections, evcon, next);
1009 event_del(&evcon->close_ev);
1012 event_del(&evcon->ev);
1014 if (evcon->fd != -1)
1015 EVUTIL_CLOSESOCKET(evcon->fd);
1017 if (evcon->bind_address != NULL)
1018 free(evcon->bind_address);
1020 if (evcon->address != NULL)
1021 free(evcon->address);
1023 if (evcon->input_buffer != NULL)
1024 evbuffer_free(evcon->input_buffer);
1026 if (evcon->output_buffer != NULL)
1027 evbuffer_free(evcon->output_buffer);
1034 const char *address)
1036 assert(evcon->state == EVCON_DISCONNECTED);
1037 if (evcon->bind_address)
1038 free(evcon->bind_address);
1039 if ((evcon->bind_address = strdup(address)) == NULL)
1040 event_err(1,
"%s: strdup", __func__);
1045 unsigned short port)
1047 assert(evcon->state == EVCON_DISCONNECTED);
1048 evcon->bind_port = port;
1061 evhttp_connection_stop_detectclose(evcon);
1064 assert(evcon->state == EVCON_IDLE);
1066 evcon->state = EVCON_WRITING;
1069 evhttp_make_header(evcon, req);
1071 evhttp_write_buffer(evcon, evhttp_write_connectioncb, NULL);
1079 event_del(&evcon->ev);
1081 if (evcon->fd != -1) {
1083 if (evhttp_connected(evcon) && evcon->closecb != NULL)
1084 (*evcon->closecb)(evcon, evcon->closecb_arg);
1086 EVUTIL_CLOSESOCKET(evcon->fd);
1089 evcon->state = EVCON_DISCONNECTED;
1091 evbuffer_drain(evcon->input_buffer,
1092 EVBUFFER_LENGTH(evcon->input_buffer));
1093 evbuffer_drain(evcon->output_buffer,
1094 EVBUFFER_LENGTH(evcon->output_buffer));
1098 evhttp_detect_close_cb(
int fd,
short what,
void *arg)
1101 evhttp_connection_reset(evcon);
1107 evcon->flags |= EVHTTP_CON_CLOSEDETECT;
1110 event_del(&evcon->close_ev);
1111 event_set(&evcon->close_ev, evcon->fd, EV_READ,
1112 evhttp_detect_close_cb, evcon);
1113 EVHTTP_BASE_SET(evcon, &evcon->close_ev);
1114 event_add(&evcon->close_ev, NULL);
1120 evcon->flags &= ~EVHTTP_CON_CLOSEDETECT;
1121 event_del(&evcon->close_ev);
1125 evhttp_connection_retry(
int fd,
short what,
void *arg)
1129 evcon->state = EVCON_DISCONNECTED;
1130 evhttp_connection_connect(evcon);
1138 evhttp_connectioncb(
int fd,
short what,
void *arg)
1142 socklen_t errsz =
sizeof(error);
1144 if (what == EV_TIMEOUT) {
1145 event_debug((
"%s: connection timeout for \"%s:%d\" on %d",
1146 __func__, evcon->address, evcon->port, evcon->fd));
1151 if (getsockopt(evcon->fd, SOL_SOCKET, SO_ERROR, (
void*)&error,
1153 event_debug((
"%s: getsockopt for \"%s:%d\" on %d",
1154 __func__, evcon->address, evcon->port, evcon->fd));
1159 event_debug((
"%s: connect failed for \"%s:%d\" on %d: %s",
1160 __func__, evcon->address, evcon->port, evcon->fd,
1166 event_debug((
"%s: connected to \"%s:%d\" on %d\n",
1167 __func__, evcon->address, evcon->port, evcon->fd));
1170 evcon->retry_cnt = 0;
1171 evcon->state = EVCON_IDLE;
1174 evhttp_request_dispatch(evcon);
1178 if (evcon->retry_max < 0 || evcon->retry_cnt < evcon->retry_max) {
1179 evtimer_set(&evcon->ev, evhttp_connection_retry, evcon);
1180 EVHTTP_BASE_SET(evcon, &evcon->ev);
1181 evhttp_add_event(&evcon->ev, MIN(3600, 2 << evcon->retry_cnt),
1182 HTTP_CONNECT_TIMEOUT);
1186 evhttp_connection_reset(evcon);
1189 while (TAILQ_FIRST(&evcon->requests) != NULL) {
1191 TAILQ_REMOVE(&evcon->requests, request, next);
1192 request->evcon = NULL;
1195 request->cb(request, request->cb_arg);
1205 evhttp_valid_response_code(
int code)
1216 evhttp_parse_response_line(
struct evhttp_request *req,
char *line)
1222 protocol = strsep(&line,
" ");
1225 number = strsep(&line,
" ");
1230 if (strcmp(protocol,
"HTTP/1.0") == 0) {
1233 }
else if (strcmp(protocol,
"HTTP/1.1") == 0) {
1237 event_debug((
"%s: bad protocol \"%s\"",
1238 __func__, protocol));
1242 req->response_code = atoi(number);
1243 if (!evhttp_valid_response_code(req->response_code)) {
1244 event_debug((
"%s: bad response code \"%s\"",
1249 if ((req->response_code_line = strdup(readable)) == NULL)
1250 event_err(1,
"%s: strdup", __func__);
1258 evhttp_parse_request_line(
struct evhttp_request *req,
char *line)
1265 method = strsep(&line,
" ");
1268 uri = strsep(&line,
" ");
1271 version = strsep(&line,
" ");
1276 if (strcmp(method,
"GET") == 0) {
1277 req->type = EVHTTP_REQ_GET;
1278 }
else if (strcmp(method,
"POST") == 0) {
1279 req->type = EVHTTP_REQ_POST;
1280 }
else if (strcmp(method,
"HEAD") == 0) {
1281 req->type = EVHTTP_REQ_HEAD;
1283 event_debug((
"%s: bad method %s on request %p from %s",
1284 __func__, method, req, req->remote_host));
1288 if (strcmp(version,
"HTTP/1.0") == 0) {
1291 }
else if (strcmp(version,
"HTTP/1.1") == 0) {
1295 event_debug((
"%s: bad version %s on request %p from %s",
1296 __func__, version, req, req->remote_host));
1300 if ((req->uri = strdup(uri)) == NULL) {
1301 event_debug((
"%s: evhttp_decode_uri", __func__));
1306 if (strlen(req->uri) > 0 && req->uri[0] !=
'/')
1307 req->flags |= EVHTTP_PROXY_REQUEST;
1313 evhttp_find_header(
const struct evkeyvalq *headers,
const char *key)
1317 TAILQ_FOREACH(header, headers, next) {
1318 if (strcasecmp(header->key, key) == 0)
1319 return (header->value);
1326 evhttp_clear_headers(
struct evkeyvalq *headers)
1330 for (header = TAILQ_FIRST(headers);
1332 header = TAILQ_FIRST(headers)) {
1333 TAILQ_REMOVE(headers, header, next);
1335 free(header->value);
1346 evhttp_remove_header(
struct evkeyvalq *headers,
const char *key)
1350 TAILQ_FOREACH(header, headers, next) {
1351 if (strcasecmp(header->key, key) == 0)
1359 TAILQ_REMOVE(headers, header, next);
1361 free(header->value);
1368 evhttp_header_is_valid_value(
const char *value)
1370 const char *p = value;
1372 while ((p = strpbrk(p,
"\r\n")) != NULL) {
1374 p += strspn(p,
"\r\n");
1376 if (*p !=
' ' && *p !=
'\t')
1383 evhttp_add_header(
struct evkeyvalq *headers,
1384 const char *key,
const char *value)
1386 event_debug((
"%s: key: %s val: %s\n", __func__, key, value));
1388 if (strchr(key,
'\r') != NULL || strchr(key,
'\n') != NULL) {
1390 event_debug((
"%s: dropping illegal header key\n", __func__));
1394 if (!evhttp_header_is_valid_value(value)) {
1395 event_debug((
"%s: dropping illegal header value\n", __func__));
1399 return (evhttp_add_header_internal(headers, key, value));
1403 evhttp_add_header_internal(
struct evkeyvalq *headers,
1404 const char *key,
const char *value)
1407 if (header == NULL) {
1408 event_warn(
"%s: calloc", __func__);
1411 if ((header->key = strdup(key)) == NULL) {
1413 event_warn(
"%s: strdup", __func__);
1416 if ((header->value = strdup(value)) == NULL) {
1419 event_warn(
"%s: strdup", __func__);
1423 TAILQ_INSERT_TAIL(headers, header, next);
1438 enum message_read_status
1442 enum message_read_status status = ALL_DATA_READ;
1444 line = evbuffer_readline(buffer);
1446 return (MORE_DATA_EXPECTED);
1448 switch (req->kind) {
1449 case EVHTTP_REQUEST:
1450 if (evhttp_parse_request_line(req, line) == -1)
1451 status = DATA_CORRUPTED;
1453 case EVHTTP_RESPONSE:
1454 if (evhttp_parse_response_line(req, line) == -1)
1455 status = DATA_CORRUPTED;
1458 status = DATA_CORRUPTED;
1466 evhttp_append_to_last_header(
struct evkeyvalq *headers,
const char *line)
1468 struct evkeyval *header = TAILQ_LAST(headers, evkeyvalq);
1470 size_t old_len, line_len;
1475 old_len = strlen(header->value);
1476 line_len = strlen(line);
1478 newval = realloc(header->value, old_len + line_len + 1);
1482 memcpy(newval + old_len, line, line_len + 1);
1483 header->value = newval;
1488 enum message_read_status
1492 enum message_read_status status = MORE_DATA_EXPECTED;
1494 struct evkeyvalq* headers = req->input_headers;
1495 while ((line = evbuffer_readline(buffer))
1497 char *skey, *svalue;
1499 if (*line ==
'\0') {
1500 status = ALL_DATA_READ;
1506 if (*line ==
' ' || *line ==
'\t') {
1507 if (evhttp_append_to_last_header(headers, line) == -1)
1515 skey = strsep(&svalue,
":");
1519 svalue += strspn(svalue,
" ");
1521 if (evhttp_add_header(headers, skey, svalue) == -1)
1531 return (DATA_CORRUPTED);
1537 struct evkeyvalq *headers = req->input_headers;
1538 const char *content_length;
1539 const char *connection;
1541 content_length = evhttp_find_header(headers,
"Content-Length");
1542 connection = evhttp_find_header(headers,
"Connection");
1544 if (content_length == NULL && connection == NULL)
1546 else if (content_length == NULL &&
1547 strcasecmp(connection,
"Close") != 0) {
1549 event_warnx(
"%s: we got no content length, but the "
1550 "server wants to keep the connection open: %s.",
1551 __func__, connection);
1553 }
else if (content_length == NULL) {
1557 ev_int64_t ntoread = evutil_strtoll(content_length, &endp, 10);
1558 if (*content_length ==
'\0' || *endp !=
'\0' || ntoread < 0) {
1559 event_debug((
"%s: illegal content length: %s",
1560 __func__, content_length));
1563 req->ntoread = ntoread;
1566 event_debug((
"%s: bytes to read: %lld (in buffer %ld)\n",
1567 __func__, req->ntoread,
1568 EVBUFFER_LENGTH(req->evcon->input_buffer)));
1576 const char *xfer_enc;
1579 if (req->kind == EVHTTP_REQUEST && req->type != EVHTTP_REQ_POST) {
1580 evhttp_connection_done(evcon);
1583 evcon->state = EVCON_READING_BODY;
1584 xfer_enc = evhttp_find_header(req->input_headers,
"Transfer-Encoding");
1585 if (xfer_enc != NULL && strcasecmp(xfer_enc,
"chunked") == 0) {
1589 if (evhttp_get_body_length(req) == -1) {
1590 evhttp_connection_fail(evcon,
1591 EVCON_HTTP_INVALID_HEADER);
1595 evhttp_read_body(evcon, req);
1602 enum message_read_status res;
1604 res = evhttp_parse_firstline(req, evcon->input_buffer);
1605 if (res == DATA_CORRUPTED) {
1607 event_debug((
"%s: bad header lines on %d\n",
1608 __func__, evcon->fd));
1609 evhttp_connection_fail(evcon, EVCON_HTTP_INVALID_HEADER);
1611 }
else if (res == MORE_DATA_EXPECTED) {
1613 evhttp_add_event(&evcon->ev,
1614 evcon->timeout, HTTP_READ_TIMEOUT);
1618 evcon->state = EVCON_READING_HEADERS;
1619 evhttp_read_header(evcon, req);
1625 enum message_read_status res;
1628 res = evhttp_parse_headers(req, evcon->input_buffer);
1629 if (res == DATA_CORRUPTED) {
1631 event_debug((
"%s: bad header lines on %d\n", __func__, fd));
1632 evhttp_connection_fail(evcon, EVCON_HTTP_INVALID_HEADER);
1634 }
else if (res == MORE_DATA_EXPECTED) {
1636 evhttp_add_event(&evcon->ev,
1637 evcon->timeout, HTTP_READ_TIMEOUT);
1642 switch (req->kind) {
1643 case EVHTTP_REQUEST:
1644 event_debug((
"%s: checking for post data on %d\n",
1646 evhttp_get_body(evcon, req);
1649 case EVHTTP_RESPONSE:
1650 if (req->response_code == HTTP_NOCONTENT ||
1651 req->response_code == HTTP_NOTMODIFIED ||
1652 (req->response_code >= 100 && req->response_code < 200)) {
1653 event_debug((
"%s: skipping body for code %d\n",
1654 __func__, req->response_code));
1655 evhttp_connection_done(evcon);
1657 event_debug((
"%s: start of read body for %s on %d\n",
1658 __func__, req->remote_host, fd));
1659 evhttp_get_body(evcon, req);
1664 event_warnx(
"%s: bad header on %d", __func__, fd);
1665 evhttp_connection_fail(evcon, EVCON_HTTP_INVALID_HEADER);
1685 event_debug((
"Attempting connection to %s:%d\n", address, port));
1688 event_warn(
"%s: calloc failed", __func__);
1695 evcon->timeout = -1;
1696 evcon->retry_cnt = evcon->retry_max = 0;
1698 if ((evcon->address = strdup(address)) == NULL) {
1699 event_warn(
"%s: strdup failed", __func__);
1703 if ((evcon->input_buffer = evbuffer_new()) == NULL) {
1704 event_warn(
"%s: evbuffer_new failed", __func__);
1708 if ((evcon->output_buffer = evbuffer_new()) == NULL) {
1709 event_warn(
"%s: evbuffer_new failed", __func__);
1713 evcon->state = EVCON_DISCONNECTED;
1714 TAILQ_INIT(&evcon->requests);
1727 assert(evcon->base == NULL);
1728 assert(evcon->state == EVCON_DISCONNECTED);
1734 int timeout_in_secs)
1736 evcon->timeout = timeout_in_secs;
1743 evcon->retry_max = retry_max;
1750 evcon->closecb = cb;
1751 evcon->closecb_arg = cbarg;
1756 char **address, u_short *port)
1758 *address = evcon->address;
1759 *port = evcon->port;
1765 if (evcon->state == EVCON_CONNECTING)
1768 evhttp_connection_reset(evcon);
1770 assert(!(evcon->flags & EVHTTP_CON_INCOMING));
1771 evcon->flags |= EVHTTP_CON_OUTGOING;
1773 evcon->fd = bind_socket(
1774 evcon->bind_address, evcon->bind_port, 0 );
1775 if (evcon->fd == -1) {
1776 event_debug((
"%s: failed to bind to \"%s\"",
1777 __func__, evcon->bind_address));
1781 if (socket_connect(evcon->fd, evcon->address, evcon->port) == -1) {
1782 EVUTIL_CLOSESOCKET(evcon->fd); evcon->fd = -1;
1787 event_set(&evcon->ev, evcon->fd, EV_WRITE, evhttp_connectioncb, evcon);
1788 EVHTTP_BASE_SET(evcon, &evcon->ev);
1789 evhttp_add_event(&evcon->ev, evcon->timeout, HTTP_CONNECT_TIMEOUT);
1791 evcon->state = EVCON_CONNECTING;
1805 enum evhttp_cmd_type type,
const char *uri)
1808 req->kind = EVHTTP_REQUEST;
1810 if (req->uri != NULL)
1812 if ((req->uri = strdup(uri)) == NULL)
1813 event_err(1,
"%s: strdup", __func__);
1816 if (!req->major && !req->minor) {
1821 assert(req->evcon == NULL);
1823 assert(!(req->flags & EVHTTP_REQ_OWN_CONNECTION));
1825 TAILQ_INSERT_TAIL(&evcon->requests, req, next);
1828 if (!evhttp_connected(evcon))
1829 return (evhttp_connection_connect(evcon));
1836 if (TAILQ_FIRST(&evcon->requests) == req)
1837 evhttp_request_dispatch(evcon);
1852 event_del(&evcon->ev);
1853 event_set(&evcon->ev, evcon->fd, EV_READ, evhttp_read, evcon);
1854 EVHTTP_BASE_SET(evcon, &evcon->ev);
1856 evhttp_add_event(&evcon->ev, evcon->timeout, HTTP_READ_TIMEOUT);
1857 evcon->state = EVCON_READING_FIRSTLINE;
1865 TAILQ_REMOVE(&evcon->requests, req, next);
1868 evhttp_connection_stop_detectclose(evcon);
1872 !evhttp_is_connection_keepalive(req->input_headers))||
1873 evhttp_is_connection_close(req->flags, req->input_headers) ||
1874 evhttp_is_connection_close(req->flags, req->output_headers);
1876 assert(req->flags & EVHTTP_REQ_OWN_CONNECTION);
1885 if (evhttp_associate_new_request_with_connection(evcon) == -1)
1896 #define ERR_FORMAT "<HTML><HEAD>\n" \
1897 "<TITLE>%d %s</TITLE>\n" \
1899 "<H1>Method Not Implemented</H1>\n" \
1900 "Invalid method in request<P>\n" \
1903 struct evbuffer *buf = evbuffer_new();
1906 evhttp_add_header(req->output_headers,
"Connection",
"close");
1908 evhttp_response_code(req, error, reason);
1910 evbuffer_add_printf(buf, ERR_FORMAT, error, reason);
1912 evhttp_send_page(req, buf);
1925 assert(TAILQ_FIRST(&evcon->requests) == req);
1928 if (databuf != NULL)
1929 evbuffer_add_buffer(req->output_buffer, databuf);
1932 evhttp_make_header(evcon, req);
1934 evhttp_write_buffer(evcon, evhttp_send_done, NULL);
1941 evhttp_response_code(req, code, reason);
1943 evhttp_send(req, databuf);
1950 evhttp_response_code(req, code, reason);
1951 if (req->major == 1 && req->minor == 1) {
1953 evhttp_add_header(req->output_headers,
"Transfer-Encoding",
1957 evhttp_make_header(req->evcon, req);
1958 evhttp_write_buffer(req->evcon, NULL, NULL);
1965 evbuffer_add_printf(req->evcon->output_buffer,
"%x\r\n",
1966 (
unsigned)EVBUFFER_LENGTH(databuf));
1968 evbuffer_add_buffer(req->evcon->output_buffer, databuf);
1970 evbuffer_add(req->evcon->output_buffer,
"\r\n", 2);
1972 evhttp_write_buffer(req->evcon, NULL, NULL);
1981 evbuffer_add(req->evcon->output_buffer,
"0\r\n\r\n", 5);
1982 evhttp_write_buffer(req->evcon, evhttp_send_done, NULL);
1984 }
else if (!event_pending(&evcon->ev, EV_WRITE|EV_TIMEOUT, NULL)) {
1986 evhttp_send_done(evcon, NULL);
1989 evcon->cb = evhttp_send_done;
1990 evcon->cb_arg = NULL;
1995 evhttp_response_code(
struct evhttp_request *req,
int code,
const char *reason)
1997 req->kind = EVHTTP_RESPONSE;
1998 req->response_code = code;
1999 if (req->response_code_line != NULL)
2000 free(req->response_code_line);
2001 req->response_code_line = strdup(reason);
2007 if (!req->major || !req->minor) {
2012 if (req->kind != EVHTTP_RESPONSE)
2013 evhttp_response_code(req, 200,
"OK");
2015 evhttp_clear_headers(req->output_headers);
2016 evhttp_add_header(req->output_headers,
"Content-Type",
"text/html");
2017 evhttp_add_header(req->output_headers,
"Connection",
"close");
2019 evhttp_send(req, databuf);
2022 static const char uri_chars[256] = {
2023 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2024 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2025 0, 1, 0, 0, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1,
2026 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 0, 0,
2028 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
2029 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1,
2030 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
2031 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0,
2033 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,
2038 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2039 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2040 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2041 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2051 struct evbuffer *buf = evbuffer_new();
2054 for (p = (
char *)uri; *p !=
'\0'; p++) {
2055 if (uri_chars[(u_char)(*p)]) {
2056 evbuffer_add(buf, p, 1);
2058 evbuffer_add_printf(buf,
"%%%02X", (u_char)(*p));
2061 evbuffer_add(buf,
"", 1);
2062 p = strdup((
char *)EVBUFFER_DATA(buf));
2073 evhttp_decode_uri_internal(
2074 const char *uri,
size_t length,
char *
ret,
int always_decode_plus)
2077 int i, j, in_query = always_decode_plus;
2079 for (i = j = 0; uri[
i] !=
'\0'; i++) {
2083 }
else if (c ==
'+' && in_query) {
2085 }
else if (c ==
'%' && isxdigit((
unsigned char)uri[i+1]) &&
2086 isxdigit((
unsigned char)uri[i+2])) {
2087 char tmp[] = { uri[i+1], uri[i+2],
'\0' };
2088 c = (char)strtol(tmp, NULL, 16);
2103 if ((ret = malloc(strlen(uri) + 1)) == NULL)
2104 event_err(1,
"%s: malloc(%lu)", __func__,
2105 (
unsigned long)(strlen(uri) + 1));
2107 evhttp_decode_uri_internal(uri, strlen(uri),
2125 TAILQ_INIT(headers);
2128 if (strchr(uri,
'?') == NULL)
2131 if ((line = strdup(uri)) == NULL)
2132 event_err(1,
"%s: strdup", __func__);
2138 strsep(&argument,
"?");
2141 while (p != NULL && *p !=
'\0') {
2142 char *key, *value, *decoded_value;
2143 argument = strsep(&p,
"&");
2146 key = strsep(&value,
"=");
2150 if ((decoded_value = malloc(strlen(value) + 1)) == NULL)
2151 event_err(1,
"%s: malloc", __func__);
2153 evhttp_decode_uri_internal(value, strlen(value),
2155 event_debug((
"Query Param: %s -> %s\n", key, decoded_value));
2156 evhttp_add_header_internal(headers, key, decoded_value);
2157 free(decoded_value);
2165 evhttp_dispatch_callback(
struct httpcbq *callbacks,
struct evhttp_request *req)
2171 char *p = strchr(req->uri,
'?');
2173 offset = (size_t)(p - req->uri);
2175 TAILQ_FOREACH(cb, callbacks, next) {
2178 res = strcmp(cb->what, req->uri) == 0;
2180 res = ((strncmp(cb->what, req->uri, offset) == 0) &&
2181 (cb->what[offset] ==
'\0'));
2194 struct evhttp *http = arg;
2197 if (req->uri == NULL) {
2202 if ((cb = evhttp_dispatch_callback(&http->callbacks, req)) != NULL) {
2203 (*cb->cb)(req, cb->cbarg);
2209 (*http->gencb)(req, http->gencbarg);
2213 #define ERR_FORMAT "<html><head>" \
2214 "<title>404 Not Found</title>" \
2216 "<h1>Not Found</h1>" \
2217 "<p>The requested URL %s was not found on this server.</p>"\
2221 struct evbuffer *buf = evbuffer_new();
2223 evhttp_response_code(req, HTTP_NOTFOUND,
"Not Found");
2225 evbuffer_add_printf(buf, ERR_FORMAT, escaped_html);
2229 evhttp_send_page(req, buf);
2237 accept_socket(
int fd,
short what,
void *arg)
2239 struct evhttp *http = arg;
2240 struct sockaddr_storage ss;
2241 socklen_t addrlen =
sizeof(ss);
2244 if ((nfd = accept(fd, (
struct sockaddr *)&ss, &addrlen)) == -1) {
2245 if (errno != EAGAIN && errno != EINTR)
2246 event_warn(
"%s: bad accept", __func__);
2249 if (evutil_make_socket_nonblocking(nfd) < 0)
2252 evhttp_get_request(http, nfd, (
struct sockaddr *)&ss, addrlen);
2261 if ((fd = bind_socket(address, port, 1 )) == -1)
2264 if (listen(fd, 128) == -1) {
2265 event_warn(
"%s: listen", __func__);
2266 EVUTIL_CLOSESOCKET(fd);
2273 event_debug((
"Bound to port %d - Awaiting connections ... ",
2290 ev = &bound->bind_ev;
2293 event_set(ev, fd, EV_READ | EV_PERSIST, accept_socket, http);
2294 EVHTTP_BASE_SET(http, ev);
2296 res = event_add(ev, NULL);
2303 TAILQ_INSERT_TAIL(&http->sockets, bound, next);
2309 evhttp_new_object(
void)
2311 struct evhttp *http = NULL;
2313 if ((http = calloc(1,
sizeof(
struct evhttp))) == NULL) {
2314 event_warn(
"%s: calloc", __func__);
2320 TAILQ_INIT(&http->sockets);
2321 TAILQ_INIT(&http->callbacks);
2322 TAILQ_INIT(&http->connections);
2330 struct evhttp *http = evhttp_new_object();
2344 struct evhttp *http = evhttp_new_object();
2363 while ((bound = TAILQ_FIRST(&http->sockets)) != NULL) {
2364 TAILQ_REMOVE(&http->sockets, bound, next);
2366 fd = bound->bind_ev.ev_fd;
2367 event_del(&bound->bind_ev);
2368 EVUTIL_CLOSESOCKET(fd);
2373 while ((evcon = TAILQ_FIRST(&http->connections)) != NULL) {
2378 while ((http_cb = TAILQ_FIRST(&http->callbacks)) != NULL) {
2379 TAILQ_REMOVE(&http->callbacks, http_cb, next);
2380 free(http_cb->what);
2390 http->timeout = timeout_in_secs;
2399 if ((http_cb = calloc(1,
sizeof(
struct evhttp_cb))) == NULL)
2400 event_err(1,
"%s: calloc", __func__);
2402 http_cb->what = strdup(uri);
2404 http_cb->cbarg = cbarg;
2406 TAILQ_INSERT_TAIL(&http->callbacks, http_cb, next);
2414 TAILQ_FOREACH(http_cb, &http->callbacks, next) {
2415 if (strcmp(http_cb->what, uri) == 0)
2418 if (http_cb == NULL)
2421 TAILQ_REMOVE(&http->callbacks, http_cb, next);
2422 free(http_cb->what);
2433 http->gencbarg = cbarg;
2447 event_warn(
"%s: calloc", __func__);
2451 req->kind = EVHTTP_RESPONSE;
2452 req->input_headers = calloc(1,
sizeof(
struct evkeyvalq));
2453 if (req->input_headers == NULL) {
2454 event_warn(
"%s: calloc", __func__);
2457 TAILQ_INIT(req->input_headers);
2459 req->output_headers = calloc(1,
sizeof(
struct evkeyvalq));
2460 if (req->output_headers == NULL) {
2461 event_warn(
"%s: calloc", __func__);
2464 TAILQ_INIT(req->output_headers);
2466 if ((req->input_buffer = evbuffer_new()) == NULL) {
2467 event_warn(
"%s: evbuffer_new", __func__);
2471 if ((req->output_buffer = evbuffer_new()) == NULL) {
2472 event_warn(
"%s: evbuffer_new", __func__);
2490 if (req->remote_host != NULL)
2491 free(req->remote_host);
2492 if (req->uri != NULL)
2494 if (req->response_code_line != NULL)
2495 free(req->response_code_line);
2497 evhttp_clear_headers(req->input_headers);
2498 free(req->input_headers);
2500 evhttp_clear_headers(req->output_headers);
2501 free(req->output_headers);
2503 if (req->input_buffer != NULL)
2504 evbuffer_free(req->input_buffer);
2506 if (req->output_buffer != NULL)
2507 evbuffer_free(req->output_buffer);
2525 if (req->uri == NULL)
2526 event_debug((
"%s: request %p has no uri\n", __func__, req));
2536 evhttp_get_request_connection(
2538 int fd,
struct sockaddr *sa, socklen_t salen)
2541 char *hostname = NULL, *portname = NULL;
2543 name_from_addr(sa, salen, &hostname, &portname);
2544 if (hostname == NULL || portname == NULL) {
2545 if (hostname) free(hostname);
2546 if (portname) free(portname);
2550 event_debug((
"%s: new request from %s:%s on %d\n",
2551 __func__, hostname, portname, fd));
2563 evcon->flags |= EVHTTP_CON_INCOMING;
2564 evcon->state = EVCON_READING_FIRSTLINE;
2574 struct evhttp *http = evcon->http_server;
2580 req->flags |= EVHTTP_REQ_OWN_CONNECTION;
2582 TAILQ_INSERT_TAIL(&evcon->requests, req, next);
2584 req->kind = EVHTTP_REQUEST;
2586 if ((req->remote_host = strdup(evcon->address)) == NULL)
2587 event_err(1,
"%s: strdup", __func__);
2588 req->remote_port = evcon->port;
2590 evhttp_start_read(evcon);
2596 evhttp_get_request(
struct evhttp *http,
int fd,
2597 struct sockaddr *sa, socklen_t salen)
2601 evcon = evhttp_get_request_connection(http, fd, sa, salen);
2606 if (http->timeout != -1)
2613 evcon->http_server = http;
2614 TAILQ_INSERT_TAIL(&http->connections, evcon, next);
2616 if (evhttp_associate_new_request_with_connection(evcon) == -1)
2627 addr_from_name(
char *address)
2629 #ifdef HAVE_GETADDRINFO
2633 memset(&ai, 0,
sizeof(ai));
2634 ai.ai_family = AF_INET;
2635 ai.ai_socktype = SOCK_RAW;
2637 if ((ai_result = getaddrinfo(address, NULL, &ai, &aitop)) != 0) {
2638 if ( ai_result == EAI_SYSTEM )
2639 event_warn(
"getaddrinfo");
2641 event_warnx(
"getaddrinfo: %s", gai_strerror(ai_result));
2653 name_from_addr(
struct sockaddr *sa, socklen_t salen,
2654 char **phost,
char **pport)
2656 char ntop[NI_MAXHOST];
2657 char strport[NI_MAXSERV];
2660 #ifdef HAVE_GETNAMEINFO
2661 ni_result = getnameinfo(sa, salen,
2662 ntop,
sizeof(ntop), strport,
sizeof(strport),
2663 NI_NUMERICHOST|NI_NUMERICSERV);
2665 if (ni_result != 0) {
2666 if (ni_result == EAI_SYSTEM)
2667 event_err(1,
"getnameinfo failed");
2669 event_errx(1,
"getnameinfo failed: %s", gai_strerror(ni_result));
2673 ni_result = fake_getnameinfo(sa, salen,
2674 ntop,
sizeof(ntop), strport,
sizeof(strport),
2675 NI_NUMERICHOST|NI_NUMERICSERV);
2679 *phost = strdup(ntop);
2680 *pport = strdup(strport);
2686 bind_socket_ai(
struct addrinfo *ai,
int reuse)
2692 fd = socket(AF_INET, SOCK_STREAM, 0);
2694 event_warn(
"socket");
2698 if (evutil_make_socket_nonblocking(fd) < 0)
2702 if (fcntl(fd, F_SETFD, 1) == -1) {
2703 event_warn(
"fcntl(F_SETFD)");
2708 setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, (
void *)&on,
sizeof(on));
2710 setsockopt(fd, SOL_SOCKET, SO_REUSEADDR,
2711 (
void *)&on,
sizeof(on));
2715 r = bind(fd, ai->ai_addr, ai->ai_addrlen);
2723 serrno = EVUTIL_SOCKET_ERROR();
2724 EVUTIL_CLOSESOCKET(fd);
2725 EVUTIL_SET_SOCKET_ERROR(serrno);
2730 make_addrinfo(
const char *address, u_short port)
2734 #ifdef HAVE_GETADDRINFO
2736 char strport[NI_MAXSERV];
2739 memset(&ai, 0,
sizeof(ai));
2740 ai.ai_family = AF_INET;
2741 ai.ai_socktype = SOCK_STREAM;
2742 ai.ai_flags = AI_PASSIVE;
2743 evutil_snprintf(strport,
sizeof(strport),
"%d", port);
2744 if ((ai_result = getaddrinfo(address, strport, &ai, &aitop)) != 0) {
2745 if ( ai_result == EAI_SYSTEM )
2746 event_warn(
"getaddrinfo");
2748 event_warnx(
"getaddrinfo: %s", gai_strerror(ai_result));
2754 if (++cur == 2) cur = 0;
2756 if (fake_getaddrinfo(address, &ai[cur]) < 0) {
2757 event_warn(
"fake_getaddrinfo");
2761 ((
struct sockaddr_in *) aitop->ai_addr)->sin_port = htons(port);
2768 bind_socket(
const char *address, u_short port,
int reuse)
2774 if (address == NULL && port == 0)
2775 return bind_socket_ai(NULL, 0);
2777 aitop = make_addrinfo(address, port);
2782 fd = bind_socket_ai(aitop, reuse);
2784 #ifdef HAVE_GETADDRINFO
2785 freeaddrinfo(aitop);
2787 fake_freeaddrinfo(aitop);
2794 socket_connect(
int fd,
const char *address,
unsigned short port)
2796 struct addrinfo *ai = make_addrinfo(address, port);
2800 event_debug((
"%s: make_addrinfo: \"%s:%d\"",
2801 __func__, address, port));
2805 if (connect(fd, ai->ai_addr, ai->ai_addrlen) == -1) {
2807 int tmp_error = WSAGetLastError();
2808 if (tmp_error != WSAEWOULDBLOCK && tmp_error != WSAEINVAL &&
2809 tmp_error != WSAEINPROGRESS) {
2813 if (errno != EINPROGRESS) {
2823 #ifdef HAVE_GETADDRINFO
2826 fake_freeaddrinfo(ai);