OLD | NEW |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 } |
OLD | NEW |