90
90
#include "http-internal.h"
93
#define snprintf _snprintf
94
93
#define strcasecmp _stricmp
95
94
#define strncasecmp _strnicmp
96
95
#define strdup _strdup
98
#ifndef HAVE_GETNAMEINFO
100
#define NI_MAXHOST 1025
102
#define NI_NUMERICHOST 1
103
#define NI_NUMERICSERV 2
106
fake_getnameinfo(const struct sockaddr *sa, size_t salen, char *host,
107
size_t hostlen, char *serv, size_t servlen, int flags)
109
struct sockaddr_in *sin = (struct sockaddr_in *)sa;
113
evutil_snprintf(tmpserv, sizeof(tmpserv),
114
"%d", ntohs(sin->sin_port));
115
if (strlcpy(serv, tmpserv, servlen) >= servlen)
120
if (flags & NI_NUMERICHOST) {
121
if (strlcpy(host, inet_ntoa(sin->sin_addr),
128
hp = gethostbyaddr((char *)&sin->sin_addr,
129
sizeof(struct in_addr), AF_INET);
133
if (strlcpy(host, hp->h_name, hostlen) >= hostlen)
99
144
#ifndef HAVE_GETADDRINFO
100
145
struct addrinfo {
152
197
extern int debug;
154
199
static int socket_connect(int fd, const char *address, unsigned short port);
155
static int bind_socket_ai(struct addrinfo *);
156
static int bind_socket(const char *, u_short);
200
static int bind_socket_ai(struct addrinfo *, int reuse);
201
static int bind_socket(const char *, u_short, int reuse);
157
202
static void name_from_addr(struct sockaddr *, socklen_t, char **, char **);
158
203
static int evhttp_associate_new_request_with_connection(
159
204
struct evhttp_connection *evcon);
162
207
static void evhttp_connection_stop_detectclose(
163
208
struct evhttp_connection *evcon);
164
209
static void evhttp_request_dispatch(struct evhttp_connection* evcon);
210
static void evhttp_read_firstline(struct evhttp_connection *evcon,
211
struct evhttp_request *req);
212
static void evhttp_read_header(struct evhttp_connection *evcon,
213
struct evhttp_request *req);
214
static int evhttp_add_header_internal(struct evkeyvalq *headers,
215
const char *key, const char *value);
216
static int evhttp_decode_uri_internal(const char *uri, size_t length,
217
char *ret, int always_decode_plus);
166
219
void evhttp_read(int, short, void *);
167
220
void evhttp_write(int, short, void *);
300
353
evhttp_add_event(&evcon->ev, evcon->timeout, HTTP_WRITE_TIMEOUT);
357
evhttp_connected(struct evhttp_connection *evcon)
359
switch (evcon->state) {
360
case EVCON_DISCONNECTED:
361
case EVCON_CONNECTING:
364
case EVCON_READING_FIRSTLINE:
365
case EVCON_READING_HEADERS:
366
case EVCON_READING_BODY:
367
case EVCON_READING_TRAILER:
304
* Create the headers need for an HTTP request
375
* Create the headers needed for an HTTP request
307
378
evhttp_make_header_request(struct evhttp_connection *evcon,
308
379
struct evhttp_request *req)
311
381
const char *method;
313
evhttp_remove_header(req->output_headers, "Accept-Encoding");
314
383
evhttp_remove_header(req->output_headers, "Proxy-Connection");
316
385
/* Generate request line */
317
386
method = evhttp_method(req->type);
318
snprintf(line, sizeof(line), "%s %s HTTP/%d.%d\r\n",
387
evbuffer_add_printf(evcon->output_buffer, "%s %s HTTP/%d.%d\r\n",
319
388
method, req->uri, req->major, req->minor);
320
evbuffer_add(evcon->output_buffer, line, strlen(line));
322
390
/* Add the content length on a post request if missing */
323
391
if (req->type == EVHTTP_REQ_POST &&
324
392
evhttp_find_header(req->output_headers, "Content-Length") == NULL){
326
snprintf(size, sizeof(size), "%ld",
327
(long)EVBUFFER_LENGTH(req->output_buffer));
394
evutil_snprintf(size, sizeof(size), "%ld",
395
(long)EVBUFFER_LENGTH(req->output_buffer));
328
396
evhttp_add_header(req->output_headers, "Content-Length", size);
380
448
if (evhttp_find_header(headers, "Transfer-Encoding") == NULL &&
381
449
evhttp_find_header(headers, "Content-Length") == NULL) {
383
snprintf(len, sizeof(len), "%ld", content_length);
451
evutil_snprintf(len, sizeof(len), "%ld", content_length);
384
452
evhttp_add_header(headers, "Content-Length", len);
394
462
struct evhttp_request *req)
396
464
int is_keepalive = evhttp_is_connection_keepalive(req->input_headers);
398
snprintf(line, sizeof(line), "HTTP/%d.%d %d %s\r\n",
465
evbuffer_add_printf(evcon->output_buffer, "HTTP/%d.%d %d %s\r\n",
399
466
req->major, req->minor, req->response_code,
400
467
req->response_code_line);
401
evbuffer_add(evcon->output_buffer, line, strlen(line));
403
469
if (req->major == 1) {
404
470
if (req->minor == 1)
461
526
TAILQ_FOREACH(header, req->output_headers, next) {
462
snprintf(line, sizeof(line), "%s: %s\r\n",
527
evbuffer_add_printf(evcon->output_buffer, "%s: %s\r\n",
463
528
header->key, header->value);
464
evbuffer_add(evcon->output_buffer, line, strlen(line));
466
530
evbuffer_add(evcon->output_buffer, "\r\n", 2);
642
706
(*evcon->cb)(evcon, evcon->cb_arg);
710
* Advance the connection state.
711
* - If this is an outgoing connection, we've just processed the response;
712
* idle or close the connection.
713
* - If this is an incoming connection, we've just processed the request;
646
717
evhttp_connection_done(struct evhttp_connection *evcon)
648
719
struct evhttp_request *req = TAILQ_FIRST(&evcon->requests);
649
720
int con_outgoing = evcon->flags & EVHTTP_CON_OUTGOING;
652
* if this is an incoming connection, we need to leave the request
653
* on the connection, so that we can reply to it.
655
722
if (con_outgoing) {
723
/* idle or close the connection */
657
725
TAILQ_REMOVE(&evcon->requests, req, next);
658
726
req->evcon = NULL;
728
evcon->state = EVCON_IDLE;
661
evhttp_is_connection_close(req->flags, req->input_headers) ||
731
evhttp_is_connection_close(req->flags, req->input_headers)||
662
732
evhttp_is_connection_close(req->flags, req->output_headers);
664
734
/* check if we got asked to close the connection */
668
738
if (TAILQ_FIRST(&evcon->requests) != NULL) {
670
740
* We have more requests; reset the connection
671
* and deal with the next request. xxx: no
672
* persistent connection right now
741
* and deal with the next request.
674
if (evcon->state != EVCON_CONNECTED)
743
if (!evhttp_connected(evcon))
675
744
evhttp_connection_connect(evcon);
677
746
evhttp_request_dispatch(evcon);
697
772
* Handles reading from a chunked request.
698
* return 1: all data has been read
699
* return 0: more data is expected
700
* return -1: data is corrupted
773
* return ALL_DATA_READ:
774
* all data has been read
775
* return MORE_DATA_EXPECTED:
776
* more data is expected
777
* return DATA_CORRUPTED:
779
* return REQUEST_CANCLED:
780
* request was canceled by the user calling evhttp_cancel_request
783
static enum message_read_status
704
784
evhttp_handle_chunked_read(struct evhttp_request *req, struct evbuffer *buf)
721
req->ntoread = evutil_strtoll(p, &endp, 16);
722
error = *p == '\0' || (*endp != '\0' && *endp != ' ');
802
ntoread = evutil_strtoll(p, &endp, 16);
803
error = (*p == '\0' ||
804
(*endp != '\0' && *endp != ' ') ||
725
808
/* could not get chunk size */
809
return (DATA_CORRUPTED);
811
req->ntoread = ntoread;
728
812
if (req->ntoread == 0) {
814
return (ALL_DATA_READ);
735
819
/* don't have enough to complete a chunk; wait for more */
736
820
if (len < req->ntoread)
821
return (MORE_DATA_EXPECTED);
739
823
/* Completed chunk */
740
824
evbuffer_add(req->input_buffer,
835
return (MORE_DATA_EXPECTED);
839
evhttp_read_trailer(struct evhttp_connection *evcon, struct evhttp_request *req)
841
struct evbuffer *buf = evcon->input_buffer;
843
switch (evhttp_parse_headers(req, buf)) {
845
evhttp_connection_fail(evcon, EVCON_HTTP_INVALID_HEADER);
848
event_del(&evcon->ev);
849
evhttp_connection_done(evcon);
851
case MORE_DATA_EXPECTED:
853
evhttp_add_event(&evcon->ev, evcon->timeout,
757
862
struct evbuffer *buf = evcon->input_buffer;
759
864
if (req->chunked) {
760
int res = evhttp_handle_chunked_read(req, buf);
865
switch (evhttp_handle_chunked_read(req, buf)) {
762
867
/* finished last chunk */
763
evhttp_connection_done(evcon);
868
evcon->state = EVCON_READING_TRAILER;
869
evhttp_read_trailer(evcon, req);
765
} else if (res == -1) {
766
872
/* corrupted data */
767
873
evhttp_connection_fail(evcon,
768
874
EVCON_HTTP_INVALID_HEADER);
876
case REQUEST_CANCELED:
877
/* request canceled */
878
evhttp_request_free(req);
880
case MORE_DATA_EXPECTED:
771
884
} else if (req->ntoread < 0) {
772
885
/* Read until connection close. */
810
923
event_debug(("%s: got %d on %d\n", __func__, n, fd));
813
event_debug(("%s: evbuffer_read", __func__));
814
evhttp_connection_fail(evcon, EVCON_HTTP_EOF);
926
if (errno != EINTR && errno != EAGAIN) {
927
event_debug(("%s: evbuffer_read", __func__));
928
evhttp_connection_fail(evcon, EVCON_HTTP_EOF);
930
evhttp_add_event(&evcon->ev, evcon->timeout,
816
934
} else if (n == 0) {
817
935
/* Connection closed */
818
936
evhttp_connection_done(evcon);
821
evhttp_read_body(evcon, req);
940
switch (evcon->state) {
941
case EVCON_READING_FIRSTLINE:
942
evhttp_read_firstline(evcon, req);
944
case EVCON_READING_HEADERS:
945
evhttp_read_header(evcon, req);
947
case EVCON_READING_BODY:
948
evhttp_read_body(evcon, req);
950
case EVCON_READING_TRAILER:
951
evhttp_read_trailer(evcon, req);
953
case EVCON_DISCONNECTED:
954
case EVCON_CONNECTING:
958
event_errx(1, "%s: illegal connection state %d",
959
__func__, evcon->state);
909
1057
evhttp_connection_stop_detectclose(evcon);
911
1059
/* we assume that the connection is connected already */
912
assert(evcon->state == EVCON_CONNECTED);
1060
assert(evcon->state == EVCON_IDLE);
1062
evcon->state = EVCON_WRITING;
914
1064
/* Create the header from the store arguments */
915
1065
evhttp_make_header(evcon, req);
935
1085
evcon->state = EVCON_DISCONNECTED;
937
/* remove unneeded flags */
938
evcon->flags &= ~EVHTTP_CON_CLOSEDETECT;
1087
evbuffer_drain(evcon->input_buffer,
1088
EVBUFFER_LENGTH(evcon->input_buffer));
1089
evbuffer_drain(evcon->output_buffer,
1090
EVBUFFER_LENGTH(evcon->output_buffer));
1364
evhttp_header_is_valid_value(const char *value)
1366
const char *p = value;
1368
while ((p = strpbrk(p, "\r\n")) != NULL) {
1369
/* we really expect only one new line */
1370
p += strspn(p, "\r\n");
1371
/* we expect a space or tab for continuation */
1372
if (*p != ' ' && *p != '\t')
1212
1379
evhttp_add_header(struct evkeyvalq *headers,
1213
1380
const char *key, const char *value)
1215
struct evkeyval *header = NULL;
1217
1382
event_debug(("%s: key: %s val: %s\n", __func__, key, value));
1219
if (strchr(value, '\r') != NULL || strchr(value, '\n') != NULL ||
1220
strchr(key, '\r') != NULL || strchr(key, '\n') != NULL) {
1384
if (strchr(key, '\r') != NULL || strchr(key, '\n') != NULL) {
1221
1385
/* drop illegal headers */
1222
event_debug(("%s: dropping illegal header\n", __func__));
1226
header = calloc(1, sizeof(struct evkeyval));
1386
event_debug(("%s: dropping illegal header key\n", __func__));
1390
if (!evhttp_header_is_valid_value(value)) {
1391
event_debug(("%s: dropping illegal header value\n", __func__));
1395
return (evhttp_add_header_internal(headers, key, value));
1399
evhttp_add_header_internal(struct evkeyvalq *headers,
1400
const char *key, const char *value)
1402
struct evkeyval *header = calloc(1, sizeof(struct evkeyval));
1227
1403
if (header == NULL) {
1228
1404
event_warn("%s: calloc", __func__);
1250
1426
* request object given an event buffer.
1254
* 0 when we need to read more headers
1255
* 1 when all headers have been read.
1429
* DATA_CORRUPTED on error
1430
* MORE_DATA_EXPECTED when we need to read more headers
1431
* ALL_DATA_READ when all headers have been read.
1259
evhttp_parse_lines(struct evhttp_request *req, struct evbuffer* buffer)
1434
enum message_read_status
1435
evhttp_parse_firstline(struct evhttp_request *req, struct evbuffer *buffer)
1438
enum message_read_status status = ALL_DATA_READ;
1440
line = evbuffer_readline(buffer);
1442
return (MORE_DATA_EXPECTED);
1444
switch (req->kind) {
1445
case EVHTTP_REQUEST:
1446
if (evhttp_parse_request_line(req, line) == -1)
1447
status = DATA_CORRUPTED;
1449
case EVHTTP_RESPONSE:
1450
if (evhttp_parse_response_line(req, line) == -1)
1451
status = DATA_CORRUPTED;
1454
status = DATA_CORRUPTED;
1462
evhttp_append_to_last_header(struct evkeyvalq *headers, const char *line)
1464
struct evkeyval *header = TAILQ_LAST(headers, evkeyvalq);
1466
size_t old_len, line_len;
1471
old_len = strlen(header->value);
1472
line_len = strlen(line);
1474
newval = realloc(header->value, old_len + line_len + 1);
1478
memcpy(newval + old_len, line, line_len + 1);
1479
header->value = newval;
1484
enum message_read_status
1485
evhttp_parse_headers(struct evhttp_request *req, struct evbuffer* buffer)
1488
enum message_read_status status = MORE_DATA_EXPECTED;
1264
1490
struct evkeyvalq* headers = req->input_headers;
1265
while ((line = evbuffer_readline(buffer)) != NULL) {
1491
while ((line = evbuffer_readline(buffer))
1266
1493
char *skey, *svalue;
1268
1495
if (*line == '\0') { /* Last header - Done */
1496
status = ALL_DATA_READ;
1501
/* Check if this is a continuation line */
1502
if (*line == ' ' || *line == '\t') {
1503
if (evhttp_append_to_last_header(headers, line) == -1)
1274
1509
/* Processing of header lines */
1275
if (req->got_firstline == 0) {
1276
switch (req->kind) {
1277
case EVHTTP_REQUEST:
1278
if (evhttp_parse_request_line(req, line) == -1)
1281
case EVHTTP_RESPONSE:
1282
if (evhttp_parse_response_line(req, line) == -1)
1288
req->got_firstline = 1;
1290
/* Regular header */
1292
skey = strsep(&svalue, ":");
1296
svalue += strspn(svalue, " ");
1298
if (evhttp_add_header(headers, skey, svalue) == -1)
1511
skey = strsep(&svalue, ":");
1515
svalue += strspn(svalue, " ");
1517
if (evhttp_add_header(headers, skey, svalue) == -1)
1527
return (DATA_CORRUPTED);
1332
1550
req->ntoread = -1;
1335
req->ntoread = evutil_strtoll(content_length, &endp, 10);
1336
if (*content_length == '\0' || *endp != '\0') {
1337
event_warnx("%s: illegal content length: %s",
1338
__func__, content_length);
1553
ev_int64_t ntoread = evutil_strtoll(content_length, &endp, 10);
1554
if (*content_length == '\0' || *endp != '\0' || ntoread < 0) {
1555
event_debug(("%s: illegal content length: %s",
1556
__func__, content_length));
1559
req->ntoread = ntoread;
1343
event_debug(("%s: bytes to read: %d (in buffer %d)\n",
1562
event_debug(("%s: bytes to read: %lld (in buffer %ld)\n",
1344
1563
__func__, req->ntoread,
1345
1564
EVBUFFER_LENGTH(req->evcon->input_buffer)));
1371
1591
evhttp_read_body(evcon, req);
1375
evhttp_read_header(int fd, short what, void *arg)
1377
struct evhttp_connection *evcon = arg;
1378
struct evhttp_request *req = TAILQ_FIRST(&evcon->requests);
1381
if (what == EV_TIMEOUT) {
1382
event_debug(("%s: timeout on %d\n", __func__, fd));
1383
evhttp_connection_fail(evcon, EVCON_HTTP_TIMEOUT);
1387
n = evbuffer_read(evcon->input_buffer, fd, -1);
1389
event_debug(("%s: no more data on %d", __func__, fd));
1390
evhttp_connection_fail(evcon, EVCON_HTTP_EOF);
1394
event_debug(("%s: bad read on %d", __func__, fd));
1395
evhttp_connection_fail(evcon, EVCON_HTTP_EOF);
1399
res = evhttp_parse_lines(req, evcon->input_buffer);
1595
evhttp_read_firstline(struct evhttp_connection *evcon,
1596
struct evhttp_request *req)
1598
enum message_read_status res;
1600
res = evhttp_parse_firstline(req, evcon->input_buffer);
1601
if (res == DATA_CORRUPTED) {
1602
/* Error while reading, terminate */
1603
event_debug(("%s: bad header lines on %d\n",
1604
__func__, evcon->fd));
1605
evhttp_connection_fail(evcon, EVCON_HTTP_INVALID_HEADER);
1607
} else if (res == MORE_DATA_EXPECTED) {
1608
/* Need more header lines */
1609
evhttp_add_event(&evcon->ev,
1610
evcon->timeout, HTTP_READ_TIMEOUT);
1614
evcon->state = EVCON_READING_HEADERS;
1615
evhttp_read_header(evcon, req);
1619
evhttp_read_header(struct evhttp_connection *evcon, struct evhttp_request *req)
1621
enum message_read_status res;
1624
res = evhttp_parse_headers(req, evcon->input_buffer);
1625
if (res == DATA_CORRUPTED) {
1401
1626
/* Error while reading, terminate */
1402
1627
event_debug(("%s: bad header lines on %d\n", __func__, fd));
1403
1628
evhttp_connection_fail(evcon, EVCON_HTTP_INVALID_HEADER);
1405
} else if (res == 0) {
1630
} else if (res == MORE_DATA_EXPECTED) {
1406
1631
/* Need more header lines */
1407
1632
evhttp_add_event(&evcon->ev,
1408
1633
evcon->timeout, HTTP_READ_TIMEOUT);
1541
1766
assert(!(evcon->flags & EVHTTP_CON_INCOMING));
1542
1767
evcon->flags |= EVHTTP_CON_OUTGOING;
1544
evcon->fd = bind_socket(evcon->bind_address, 0);
1769
evcon->fd = bind_socket(
1770
evcon->bind_address, evcon->bind_port, 0 /*reuse*/);
1545
1771
if (evcon->fd == -1) {
1546
1772
event_debug(("%s: failed to bind to \"%s\"",
1547
1773
__func__, evcon->bind_address));
1620
1846
/* Set up an event to read the headers */
1621
1847
if (event_initialized(&evcon->ev))
1622
1848
event_del(&evcon->ev);
1623
event_set(&evcon->ev, evcon->fd, EV_READ, evhttp_read_header, evcon);
1849
event_set(&evcon->ev, evcon->fd, EV_READ, evhttp_read, evcon);
1624
1850
EVHTTP_BASE_SET(evcon, &evcon->ev);
1626
1852
evhttp_add_event(&evcon->ev, evcon->timeout, HTTP_READ_TIMEOUT);
1853
evcon->state = EVCON_READING_FIRSTLINE;
1707
1934
evhttp_send_reply(struct evhttp_request *req, int code, const char *reason,
1708
1935
struct evbuffer *databuf)
1710
/* set up to watch for client close */
1711
evhttp_connection_start_detectclose(req->evcon);
1712
1937
evhttp_response_code(req, code, reason);
1714
1939
evhttp_send(req, databuf);
1718
1943
evhttp_send_reply_start(struct evhttp_request *req, int code,
1719
1944
const char *reason)
1721
/* set up to watch for client close */
1722
evhttp_connection_start_detectclose(req->evcon);
1723
1946
evhttp_response_code(req, code, reason);
1724
1947
if (req->major == 1 && req->minor == 1) {
1725
1948
/* use chunked encoding for HTTP/1.1 */
1842
evhttp_decode_uri(const char *uri)
2065
* @param always_decode_plus: when true we transform plus to space even
2066
* if we have not seen a ?.
2069
evhttp_decode_uri_internal(
2070
const char *uri, size_t length, char *ret, int always_decode_plus)
1845
int i, j, in_query = 0;
1847
ret = malloc(strlen(uri) + 1);
1849
event_err(1, "%s: malloc(%lu)", __func__,
1850
(unsigned long)(strlen(uri) + 1));
2073
int i, j, in_query = always_decode_plus;
1852
2075
for (i = j = 0; uri[i] != '\0'; i++) {
2095
evhttp_decode_uri(const char *uri)
2099
if ((ret = malloc(strlen(uri) + 1)) == NULL)
2100
event_err(1, "%s: malloc(%lu)", __func__,
2101
(unsigned long)(strlen(uri) + 1));
2103
evhttp_decode_uri_internal(uri, strlen(uri),
2104
ret, 0 /*always_decode_plus*/);
1872
2110
* Helper function to parse out arguments in a query.
1873
2111
* The arguments are separated by key and value.
1874
* URI should already be decoded.
1906
2143
if (value == NULL)
1909
value = evhttp_decode_uri(value);
1910
event_debug(("Query Param: %s -> %s\n", key, value));
1911
evhttp_add_header(headers, key, value);
2146
if ((decoded_value = malloc(strlen(value) + 1)) == NULL)
2147
event_err(1, "%s: malloc", __func__);
2149
evhttp_decode_uri_internal(value, strlen(value),
2150
decoded_value, 1 /*always_decode_plus*/);
2151
event_debug(("Query Param: %s -> %s\n", key, decoded_value));
2152
evhttp_add_header_internal(headers, key, decoded_value);
2153
free(decoded_value);
2292
2534
int fd, struct sockaddr *sa, socklen_t salen)
2294
2536
struct evhttp_connection *evcon;
2295
char *hostname, *portname;
2537
char *hostname = NULL, *portname = NULL;
2297
2539
name_from_addr(sa, salen, &hostname, &portname);
2540
if (hostname == NULL || portname == NULL) {
2541
if (hostname) free(hostname);
2542
if (portname) free(portname);
2298
2546
event_debug(("%s: new request from %s:%s on %d\n",
2299
2547
__func__, hostname, portname, fd));
2301
2549
/* we need a connection object to put the http request on */
2302
if ((evcon = evhttp_connection_new(hostname, atoi(portname))) == NULL)
2550
evcon = evhttp_connection_new(hostname, atoi(portname));
2305
2556
/* associate the base if we have one*/
2306
2557
evhttp_connection_set_base(evcon, http->base);
2308
2559
evcon->flags |= EVHTTP_CON_INCOMING;
2309
evcon->state = EVCON_CONNECTED;
2560
evcon->state = EVCON_READING_FIRSTLINE;
2311
2562
evcon->fd = fd;
2398
2649
name_from_addr(struct sockaddr *sa, socklen_t salen,
2399
2650
char **phost, char **pport)
2652
char ntop[NI_MAXHOST];
2653
char strport[NI_MAXSERV];
2401
2656
#ifdef HAVE_GETNAMEINFO
2402
/* XXXX not threadsafe. */
2403
static char ntop[NI_MAXHOST];
2404
static char strport[NI_MAXSERV];
2407
if ((ni_result = getnameinfo(sa, salen,
2657
ni_result = getnameinfo(sa, salen,
2408
2658
ntop, sizeof(ntop), strport, sizeof(strport),
2409
NI_NUMERICHOST|NI_NUMERICSERV)) != 0) {
2659
NI_NUMERICHOST|NI_NUMERICSERV);
2661
if (ni_result != 0) {
2410
2662
if (ni_result == EAI_SYSTEM)
2411
2663
event_err(1, "getnameinfo failed");
2413
2665
event_errx(1, "getnameinfo failed: %s", gai_strerror(ni_result));
2669
ni_result = fake_getnameinfo(sa, salen,
2670
ntop, sizeof(ntop), strport, sizeof(strport),
2671
NI_NUMERICHOST|NI_NUMERICSERV);
2675
*phost = strdup(ntop);
2676
*pport = strdup(strport);
2423
/* Either connect or bind */
2679
/* Create a non-blocking socket and bind it */
2680
/* todo: rename this function */
2426
bind_socket_ai(struct addrinfo *ai)
2682
bind_socket_ai(struct addrinfo *ai, int reuse)
2428
2684
int fd, on = 1, r;
2448
2704
setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, (void *)&on, sizeof(on));
2449
setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (void *)&on, sizeof(on));
2706
setsockopt(fd, SOL_SOCKET, SO_REUSEADDR,
2707
(void *)&on, sizeof(on));
2451
r = bind(fd, ai->ai_addr, ai->ai_addrlen);
2711
r = bind(fd, ai->ai_addr, ai->ai_addrlen);
2475
2736
ai.ai_family = AF_INET;
2476
2737
ai.ai_socktype = SOCK_STREAM;
2477
2738
ai.ai_flags = AI_PASSIVE; /* turn NULL host name into INADDR_ANY */
2478
snprintf(strport, sizeof(strport), "%d", port);
2739
evutil_snprintf(strport, sizeof(strport), "%d", port);
2479
2740
if ((ai_result = getaddrinfo(address, strport, &ai, &aitop)) != 0) {
2480
2741
if ( ai_result == EAI_SYSTEM )
2481
2742
event_warn("getaddrinfo");
2503
bind_socket(const char *address, u_short port)
2764
bind_socket(const char *address, u_short port, int reuse)
2506
struct addrinfo *aitop = make_addrinfo(address, port);
2767
struct addrinfo *aitop = NULL;
2769
/* just create an unbound socket */
2770
if (address == NULL && port == 0)
2771
return bind_socket_ai(NULL, 0);
2773
aitop = make_addrinfo(address, port);
2508
2775
if (aitop == NULL)
2511
fd = bind_socket_ai(aitop);
2778
fd = bind_socket_ai(aitop, reuse);
2513
2780
#ifdef HAVE_GETADDRINFO
2514
2781
freeaddrinfo(aitop);