| 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 |