00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00028 #include "internal.h"
00029 #include "connection.h"
00030 #include "memorypool.h"
00031 #include "response.h"
00032 #include "reason_phrase.h"
00033
00034 #ifndef LINUX
00035 #ifndef MSG_NOSIGNAL
00036 #define MSG_NOSIGNAL 0
00037 #endif
00038 #endif
00039
00040
00044 #define HTTP_100_CONTINUE "HTTP/1.1 100 Continue\r\n\r\n"
00045
00053 #if HAVE_MESSAGES
00054 #define REQUEST_TOO_BIG "<html><head><title>Request too big</title></head><body>Your HTTP header was too big for the memory constraints of this webserver.</body></html>"
00055 #else
00056 #define REQUEST_TOO_BIG ""
00057 #endif
00058
00066 #if HAVE_MESSAGES
00067 #define REQUEST_LACKS_HOST "<html><head><title>"Host:" header required</title></head><body>In HTTP 1.1, requests must include a "Host:" header, and your HTTP 1.1 request lacked such a header.</body></html>"
00068 #else
00069 #define REQUEST_LACKS_HOST ""
00070 #endif
00071
00079 #if HAVE_MESSAGES
00080 #define REQUEST_MALFORMED "<html><head><title>Request malformed</title></head><body>Your HTTP request was syntactically incorrect.</body></html>"
00081 #else
00082 #define REQUEST_MALFORMED ""
00083 #endif
00084
00091 #if HAVE_MESSAGES
00092 #define INTERNAL_ERROR "<html><head><title>Internal server error</title></head><body>Some programmer needs to study the manual more carefully.</body></html>"
00093 #else
00094 #define INTERNAL_ERROR ""
00095 #endif
00096
00097 #define EXTRA_CHECKS MHD_YES
00098
00099 #if EXTRA_CHECKS
00100 #define EXTRA_CHECK(a) if (!(a)) abort();
00101 #else
00102 #define EXTRA_CHECK(a)
00103 #endif
00104
00109 #define DEBUG_CLOSE MHD_NO
00110
00114 #define DEBUG_SEND_DATA MHD_NO
00115
00119 #define DEBUG_STATES MHD_NO
00120
00129 int
00130 MHD_get_connection_values (struct MHD_Connection *connection,
00131 enum MHD_ValueKind kind,
00132 MHD_KeyValueIterator iterator, void *iterator_cls)
00133 {
00134 int ret;
00135 struct MHD_HTTP_Header *pos;
00136
00137 if (connection == NULL)
00138 return -1;
00139 ret = 0;
00140 pos = connection->headers_received;
00141 while (pos != NULL)
00142 {
00143 if (0 != (pos->kind & kind))
00144 {
00145 ret++;
00146 if ((iterator != NULL) &&
00147 (MHD_YES != iterator (iterator_cls,
00148 kind, pos->header, pos->value)))
00149 return ret;
00150 }
00151 pos = pos->next;
00152 }
00153 return ret;
00154 }
00155
00163 const char *
00164 MHD_lookup_connection_value (struct MHD_Connection *connection,
00165 enum MHD_ValueKind kind, const char *key)
00166 {
00167 struct MHD_HTTP_Header *pos;
00168
00169 if (connection == NULL)
00170 return NULL;
00171 pos = connection->headers_received;
00172 while (pos != NULL)
00173 {
00174 if ((0 != (pos->kind & kind)) && (0 == strcasecmp (key, pos->header)))
00175 return pos->value;
00176 pos = pos->next;
00177 }
00178 return NULL;
00179 }
00180
00191 int
00192 MHD_queue_response (struct MHD_Connection *connection,
00193 unsigned int status_code, struct MHD_Response *response)
00194 {
00195 if ((connection == NULL) ||
00196 (response == NULL) ||
00197 (connection->response != NULL) ||
00198 ((connection->state != MHD_CONNECTION_HEADERS_PROCESSED) &&
00199 (connection->state != MHD_CONNECTION_FOOTERS_RECEIVED)))
00200 return MHD_NO;
00201 MHD_increment_response_rc (response);
00202 connection->response = response;
00203 connection->responseCode = status_code;
00204 if ((connection->method != NULL) &&
00205 (0 == strcasecmp (connection->method, MHD_HTTP_METHOD_HEAD)))
00206 {
00207
00208
00209 connection->response_write_position = response->total_size;
00210 }
00211 if ((response->total_size == -1) &&
00212 (0 == strcasecmp (connection->version, MHD_HTTP_VERSION_1_1)))
00213 connection->have_chunked_response = MHD_YES;
00214 else
00215 connection->have_chunked_response = MHD_NO;
00216 if (connection->state == MHD_CONNECTION_HEADERS_PROCESSED)
00217 {
00218
00219
00220
00221 SHUTDOWN (connection->socket_fd, SHUT_RD);
00222 connection->read_closed = MHD_YES;
00223 connection->state = MHD_CONNECTION_FOOTERS_RECEIVED;
00224 }
00225 return MHD_YES;
00226 }
00227
00232 static int
00233 need_100_continue (struct MHD_Connection *connection)
00234 {
00235 const char *expect;
00236
00237 return ((connection->response == NULL) &&
00238 (connection->version != NULL) &&
00239 (0 == strcasecmp (connection->version,
00240 MHD_HTTP_VERSION_1_1)) &&
00241 (NULL != (expect = MHD_lookup_connection_value (connection,
00242 MHD_HEADER_KIND,
00243 MHD_HTTP_HEADER_EXPECT)))
00244 && (0 == strcasecmp (expect, "100-continue"))
00245 && (connection->continue_message_write_offset <
00246 strlen (HTTP_100_CONTINUE)));
00247 }
00248
00253 static void
00254 connection_close_error (struct MHD_Connection *connection)
00255 {
00256 SHUTDOWN (connection->socket_fd, SHUT_RDWR);
00257 CLOSE (connection->socket_fd);
00258 connection->socket_fd = -1;
00259 connection->state = MHD_CONNECTION_CLOSED;
00260 if (connection->daemon->notify_completed != NULL)
00261 connection->daemon->notify_completed (connection->daemon->
00262 notify_completed_cls, connection,
00263 &connection->client_context,
00264 MHD_REQUEST_TERMINATED_WITH_ERROR);
00265 }
00266
00276 static int
00277 try_ready_normal_body (struct MHD_Connection *connection)
00278 {
00279 int ret;
00280 struct MHD_Response *response;
00281
00282 response = connection->response;
00283 if (response->crc == NULL)
00284 return MHD_YES;
00285 ret = response->crc (response->crc_cls,
00286 connection->response_write_position,
00287 response->data,
00288 MIN (response->data_buffer_size,
00289 response->total_size -
00290 connection->response_write_position));
00291 if (ret == -1)
00292 {
00293
00294
00295 #if DEBUG_CLOSE
00296 #if HAVE_MESSAGES
00297 MHD_DLOG (connection->daemon, "Closing connection (end of response)\n");
00298 #endif
00299 #endif
00300 response->total_size = connection->response_write_position;
00301 connection_close_error (connection);
00302 return MHD_NO;
00303 }
00304 response->data_start = connection->response_write_position;
00305 response->data_size = ret;
00306 if (ret == 0)
00307 return MHD_NO;
00308 return MHD_YES;
00309 }
00310
00320 static int
00321 try_ready_chunked_body (struct MHD_Connection *connection)
00322 {
00323 int ret;
00324 char *buf;
00325 struct MHD_Response *response;
00326 unsigned int size;
00327 char cbuf[9];
00328
00329 response = connection->response;
00330 if (connection->write_buffer_size == 0)
00331 {
00332 size = connection->daemon->pool_size;
00333 do
00334 {
00335 size /= 2;
00336 if (size < 128)
00337 {
00338
00339 #if DEBUG_CLOSE
00340 #if HAVE_MESSAGES
00341 MHD_DLOG (connection->daemon,
00342 "Closing connection (out of memory)\n");
00343 #endif
00344 #endif
00345 connection_close_error (connection);
00346 return MHD_NO;
00347 }
00348 buf = MHD_pool_allocate (connection->pool, size, MHD_NO);
00349 }
00350 while (buf == NULL);
00351 connection->write_buffer_size = size;
00352 connection->write_buffer = buf;
00353 }
00354
00355 ret = response->crc (response->crc_cls,
00356 connection->response_write_position,
00357 &connection->write_buffer[8],
00358 connection->write_buffer_size - 8 - 2);
00359 if (ret == -1)
00360 {
00361
00362 strcpy (connection->write_buffer, "0\r\n");
00363 connection->write_buffer_append_offset = 3;
00364 connection->write_buffer_send_offset = 0;
00365 response->total_size = connection->response_write_position;
00366 return MHD_YES;
00367 }
00368 if (ret == 0)
00369 {
00370 connection->state = MHD_CONNECTION_CHUNKED_BODY_UNREADY;
00371 return MHD_NO;
00372 }
00373 if (ret > 0xFFFFFF)
00374 ret = 0xFFFFFF;
00375 snprintf (cbuf, 8, "%X\r\n", ret);
00376 memcpy (&connection->write_buffer[8 - strlen (cbuf)], cbuf, strlen (cbuf));
00377 memcpy (&connection->write_buffer[8 + ret], "\r\n", 2);
00378 connection->response_write_position += ret;
00379 connection->write_buffer_send_offset = 8 - strlen (cbuf);
00380 connection->write_buffer_append_offset = 8 + ret + 2;
00381 return MHD_YES;
00382 }
00383
00388 static void
00389 add_extra_headers (struct MHD_Connection *connection)
00390 {
00391 const char *have;
00392 char buf[128];
00393
00394 connection->have_chunked_upload = MHD_NO;
00395 if (connection->response->total_size == -1)
00396 {
00397 have = MHD_get_response_header (connection->response,
00398 MHD_HTTP_HEADER_CONNECTION);
00399 if ((have == NULL) || (0 != strcasecmp (have, "close")))
00400 {
00401 if ((connection->version != NULL) &&
00402 (0 == strcasecmp (connection->version, MHD_HTTP_VERSION_1_1)))
00403 {
00404 connection->have_chunked_upload = MHD_YES;
00405 have = MHD_get_response_header (connection->response,
00406 MHD_HTTP_HEADER_TRANSFER_ENCODING);
00407 if (have == NULL)
00408 MHD_add_response_header (connection->response,
00409 MHD_HTTP_HEADER_TRANSFER_ENCODING,
00410 "chunked");
00411 }
00412 else
00413 {
00414 MHD_add_response_header (connection->response,
00415 MHD_HTTP_HEADER_CONNECTION, "close");
00416 }
00417 }
00418 }
00419 else if (NULL == MHD_get_response_header (connection->response,
00420 MHD_HTTP_HEADER_CONTENT_LENGTH))
00421 {
00422 _REAL_SNPRINTF (buf,
00423 128,
00424 "%llu",
00425 (unsigned long long) connection->response->total_size);
00426 MHD_add_response_header (connection->response,
00427 MHD_HTTP_HEADER_CONTENT_LENGTH, buf);
00428 }
00429 }
00430
00436 static void
00437 get_date_string (char *date, unsigned int max)
00438 {
00439 static const char *days[] =
00440 { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" };
00441 static const char *mons[] =
00442 { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct",
00443 "Nov", "Dec"
00444 };
00445 struct tm now;
00446 time_t t;
00447
00448 time (&t);
00449 gmtime_r (&t, &now);
00450 snprintf (date,
00451 max - 1,
00452 "Date: %3s, %02u %3s %04u %02u:%02u:%02u GMT\r\n",
00453 days[now.tm_wday % 7],
00454 now.tm_mday,
00455 mons[now.tm_mon % 12],
00456 1900 + now.tm_year, now.tm_hour, now.tm_min, now.tm_sec);
00457 }
00458
00463 static int
00464 try_grow_read_buffer (struct MHD_Connection *connection)
00465 {
00466 void *buf;
00467
00468 buf = MHD_pool_reallocate (connection->pool,
00469 connection->read_buffer,
00470 connection->read_buffer_size,
00471 connection->read_buffer_size * 2 +
00472 MHD_BUF_INC_SIZE + 1);
00473 if (buf == NULL)
00474 return MHD_NO;
00475
00476 connection->read_buffer = buf;
00477 connection->read_buffer_size =
00478 connection->read_buffer_size * 2 + MHD_BUF_INC_SIZE;
00479 return MHD_YES;
00480 }
00481
00488 static int
00489 build_header_response (struct MHD_Connection *connection)
00490 {
00491 size_t size;
00492 size_t off;
00493 struct MHD_HTTP_Header *pos;
00494 char code[128];
00495 char date[128];
00496 char *data;
00497 enum MHD_ValueKind kind;
00498 const char *reason_phrase;
00499
00500 if (connection->state == MHD_CONNECTION_FOOTERS_RECEIVED)
00501 {
00502 add_extra_headers (connection);
00503 reason_phrase = MHD_get_reason_phrase_for (connection->responseCode);
00504 _REAL_SNPRINTF (code, 128, "%s %u %s\r\n", MHD_HTTP_VERSION_1_1,
00505 connection->responseCode, reason_phrase);
00506 off = strlen (code);
00507
00508 size = off + 2;
00509 kind = MHD_HEADER_KIND;
00510 if (NULL == MHD_get_response_header (connection->response,
00511 MHD_HTTP_HEADER_DATE))
00512 get_date_string (date, sizeof (date));
00513 else
00514 date[0] = '\0';
00515 size += strlen (date);
00516 }
00517 else
00518 {
00519 size = 2;
00520 kind = MHD_FOOTER_KIND;
00521 off = 0;
00522 }
00523 pos = connection->response->first_header;
00524 while (pos != NULL)
00525 {
00526 if (pos->kind == kind)
00527 size += strlen (pos->header) + strlen (pos->value) + 4;
00528 pos = pos->next;
00529 }
00530
00531 data = MHD_pool_allocate (connection->pool, size + 1, MHD_YES);
00532 if (data == NULL)
00533 {
00534 #if HAVE_MESSAGES
00535 MHD_DLOG (connection->daemon, "Not enough memory for write!\n");
00536 #endif
00537 return MHD_NO;
00538 }
00539 if (connection->state == MHD_CONNECTION_FOOTERS_RECEIVED)
00540 {
00541 memcpy (data, code, off);
00542 }
00543 pos = connection->response->first_header;
00544 while (pos != NULL)
00545 {
00546 if (pos->kind == kind)
00547 {
00548 SPRINTF (&data[off], "%s: %s\r\n", pos->header, pos->value);
00549 off += strlen (pos->header) + strlen (pos->value) + 4;
00550 }
00551 pos = pos->next;
00552 }
00553 if (connection->state == MHD_CONNECTION_FOOTERS_RECEIVED)
00554 {
00555 strcpy (&data[off], date);
00556 off += strlen (date);
00557 }
00558 sprintf (&data[off], "\r\n");
00559 off += 2;
00560 if (off != size)
00561 abort ();
00562 connection->write_buffer = data;
00563 connection->write_buffer_append_offset = size;
00564 connection->write_buffer_send_offset = 0;
00565 connection->write_buffer_size = size + 1;
00566 return MHD_YES;
00567 }
00568
00576 static void
00577 transmit_error_response (struct MHD_Connection *connection,
00578 unsigned int status_code, const char *message)
00579 {
00580 struct MHD_Response *response;
00581
00582
00583 connection->state = MHD_CONNECTION_FOOTERS_RECEIVED;
00584 connection->read_closed = MHD_YES;
00585 #if HAVE_MESSAGES
00586 MHD_DLOG (connection->daemon,
00587 "Error %u (`%s') processing request, closing connection.\n",
00588 status_code, message);
00589 #endif
00590 response = MHD_create_response_from_data (strlen (message),
00591 (void *) message, MHD_NO, MHD_NO);
00592 MHD_queue_response (connection, status_code, response);
00593 EXTRA_CHECK (connection->response != NULL);
00594 MHD_destroy_response (response);
00595 if (MHD_NO == build_header_response (connection))
00596 {
00597
00598 #if HAVE_MESSAGES
00599 MHD_DLOG (connection->daemon,
00600 "Closing connection (failed to create response header)\n");
00601 #endif
00602 connection->state = MHD_CONNECTION_CLOSED;
00603 }
00604 else
00605 {
00606 connection->state = MHD_CONNECTION_HEADERS_SENDING;
00607 }
00608 }
00609
00614 static void
00615 do_fd_set (int fd, fd_set * set, int *max_fd)
00616 {
00617 FD_SET (fd, set);
00618 if (fd > *max_fd)
00619 *max_fd = fd;
00620 }
00621
00627 int
00628 MHD_connection_get_fdset (struct MHD_Connection *connection,
00629 fd_set * read_fd_set,
00630 fd_set * write_fd_set,
00631 fd_set * except_fd_set, int *max_fd)
00632 {
00633 int fd;
00634
00635 if (connection->pool == NULL)
00636 connection->pool = MHD_pool_create (connection->daemon->pool_size);
00637 if (connection->pool == NULL)
00638 {
00639 #if HAVE_MESSAGES
00640 MHD_DLOG (connection->daemon, "Failed to create memory pool!\n");
00641 #endif
00642 connection_close_error (connection);
00643 return MHD_NO;
00644 }
00645 fd = connection->socket_fd;
00646 if (fd == -1)
00647 return MHD_YES;
00648 while (1)
00649 {
00650 #if DEBUG_STATES
00651 fprintf (stderr, "`%s' in state %u\n", __FUNCTION__, connection->state);
00652 #endif
00653 switch (connection->state)
00654 {
00655 case MHD_CONNECTION_INIT:
00656 case MHD_CONNECTION_URL_RECEIVED:
00657 case MHD_CONNECTION_HEADER_PART_RECEIVED:
00658
00659
00660 if ((connection->read_closed) &&
00661 (connection->read_buffer_offset == 0))
00662 {
00663 connection->state = MHD_CONNECTION_CLOSED;
00664 continue;
00665 }
00666 if ((connection->read_buffer_offset == connection->read_buffer_size)
00667 && (MHD_NO == try_grow_read_buffer (connection)))
00668 {
00669 transmit_error_response (connection,
00670 (connection->url != NULL)
00671 ? MHD_HTTP_REQUEST_ENTITY_TOO_LARGE
00672 : MHD_HTTP_REQUEST_URI_TOO_LONG,
00673 REQUEST_TOO_BIG);
00674 continue;
00675 }
00676 if (MHD_NO == connection->read_closed)
00677 do_fd_set (fd, read_fd_set, max_fd);
00678 break;
00679 case MHD_CONNECTION_HEADERS_RECEIVED:
00680
00681 EXTRA_CHECK (0);
00682 break;
00683 case MHD_CONNECTION_HEADERS_PROCESSED:
00684 EXTRA_CHECK (0);
00685 break;
00686 case MHD_CONNECTION_CONTINUE_SENDING:
00687 do_fd_set (fd, write_fd_set, max_fd);
00688 break;
00689 case MHD_CONNECTION_CONTINUE_SENT:
00690 if (connection->read_buffer_offset == connection->read_buffer_size)
00691 {
00692 if ((MHD_YES != try_grow_read_buffer (connection)) &&
00693 (0 != (connection->daemon->options &
00694 (MHD_USE_SELECT_INTERNALLY |
00695 MHD_USE_THREAD_PER_CONNECTION))))
00696 {
00697
00698
00699
00700
00701
00702
00703
00704
00705
00706
00707
00708 transmit_error_response (connection,
00709 MHD_HTTP_INTERNAL_SERVER_ERROR,
00710 INTERNAL_ERROR);
00711 continue;
00712 }
00713 }
00714 if ((connection->read_buffer_offset < connection->read_buffer_size)
00715 && (MHD_NO == connection->read_closed))
00716 do_fd_set (fd, read_fd_set, max_fd);
00717 break;
00718 case MHD_CONNECTION_BODY_RECEIVED:
00719 case MHD_CONNECTION_FOOTER_PART_RECEIVED:
00720
00721
00722 if (MHD_YES == connection->read_closed)
00723 {
00724 connection->state = MHD_CONNECTION_CLOSED;
00725 continue;
00726 }
00727 do_fd_set (fd, read_fd_set, max_fd);
00728
00729
00730 break;
00731 case MHD_CONNECTION_FOOTERS_RECEIVED:
00732
00733
00734 break;
00735 case MHD_CONNECTION_HEADERS_SENDING:
00736
00737 do_fd_set (fd, write_fd_set, max_fd);
00738 break;
00739 case MHD_CONNECTION_HEADERS_SENT:
00740 EXTRA_CHECK (0);
00741 break;
00742 case MHD_CONNECTION_NORMAL_BODY_READY:
00743 do_fd_set (fd, write_fd_set, max_fd);
00744 break;
00745 case MHD_CONNECTION_NORMAL_BODY_UNREADY:
00746
00747 break;
00748 case MHD_CONNECTION_CHUNKED_BODY_READY:
00749 do_fd_set (fd, write_fd_set, max_fd);
00750 break;
00751 case MHD_CONNECTION_CHUNKED_BODY_UNREADY:
00752
00753 break;
00754 case MHD_CONNECTION_BODY_SENT:
00755 EXTRA_CHECK (0);
00756 break;
00757 case MHD_CONNECTION_FOOTERS_SENDING:
00758 do_fd_set (fd, write_fd_set, max_fd);
00759 break;
00760 case MHD_CONNECTION_FOOTERS_SENT:
00761 EXTRA_CHECK (0);
00762 break;
00763 case MHD_CONNECTION_CLOSED:
00764 if (connection->socket_fd != -1)
00765 connection_close_error (connection);
00766 return MHD_YES;
00767 default:
00768 EXTRA_CHECK (0);
00769 }
00770 break;
00771 }
00772 return MHD_YES;
00773 }
00774
00783 static char *
00784 get_next_header_line (struct MHD_Connection *connection)
00785 {
00786 char *rbuf;
00787 size_t pos;
00788
00789 if (connection->read_buffer_offset == 0)
00790 return NULL;
00791 pos = 0;
00792 rbuf = connection->read_buffer;
00793 while ((pos < connection->read_buffer_offset - 1) &&
00794 (rbuf[pos] != '\r') && (rbuf[pos] != '\n'))
00795 pos++;
00796 if (pos == connection->read_buffer_offset - 1)
00797 {
00798
00799 if (connection->read_buffer_offset == connection->read_buffer_size)
00800 {
00801 rbuf = MHD_pool_reallocate (connection->pool,
00802 connection->read_buffer,
00803 connection->read_buffer_size,
00804 connection->read_buffer_size * 2 +
00805 MHD_BUF_INC_SIZE);
00806 if (rbuf == NULL)
00807 {
00808 transmit_error_response (connection,
00809 (connection->url != NULL)
00810 ? MHD_HTTP_REQUEST_ENTITY_TOO_LARGE
00811 : MHD_HTTP_REQUEST_URI_TOO_LONG,
00812 REQUEST_TOO_BIG);
00813 }
00814 else
00815 {
00816 connection->read_buffer_size =
00817 connection->read_buffer_size * 2 + MHD_BUF_INC_SIZE;
00818 connection->read_buffer = rbuf;
00819 }
00820 }
00821 return NULL;
00822 }
00823
00824 if ((rbuf[pos] == '\r') && (rbuf[pos + 1] == '\n'))
00825 rbuf[pos++] = '\0';
00826 rbuf[pos++] = '\0';
00827 connection->read_buffer += pos;
00828 connection->read_buffer_size -= pos;
00829 connection->read_buffer_offset -= pos;
00830 return rbuf;
00831 }
00832
00836 static int
00837 connection_add_header (struct MHD_Connection *connection,
00838 char *key, char *value, enum MHD_ValueKind kind)
00839 {
00840 struct MHD_HTTP_Header *hdr;
00841
00842 hdr = MHD_pool_allocate (connection->pool,
00843 sizeof (struct MHD_HTTP_Header), MHD_YES);
00844 if (hdr == NULL)
00845 {
00846 #if HAVE_MESSAGES
00847 MHD_DLOG (connection->daemon,
00848 "Not enough memory to allocate header record!\n");
00849 #endif
00850 transmit_error_response (connection, MHD_HTTP_REQUEST_ENTITY_TOO_LARGE,
00851 REQUEST_TOO_BIG);
00852 return MHD_NO;
00853 }
00854 hdr->next = connection->headers_received;
00855 hdr->header = key;
00856 hdr->value = value;
00857 hdr->kind = kind;
00858 connection->headers_received = hdr;
00859 return MHD_YES;
00860 }
00861
00865 static int
00866 parse_arguments (enum MHD_ValueKind kind,
00867 struct MHD_Connection *connection, char *args)
00868 {
00869 char *equals;
00870 char *amper;
00871
00872 while (args != NULL)
00873 {
00874 equals = strstr (args, "=");
00875 if (equals == NULL)
00876 return MHD_NO;
00877 equals[0] = '\0';
00878 equals++;
00879 amper = strstr (equals, "&");
00880 if (amper != NULL)
00881 {
00882 amper[0] = '\0';
00883 amper++;
00884 }
00885 MHD_http_unescape (args);
00886 MHD_http_unescape (equals);
00887 if (MHD_NO == connection_add_header (connection, args, equals, kind))
00888 return MHD_NO;
00889 args = amper;
00890 }
00891 return MHD_YES;
00892 }
00893
00899 static int
00900 parse_cookie_header (struct MHD_Connection *connection)
00901 {
00902 const char *hdr;
00903 char *cpy;
00904 char *pos;
00905 char *semicolon;
00906 char *equals;
00907 int quotes;
00908
00909 hdr = MHD_lookup_connection_value (connection, MHD_HEADER_KIND, "Cookie");
00910 if (hdr == NULL)
00911 return MHD_YES;
00912 cpy = MHD_pool_allocate (connection->pool, strlen (hdr) + 1, MHD_YES);
00913 if (cpy == NULL)
00914 {
00915 #if HAVE_MESSAGES
00916 MHD_DLOG (connection->daemon, "Not enough memory to parse cookies!\n");
00917 #endif
00918 transmit_error_response (connection, MHD_HTTP_REQUEST_ENTITY_TOO_LARGE,
00919 REQUEST_TOO_BIG);
00920 return MHD_NO;
00921 }
00922 memcpy (cpy, hdr, strlen (hdr) + 1);
00923 pos = cpy;
00924 while (pos != NULL)
00925 {
00926 equals = strstr (pos, "=");
00927 if (equals == NULL)
00928 break;
00929 equals[0] = '\0';
00930 equals++;
00931 quotes = 0;
00932 semicolon = equals;
00933 while ((semicolon[0] != '\0') &&
00934 ((quotes != 0) ||
00935 ((semicolon[0] != ';') && (semicolon[0] != ','))))
00936 {
00937 if (semicolon[0] == '"')
00938 quotes = (quotes + 1) & 1;
00939 semicolon++;
00940 }
00941 if (semicolon[0] == '\0')
00942 semicolon = NULL;
00943 if (semicolon != NULL)
00944 {
00945 semicolon[0] = '\0';
00946 semicolon++;
00947 }
00948
00949 if ((equals[0] == '"') && (equals[strlen (equals) - 1] == '"'))
00950 {
00951 equals[strlen (equals) - 1] = '\0';
00952 equals++;
00953 }
00954 if (MHD_NO == connection_add_header (connection,
00955 pos, equals, MHD_COOKIE_KIND))
00956 return MHD_NO;
00957 pos = semicolon;
00958 }
00959 return MHD_YES;
00960 }
00961
00969 static int
00970 parse_initial_message_line (struct MHD_Connection *connection, char *line)
00971 {
00972 char *uri;
00973 char *httpVersion;
00974 char *args;
00975
00976 uri = strstr (line, " ");
00977 if (uri == NULL)
00978 return MHD_NO;
00979 uri[0] = '\0';
00980 connection->method = line;
00981 uri++;
00982 while (uri[0] == ' ')
00983 uri++;
00984 httpVersion = strstr (uri, " ");
00985 if (httpVersion != NULL)
00986 {
00987 httpVersion[0] = '\0';
00988 httpVersion++;
00989 }
00990 args = strstr (uri, "?");
00991 if (args != NULL)
00992 {
00993 args[0] = '\0';
00994 args++;
00995 parse_arguments (MHD_GET_ARGUMENT_KIND, connection, args);
00996 }
00997 connection->url = uri;
00998 if (httpVersion == NULL)
00999 connection->version = "";
01000 else
01001 connection->version = httpVersion;
01002 return MHD_YES;
01003 }
01004
01010 static void
01011 call_connection_handler (struct MHD_Connection *connection)
01012 {
01013 unsigned int processed;
01014 unsigned int available;
01015 unsigned int used;
01016 int instant_retry;
01017 unsigned int i;
01018 int malformed;
01019
01020 if (connection->response != NULL)
01021 return;
01022 do
01023 {
01024 instant_retry = MHD_NO;
01025 available = connection->read_buffer_offset;
01026 if ((connection->have_chunked_upload == MHD_YES) &&
01027 (connection->remaining_upload_size == -1))
01028 {
01029 if ((connection->current_chunk_offset ==
01030 connection->current_chunk_size)
01031 && (connection->current_chunk_offset != 0) && (available >= 2))
01032 {
01033
01034 i = 0;
01035 if ((connection->read_buffer[i] == '\r') ||
01036 (connection->read_buffer[i] == '\n'))
01037 i++;
01038 if ((connection->read_buffer[i] == '\r') ||
01039 (connection->read_buffer[i] == '\n'))
01040 i++;
01041 if (i == 0)
01042 {
01043
01044 #if HAVE_MESSAGES
01045 MHD_DLOG (connection->daemon,
01046 "Received malformed HTTP request (bad chunked encoding), closing connection.\n");
01047 #endif
01048 connection_close_error (connection);
01049 return;
01050 }
01051 connection->read_buffer_offset -= i;
01052 available -= i;
01053 memmove (connection->read_buffer,
01054 &connection->read_buffer[i], available);
01055 connection->current_chunk_offset = 0;
01056 connection->current_chunk_size = 0;
01057 }
01058 if (connection->current_chunk_offset <
01059 connection->current_chunk_size)
01060 {
01061
01062
01063
01064 processed =
01065 connection->current_chunk_size -
01066 connection->current_chunk_offset;
01067 if (processed > available)
01068 processed = available;
01069 available -= processed;
01070 if (available > 0)
01071 instant_retry = MHD_YES;
01072 }
01073 else
01074 {
01075
01076 i = 0;
01077 while (i < available)
01078 {
01079 if ((connection->read_buffer[i] == '\r') ||
01080 (connection->read_buffer[i] == '\n'))
01081 break;
01082 i++;
01083 if (i >= 6)
01084 break;
01085 }
01086 if (i >= available)
01087 return;
01088 malformed = (i >= 6);
01089 if (!malformed)
01090 {
01091 connection->read_buffer[i] = '\0';
01092 malformed = (1 != sscanf (connection->read_buffer,
01093 "%X",
01094 &connection->current_chunk_size))
01095 && (1 !=
01096 sscanf (connection->read_buffer, "%x",
01097 &connection->current_chunk_size));
01098 }
01099 if (malformed)
01100 {
01101
01102 #if HAVE_MESSAGES
01103 MHD_DLOG (connection->daemon,
01104 "Received malformed HTTP request (bad chunked encoding), closing connection.\n");
01105 #endif
01106 connection_close_error (connection);
01107 return;
01108 }
01109 i++;
01110 if ((connection->read_buffer[i] == '\r') ||
01111 (connection->read_buffer[i] == '\n'))
01112 i++;
01113 memmove (connection->read_buffer,
01114 &connection->read_buffer[i], available - i);
01115 connection->read_buffer_offset -= i;
01116 connection->current_chunk_offset = 0;
01117 instant_retry = MHD_YES;
01118 if (connection->current_chunk_size == 0)
01119 {
01120 connection->remaining_upload_size = 0;
01121 return;
01122 }
01123 continue;
01124 }
01125 }
01126 else
01127 {
01128
01129 processed = available;
01130 available = 0;
01131 }
01132 used = processed;
01133 if (MHD_NO ==
01134 connection->daemon->default_handler (connection->daemon->
01135 default_handler_cls,
01136 connection, connection->url,
01137 connection->method,
01138 connection->version,
01139 connection->read_buffer,
01140 &processed,
01141 &connection->client_context))
01142 {
01143
01144 #if HAVE_MESSAGES
01145 MHD_DLOG (connection->daemon,
01146 "Internal application error, closing connection.\n");
01147 #endif
01148 connection_close_error (connection);
01149 return;
01150 }
01151 if (processed > used)
01152 abort ();
01153 if (processed != 0)
01154 instant_retry = MHD_NO;
01155 used -= processed;
01156 if (connection->have_chunked_upload == MHD_YES)
01157 connection->current_chunk_offset += used;
01158
01159 if (used > 0)
01160 memmove (connection->read_buffer,
01161 &connection->read_buffer[used], processed + available);
01162 if (connection->remaining_upload_size != -1)
01163 connection->remaining_upload_size -= used;
01164 connection->read_buffer_offset = processed + available;
01165 }
01166 while (instant_retry == MHD_YES);
01167 }
01168
01177 static int
01178 do_read (struct MHD_Connection *connection)
01179 {
01180 int bytes_read;
01181
01182 if (connection->read_buffer_size == connection->read_buffer_offset)
01183 return MHD_NO;
01184 bytes_read = RECV (connection->socket_fd,
01185 &connection->read_buffer[connection->read_buffer_offset],
01186 connection->read_buffer_size -
01187 connection->read_buffer_offset, MSG_NOSIGNAL);
01188 if (bytes_read < 0)
01189 {
01190 if (errno == EINTR)
01191 return MHD_NO;
01192 #if HAVE_MESSAGES
01193 MHD_DLOG (connection->daemon,
01194 "Failed to receive data: %s\n", STRERROR (errno));
01195 #endif
01196 connection_close_error (connection);
01197 return MHD_YES;
01198 }
01199 if (bytes_read == 0)
01200 {
01201
01202 connection->read_closed = MHD_YES;
01203 SHUTDOWN (connection->socket_fd, SHUT_RD);
01204 return MHD_NO;
01205 }
01206 connection->read_buffer_offset += bytes_read;
01207 return MHD_YES;
01208 }
01209
01215 static int
01216 process_header_line (struct MHD_Connection *connection, char *line)
01217 {
01218 char *colon;
01219
01220
01221 colon = strstr (line, ":");
01222 if (colon == NULL)
01223 {
01224
01225 #if HAVE_MESSAGES
01226 MHD_DLOG (connection->daemon,
01227 "Received malformed line (no colon), closing connection.\n");
01228 #endif
01229 connection->state = MHD_CONNECTION_CLOSED;
01230 return MHD_NO;
01231 }
01232
01233 colon[0] = '\0';
01234 colon++;
01235 while ((colon[0] != '\0') && ((colon[0] == ' ') || (colon[0] == '\t')))
01236 colon++;
01237
01238
01239
01240
01241
01242 connection->last = line;
01243 connection->colon = colon;
01244 return MHD_YES;
01245 }
01246
01256 static int
01257 process_broken_line (struct MHD_Connection *connection,
01258 char *line, enum MHD_ValueKind kind)
01259 {
01260 char *last;
01261 char *tmp;
01262
01263 last = connection->last;
01264 if ((line[0] == ' ') || (line[0] == '\t'))
01265 {
01266
01267
01268 last = MHD_pool_reallocate (connection->pool,
01269 last,
01270 strlen (last) + 1,
01271 strlen (line) + strlen (last) + 1);
01272 if (last == NULL)
01273 {
01274 transmit_error_response (connection,
01275 MHD_HTTP_REQUEST_ENTITY_TOO_LARGE,
01276 REQUEST_TOO_BIG);
01277 return MHD_NO;
01278 }
01279 tmp = line;
01280 while ((tmp[0] == ' ') || (tmp[0] == '\t'))
01281 tmp++;
01282 strcat (last, tmp);
01283 connection->last = last;
01284 return MHD_YES;
01285 }
01286 EXTRA_CHECK ((last != NULL) && (connection->colon != NULL));
01287 if ((MHD_NO == connection_add_header (connection,
01288 last, connection->colon, kind)))
01289 {
01290 transmit_error_response (connection, MHD_HTTP_REQUEST_ENTITY_TOO_LARGE,
01291 REQUEST_TOO_BIG);
01292 return MHD_NO;
01293 }
01294
01295 if (strlen (line) != 0)
01296 {
01297 if (MHD_NO == process_header_line (connection, line))
01298 {
01299 transmit_error_response (connection,
01300 MHD_HTTP_BAD_REQUEST, REQUEST_MALFORMED);
01301 return MHD_NO;
01302 }
01303 }
01304 return MHD_YES;
01305 }
01306
01312 static void
01313 parse_connection_headers (struct MHD_Connection *connection)
01314 {
01315 const char *clen;
01316 unsigned long long cval;
01317 struct MHD_Response *response;
01318
01319 parse_cookie_header (connection);
01320 if ((0 != (MHD_USE_PEDANTIC_CHECKS & connection->daemon->options))
01321 && (NULL != connection->version)
01322 && (0 == strcasecmp (MHD_HTTP_VERSION_1_1, connection->version))
01323 && (NULL ==
01324 MHD_lookup_connection_value (connection, MHD_HEADER_KIND,
01325 MHD_HTTP_HEADER_HOST)))
01326 {
01327
01328 connection->state = MHD_CONNECTION_FOOTERS_RECEIVED;
01329 connection->read_closed = MHD_YES;
01330 #if HAVE_MESSAGES
01331 MHD_DLOG (connection->daemon,
01332 "Received `%s' request without `%s' header.\n",
01333 MHD_HTTP_VERSION_1_1, MHD_HTTP_HEADER_HOST);
01334 #endif
01335 response =
01336 MHD_create_response_from_data (strlen (REQUEST_LACKS_HOST),
01337 REQUEST_LACKS_HOST, MHD_NO, MHD_NO);
01338 MHD_queue_response (connection, MHD_HTTP_BAD_REQUEST, response);
01339 MHD_destroy_response (response);
01340 return;
01341 }
01342
01343 clen = MHD_lookup_connection_value (connection,
01344 MHD_HEADER_KIND,
01345 MHD_HTTP_HEADER_CONTENT_LENGTH);
01346 if (clen != NULL)
01347 {
01348 if (1 != sscanf (clen, "%llu", &cval))
01349 {
01350 #if HAVE_MESSAGES
01351 MHD_DLOG (connection->daemon,
01352 "Failed to parse `%s' header `%s', closing connection.\n",
01353 MHD_HTTP_HEADER_CONTENT_LENGTH, clen);
01354 #endif
01355 connection->state = MHD_CONNECTION_CLOSED;
01356 return;
01357 }
01358 connection->remaining_upload_size = cval;
01359 }
01360 else
01361 {
01362 if (NULL == MHD_lookup_connection_value (connection,
01363 MHD_HEADER_KIND,
01364 MHD_HTTP_HEADER_TRANSFER_ENCODING))
01365 {
01366
01367 connection->remaining_upload_size = 0;
01368 }
01369 else
01370 {
01371 connection->remaining_upload_size = -1;
01372 if (0 ==
01373 strcasecmp (MHD_lookup_connection_value
01374 (connection, MHD_HEADER_KIND,
01375 MHD_HTTP_HEADER_TRANSFER_ENCODING), "chunked"))
01376 connection->have_chunked_upload = MHD_YES;
01377 }
01378 }
01379 }
01380
01390 int
01391 MHD_connection_handle_read (struct MHD_Connection *connection)
01392 {
01393 connection->last_activity = time (NULL);
01394 if (connection->state == MHD_CONNECTION_CLOSED)
01395 return MHD_NO;
01396 if (MHD_NO == do_read (connection))
01397 return MHD_YES;
01398 while (1)
01399 {
01400 #if DEBUG_STATES
01401 fprintf (stderr, "`%s' in state %u\n", __FUNCTION__, connection->state);
01402 #endif
01403 switch (connection->state)
01404 {
01405 case MHD_CONNECTION_INIT:
01406 case MHD_CONNECTION_URL_RECEIVED:
01407 case MHD_CONNECTION_HEADER_PART_RECEIVED:
01408 case MHD_CONNECTION_HEADERS_RECEIVED:
01409 case MHD_CONNECTION_HEADERS_PROCESSED:
01410 case MHD_CONNECTION_CONTINUE_SENDING:
01411 case MHD_CONNECTION_CONTINUE_SENT:
01412 case MHD_CONNECTION_BODY_RECEIVED:
01413 case MHD_CONNECTION_FOOTER_PART_RECEIVED:
01414
01415 if (MHD_YES == connection->read_closed)
01416 {
01417 connection->state = MHD_CONNECTION_CLOSED;
01418 continue;
01419 }
01420 break;
01421 case MHD_CONNECTION_CLOSED:
01422 if (connection->socket_fd != -1)
01423 connection_close_error (connection);
01424 return MHD_NO;
01425 default:
01426
01427 MHD_pool_reallocate (connection->pool,
01428 connection->read_buffer,
01429 connection->read_buffer_size + 1,
01430 connection->read_buffer_offset);
01431 break;
01432 }
01433 break;
01434 }
01435 return MHD_YES;
01436 }
01437
01445 static int
01446 do_write (struct MHD_Connection *connection)
01447 {
01448 int ret;
01449
01450 ret = SEND (connection->socket_fd,
01451 &connection->write_buffer[connection->
01452 write_buffer_send_offset],
01453 connection->write_buffer_append_offset -
01454 connection->write_buffer_send_offset, MSG_NOSIGNAL);
01455 if (ret < 0)
01456 {
01457 if (errno == EINTR)
01458 return MHD_NO;
01459 #if HAVE_MESSAGES
01460 MHD_DLOG (connection->daemon,
01461 "Failed to send data: %s\n", STRERROR (errno));
01462 #endif
01463 connection_close_error (connection);
01464 return MHD_YES;
01465 }
01466 #if DEBUG_SEND_DATA
01467 fprintf (stderr,
01468 "Sent HEADER response: `%.*s'\n",
01469 ret,
01470 &connection->write_buffer[connection->write_buffer_send_offset]);
01471 #endif
01472 connection->write_buffer_send_offset += ret;
01473 return MHD_YES;
01474 }
01475
01481 static int
01482 check_write_done (struct MHD_Connection *connection,
01483 enum MHD_CONNECTION_STATE next_state)
01484 {
01485 if (connection->write_buffer_append_offset !=
01486 connection->write_buffer_send_offset)
01487 return MHD_NO;
01488 connection->write_buffer_append_offset = 0;
01489 connection->write_buffer_send_offset = 0;
01490 connection->state = next_state;
01491 MHD_pool_reallocate (connection->pool,
01492 connection->write_buffer,
01493 connection->write_buffer_size, 0);
01494 connection->write_buffer = NULL;
01495 connection->write_buffer_size = 0;
01496 return MHD_YES;
01497 }
01498
01508 int
01509 MHD_connection_handle_write (struct MHD_Connection *connection)
01510 {
01511 struct MHD_Response *response;
01512 int ret;
01513
01514 connection->last_activity = time (NULL);
01515 while (1)
01516 {
01517 #if DEBUG_STATES
01518 fprintf (stderr, "`%s' in state %u\n", __FUNCTION__, connection->state);
01519 #endif
01520 switch (connection->state)
01521 {
01522 case MHD_CONNECTION_INIT:
01523 case MHD_CONNECTION_URL_RECEIVED:
01524 case MHD_CONNECTION_HEADER_PART_RECEIVED:
01525 case MHD_CONNECTION_HEADERS_RECEIVED:
01526 EXTRA_CHECK (0);
01527 break;
01528 case MHD_CONNECTION_HEADERS_PROCESSED:
01529 break;
01530 case MHD_CONNECTION_CONTINUE_SENDING:
01531 ret = SEND (connection->socket_fd,
01532 &HTTP_100_CONTINUE[connection->
01533 continue_message_write_offset],
01534 strlen (HTTP_100_CONTINUE) -
01535 connection->continue_message_write_offset,
01536 MSG_NOSIGNAL);
01537 if (ret < 0)
01538 {
01539 if (errno == EINTR)
01540 break;
01541 #if HAVE_MESSAGES
01542 MHD_DLOG (connection->daemon,
01543 "Failed to send data: %s\n", STRERROR (errno));
01544 #endif
01545 connection_close_error (connection);
01546 return MHD_NO;
01547 }
01548 #if DEBUG_SEND_DATA
01549 fprintf (stderr,
01550 "Sent 100 continue response: `%.*s'\n",
01551 ret,
01552 &HTTP_100_CONTINUE[connection->
01553 continue_message_write_offset]);
01554 #endif
01555 connection->continue_message_write_offset += ret;
01556 break;
01557 case MHD_CONNECTION_CONTINUE_SENT:
01558 case MHD_CONNECTION_BODY_RECEIVED:
01559 case MHD_CONNECTION_FOOTER_PART_RECEIVED:
01560 case MHD_CONNECTION_FOOTERS_RECEIVED:
01561 EXTRA_CHECK (0);
01562 break;
01563 case MHD_CONNECTION_HEADERS_SENDING:
01564 do_write (connection);
01565 check_write_done (connection, MHD_CONNECTION_HEADERS_SENT);
01566 break;
01567 case MHD_CONNECTION_HEADERS_SENT:
01568 EXTRA_CHECK (0);
01569 break;
01570 case MHD_CONNECTION_NORMAL_BODY_READY:
01571 response = connection->response;
01572 if (response->crc != NULL)
01573 pthread_mutex_lock (&response->mutex);
01574 if (MHD_YES != try_ready_normal_body (connection))
01575 {
01576 if (response->crc != NULL)
01577 pthread_mutex_unlock (&response->mutex);
01578 connection->state = MHD_CONNECTION_NORMAL_BODY_UNREADY;
01579 break;
01580 }
01581 ret = SEND (connection->socket_fd,
01582 &response->data[connection->response_write_position -
01583 response->data_start],
01584 response->data_size -
01585 (connection->response_write_position -
01586 response->data_start), MSG_NOSIGNAL);
01587 #if DEBUG_SEND_DATA
01588 if (ret > 0)
01589 fprintf (stderr,
01590 "Sent DATA response: `%.*s'\n",
01591 ret,
01592 &response->data[connection->response_write_position -
01593 response->data_start]);
01594 #endif
01595 if (response->crc != NULL)
01596 pthread_mutex_unlock (&response->mutex);
01597 if (ret < 0)
01598 {
01599 if (errno == EINTR)
01600 return MHD_YES;
01601 #if HAVE_MESSAGES
01602 MHD_DLOG (connection->daemon,
01603 "Failed to send data: %s\n", STRERROR (errno));
01604 #endif
01605 connection_close_error (connection);
01606 return MHD_NO;
01607 }
01608 connection->response_write_position += ret;
01609 if (connection->response_write_position ==
01610 connection->response->total_size)
01611 connection->state = MHD_CONNECTION_FOOTERS_SENT;
01612 break;
01613 case MHD_CONNECTION_NORMAL_BODY_UNREADY:
01614 EXTRA_CHECK (0);
01615 break;
01616 case MHD_CONNECTION_CHUNKED_BODY_READY:
01617 do_write (connection);
01618 check_write_done (connection,
01619 (connection->response->total_size ==
01620 connection->
01621 response_write_position) ?
01622 MHD_CONNECTION_BODY_SENT :
01623 MHD_CONNECTION_CHUNKED_BODY_UNREADY);
01624 break;
01625 case MHD_CONNECTION_CHUNKED_BODY_UNREADY:
01626 case MHD_CONNECTION_BODY_SENT:
01627 EXTRA_CHECK (0);
01628 break;
01629 case MHD_CONNECTION_FOOTERS_SENDING:
01630 do_write (connection);
01631 check_write_done (connection, MHD_CONNECTION_FOOTERS_SENT);
01632 break;
01633 case MHD_CONNECTION_FOOTERS_SENT:
01634 EXTRA_CHECK (0);
01635 break;
01636 case MHD_CONNECTION_CLOSED:
01637 if (connection->socket_fd != -1)
01638 connection_close_error (connection);
01639 return MHD_NO;
01640 }
01641 break;
01642 }
01643 return MHD_YES;
01644 }
01645
01655 int
01656 MHD_connection_handle_idle (struct MHD_Connection *connection)
01657 {
01658 unsigned int timeout;
01659 const char *end;
01660 char *line;
01661
01662 while (1)
01663 {
01664 #if DEBUG_STATES
01665 fprintf (stderr, "`%s' in state %u\n", __FUNCTION__, connection->state);
01666 #endif
01667 switch (connection->state)
01668 {
01669 case MHD_CONNECTION_INIT:
01670 line = get_next_header_line (connection);
01671 if (line == NULL)
01672 {
01673 if (connection->state != MHD_CONNECTION_INIT)
01674 continue;
01675 if (connection->read_closed)
01676 {
01677 connection->state = MHD_CONNECTION_CLOSED;
01678 continue;
01679 }
01680 break;
01681 }
01682 if (MHD_NO == parse_initial_message_line (connection, line))
01683 connection->state = MHD_CONNECTION_CLOSED;
01684 else
01685 connection->state = MHD_CONNECTION_URL_RECEIVED;
01686 continue;
01687 case MHD_CONNECTION_URL_RECEIVED:
01688 line = get_next_header_line (connection);
01689 if (line == NULL)
01690 {
01691 if (connection->state != MHD_CONNECTION_URL_RECEIVED)
01692 continue;
01693 if (connection->read_closed)
01694 {
01695 connection->state = MHD_CONNECTION_CLOSED;
01696 continue;
01697 }
01698 break;
01699 }
01700 if (strlen (line) == 0)
01701 {
01702 connection->state = MHD_CONNECTION_HEADERS_RECEIVED;
01703 continue;
01704 }
01705 if (MHD_NO == process_header_line (connection, line))
01706 {
01707 transmit_error_response (connection,
01708 MHD_HTTP_BAD_REQUEST,
01709 REQUEST_MALFORMED);
01710 break;
01711 }
01712 connection->state = MHD_CONNECTION_HEADER_PART_RECEIVED;
01713 continue;
01714 case MHD_CONNECTION_HEADER_PART_RECEIVED:
01715 line = get_next_header_line (connection);
01716 if (line == NULL)
01717 {
01718 if (connection->state != MHD_CONNECTION_HEADER_PART_RECEIVED)
01719 continue;
01720 if (connection->read_closed)
01721 {
01722 connection->state = MHD_CONNECTION_CLOSED;
01723 continue;
01724 }
01725 break;
01726 }
01727 if (MHD_NO ==
01728 process_broken_line (connection, line, MHD_HEADER_KIND))
01729 continue;
01730 if (strlen (line) == 0)
01731 {
01732 connection->state = MHD_CONNECTION_HEADERS_RECEIVED;
01733 continue;
01734 }
01735 continue;
01736 case MHD_CONNECTION_HEADERS_RECEIVED:
01737 parse_connection_headers (connection);
01738 if (connection->state == MHD_CONNECTION_CLOSED)
01739 continue;
01740 connection->state = MHD_CONNECTION_HEADERS_PROCESSED;
01741 continue;
01742 case MHD_CONNECTION_HEADERS_PROCESSED:
01743 call_connection_handler (connection);
01744 if (connection->state == MHD_CONNECTION_CLOSED)
01745 continue;
01746 if (need_100_continue (connection))
01747 {
01748 connection->state = MHD_CONNECTION_CONTINUE_SENDING;
01749 break;
01750 }
01751 connection->state = (connection->remaining_upload_size == 0)
01752 ? MHD_CONNECTION_FOOTERS_RECEIVED : MHD_CONNECTION_CONTINUE_SENT;
01753 continue;
01754 case MHD_CONNECTION_CONTINUE_SENDING:
01755 if (connection->continue_message_write_offset ==
01756 strlen (HTTP_100_CONTINUE))
01757 {
01758 connection->state = MHD_CONNECTION_CONTINUE_SENT;
01759 continue;
01760 }
01761 break;
01762 case MHD_CONNECTION_CONTINUE_SENT:
01763 if (connection->read_buffer_offset != 0)
01764 {
01765 call_connection_handler (connection);
01766 if (connection->state == MHD_CONNECTION_CLOSED)
01767 continue;
01768 }
01769 if ((connection->remaining_upload_size == 0) ||
01770 ((connection->remaining_upload_size == -1) &&
01771 (connection->read_buffer_offset == 0) &&
01772 (MHD_YES == connection->read_closed)))
01773 {
01774 if ((MHD_YES == connection->have_chunked_upload) &&
01775 (MHD_NO == connection->read_closed))
01776 connection->state = MHD_CONNECTION_BODY_RECEIVED;
01777 else
01778 connection->state = MHD_CONNECTION_FOOTERS_RECEIVED;
01779 continue;
01780 }
01781 break;
01782 case MHD_CONNECTION_BODY_RECEIVED:
01783 line = get_next_header_line (connection);
01784 if (line == NULL)
01785 {
01786 if (connection->state != MHD_CONNECTION_BODY_RECEIVED)
01787 continue;
01788 if (connection->read_closed)
01789 {
01790 connection->state = MHD_CONNECTION_CLOSED;
01791 continue;
01792 }
01793 break;
01794 }
01795 if (strlen (line) == 0)
01796 {
01797 connection->state = MHD_CONNECTION_FOOTERS_RECEIVED;
01798 continue;
01799 }
01800 if (MHD_NO == process_header_line (connection, line))
01801 {
01802 transmit_error_response (connection,
01803 MHD_HTTP_BAD_REQUEST,
01804 REQUEST_MALFORMED);
01805 break;
01806 }
01807 connection->state = MHD_CONNECTION_FOOTER_PART_RECEIVED;
01808 continue;
01809 case MHD_CONNECTION_FOOTER_PART_RECEIVED:
01810 line = get_next_header_line (connection);
01811 if (line == NULL)
01812 {
01813 if (connection->state != MHD_CONNECTION_FOOTER_PART_RECEIVED)
01814 continue;
01815 if (connection->read_closed)
01816 {
01817 connection->state = MHD_CONNECTION_CLOSED;
01818 continue;
01819 }
01820 break;
01821 }
01822 if (MHD_NO ==
01823 process_broken_line (connection, line, MHD_FOOTER_KIND))
01824 continue;
01825 if (strlen (line) == 0)
01826 {
01827 connection->state = MHD_CONNECTION_FOOTERS_RECEIVED;
01828 continue;
01829 }
01830 continue;
01831 case MHD_CONNECTION_FOOTERS_RECEIVED:
01832 call_connection_handler (connection);
01833 if (connection->state == MHD_CONNECTION_CLOSED)
01834 continue;
01835 if (connection->response == NULL)
01836 break;
01837 if (MHD_NO == build_header_response (connection))
01838 {
01839
01840 #if HAVE_MESSAGES
01841 MHD_DLOG (connection->daemon,
01842 "Closing connection (failed to create response header)\n");
01843 #endif
01844 connection->state = MHD_CONNECTION_CLOSED;
01845 continue;
01846 }
01847 connection->state = MHD_CONNECTION_HEADERS_SENDING;
01848 break;
01849 case MHD_CONNECTION_HEADERS_SENDING:
01850
01851 break;
01852 case MHD_CONNECTION_HEADERS_SENT:
01853 if (connection->have_chunked_upload)
01854 connection->state = MHD_CONNECTION_CHUNKED_BODY_UNREADY;
01855 else
01856 connection->state = MHD_CONNECTION_NORMAL_BODY_UNREADY;
01857 continue;
01858 case MHD_CONNECTION_NORMAL_BODY_READY:
01859
01860 break;
01861 case MHD_CONNECTION_NORMAL_BODY_UNREADY:
01862 if (connection->response->crc != NULL)
01863 pthread_mutex_lock (&connection->response->mutex);
01864 if (MHD_YES == try_ready_normal_body (connection))
01865 {
01866 if (connection->response->crc != NULL)
01867 pthread_mutex_unlock (&connection->response->mutex);
01868 connection->state = MHD_CONNECTION_NORMAL_BODY_READY;
01869 break;
01870 }
01871 if (connection->response->crc != NULL)
01872 pthread_mutex_unlock (&connection->response->mutex);
01873
01874 break;
01875 case MHD_CONNECTION_CHUNKED_BODY_READY:
01876
01877 break;
01878 case MHD_CONNECTION_CHUNKED_BODY_UNREADY:
01879 if (connection->response->crc != NULL)
01880 pthread_mutex_lock (&connection->response->mutex);
01881 if (MHD_YES == try_ready_chunked_body (connection))
01882 {
01883 if (connection->response->crc != NULL)
01884 pthread_mutex_unlock (&connection->response->mutex);
01885 connection->state = MHD_CONNECTION_CHUNKED_BODY_READY;
01886 continue;
01887 }
01888 if (connection->response->crc != NULL)
01889 pthread_mutex_unlock (&connection->response->mutex);
01890 break;
01891 case MHD_CONNECTION_BODY_SENT:
01892 build_header_response (connection);
01893 if (connection->write_buffer_send_offset ==
01894 connection->write_buffer_append_offset)
01895 connection->state = MHD_CONNECTION_FOOTERS_SENT;
01896 else
01897 connection->state = MHD_CONNECTION_FOOTERS_SENDING;
01898 continue;
01899 case MHD_CONNECTION_FOOTERS_SENDING:
01900
01901 break;
01902 case MHD_CONNECTION_FOOTERS_SENT:
01903 MHD_destroy_response (connection->response);
01904 if (connection->daemon->notify_completed != NULL)
01905 connection->daemon->notify_completed (connection->daemon->
01906 notify_completed_cls,
01907 connection,
01908 &connection->client_context,
01909 MHD_REQUEST_TERMINATED_COMPLETED_OK);
01910 end = MHD_lookup_connection_value (connection,
01911 MHD_HEADER_KIND,
01912 MHD_HTTP_HEADER_CONNECTION);
01913 connection->client_context = NULL;
01914 connection->continue_message_write_offset = 0;
01915 connection->responseCode = 0;
01916 connection->response = NULL;
01917 connection->headers_received = NULL;
01918 connection->response_write_position = 0;
01919 connection->have_chunked_upload = MHD_NO;
01920 connection->method = NULL;
01921 connection->url = NULL;
01922 connection->write_buffer = NULL;
01923 connection->write_buffer_size = 0;
01924 connection->write_buffer_send_offset = 0;
01925 connection->write_buffer_append_offset = 0;
01926 if ((end != NULL) && (0 == strcasecmp (end, "close")))
01927 {
01928 connection->read_closed = MHD_YES;
01929 connection->read_buffer_offset = 0;
01930 }
01931 if (((MHD_YES == connection->read_closed) &&
01932 (0 == connection->read_buffer_offset)) ||
01933 (connection->version == NULL) ||
01934 (0 != strcasecmp (MHD_HTTP_VERSION_1_1, connection->version)))
01935 {
01936
01937 connection->state = MHD_CONNECTION_CLOSED;
01938 MHD_pool_destroy (connection->pool);
01939 connection->pool = NULL;
01940 connection->read_buffer = NULL;
01941 connection->read_buffer_size = 0;
01942 connection->read_buffer_offset = 0;
01943 }
01944 else
01945 {
01946 connection->version = NULL;
01947 connection->state = MHD_CONNECTION_INIT;
01948 connection->read_buffer
01949 = MHD_pool_reset (connection->pool,
01950 connection->read_buffer,
01951 connection->read_buffer_size);
01952 }
01953 continue;
01954 case MHD_CONNECTION_CLOSED:
01955 if (connection->socket_fd != -1)
01956 connection_close_error (connection);
01957 break;
01958 default:
01959 EXTRA_CHECK (0);
01960 break;
01961 }
01962 break;
01963 }
01964 timeout = connection->daemon->connection_timeout;
01965 if ((connection->socket_fd != -1) &&
01966 (timeout != 0) && (time (NULL) - timeout > connection->last_activity))
01967 {
01968 connection_close_error (connection);
01969 return MHD_NO;
01970 }
01971 return MHD_YES;
01972
01973 }
01974
01975