Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(333)

Side by Side Diff: third_party/libevent/http.c

Issue 412006: posix: upgrade libevent from 1.4.7 to 1.4.13 (Closed)
Patch Set: better readme Created 11 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 /* 1 /*
2 * Copyright (c) 2002-2006 Niels Provos <provos@citi.umich.edu> 2 * Copyright (c) 2002-2006 Niels Provos <provos@citi.umich.edu>
3 * All rights reserved. 3 * All rights reserved.
4 * 4 *
5 * Redistribution and use in source and binary forms, with or without 5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions 6 * modification, are permitted provided that the following conditions
7 * are met: 7 * are met:
8 * 1. Redistributions of source code must retain the above copyright 8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer. 9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright 10 * 2. Redistributions in binary form must reproduce the above copyright
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after
81 81
82 #undef timeout_pending 82 #undef timeout_pending
83 #undef timeout_initialized 83 #undef timeout_initialized
84 84
85 #include "strlcpy-internal.h" 85 #include "strlcpy-internal.h"
86 #include "event.h" 86 #include "event.h"
87 #include "evhttp.h" 87 #include "evhttp.h"
88 #include "evutil.h" 88 #include "evutil.h"
89 #include "log.h" 89 #include "log.h"
90 #include "http-internal.h" 90 #include "http-internal.h"
91 #include "event-internal.h"
92 91
93 #ifdef WIN32 92 #ifdef WIN32
94 #define strcasecmp _stricmp 93 #define strcasecmp _stricmp
95 #define strncasecmp _strnicmp 94 #define strncasecmp _strnicmp
96 #define strdup _strdup 95 #define strdup _strdup
97 #endif 96 #endif
98 97
99 #ifndef HAVE_GETNAMEINFO 98 #ifndef HAVE_GETNAMEINFO
100 #define NI_MAXSERV 32 99 #define NI_MAXSERV 32
101 #define NI_MAXHOST 1025 100 #define NI_MAXHOST 1025
102 101
103 #define NI_NUMERICHOST 1 102 #define NI_NUMERICHOST 1
104 #define NI_NUMERICSERV 2 103 #define NI_NUMERICSERV 2
105 104
106 int 105 static int
107 fake_getnameinfo(const struct sockaddr *sa, size_t salen, char *host, 106 fake_getnameinfo(const struct sockaddr *sa, size_t salen, char *host,
108 size_t hostlen, char *serv, size_t servlen, int flags) 107 size_t hostlen, char *serv, size_t servlen, int flags)
109 { 108 {
110 struct sockaddr_in *sin = (struct sockaddr_in *)sa; 109 struct sockaddr_in *sin = (struct sockaddr_in *)sa;
111 110
112 if (serv != NULL) { 111 if (serv != NULL) {
113 char tmpserv[16]; 112 char tmpserv[16];
114 evutil_snprintf(tmpserv, sizeof(tmpserv), 113 evutil_snprintf(tmpserv, sizeof(tmpserv),
115 "%d", ntohs(sin->sin_port)); 114 "%d", ntohs(sin->sin_port));
116 if (strlcpy(serv, tmpserv, servlen) >= servlen) 115 if (strlcpy(serv, tmpserv, servlen) >= servlen)
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after
205 struct evhttp_connection *evcon); 204 struct evhttp_connection *evcon);
206 static void evhttp_connection_start_detectclose( 205 static void evhttp_connection_start_detectclose(
207 struct evhttp_connection *evcon); 206 struct evhttp_connection *evcon);
208 static void evhttp_connection_stop_detectclose( 207 static void evhttp_connection_stop_detectclose(
209 struct evhttp_connection *evcon); 208 struct evhttp_connection *evcon);
210 static void evhttp_request_dispatch(struct evhttp_connection* evcon); 209 static void evhttp_request_dispatch(struct evhttp_connection* evcon);
211 static void evhttp_read_firstline(struct evhttp_connection *evcon, 210 static void evhttp_read_firstline(struct evhttp_connection *evcon,
212 struct evhttp_request *req); 211 struct evhttp_request *req);
213 static void evhttp_read_header(struct evhttp_connection *evcon, 212 static void evhttp_read_header(struct evhttp_connection *evcon,
214 struct evhttp_request *req); 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);
215 218
216 void evhttp_read(int, short, void *); 219 void evhttp_read(int, short, void *);
217 void evhttp_write(int, short, void *); 220 void evhttp_write(int, short, void *);
218 221
219 #ifndef HAVE_STRSEP 222 #ifndef HAVE_STRSEP
220 /* strsep replacement for platforms that lack it. Only works if 223 /* strsep replacement for platforms that lack it. Only works if
221 * del is one character long. */ 224 * del is one character long. */
222 static char * 225 static char *
223 strsep(char **s, const char *del) 226 strsep(char **s, const char *del)
224 { 227 {
(...skipping 137 matching lines...) Expand 10 before | Expand all | Expand 10 after
362 case EVCON_READING_HEADERS: 365 case EVCON_READING_HEADERS:
363 case EVCON_READING_BODY: 366 case EVCON_READING_BODY:
364 case EVCON_READING_TRAILER: 367 case EVCON_READING_TRAILER:
365 case EVCON_WRITING: 368 case EVCON_WRITING:
366 default: 369 default:
367 return (1); 370 return (1);
368 } 371 }
369 } 372 }
370 373
371 /* 374 /*
372 * Create the headers need for an HTTP request 375 * Create the headers needed for an HTTP request
373 */ 376 */
374 static void 377 static void
375 evhttp_make_header_request(struct evhttp_connection *evcon, 378 evhttp_make_header_request(struct evhttp_connection *evcon,
376 struct evhttp_request *req) 379 struct evhttp_request *req)
377 { 380 {
378 char line[1024];
379 const char *method; 381 const char *method;
380 382
381 evhttp_remove_header(req->output_headers, "Accept-Encoding");
382 evhttp_remove_header(req->output_headers, "Proxy-Connection"); 383 evhttp_remove_header(req->output_headers, "Proxy-Connection");
383 384
384 /* Generate request line */ 385 /* Generate request line */
385 method = evhttp_method(req->type); 386 method = evhttp_method(req->type);
386 » evutil_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",
387 method, req->uri, req->major, req->minor); 388 method, req->uri, req->major, req->minor);
388 evbuffer_add(evcon->output_buffer, line, strlen(line));
389 389
390 /* Add the content length on a post request if missing */ 390 /* Add the content length on a post request if missing */
391 if (req->type == EVHTTP_REQ_POST && 391 if (req->type == EVHTTP_REQ_POST &&
392 evhttp_find_header(req->output_headers, "Content-Length") == NULL){ 392 evhttp_find_header(req->output_headers, "Content-Length") == NULL){
393 char size[12]; 393 char size[12];
394 evutil_snprintf(size, sizeof(size), "%ld", 394 evutil_snprintf(size, sizeof(size), "%ld",
395 (long)EVBUFFER_LENGTH(req->output_buffer)); 395 (long)EVBUFFER_LENGTH(req->output_buffer));
396 evhttp_add_header(req->output_headers, "Content-Length", size); 396 evhttp_add_header(req->output_headers, "Content-Length", size);
397 } 397 }
398 } 398 }
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after
455 455
456 /* 456 /*
457 * Create the headers needed for an HTTP reply 457 * Create the headers needed for an HTTP reply
458 */ 458 */
459 459
460 static void 460 static void
461 evhttp_make_header_response(struct evhttp_connection *evcon, 461 evhttp_make_header_response(struct evhttp_connection *evcon,
462 struct evhttp_request *req) 462 struct evhttp_request *req)
463 { 463 {
464 int is_keepalive = evhttp_is_connection_keepalive(req->input_headers); 464 int is_keepalive = evhttp_is_connection_keepalive(req->input_headers);
465 » char line[1024]; 465 » evbuffer_add_printf(evcon->output_buffer, "HTTP/%d.%d %d %s\r\n",
466 » evutil_snprintf(line, sizeof(line), "HTTP/%d.%d %d %s\r\n",
467 req->major, req->minor, req->response_code, 466 req->major, req->minor, req->response_code,
468 req->response_code_line); 467 req->response_code_line);
469 evbuffer_add(evcon->output_buffer, line, strlen(line));
470 468
471 if (req->major == 1) { 469 if (req->major == 1) {
472 if (req->minor == 1) 470 if (req->minor == 1)
473 evhttp_maybe_add_date_header(req->output_headers); 471 evhttp_maybe_add_date_header(req->output_headers);
474 472
475 /* 473 /*
476 * if the protocol is 1.0; and the connection was keep-alive 474 * if the protocol is 1.0; and the connection was keep-alive
477 * we need to add a keep-alive header, too. 475 * we need to add a keep-alive header, too.
478 */ 476 */
479 if (req->minor == 0 && is_keepalive) 477 if (req->minor == 0 && is_keepalive)
(...skipping 26 matching lines...) Expand all
506 evhttp_remove_header(req->output_headers, "Connection"); 504 evhttp_remove_header(req->output_headers, "Connection");
507 if (!(req->flags & EVHTTP_PROXY_REQUEST)) 505 if (!(req->flags & EVHTTP_PROXY_REQUEST))
508 evhttp_add_header(req->output_headers, "Connection", "close" ); 506 evhttp_add_header(req->output_headers, "Connection", "close" );
509 evhttp_remove_header(req->output_headers, "Proxy-Connection"); 507 evhttp_remove_header(req->output_headers, "Proxy-Connection");
510 } 508 }
511 } 509 }
512 510
513 void 511 void
514 evhttp_make_header(struct evhttp_connection *evcon, struct evhttp_request *req) 512 evhttp_make_header(struct evhttp_connection *evcon, struct evhttp_request *req)
515 { 513 {
516 char line[1024];
517 struct evkeyval *header; 514 struct evkeyval *header;
518 515
519 /* 516 /*
520 * Depending if this is a HTTP request or response, we might need to 517 * Depending if this is a HTTP request or response, we might need to
521 * add some new headers or remove existing headers. 518 * add some new headers or remove existing headers.
522 */ 519 */
523 if (req->kind == EVHTTP_REQUEST) { 520 if (req->kind == EVHTTP_REQUEST) {
524 evhttp_make_header_request(evcon, req); 521 evhttp_make_header_request(evcon, req);
525 } else { 522 } else {
526 evhttp_make_header_response(evcon, req); 523 evhttp_make_header_response(evcon, req);
527 } 524 }
528 525
529 TAILQ_FOREACH(header, req->output_headers, next) { 526 TAILQ_FOREACH(header, req->output_headers, next) {
530 » » evutil_snprintf(line, sizeof(line), "%s: %s\r\n", 527 » » evbuffer_add_printf(evcon->output_buffer, "%s: %s\r\n",
531 header->key, header->value); 528 header->key, header->value);
532 evbuffer_add(evcon->output_buffer, line, strlen(line));
533 } 529 }
534 evbuffer_add(evcon->output_buffer, "\r\n", 2); 530 evbuffer_add(evcon->output_buffer, "\r\n", 2);
535 531
536 if (EVBUFFER_LENGTH(req->output_buffer) > 0) { 532 if (EVBUFFER_LENGTH(req->output_buffer) > 0) {
537 /* 533 /*
538 * For a request, we add the POST data, for a reply, this 534 * For a request, we add the POST data, for a reply, this
539 * is the regular data. 535 * is the regular data.
540 */ 536 */
541 evbuffer_add_buffer(evcon->output_buffer, req->output_buffer); 537 evbuffer_add_buffer(evcon->output_buffer, req->output_buffer);
542 } 538 }
(...skipping 276 matching lines...) Expand 10 before | Expand all | Expand 10 after
819 } 815 }
820 continue; 816 continue;
821 } 817 }
822 818
823 /* don't have enough to complete a chunk; wait for more */ 819 /* don't have enough to complete a chunk; wait for more */
824 if (len < req->ntoread) 820 if (len < req->ntoread)
825 return (MORE_DATA_EXPECTED); 821 return (MORE_DATA_EXPECTED);
826 822
827 /* Completed chunk */ 823 /* Completed chunk */
828 evbuffer_add(req->input_buffer, 824 evbuffer_add(req->input_buffer,
829 » » EVBUFFER_DATA(buf), req->ntoread); 825 » » EVBUFFER_DATA(buf), (size_t)req->ntoread);
830 » » evbuffer_drain(buf, req->ntoread); 826 » » evbuffer_drain(buf, (size_t)req->ntoread);
831 req->ntoread = -1; 827 req->ntoread = -1;
832 if (req->chunk_cb != NULL) { 828 if (req->chunk_cb != NULL) {
833 (*req->chunk_cb)(req, req->cb_arg); 829 (*req->chunk_cb)(req, req->cb_arg);
834 evbuffer_drain(req->input_buffer, 830 evbuffer_drain(req->input_buffer,
835 EVBUFFER_LENGTH(req->input_buffer)); 831 EVBUFFER_LENGTH(req->input_buffer));
836 } 832 }
837 } 833 }
838 834
839 return (MORE_DATA_EXPECTED); 835 return (MORE_DATA_EXPECTED);
840 } 836 }
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
884 case MORE_DATA_EXPECTED: 880 case MORE_DATA_EXPECTED:
885 default: 881 default:
886 break; 882 break;
887 } 883 }
888 } else if (req->ntoread < 0) { 884 } else if (req->ntoread < 0) {
889 /* Read until connection close. */ 885 /* Read until connection close. */
890 evbuffer_add_buffer(req->input_buffer, buf); 886 evbuffer_add_buffer(req->input_buffer, buf);
891 } else if (EVBUFFER_LENGTH(buf) >= req->ntoread) { 887 } else if (EVBUFFER_LENGTH(buf) >= req->ntoread) {
892 /* Completed content length */ 888 /* Completed content length */
893 evbuffer_add(req->input_buffer, EVBUFFER_DATA(buf), 889 evbuffer_add(req->input_buffer, EVBUFFER_DATA(buf),
894 » » req->ntoread); 890 » » (size_t)req->ntoread);
895 » » evbuffer_drain(buf, req->ntoread); 891 » » evbuffer_drain(buf, (size_t)req->ntoread);
896 req->ntoread = 0; 892 req->ntoread = 0;
897 evhttp_connection_done(evcon); 893 evhttp_connection_done(evcon);
898 return; 894 return;
899 } 895 }
900 /* Read more! */ 896 /* Read more! */
901 event_set(&evcon->ev, evcon->fd, EV_READ, evhttp_read, evcon); 897 event_set(&evcon->ev, evcon->fd, EV_READ, evhttp_read, evcon);
902 EVHTTP_BASE_SET(evcon, &evcon->ev); 898 EVHTTP_BASE_SET(evcon, &evcon->ev);
903 evhttp_add_event(&evcon->ev, evcon->timeout, HTTP_READ_TIMEOUT); 899 evhttp_add_event(&evcon->ev, evcon->timeout, HTTP_READ_TIMEOUT);
904 } 900 }
905 901
(...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after
1033 evhttp_connection_set_local_address(struct evhttp_connection *evcon, 1029 evhttp_connection_set_local_address(struct evhttp_connection *evcon,
1034 const char *address) 1030 const char *address)
1035 { 1031 {
1036 assert(evcon->state == EVCON_DISCONNECTED); 1032 assert(evcon->state == EVCON_DISCONNECTED);
1037 if (evcon->bind_address) 1033 if (evcon->bind_address)
1038 free(evcon->bind_address); 1034 free(evcon->bind_address);
1039 if ((evcon->bind_address = strdup(address)) == NULL) 1035 if ((evcon->bind_address = strdup(address)) == NULL)
1040 event_err(1, "%s: strdup", __func__); 1036 event_err(1, "%s: strdup", __func__);
1041 } 1037 }
1042 1038
1039 void
1040 evhttp_connection_set_local_port(struct evhttp_connection *evcon,
1041 unsigned short port)
1042 {
1043 assert(evcon->state == EVCON_DISCONNECTED);
1044 evcon->bind_port = port;
1045 }
1043 1046
1044 static void 1047 static void
1045 evhttp_request_dispatch(struct evhttp_connection* evcon) 1048 evhttp_request_dispatch(struct evhttp_connection* evcon)
1046 { 1049 {
1047 struct evhttp_request *req = TAILQ_FIRST(&evcon->requests); 1050 struct evhttp_request *req = TAILQ_FIRST(&evcon->requests);
1048 1051
1049 /* this should not usually happy but it's possible */ 1052 /* this should not usually happy but it's possible */
1050 if (req == NULL) 1053 if (req == NULL)
1051 return; 1054 return;
1052 1055
(...skipping 20 matching lines...) Expand all
1073 1076
1074 if (evcon->fd != -1) { 1077 if (evcon->fd != -1) {
1075 /* inform interested parties about connection close */ 1078 /* inform interested parties about connection close */
1076 if (evhttp_connected(evcon) && evcon->closecb != NULL) 1079 if (evhttp_connected(evcon) && evcon->closecb != NULL)
1077 (*evcon->closecb)(evcon, evcon->closecb_arg); 1080 (*evcon->closecb)(evcon, evcon->closecb_arg);
1078 1081
1079 EVUTIL_CLOSESOCKET(evcon->fd); 1082 EVUTIL_CLOSESOCKET(evcon->fd);
1080 evcon->fd = -1; 1083 evcon->fd = -1;
1081 } 1084 }
1082 evcon->state = EVCON_DISCONNECTED; 1085 evcon->state = EVCON_DISCONNECTED;
1086
1087 evbuffer_drain(evcon->input_buffer,
1088 EVBUFFER_LENGTH(evcon->input_buffer));
1089 evbuffer_drain(evcon->output_buffer,
1090 EVBUFFER_LENGTH(evcon->output_buffer));
1083 } 1091 }
1084 1092
1085 static void 1093 static void
1086 evhttp_detect_close_cb(int fd, short what, void *arg) 1094 evhttp_detect_close_cb(int fd, short what, void *arg)
1087 { 1095 {
1088 struct evhttp_connection *evcon = arg; 1096 struct evhttp_connection *evcon = arg;
1089 evhttp_connection_reset(evcon); 1097 evhttp_connection_reset(evcon);
1090 } 1098 }
1091 1099
1092 static void 1100 static void
(...skipping 252 matching lines...) Expand 10 before | Expand all | Expand 10 after
1345 1353
1346 /* Free and remove the header that we found */ 1354 /* Free and remove the header that we found */
1347 TAILQ_REMOVE(headers, header, next); 1355 TAILQ_REMOVE(headers, header, next);
1348 free(header->key); 1356 free(header->key);
1349 free(header->value); 1357 free(header->value);
1350 free(header); 1358 free(header);
1351 1359
1352 return (0); 1360 return (0);
1353 } 1361 }
1354 1362
1363 static int
1364 evhttp_header_is_valid_value(const char *value)
1365 {
1366 const char *p = value;
1367
1368 while ((p = strpbrk(p, "\r\n")) != NULL) {
1369 /* we really expect only one new line */
1370 p += strspn(p, "\r\n");
1371 /* we expect a space or tab for continuation */
1372 if (*p != ' ' && *p != '\t')
1373 return (0);
1374 }
1375 return (1);
1376 }
1377
1355 int 1378 int
1356 evhttp_add_header(struct evkeyvalq *headers, 1379 evhttp_add_header(struct evkeyvalq *headers,
1357 const char *key, const char *value) 1380 const char *key, const char *value)
1358 { 1381 {
1359 struct evkeyval *header = NULL;
1360
1361 event_debug(("%s: key: %s val: %s\n", __func__, key, value)); 1382 event_debug(("%s: key: %s val: %s\n", __func__, key, value));
1362 1383
1363 » if (strchr(value, '\r') != NULL || strchr(value, '\n') != NULL || 1384 » if (strchr(key, '\r') != NULL || strchr(key, '\n') != NULL) {
1364 » strchr(key, '\r') != NULL || strchr(key, '\n') != NULL) {
1365 /* drop illegal headers */ 1385 /* drop illegal headers */
1366 » » event_debug(("%s: dropping illegal header\n", __func__)); 1386 » » event_debug(("%s: dropping illegal header key\n", __func__));
1387 » » return (-1);
1388 » }
1389 »
1390 » if (!evhttp_header_is_valid_value(value)) {
1391 » » event_debug(("%s: dropping illegal header value\n", __func__));
1367 return (-1); 1392 return (-1);
1368 } 1393 }
1369 1394
1370 » header = calloc(1, sizeof(struct evkeyval)); 1395 » return (evhttp_add_header_internal(headers, key, value));
1396 }
1397
1398 static int
1399 evhttp_add_header_internal(struct evkeyvalq *headers,
1400 const char *key, const char *value)
1401 {
1402 » struct evkeyval *header = calloc(1, sizeof(struct evkeyval));
1371 if (header == NULL) { 1403 if (header == NULL) {
1372 event_warn("%s: calloc", __func__); 1404 event_warn("%s: calloc", __func__);
1373 return (-1); 1405 return (-1);
1374 } 1406 }
1375 if ((header->key = strdup(key)) == NULL) { 1407 if ((header->key = strdup(key)) == NULL) {
1376 free(header); 1408 free(header);
1377 event_warn("%s: strdup", __func__); 1409 event_warn("%s: strdup", __func__);
1378 return (-1); 1410 return (-1);
1379 } 1411 }
1380 if ((header->value = strdup(value)) == NULL) { 1412 if ((header->value = strdup(value)) == NULL) {
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after
1463 if (*line == '\0') { /* Last header - Done */ 1495 if (*line == '\0') { /* Last header - Done */
1464 status = ALL_DATA_READ; 1496 status = ALL_DATA_READ;
1465 free(line); 1497 free(line);
1466 break; 1498 break;
1467 } 1499 }
1468 1500
1469 /* Check if this is a continuation line */ 1501 /* Check if this is a continuation line */
1470 if (*line == ' ' || *line == '\t') { 1502 if (*line == ' ' || *line == '\t') {
1471 if (evhttp_append_to_last_header(headers, line) == -1) 1503 if (evhttp_append_to_last_header(headers, line) == -1)
1472 goto error; 1504 goto error;
1505 free(line);
1473 continue; 1506 continue;
1474 } 1507 }
1475 1508
1476 /* Processing of header lines */ 1509 /* Processing of header lines */
1477 svalue = line; 1510 svalue = line;
1478 skey = strsep(&svalue, ":"); 1511 skey = strsep(&svalue, ":");
1479 if (svalue == NULL) 1512 if (svalue == NULL)
1480 goto error; 1513 goto error;
1481 1514
1482 svalue += strspn(svalue, " "); 1515 svalue += strspn(svalue, " ");
(...skipping 243 matching lines...) Expand 10 before | Expand all | Expand 10 after
1726 evhttp_connection_connect(struct evhttp_connection *evcon) 1759 evhttp_connection_connect(struct evhttp_connection *evcon)
1727 { 1760 {
1728 if (evcon->state == EVCON_CONNECTING) 1761 if (evcon->state == EVCON_CONNECTING)
1729 return (0); 1762 return (0);
1730 1763
1731 evhttp_connection_reset(evcon); 1764 evhttp_connection_reset(evcon);
1732 1765
1733 assert(!(evcon->flags & EVHTTP_CON_INCOMING)); 1766 assert(!(evcon->flags & EVHTTP_CON_INCOMING));
1734 evcon->flags |= EVHTTP_CON_OUTGOING; 1767 evcon->flags |= EVHTTP_CON_OUTGOING;
1735 1768
1736 » evcon->fd = bind_socket(evcon->bind_address, 0 /*port*/, 0 /*reuse*/); 1769 » evcon->fd = bind_socket(
1770 » » evcon->bind_address, evcon->bind_port, 0 /*reuse*/);
1737 if (evcon->fd == -1) { 1771 if (evcon->fd == -1) {
1738 event_debug(("%s: failed to bind to \"%s\"", 1772 event_debug(("%s: failed to bind to \"%s\"",
1739 __func__, evcon->bind_address)); 1773 __func__, evcon->bind_address));
1740 return (-1); 1774 return (-1);
1741 } 1775 }
1742 1776
1743 if (socket_connect(evcon->fd, evcon->address, evcon->port) == -1) { 1777 if (socket_connect(evcon->fd, evcon->address, evcon->port) == -1) {
1744 EVUTIL_CLOSESOCKET(evcon->fd); evcon->fd = -1; 1778 EVUTIL_CLOSESOCKET(evcon->fd); evcon->fd = -1;
1745 return (-1); 1779 return (-1);
1746 } 1780 }
(...skipping 146 matching lines...) Expand 10 before | Expand all | Expand 10 after
1893 /* Adds headers to the response */ 1927 /* Adds headers to the response */
1894 evhttp_make_header(evcon, req); 1928 evhttp_make_header(evcon, req);
1895 1929
1896 evhttp_write_buffer(evcon, evhttp_send_done, NULL); 1930 evhttp_write_buffer(evcon, evhttp_send_done, NULL);
1897 } 1931 }
1898 1932
1899 void 1933 void
1900 evhttp_send_reply(struct evhttp_request *req, int code, const char *reason, 1934 evhttp_send_reply(struct evhttp_request *req, int code, const char *reason,
1901 struct evbuffer *databuf) 1935 struct evbuffer *databuf)
1902 { 1936 {
1903 /* set up to watch for client close */
1904 evhttp_connection_start_detectclose(req->evcon);
1905 evhttp_response_code(req, code, reason); 1937 evhttp_response_code(req, code, reason);
1906 1938
1907 evhttp_send(req, databuf); 1939 evhttp_send(req, databuf);
1908 } 1940 }
1909 1941
1910 void 1942 void
1911 evhttp_send_reply_start(struct evhttp_request *req, int code, 1943 evhttp_send_reply_start(struct evhttp_request *req, int code,
1912 const char *reason) 1944 const char *reason)
1913 { 1945 {
1914 /* set up to watch for client close */
1915 evhttp_connection_start_detectclose(req->evcon);
1916 evhttp_response_code(req, code, reason); 1946 evhttp_response_code(req, code, reason);
1917 if (req->major == 1 && req->minor == 1) { 1947 if (req->major == 1 && req->minor == 1) {
1918 /* use chunked encoding for HTTP/1.1 */ 1948 /* use chunked encoding for HTTP/1.1 */
1919 evhttp_add_header(req->output_headers, "Transfer-Encoding", 1949 evhttp_add_header(req->output_headers, "Transfer-Encoding",
1920 "chunked"); 1950 "chunked");
1921 req->chunked = 1; 1951 req->chunked = 1;
1922 } 1952 }
1923 evhttp_make_header(req->evcon, req); 1953 evhttp_make_header(req->evcon, req);
1924 evhttp_write_buffer(req->evcon, NULL, NULL); 1954 evhttp_write_buffer(req->evcon, NULL, NULL);
1925 } 1955 }
(...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after
2024 evbuffer_add_printf(buf, "%%%02X", (u_char)(*p)); 2054 evbuffer_add_printf(buf, "%%%02X", (u_char)(*p));
2025 } 2055 }
2026 } 2056 }
2027 evbuffer_add(buf, "", 1); 2057 evbuffer_add(buf, "", 1);
2028 p = strdup((char *)EVBUFFER_DATA(buf)); 2058 p = strdup((char *)EVBUFFER_DATA(buf));
2029 evbuffer_free(buf); 2059 evbuffer_free(buf);
2030 2060
2031 return (p); 2061 return (p);
2032 } 2062 }
2033 2063
2034 char * 2064 /*
2035 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 ?.
2067 */
2068 static int
2069 evhttp_decode_uri_internal(
2070 » const char *uri, size_t length, char *ret, int always_decode_plus)
2036 { 2071 {
2037 » char c, *ret; 2072 » char c;
2038 » int i, j, in_query = 0; 2073 » int i, j, in_query = always_decode_plus;
2039 »
2040 » ret = malloc(strlen(uri) + 1);
2041 » if (ret == NULL)
2042 » » event_err(1, "%s: malloc(%lu)", __func__,
2043 » » » (unsigned long)(strlen(uri) + 1));
2044 2074
2045 for (i = j = 0; uri[i] != '\0'; i++) { 2075 for (i = j = 0; uri[i] != '\0'; i++) {
2046 c = uri[i]; 2076 c = uri[i];
2047 if (c == '?') { 2077 if (c == '?') {
2048 in_query = 1; 2078 in_query = 1;
2049 } else if (c == '+' && in_query) { 2079 } else if (c == '+' && in_query) {
2050 c = ' '; 2080 c = ' ';
2051 } else if (c == '%' && isxdigit((unsigned char)uri[i+1]) && 2081 } else if (c == '%' && isxdigit((unsigned char)uri[i+1]) &&
2052 isxdigit((unsigned char)uri[i+2])) { 2082 isxdigit((unsigned char)uri[i+2])) {
2053 char tmp[] = { uri[i+1], uri[i+2], '\0' }; 2083 char tmp[] = { uri[i+1], uri[i+2], '\0' };
2054 c = (char)strtol(tmp, NULL, 16); 2084 c = (char)strtol(tmp, NULL, 16);
2055 i += 2; 2085 i += 2;
2056 } 2086 }
2057 ret[j++] = c; 2087 ret[j++] = c;
2058 } 2088 }
2059 ret[j] = '\0'; 2089 ret[j] = '\0';
2060 » 2090
2091 » return (j);
2092 }
2093
2094 char *
2095 evhttp_decode_uri(const char *uri)
2096 {
2097 » char *ret;
2098
2099 » if ((ret = malloc(strlen(uri) + 1)) == NULL)
2100 » » event_err(1, "%s: malloc(%lu)", __func__,
2101 » » » (unsigned long)(strlen(uri) + 1));
2102
2103 » evhttp_decode_uri_internal(uri, strlen(uri),
2104 » ret, 0 /*always_decode_plus*/);
2105
2061 return (ret); 2106 return (ret);
2062 } 2107 }
2063 2108
2064 /* 2109 /*
2065 * Helper function to parse out arguments in a query. 2110 * Helper function to parse out arguments in a query.
2066 * The arguments are separated by key and value. 2111 * The arguments are separated by key and value.
2067 * URI should already be decoded.
2068 */ 2112 */
2069 2113
2070 void 2114 void
2071 evhttp_parse_query(const char *uri, struct evkeyvalq *headers) 2115 evhttp_parse_query(const char *uri, struct evkeyvalq *headers)
2072 { 2116 {
2073 char *line; 2117 char *line;
2074 char *argument; 2118 char *argument;
2075 char *p; 2119 char *p;
2076 2120
2077 TAILQ_INIT(headers); 2121 TAILQ_INIT(headers);
2078 2122
2079 /* No arguments - we are done */ 2123 /* No arguments - we are done */
2080 if (strchr(uri, '?') == NULL) 2124 if (strchr(uri, '?') == NULL)
2081 return; 2125 return;
2082 2126
2083 if ((line = strdup(uri)) == NULL) 2127 if ((line = strdup(uri)) == NULL)
2084 event_err(1, "%s: strdup", __func__); 2128 event_err(1, "%s: strdup", __func__);
2085 2129
2086 2130
2087 argument = line; 2131 argument = line;
2088 2132
2089 /* We already know that there has to be a ? */ 2133 /* We already know that there has to be a ? */
2090 strsep(&argument, "?"); 2134 strsep(&argument, "?");
2091 2135
2092 p = argument; 2136 p = argument;
2093 while (p != NULL && *p != '\0') { 2137 while (p != NULL && *p != '\0') {
2094 » » char *key, *value; 2138 » » char *key, *value, *decoded_value;
2095 argument = strsep(&p, "&"); 2139 argument = strsep(&p, "&");
2096 2140
2097 value = argument; 2141 value = argument;
2098 key = strsep(&value, "="); 2142 key = strsep(&value, "=");
2099 if (value == NULL) 2143 if (value == NULL)
2100 goto error; 2144 goto error;
2101 2145
2102 » » value = evhttp_decode_uri(value); 2146 » » if ((decoded_value = malloc(strlen(value) + 1)) == NULL)
2103 » » event_debug(("Query Param: %s -> %s\n", key, value)); 2147 » » » event_err(1, "%s: malloc", __func__);
2104 » » evhttp_add_header(headers, key, value); 2148
2105 » » free(value); 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);
2106 } 2154 }
2107 2155
2108 error: 2156 error:
2109 free(line); 2157 free(line);
2110 } 2158 }
2111 2159
2112 static struct evhttp_cb * 2160 static struct evhttp_cb *
2113 evhttp_dispatch_callback(struct httpcbq *callbacks, struct evhttp_request *req) 2161 evhttp_dispatch_callback(struct httpcbq *callbacks, struct evhttp_request *req)
2114 { 2162 {
2115 struct evhttp_cb *cb; 2163 struct evhttp_cb *cb;
(...skipping 366 matching lines...) Expand 10 before | Expand all | Expand 10 after
2482 2530
2483 static struct evhttp_connection* 2531 static struct evhttp_connection*
2484 evhttp_get_request_connection( 2532 evhttp_get_request_connection(
2485 struct evhttp* http, 2533 struct evhttp* http,
2486 int fd, struct sockaddr *sa, socklen_t salen) 2534 int fd, struct sockaddr *sa, socklen_t salen)
2487 { 2535 {
2488 struct evhttp_connection *evcon; 2536 struct evhttp_connection *evcon;
2489 char *hostname = NULL, *portname = NULL; 2537 char *hostname = NULL, *portname = NULL;
2490 2538
2491 name_from_addr(sa, salen, &hostname, &portname); 2539 name_from_addr(sa, salen, &hostname, &portname);
2540 if (hostname == NULL || portname == NULL) {
2541 if (hostname) free(hostname);
2542 if (portname) free(portname);
2543 return (NULL);
2544 }
2545
2492 event_debug(("%s: new request from %s:%s on %d\n", 2546 event_debug(("%s: new request from %s:%s on %d\n",
2493 __func__, hostname, portname, fd)); 2547 __func__, hostname, portname, fd));
2494 2548
2495 /* we need a connection object to put the http request on */ 2549 /* we need a connection object to put the http request on */
2496 » if ((evcon = evhttp_connection_new(hostname, atoi(portname))) == NULL) 2550 » evcon = evhttp_connection_new(hostname, atoi(portname));
2551 » free(hostname);
2552 » free(portname);
2553 » if (evcon == NULL)
2497 return (NULL); 2554 return (NULL);
2498 2555
2499 /* associate the base if we have one*/ 2556 /* associate the base if we have one*/
2500 evhttp_connection_set_base(evcon, http->base); 2557 evhttp_connection_set_base(evcon, http->base);
2501 2558
2502 evcon->flags |= EVHTTP_CON_INCOMING; 2559 evcon->flags |= EVHTTP_CON_INCOMING;
2503 evcon->state = EVCON_READING_FIRSTLINE; 2560 evcon->state = EVCON_READING_FIRSTLINE;
2504 2561
2505 evcon->fd = fd; 2562 evcon->fd = fd;
2506 2563
(...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after
2608 event_errx(1, "getnameinfo failed: %s", gai_strerror(ni_ result)); 2665 event_errx(1, "getnameinfo failed: %s", gai_strerror(ni_ result));
2609 return; 2666 return;
2610 } 2667 }
2611 #else 2668 #else
2612 ni_result = fake_getnameinfo(sa, salen, 2669 ni_result = fake_getnameinfo(sa, salen,
2613 ntop, sizeof(ntop), strport, sizeof(strport), 2670 ntop, sizeof(ntop), strport, sizeof(strport),
2614 NI_NUMERICHOST|NI_NUMERICSERV); 2671 NI_NUMERICHOST|NI_NUMERICSERV);
2615 if (ni_result != 0) 2672 if (ni_result != 0)
2616 return; 2673 return;
2617 #endif 2674 #endif
2618 » *phost = ntop; 2675 » *phost = strdup(ntop);
2619 » *pport = strport; 2676 » *pport = strdup(strport);
2620 } 2677 }
2621 2678
2622 /* Either connect or bind */ 2679 /* Create a non-blocking socket and bind it */
2623 2680 /* todo: rename this function */
2624 static int 2681 static int
2625 bind_socket_ai(struct addrinfo *ai, int reuse) 2682 bind_socket_ai(struct addrinfo *ai, int reuse)
2626 { 2683 {
2627 int fd, on = 1, r; 2684 int fd, on = 1, r;
2628 int serrno; 2685 int serrno;
2629 2686
2630 /* Create listen socket */ 2687 /* Create listen socket */
2631 fd = socket(AF_INET, SOCK_STREAM, 0); 2688 fd = socket(AF_INET, SOCK_STREAM, 0);
2632 if (fd == -1) { 2689 if (fd == -1) {
2633 event_warn("socket"); 2690 event_warn("socket");
2634 return (-1); 2691 return (-1);
2635 } 2692 }
2636 2693
2637 if (evutil_make_socket_nonblocking(fd) < 0) 2694 if (evutil_make_socket_nonblocking(fd) < 0)
2638 goto out; 2695 goto out;
2639 2696
2640 #ifndef WIN32 2697 #ifndef WIN32
2641 if (fcntl(fd, F_SETFD, 1) == -1) { 2698 if (fcntl(fd, F_SETFD, 1) == -1) {
2642 event_warn("fcntl(F_SETFD)"); 2699 event_warn("fcntl(F_SETFD)");
2643 goto out; 2700 goto out;
2644 } 2701 }
2645 #endif 2702 #endif
2646 2703
2647 setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, (void *)&on, sizeof(on)); 2704 setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, (void *)&on, sizeof(on));
2648 if (reuse) { 2705 if (reuse) {
2649 setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, 2706 setsockopt(fd, SOL_SOCKET, SO_REUSEADDR,
2650 (void *)&on, sizeof(on)); 2707 (void *)&on, sizeof(on));
2651 } 2708 }
2652 2709
2653 » r = bind(fd, ai->ai_addr, ai->ai_addrlen); 2710 » if (ai != NULL) {
2654 » if (r == -1) 2711 » » r = bind(fd, ai->ai_addr, ai->ai_addrlen);
2655 » » goto out; 2712 » » if (r == -1)
2713 » » » goto out;
2714 » }
2656 2715
2657 return (fd); 2716 return (fd);
2658 2717
2659 out: 2718 out:
2660 serrno = EVUTIL_SOCKET_ERROR(); 2719 serrno = EVUTIL_SOCKET_ERROR();
2661 EVUTIL_CLOSESOCKET(fd); 2720 EVUTIL_CLOSESOCKET(fd);
2662 EVUTIL_SET_SOCKET_ERROR(serrno); 2721 EVUTIL_SET_SOCKET_ERROR(serrno);
2663 return (-1); 2722 return (-1);
2664 } 2723 }
2665 2724
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
2698 ((struct sockaddr_in *) aitop->ai_addr)->sin_port = htons(port); 2757 ((struct sockaddr_in *) aitop->ai_addr)->sin_port = htons(port);
2699 #endif 2758 #endif
2700 2759
2701 return (aitop); 2760 return (aitop);
2702 } 2761 }
2703 2762
2704 static int 2763 static int
2705 bind_socket(const char *address, u_short port, int reuse) 2764 bind_socket(const char *address, u_short port, int reuse)
2706 { 2765 {
2707 int fd; 2766 int fd;
2708 » struct addrinfo *aitop = make_addrinfo(address, port); 2767 » struct addrinfo *aitop = NULL;
2768
2769 » /* just create an unbound socket */
2770 » if (address == NULL && port == 0)
2771 » » return bind_socket_ai(NULL, 0);
2772 » »
2773 » aitop = make_addrinfo(address, port);
2709 2774
2710 if (aitop == NULL) 2775 if (aitop == NULL)
2711 return (-1); 2776 return (-1);
2712 2777
2713 fd = bind_socket_ai(aitop, reuse); 2778 fd = bind_socket_ai(aitop, reuse);
2714 2779
2715 #ifdef HAVE_GETADDRINFO 2780 #ifdef HAVE_GETADDRINFO
2716 freeaddrinfo(aitop); 2781 freeaddrinfo(aitop);
2717 #else 2782 #else
2718 fake_freeaddrinfo(aitop); 2783 fake_freeaddrinfo(aitop);
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
2752 2817
2753 out: 2818 out:
2754 #ifdef HAVE_GETADDRINFO 2819 #ifdef HAVE_GETADDRINFO
2755 freeaddrinfo(ai); 2820 freeaddrinfo(ai);
2756 #else 2821 #else
2757 fake_freeaddrinfo(ai); 2822 fake_freeaddrinfo(ai);
2758 #endif 2823 #endif
2759 2824
2760 return (res); 2825 return (res);
2761 } 2826 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698