connection.c

Go to the documentation of this file.
00001 /*
00002      This file is part of libmicrohttpd
00003      (C) 2007, 2008 Daniel Pittman and Christian Grothoff
00004 
00005      This library is free software; you can redistribute it and/or
00006      modify it under the terms of the GNU Lesser General Public
00007      License as published by the Free Software Foundation; either
00008      version 2.1 of the License, or (at your option) any later version.
00009 
00010      This library is distributed in the hope that it will be useful,
00011      but WITHOUT ANY WARRANTY; without even the implied warranty of
00012      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013      Lesser General Public License for more details.
00014 
00015      You should have received a copy of the GNU Lesser General Public
00016      License along with this library; if not, write to the Free Software
00017      Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
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 #if HAVE_NETINET_TCP_H
00035 /* for TCP_CORK */
00036 #include <netinet/tcp.h>
00037 #endif
00038 
00042 #define HTTP_100_CONTINUE "HTTP/1.1 100 Continue\r\n\r\n"
00043 
00051 #if HAVE_MESSAGES
00052 #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>"
00053 #else
00054 #define REQUEST_TOO_BIG ""
00055 #endif
00056 
00064 #if HAVE_MESSAGES
00065 #define REQUEST_LACKS_HOST "<html><head><title>&quot;Host:&quot; header required</title></head><body>In HTTP 1.1, requests must include a &quot;Host:&quot; header, and your HTTP 1.1 request lacked such a header.</body></html>"
00066 #else
00067 #define REQUEST_LACKS_HOST ""
00068 #endif
00069 
00077 #if HAVE_MESSAGES
00078 #define REQUEST_MALFORMED "<html><head><title>Request malformed</title></head><body>Your HTTP request was syntactically incorrect.</body></html>"
00079 #else
00080 #define REQUEST_MALFORMED ""
00081 #endif
00082 
00089 #if HAVE_MESSAGES
00090 #define INTERNAL_ERROR "<html><head><title>Internal server error</title></head><body>Some programmer needs to study the manual more carefully.</body></html>"
00091 #else
00092 #define INTERNAL_ERROR ""
00093 #endif
00094 
00099 #define DEBUG_CLOSE MHD_NO
00100 
00104 #define DEBUG_SEND_DATA MHD_NO
00105 
00114 int
00115 MHD_get_connection_values (struct MHD_Connection *connection,
00116                            enum MHD_ValueKind kind,
00117                            MHD_KeyValueIterator iterator, void *iterator_cls)
00118 {
00119   int ret;
00120   struct MHD_HTTP_Header *pos;
00121 
00122   if (connection == NULL)
00123     return -1;
00124   ret = 0;
00125   pos = connection->headers_received;
00126   while (pos != NULL)
00127     {
00128       if (0 != (pos->kind & kind))
00129         {
00130           ret++;
00131           if ((iterator != NULL) &&
00132               (MHD_YES != iterator (iterator_cls,
00133                                     kind, pos->header, pos->value)))
00134             return ret;
00135         }
00136       pos = pos->next;
00137     }
00138   return ret;
00139 }
00140 
00170 int
00171 MHD_set_connection_value (struct MHD_Connection *connection,
00172                           enum MHD_ValueKind kind,
00173                           const char *key, const char *value)
00174 {
00175   struct MHD_HTTP_Header *pos;
00176 
00177   pos = MHD_pool_allocate (connection->pool,
00178                            sizeof (struct MHD_HTTP_Header), MHD_NO);
00179   if (pos == NULL)
00180     return MHD_NO;
00181   pos->header = (char *) key;
00182   pos->value = (char *) value;
00183   pos->kind = kind;
00184   pos->next = connection->headers_received;
00185   connection->headers_received = pos;
00186   return MHD_YES;
00187 }
00188 
00196 const char *
00197 MHD_lookup_connection_value (struct MHD_Connection *connection,
00198                              enum MHD_ValueKind kind, const char *key)
00199 {
00200   struct MHD_HTTP_Header *pos;
00201 
00202   if (connection == NULL)
00203     return NULL;
00204   pos = connection->headers_received;
00205   while (pos != NULL)
00206     {
00207       if ((0 != (pos->kind & kind)) && (0 == strcasecmp (key, pos->header)))
00208         return pos->value;
00209       pos = pos->next;
00210     }
00211   return NULL;
00212 }
00213 
00224 int
00225 MHD_queue_response (struct MHD_Connection *connection,
00226                     unsigned int status_code, struct MHD_Response *response)
00227 {
00228   if ((connection == NULL) ||
00229       (response == NULL) ||
00230       (connection->response != NULL) ||
00231       ((connection->state != MHD_CONNECTION_HEADERS_PROCESSED) &&
00232        (connection->state != MHD_CONNECTION_FOOTERS_RECEIVED)))
00233     return MHD_NO;
00234   MHD_increment_response_rc (response);
00235   connection->response = response;
00236   connection->responseCode = status_code;
00237   if ((connection->method != NULL) &&
00238       (0 == strcasecmp (connection->method, MHD_HTTP_METHOD_HEAD)))
00239     {
00240       /* if this is a "HEAD" request, pretend that we
00241          have already sent the full message body */
00242       connection->response_write_position = response->total_size;
00243     }
00244   if ((response->total_size == MHD_SIZE_UNKNOWN) &&
00245       (0 == strcasecmp (connection->version, MHD_HTTP_VERSION_1_1)))
00246     connection->have_chunked_response = MHD_YES;
00247   else
00248     connection->have_chunked_response = MHD_NO;
00249   if (connection->state == MHD_CONNECTION_HEADERS_PROCESSED)
00250     {
00251       /* response was queued "early",
00252          refuse to read body / footers or further
00253          requests! */
00254       SHUTDOWN (connection->socket_fd, SHUT_RD);
00255       connection->read_closed = MHD_YES;
00256       connection->state = MHD_CONNECTION_FOOTERS_RECEIVED;
00257     }
00258   return MHD_YES;
00259 }
00260 
00265 static int
00266 need_100_continue (struct MHD_Connection *connection)
00267 {
00268   const char *expect;
00269 
00270   return ((connection->response == NULL) &&
00271           (connection->version != NULL) &&
00272           (0 == strcasecmp (connection->version,
00273                             MHD_HTTP_VERSION_1_1)) &&
00274           (NULL != (expect = MHD_lookup_connection_value (connection,
00275                                                           MHD_HEADER_KIND,
00276                                                           MHD_HTTP_HEADER_EXPECT)))
00277           && (0 == strcasecmp (expect, "100-continue"))
00278           && (connection->continue_message_write_offset <
00279               strlen (HTTP_100_CONTINUE)));
00280 }
00281 
00286 void
00287 MHD_connection_close (struct MHD_Connection *connection,
00288                       enum MHD_RequestTerminationCode termination_code)
00289 {
00290   SHUTDOWN (connection->socket_fd, SHUT_RDWR);
00291   CLOSE (connection->socket_fd);
00292   connection->socket_fd = -1;
00293   connection->state = MHD_CONNECTION_CLOSED;
00294   if ( (NULL != connection->daemon->notify_completed) &&
00295        (MHD_YES == connection->client_aware) )
00296     connection->daemon->notify_completed (connection->daemon->
00297                                           notify_completed_cls, connection,
00298                                           &connection->client_context,
00299                                           termination_code);
00300   connection->client_aware = MHD_NO;
00301 }
00302 
00307 static void
00308 connection_close_error (struct MHD_Connection *connection)
00309 {
00310   MHD_connection_close (connection, MHD_REQUEST_TERMINATED_WITH_ERROR);
00311 }
00312 
00322 static int
00323 try_ready_normal_body (struct MHD_Connection *connection)
00324 {
00325   int ret;
00326   struct MHD_Response *response;
00327 
00328   response = connection->response;
00329   if (response->crc == NULL)
00330     return MHD_YES;
00331   if ( (response->data_start <=
00332         connection->response_write_position) &&
00333        (response->data_size + response->data_start >
00334         connection->response_write_position) )
00335     return MHD_YES; /* response already ready */
00336   ret = response->crc (response->crc_cls,
00337                        connection->response_write_position,
00338                        response->data,
00339                        MHD_MIN (response->data_buffer_size,
00340                                 response->total_size -
00341                                 connection->response_write_position));
00342   if ((ret == 0) &&
00343       (0 != (connection->daemon->options & MHD_USE_SELECT_INTERNALLY)))
00344     mhd_panic (mhd_panic_cls, __FILE__, __LINE__, 
00345 #if HAVE_MESSAGES
00346                "API violation"
00347 #else
00348                NULL
00349 #endif
00350                );
00351   if (ret == -1)
00352     {
00353       /* either error or http 1.0 transfer, close
00354          socket! */
00355 #if DEBUG_CLOSE
00356 #if HAVE_MESSAGES
00357       MHD_DLOG (connection->daemon, "Closing connection (end of response)\n");
00358 #endif
00359 #endif
00360       response->total_size = connection->response_write_position;
00361       connection_close_error (connection);
00362       return MHD_NO;
00363     }
00364   response->data_start = connection->response_write_position;
00365   response->data_size = ret;
00366   if (ret == 0)
00367     return MHD_NO;
00368   return MHD_YES;
00369 }
00370 
00380 static int
00381 try_ready_chunked_body (struct MHD_Connection *connection)
00382 {
00383   int ret;
00384   char *buf;
00385   struct MHD_Response *response;
00386   size_t size;
00387   char cbuf[10];                /* 10: max strlen of "%x\r\n" */
00388   int cblen;
00389 
00390   response = connection->response;
00391   if (connection->write_buffer_size == 0)
00392     {
00393       size = connection->daemon->pool_size;
00394       do
00395         {
00396           size /= 2;
00397           if (size < 128)
00398             {
00399               /* not enough memory */
00400 #if DEBUG_CLOSE
00401 #if HAVE_MESSAGES
00402               MHD_DLOG (connection->daemon,
00403                         "Closing connection (out of memory)\n");
00404 #endif
00405 #endif
00406               connection_close_error (connection);
00407               return MHD_NO;
00408             }
00409           buf = MHD_pool_allocate (connection->pool, size, MHD_NO);
00410         }
00411       while (buf == NULL);
00412       connection->write_buffer_size = size;
00413       connection->write_buffer = buf;
00414     }
00415 
00416   if ( (response->data_start <=
00417         connection->response_write_position) &&
00418        (response->data_size + response->data_start >
00419         connection->response_write_position) )
00420     {
00421       /* buffer already ready, use what is there for the chunk */
00422       ret = response->data_size + response->data_start - connection->response_write_position;
00423       if (ret > connection->write_buffer_size - sizeof (cbuf) - 2)
00424         ret = connection->write_buffer_size - sizeof (cbuf) - 2;
00425       memcpy (&connection->write_buffer[sizeof (cbuf)],
00426               &response->data[connection->response_write_position - response->data_start],
00427               ret);
00428     }
00429   else
00430     {
00431       /* buffer not in range, try to fill it */
00432       ret = response->crc (response->crc_cls,
00433                            connection->response_write_position,
00434                            &connection->write_buffer[sizeof (cbuf)],
00435                            connection->write_buffer_size - sizeof (cbuf) - 2);
00436     }
00437   if (ret == -1)
00438     {
00439       /* end of message, signal other side! */
00440       strcpy (connection->write_buffer, "0\r\n");
00441       connection->write_buffer_append_offset = 3;
00442       connection->write_buffer_send_offset = 0;
00443       response->total_size = connection->response_write_position;
00444       return MHD_YES;
00445     }
00446   if (ret == 0)
00447     {
00448       connection->state = MHD_CONNECTION_CHUNKED_BODY_UNREADY;
00449       return MHD_NO;
00450     }
00451   if (ret > 0xFFFFFF)
00452     ret = 0xFFFFFF;
00453   SPRINTF (cbuf, "%X\r\n", ret);
00454   cblen = strlen (cbuf);
00455   EXTRA_CHECK (cblen <= sizeof (cbuf));
00456   memcpy (&connection->write_buffer[sizeof (cbuf) - cblen], cbuf, cblen);
00457   memcpy (&connection->write_buffer[sizeof (cbuf) + ret], "\r\n", 2);
00458   connection->response_write_position += ret;
00459   connection->write_buffer_send_offset = sizeof (cbuf) - cblen;
00460   connection->write_buffer_append_offset = sizeof (cbuf) + ret + 2;
00461   return MHD_YES;
00462 }
00463 
00468 static void
00469 add_extra_headers (struct MHD_Connection *connection)
00470 {
00471   const char *have;
00472   char buf[128];
00473 
00474   connection->have_chunked_upload = MHD_NO;
00475   if (connection->response->total_size == MHD_SIZE_UNKNOWN)
00476     {
00477       have = MHD_get_response_header (connection->response,
00478                                       MHD_HTTP_HEADER_CONNECTION);
00479       if ((have == NULL) || (0 != strcasecmp (have, "close")))
00480         {
00481           if ((connection->version != NULL) &&
00482               (0 == strcasecmp (connection->version, MHD_HTTP_VERSION_1_1)))
00483             {
00484               connection->have_chunked_upload = MHD_YES;
00485               have = MHD_get_response_header (connection->response,
00486                                               MHD_HTTP_HEADER_TRANSFER_ENCODING);
00487               if (have == NULL)
00488                 MHD_add_response_header (connection->response,
00489                                          MHD_HTTP_HEADER_TRANSFER_ENCODING,
00490                                          "chunked");
00491             }
00492           else
00493             {
00494               MHD_add_response_header (connection->response,
00495                                        MHD_HTTP_HEADER_CONNECTION, "close");
00496             }
00497         }
00498     }
00499   else if (NULL == MHD_get_response_header (connection->response,
00500                                             MHD_HTTP_HEADER_CONTENT_LENGTH))
00501     {
00502       SPRINTF (buf,
00503                "%llu",
00504                (unsigned long long)connection->response->total_size);
00505       MHD_add_response_header (connection->response,
00506                                MHD_HTTP_HEADER_CONTENT_LENGTH, buf);
00507     }
00508 }
00509 
00516 static void
00517 get_date_string (char *date)
00518 {
00519   static const char *days[] =
00520     { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" };
00521   static const char *mons[] =
00522     { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct",
00523     "Nov", "Dec"
00524   };
00525   struct tm now;
00526   time_t t;
00527 
00528   time (&t);
00529   gmtime_r (&t, &now);
00530   SPRINTF (date,
00531            "Date: %3s, %02u %3s %04u %02u:%02u:%02u GMT\r\n",
00532            days[now.tm_wday % 7],
00533            now.tm_mday,
00534            mons[now.tm_mon % 12],
00535            1900 + now.tm_year, now.tm_hour, now.tm_min, now.tm_sec);
00536 }
00537 
00543 static int
00544 try_grow_read_buffer (struct MHD_Connection *connection)
00545 {
00546   void *buf;
00547 
00548   buf = MHD_pool_reallocate (connection->pool,
00549                              connection->read_buffer,
00550                              connection->read_buffer_size,
00551                              connection->read_buffer_size * 2 +
00552                              MHD_BUF_INC_SIZE + 1);
00553   if (buf == NULL)
00554     return MHD_NO;
00555   /* we can actually grow the buffer, do it! */
00556   connection->read_buffer = buf;
00557   connection->read_buffer_size =
00558     connection->read_buffer_size * 2 + MHD_BUF_INC_SIZE;
00559   return MHD_YES;
00560 }
00561 
00568 static int
00569 build_header_response (struct MHD_Connection *connection)
00570 {
00571   size_t size;
00572   size_t off;
00573   struct MHD_HTTP_Header *pos;
00574   char code[256];
00575   char date[128];
00576   char *data;
00577   enum MHD_ValueKind kind;
00578   const char *reason_phrase;
00579 
00580   if (connection->state == MHD_CONNECTION_FOOTERS_RECEIVED)
00581     {
00582       add_extra_headers (connection);
00583       reason_phrase = MHD_get_reason_phrase_for (connection->responseCode);
00584       SPRINTF (code,
00585                "%s %u %s\r\n",
00586                MHD_HTTP_VERSION_1_1, connection->responseCode, reason_phrase);
00587       off = strlen (code);
00588       /* estimate size */
00589       size = off + 2;           /* extra \r\n at the end */
00590       kind = MHD_HEADER_KIND;
00591       if (NULL == MHD_get_response_header (connection->response,
00592                                            MHD_HTTP_HEADER_DATE))
00593         get_date_string (date);
00594       else
00595         date[0] = '\0';
00596       size += strlen (date);
00597     }
00598   else
00599     {
00600       size = 2;
00601       kind = MHD_FOOTER_KIND;
00602       off = 0;
00603     }
00604   pos = connection->response->first_header;
00605   while (pos != NULL)
00606     {
00607       if (pos->kind == kind)
00608         size += strlen (pos->header) + strlen (pos->value) + 4; /* colon, space, linefeeds */
00609       pos = pos->next;
00610     }
00611   /* produce data */
00612   data = MHD_pool_allocate (connection->pool, size + 1, MHD_YES);
00613   if (data == NULL)
00614     {
00615 #if HAVE_MESSAGES
00616       MHD_DLOG (connection->daemon, "Not enough memory for write!\n");
00617 #endif
00618       return MHD_NO;
00619     }
00620   if (connection->state == MHD_CONNECTION_FOOTERS_RECEIVED)
00621     {
00622       memcpy (data, code, off);
00623     }
00624   pos = connection->response->first_header;
00625   while (pos != NULL)
00626     {
00627       if (pos->kind == kind)
00628         off += SPRINTF (&data[off], "%s: %s\r\n", pos->header, pos->value);
00629       pos = pos->next;
00630     }
00631   if (connection->state == MHD_CONNECTION_FOOTERS_RECEIVED)
00632     {
00633       strcpy (&data[off], date);
00634       off += strlen (date);
00635     }
00636   memcpy (&data[off], "\r\n", 2);
00637   off += 2;
00638   if (off != size)
00639     mhd_panic (mhd_panic_cls, __FILE__, __LINE__, NULL);
00640   connection->write_buffer = data;
00641   connection->write_buffer_append_offset = size;
00642   connection->write_buffer_send_offset = 0;
00643   connection->write_buffer_size = size + 1;
00644   return MHD_YES;
00645 }
00646 
00654 static void
00655 transmit_error_response (struct MHD_Connection *connection,
00656                          unsigned int status_code, const char *message)
00657 {
00658   struct MHD_Response *response;
00659 
00660   /* die, header far too long to be reasonable */
00661   connection->state = MHD_CONNECTION_FOOTERS_RECEIVED;
00662   connection->read_closed = MHD_YES;
00663 #if HAVE_MESSAGES
00664   MHD_DLOG (connection->daemon,
00665             "Error %u (`%s') processing request, closing connection.\n",
00666             status_code, message);
00667 #endif
00668   response = MHD_create_response_from_data (strlen (message),
00669                                             (void *) message, MHD_NO, MHD_NO);
00670   MHD_queue_response (connection, status_code, response);
00671   EXTRA_CHECK (connection->response != NULL);
00672   MHD_destroy_response (response);
00673   if (MHD_NO == build_header_response (connection))
00674     {
00675       /* oops - close! */
00676 #if HAVE_MESSAGES
00677       MHD_DLOG (connection->daemon,
00678                 "Closing connection (failed to create response header)\n");
00679 #endif
00680       connection->state = MHD_CONNECTION_CLOSED;
00681     }
00682   else
00683     {
00684       connection->state = MHD_CONNECTION_HEADERS_SENDING;
00685     }
00686 }
00687 
00692 static void
00693 do_fd_set (int fd, fd_set * set, int *max_fd)
00694 {
00695   FD_SET (fd, set);
00696   if (fd > *max_fd)
00697     *max_fd = fd;
00698 }
00699 
00705 int
00706 MHD_connection_get_fdset (struct MHD_Connection *connection,
00707                           fd_set * read_fd_set,
00708                           fd_set * write_fd_set,
00709                           fd_set * except_fd_set, int *max_fd)
00710 {
00711   int ret;
00712   struct MHD_Pollfd p;
00713 
00714   memset(&p, 0, sizeof(struct MHD_Pollfd));
00715   ret = MHD_connection_get_pollfd(connection, &p);
00716   if ( (ret == MHD_YES) && (p.fd >= 0) ) {
00717     if (0 != (p.events & MHD_POLL_ACTION_IN)) 
00718       do_fd_set(p.fd, read_fd_set, max_fd);    
00719     if (0 != (p.events & MHD_POLL_ACTION_OUT)) 
00720       do_fd_set(p.fd, write_fd_set, max_fd);    
00721   }
00722   return ret;
00723 }
00724 
00731 int
00732 MHD_connection_get_pollfd(struct MHD_Connection *connection, struct MHD_Pollfd *p)
00733 {
00734   int fd;
00735 
00736   if (connection->pool == NULL)
00737     connection->pool = MHD_pool_create (connection->daemon->pool_size);
00738   if (connection->pool == NULL)
00739     {
00740 #if HAVE_MESSAGES
00741       MHD_DLOG (connection->daemon, "Failed to create memory pool!\n");
00742 #endif
00743       connection_close_error (connection);
00744       return MHD_NO;
00745     }
00746   fd = connection->socket_fd;
00747   p->fd = fd;
00748   if (fd == -1)
00749     return MHD_YES;
00750   while (1)
00751     {
00752 #if DEBUG_STATES
00753       MHD_DLOG (connection->daemon, "%s: state: %s\n",
00754                 __FUNCTION__, MHD_state_to_string (connection->state));
00755 #endif
00756       switch (connection->state)
00757         {
00758         case MHD_CONNECTION_INIT:
00759         case MHD_CONNECTION_URL_RECEIVED:
00760         case MHD_CONNECTION_HEADER_PART_RECEIVED:
00761 #if HTTPS_SUPPORT
00762         case MHD_TLS_CONNECTION_INIT:
00763 #endif
00764           /* while reading headers, we always grow the
00765              read buffer if needed, no size-check required */
00766           if ((connection->read_closed) &&
00767               (connection->read_buffer_offset == 0))
00768             {
00769               connection->state = MHD_CONNECTION_CLOSED;
00770               continue;
00771             }
00772           if ((connection->read_buffer_offset == connection->read_buffer_size)
00773               && (MHD_NO == try_grow_read_buffer (connection)))
00774             {
00775               transmit_error_response (connection,
00776                                        (connection->url != NULL)
00777                                        ? MHD_HTTP_REQUEST_ENTITY_TOO_LARGE
00778                                        : MHD_HTTP_REQUEST_URI_TOO_LONG,
00779                                        REQUEST_TOO_BIG);
00780               continue;
00781             }
00782           if (MHD_NO == connection->read_closed)
00783             p->events |= MHD_POLL_ACTION_IN;
00784           break;
00785         case MHD_CONNECTION_HEADERS_RECEIVED:
00786           /* we should never get here */
00787           EXTRA_CHECK (0);
00788           break;
00789         case MHD_CONNECTION_HEADERS_PROCESSED:
00790           EXTRA_CHECK (0);
00791           break;
00792         case MHD_CONNECTION_CONTINUE_SENDING:
00793           p->events |= MHD_POLL_ACTION_OUT;
00794           break;
00795         case MHD_CONNECTION_CONTINUE_SENT:
00796           if (connection->read_buffer_offset == connection->read_buffer_size)
00797             {
00798               if ((MHD_YES != try_grow_read_buffer (connection)) &&
00799                   (0 != (connection->daemon->options &
00800                          (MHD_USE_SELECT_INTERNALLY |
00801                           MHD_USE_THREAD_PER_CONNECTION))))
00802                 {
00803                   /* failed to grow the read buffer, and the
00804                      client which is supposed to handle the
00805                      received data in a *blocking* fashion
00806                      (in this mode) did not handle the data as
00807                      it was supposed to!
00808                      => we would either have to do busy-waiting
00809                      (on the client, which would likely fail),
00810                      or if we do nothing, we would just timeout
00811                      on the connection (if a timeout is even
00812                      set!).
00813                      Solution: we kill the connection with an error */
00814                   transmit_error_response (connection,
00815                                            MHD_HTTP_INTERNAL_SERVER_ERROR,
00816                                            INTERNAL_ERROR);
00817                   continue;
00818                 }
00819             }
00820           if ((connection->read_buffer_offset < connection->read_buffer_size)
00821               && (MHD_NO == connection->read_closed))
00822             p->events |= MHD_POLL_ACTION_IN;
00823           break;
00824         case MHD_CONNECTION_BODY_RECEIVED:
00825         case MHD_CONNECTION_FOOTER_PART_RECEIVED:
00826           /* while reading footers, we always grow the
00827              read buffer if needed, no size-check required */
00828           if (MHD_YES == connection->read_closed)
00829             {
00830               connection->state = MHD_CONNECTION_CLOSED;
00831               continue;
00832             }
00833           p->events |= MHD_POLL_ACTION_IN;
00834           /* transition to FOOTERS_RECEIVED
00835              happens in read handler */
00836           break;
00837         case MHD_CONNECTION_FOOTERS_RECEIVED:
00838           /* no socket action, wait for client
00839              to provide response */
00840           break;
00841         case MHD_CONNECTION_HEADERS_SENDING:
00842           /* headers in buffer, keep writing */
00843           p->events |= MHD_POLL_ACTION_OUT;
00844           break;
00845         case MHD_CONNECTION_HEADERS_SENT:
00846           EXTRA_CHECK (0);
00847           break;
00848         case MHD_CONNECTION_NORMAL_BODY_READY:
00849           p->events |= MHD_POLL_ACTION_OUT;
00850           break;
00851         case MHD_CONNECTION_NORMAL_BODY_UNREADY:
00852           /* not ready, no socket action */
00853           break;
00854         case MHD_CONNECTION_CHUNKED_BODY_READY:
00855           p->events |= MHD_POLL_ACTION_OUT;
00856           break;
00857         case MHD_CONNECTION_CHUNKED_BODY_UNREADY:
00858           /* not ready, no socket action */
00859           break;
00860         case MHD_CONNECTION_BODY_SENT:
00861           EXTRA_CHECK (0);
00862           break;
00863         case MHD_CONNECTION_FOOTERS_SENDING:
00864           p->events |= MHD_POLL_ACTION_OUT;
00865           break;
00866         case MHD_CONNECTION_FOOTERS_SENT:
00867           EXTRA_CHECK (0);
00868           break;
00869         case MHD_CONNECTION_CLOSED:
00870           if (connection->socket_fd != -1)
00871             connection_close_error (connection);
00872           return MHD_YES;       /* do nothing, not even reading */
00873 
00874         default:
00875           EXTRA_CHECK (0);
00876         }
00877       break;
00878     }
00879   return MHD_YES;
00880 }
00881 
00890 static char *
00891 get_next_header_line (struct MHD_Connection *connection)
00892 {
00893   char *rbuf;
00894   size_t pos;
00895 
00896   if (connection->read_buffer_offset == 0)
00897     return NULL;
00898   pos = 0;
00899   rbuf = connection->read_buffer;
00900   while ((pos < connection->read_buffer_offset - 1) &&
00901          (rbuf[pos] != '\r') && (rbuf[pos] != '\n'))
00902     pos++;
00903   if (pos == connection->read_buffer_offset - 1)
00904     {
00905       /* not found, consider growing... */
00906       if (connection->read_buffer_offset == connection->read_buffer_size)
00907         {
00908           rbuf = MHD_pool_reallocate (connection->pool,
00909                                       connection->read_buffer,
00910                                       connection->read_buffer_size,
00911                                       connection->read_buffer_size * 2 +
00912                                       MHD_BUF_INC_SIZE);
00913           if (rbuf == NULL)
00914             {
00915               transmit_error_response (connection,
00916                                        (connection->url != NULL)
00917                                        ? MHD_HTTP_REQUEST_ENTITY_TOO_LARGE
00918                                        : MHD_HTTP_REQUEST_URI_TOO_LONG,
00919                                        REQUEST_TOO_BIG);
00920             }
00921           else
00922             {
00923               connection->read_buffer_size =
00924                 connection->read_buffer_size * 2 + MHD_BUF_INC_SIZE;
00925               connection->read_buffer = rbuf;
00926             }
00927         }
00928       return NULL;
00929     }
00930   /* found, check if we have proper CRLF */
00931   if ((rbuf[pos] == '\r') && (rbuf[pos + 1] == '\n'))
00932     rbuf[pos++] = '\0';         /* skip both r and n */
00933   rbuf[pos++] = '\0';
00934   connection->read_buffer += pos;
00935   connection->read_buffer_size -= pos;
00936   connection->read_buffer_offset -= pos;
00937   return rbuf;
00938 }
00939 
00943 static int
00944 connection_add_header (struct MHD_Connection *connection,
00945                        char *key, char *value, enum MHD_ValueKind kind)
00946 {
00947   struct MHD_HTTP_Header *hdr;
00948 
00949   hdr = MHD_pool_allocate (connection->pool,
00950                            sizeof (struct MHD_HTTP_Header), MHD_YES);
00951   if (hdr == NULL)
00952     {
00953 #if HAVE_MESSAGES
00954       MHD_DLOG (connection->daemon,
00955                 "Not enough memory to allocate header record!\n");
00956 #endif
00957       transmit_error_response (connection, MHD_HTTP_REQUEST_ENTITY_TOO_LARGE,
00958                                REQUEST_TOO_BIG);
00959       return MHD_NO;
00960     }
00961   hdr->next = connection->headers_received;
00962   hdr->header = key;
00963   hdr->value = value;
00964   hdr->kind = kind;
00965   connection->headers_received = hdr;
00966   return MHD_YES;
00967 }
00968 
00972 static int
00973 parse_arguments (enum MHD_ValueKind kind,
00974                  struct MHD_Connection *connection, char *args)
00975 {
00976   char *equals;
00977   char *amper;
00978 
00979   while (args != NULL)
00980     {
00981       equals = strstr (args, "=");
00982       if (equals == NULL)
00983         return MHD_NO;          /* invalid, ignore */
00984       equals[0] = '\0';
00985       equals++;
00986       amper = strstr (equals, "&");
00987       if (amper != NULL)
00988         {
00989           amper[0] = '\0';
00990           amper++;
00991         }
00992       MHD_http_unescape (args);
00993       MHD_http_unescape (equals);
00994       if (MHD_NO == connection_add_header (connection, args, equals, kind))
00995         return MHD_NO;
00996       args = amper;
00997     }
00998   return MHD_YES;
00999 }
01000 
01006 static int
01007 parse_cookie_header (struct MHD_Connection *connection)
01008 {
01009   const char *hdr;
01010   char *cpy;
01011   char *pos;
01012   char *sce;
01013   char *semicolon;
01014   char *equals;
01015   char *ekill;
01016   char old;
01017   int quotes;
01018 
01019   hdr = MHD_lookup_connection_value (connection,
01020                                      MHD_HEADER_KIND,
01021                                      MHD_HTTP_HEADER_COOKIE);
01022   if (hdr == NULL)
01023     return MHD_YES;
01024   cpy = MHD_pool_allocate (connection->pool, strlen (hdr) + 1, MHD_YES);
01025   if (cpy == NULL)
01026     {
01027 #if HAVE_MESSAGES
01028       MHD_DLOG (connection->daemon, "Not enough memory to parse cookies!\n");
01029 #endif
01030       transmit_error_response (connection, MHD_HTTP_REQUEST_ENTITY_TOO_LARGE,
01031                                REQUEST_TOO_BIG);
01032       return MHD_NO;
01033     }
01034   memcpy (cpy, hdr, strlen (hdr) + 1);
01035   pos = cpy;
01036   while (pos != NULL)
01037     {
01038       while (*pos == ' ')
01039         pos++;                  /* skip spaces */
01040 
01041       sce = pos;
01042       while (((*sce) != '\0') &&
01043              ((*sce) != ',') && ((*sce) != ';') && ((*sce) != '='))
01044         sce++;
01045       /* remove tailing whitespace (if any) from key */
01046       ekill = sce - 1;
01047       while ((*ekill == ' ') && (ekill >= pos))
01048         *(ekill--) = '\0';
01049       old = *sce;
01050       *sce = '\0';
01051       if (old != '=')
01052         {
01053           /* value part omitted, use empty string... */
01054           if (MHD_NO ==
01055               connection_add_header (connection, pos, "", MHD_COOKIE_KIND))
01056             return MHD_NO;
01057           if (old == '\0')
01058             break;
01059           pos = sce + 1;
01060           continue;
01061         }
01062       equals = sce + 1;
01063       quotes = 0;
01064       semicolon = equals;
01065       while ((semicolon[0] != '\0') &&
01066              ((quotes != 0) ||
01067               ((semicolon[0] != ';') && (semicolon[0] != ','))))
01068         {
01069           if (semicolon[0] == '"')
01070             quotes = (quotes + 1) & 1;
01071           semicolon++;
01072         }
01073       if (semicolon[0] == '\0')
01074         semicolon = NULL;
01075       if (semicolon != NULL)
01076         {
01077           semicolon[0] = '\0';
01078           semicolon++;
01079         }
01080       /* remove quotes */
01081       if ((equals[0] == '"') && (equals[strlen (equals) - 1] == '"'))
01082         {
01083           equals[strlen (equals) - 1] = '\0';
01084           equals++;
01085         }
01086       if (MHD_NO == connection_add_header (connection,
01087                                            pos, equals, MHD_COOKIE_KIND))
01088         return MHD_NO;
01089       pos = semicolon;
01090     }
01091   return MHD_YES;
01092 }
01093 
01101 static int
01102 parse_initial_message_line (struct MHD_Connection *connection, char *line)
01103 {
01104   char *uri;
01105   char *httpVersion;
01106   char *args;
01107 
01108   uri = strstr (line, " ");
01109   if (uri == NULL)
01110     return MHD_NO;              /* serious error */
01111   uri[0] = '\0';
01112   connection->method = line;
01113   uri++;
01114   while (uri[0] == ' ')
01115     uri++;
01116   httpVersion = strstr (uri, " ");
01117   if (httpVersion != NULL)
01118     {
01119       httpVersion[0] = '\0';
01120       httpVersion++;
01121     }
01122   if (connection->daemon->uri_log_callback != NULL)
01123     connection->client_context
01124       =
01125       connection->daemon->uri_log_callback (connection->daemon->
01126                                             uri_log_callback_cls, uri);
01127   args = strstr (uri, "?");
01128   if (args != NULL)
01129     {
01130       args[0] = '\0';
01131       args++;
01132       parse_arguments (MHD_GET_ARGUMENT_KIND, connection, args);
01133     }
01134   MHD_http_unescape (uri);
01135   connection->url = uri;
01136   if (httpVersion == NULL)
01137     connection->version = "";
01138   else
01139     connection->version = httpVersion;
01140   return MHD_YES;
01141 }
01142 
01143 
01149 static void
01150 call_connection_handler (struct MHD_Connection *connection)
01151 {
01152   size_t processed;
01153 
01154   if (connection->response != NULL)
01155     return;                     /* already queued a response */  
01156   processed = 0;
01157   connection->client_aware = MHD_YES;
01158   if (MHD_NO ==
01159       connection->daemon->default_handler (connection->daemon->
01160                                            default_handler_cls,
01161                                            connection, connection->url,
01162                                            connection->method,
01163                                            connection->version,
01164                                            NULL, &processed,
01165                                            &connection->client_context))
01166     {
01167       /* serious internal error, close connection */
01168 #if HAVE_MESSAGES
01169       MHD_DLOG (connection->daemon,
01170                 "Internal application error, closing connection.\n");
01171 #endif
01172       connection_close_error (connection);
01173       return;
01174     }
01175 }
01176 
01177 
01178 
01184 static void
01185 process_request_body (struct MHD_Connection *connection)
01186 {
01187   size_t processed;
01188   size_t available;
01189   size_t used;
01190   size_t i;
01191   int instant_retry;
01192   int malformed;
01193   char *buffer_head;
01194 
01195   if (connection->response != NULL)
01196     return;                     /* already queued a response */
01197 
01198   buffer_head = connection->read_buffer;
01199   available = connection->read_buffer_offset;
01200   do
01201     {
01202       instant_retry = MHD_NO;
01203       if ((connection->have_chunked_upload == MHD_YES) &&
01204           (connection->remaining_upload_size == MHD_SIZE_UNKNOWN))
01205         {
01206           if ((connection->current_chunk_offset ==
01207                connection->current_chunk_size)
01208               && (connection->current_chunk_offset != 0) && (available >= 2))
01209             {
01210               /* skip new line at the *end* of a chunk */
01211               i = 0;
01212               if ((buffer_head[i] == '\r') || (buffer_head[i] == '\n'))
01213                 i++;            /* skip 1st part of line feed */
01214               if ((buffer_head[i] == '\r') || (buffer_head[i] == '\n'))
01215                 i++;            /* skip 2nd part of line feed */
01216               if (i == 0)
01217                 {
01218                   /* malformed encoding */
01219 #if HAVE_MESSAGES
01220                   MHD_DLOG (connection->daemon,
01221                             "Received malformed HTTP request (bad chunked encoding), closing connection.\n");
01222 #endif
01223                   connection_close_error (connection);
01224                   return;
01225                 }
01226               available -= i;
01227               buffer_head += i;
01228               connection->current_chunk_offset = 0;
01229               connection->current_chunk_size = 0;
01230             }
01231           if (connection->current_chunk_offset <
01232               connection->current_chunk_size)
01233             {
01234               /* we are in the middle of a chunk, give
01235                  as much as possible to the client (without
01236                  crossing chunk boundaries) */
01237               processed =
01238                 connection->current_chunk_size -
01239                 connection->current_chunk_offset;
01240               if (processed > available)
01241                 processed = available;
01242               if (available > processed)
01243                 instant_retry = MHD_YES;
01244             }
01245           else
01246             {
01247               /* we need to read chunk boundaries */
01248               i = 0;
01249               while (i < available)
01250                 {
01251                   if ((buffer_head[i] == '\r') || (buffer_head[i] == '\n'))
01252                     break;
01253                   i++;
01254                   if (i >= 6)
01255                     break;
01256                 }
01257               /* take '\n' into account; if '\n'
01258                  is the unavailable character, we
01259                  will need to wait until we have it
01260                  before going further */
01261               if ((i + 1 >= available) &&
01262                   !((i == 1) && (available == 2) && (buffer_head[0] == '0')))
01263                 break;          /* need more data... */
01264               malformed = (i >= 6);
01265               if (!malformed)
01266                 {
01267                   buffer_head[i] = '\0';
01268                   malformed =
01269                     (1 != SSCANF (buffer_head, "%X",
01270                                   &connection->current_chunk_size)) &&
01271                     (1 != SSCANF (buffer_head, "%x",
01272                                   &connection->current_chunk_size));
01273                 }
01274               if (malformed)
01275                 {
01276                   /* malformed encoding */
01277 #if HAVE_MESSAGES
01278                   MHD_DLOG (connection->daemon,
01279                             "Received malformed HTTP request (bad chunked encoding), closing connection.\n");
01280 #endif
01281                   connection_close_error (connection);
01282                   return;
01283                 }
01284               i++;
01285               if ((i < available) &&
01286                   ((buffer_head[i] == '\r') || (buffer_head[i] == '\n')))
01287                 i++;            /* skip 2nd part of line feed */
01288 
01289               buffer_head += i;
01290               available -= i;
01291               connection->current_chunk_offset = 0;
01292 
01293               if (available > 0)
01294                 instant_retry = MHD_YES;
01295               if (connection->current_chunk_size == 0)
01296                 {
01297                   connection->remaining_upload_size = 0;
01298                   break;
01299                 }
01300               continue;
01301             }
01302         }
01303       else
01304         {
01305           /* no chunked encoding, give all to the client */
01306           processed = available;
01307         }
01308       used = processed;
01309       connection->client_aware = MHD_YES;
01310       if (MHD_NO ==
01311           connection->daemon->default_handler (connection->daemon->
01312                                                default_handler_cls,
01313                                                connection, connection->url,
01314                                                connection->method,
01315                                                connection->version,
01316                                                buffer_head, &processed,
01317                                                &connection->client_context))
01318         {
01319           /* serious internal error, close connection */
01320 #if HAVE_MESSAGES
01321           MHD_DLOG (connection->daemon,
01322                     "Internal application error, closing connection.\n");
01323 #endif
01324           connection_close_error (connection);
01325           return;
01326         }
01327       if (processed > used)
01328         mhd_panic (mhd_panic_cls, __FILE__, __LINE__, 
01329 #if HAVE_MESSAGES
01330                    "API violation"
01331 #else
01332                    NULL
01333 #endif
01334                    );
01335       if (processed != 0)
01336         instant_retry = MHD_NO; /* client did not process everything */
01337       used -= processed;
01338       if (connection->have_chunked_upload == MHD_YES)
01339         connection->current_chunk_offset += used;
01340       /* dh left "processed" bytes in buffer for next time... */
01341       buffer_head += used;
01342       available -= used;
01343       if (connection->remaining_upload_size != MHD_SIZE_UNKNOWN)
01344         connection->remaining_upload_size -= used;
01345     }
01346   while (instant_retry == MHD_YES);
01347   if (available > 0)
01348     memmove (connection->read_buffer, buffer_head, available);
01349   connection->read_buffer_offset = available;
01350 }
01351 
01360 static int
01361 do_read (struct MHD_Connection *connection)
01362 {
01363   int bytes_read;
01364 
01365   if (connection->read_buffer_size == connection->read_buffer_offset)
01366     return MHD_NO;
01367 
01368   bytes_read = connection->recv_cls (connection,
01369                                      &connection->read_buffer
01370                                      [connection->read_buffer_offset],
01371                                      connection->read_buffer_size -
01372                                      connection->read_buffer_offset);
01373   if (bytes_read < 0)
01374     {
01375       if (errno == EINTR)
01376         return MHD_NO;
01377 #if HAVE_MESSAGES
01378       MHD_DLOG (connection->daemon,
01379                 "Failed to receive data: %s\n", STRERROR (errno));
01380 #endif
01381       connection_close_error (connection);
01382       return MHD_YES;
01383     }
01384   if (bytes_read == 0)
01385     {
01386       /* other side closed connection */
01387       connection->read_closed = MHD_YES;
01388       SHUTDOWN (connection->socket_fd, SHUT_RD);
01389       return MHD_NO;
01390     }
01391   connection->read_buffer_offset += bytes_read;
01392   return MHD_YES;
01393 }
01394 
01402 static int
01403 do_write (struct MHD_Connection *connection)
01404 {
01405   int ret;
01406 
01407   ret = connection->send_cls (connection,
01408                               &connection->write_buffer
01409                               [connection->write_buffer_send_offset],
01410                               connection->write_buffer_append_offset
01411                               - connection->write_buffer_send_offset);
01412 
01413   if (ret < 0)
01414     {
01415       if (errno == EINTR)
01416         return MHD_NO;
01417 #if HAVE_MESSAGES
01418       MHD_DLOG (connection->daemon,
01419                 "Failed to send data: %s\n", STRERROR (errno));
01420 #endif
01421       connection_close_error (connection);
01422       return MHD_YES;
01423     }
01424 #if DEBUG_SEND_DATA
01425   FPRINTF (stderr,
01426            "Sent response: `%.*s'\n",
01427            ret,
01428            &connection->write_buffer[connection->write_buffer_send_offset]);
01429 #endif
01430   connection->write_buffer_send_offset += ret;
01431   return MHD_YES;
01432 }
01433 
01439 static int
01440 check_write_done (struct MHD_Connection *connection,
01441                   enum MHD_CONNECTION_STATE next_state)
01442 {
01443   if (connection->write_buffer_append_offset !=
01444       connection->write_buffer_send_offset)
01445     return MHD_NO;
01446   connection->write_buffer_append_offset = 0;
01447   connection->write_buffer_send_offset = 0;
01448   connection->state = next_state;
01449   MHD_pool_reallocate (connection->pool, connection->write_buffer,
01450                        connection->write_buffer_size, 0);
01451   connection->write_buffer = NULL;
01452   connection->write_buffer_size = 0;
01453   return MHD_YES;
01454 }
01455 
01461 static int
01462 process_header_line (struct MHD_Connection *connection, char *line)
01463 {
01464   char *colon;
01465 
01466   /* line should be normal header line, find colon */
01467   colon = strstr (line, ":");
01468   if (colon == NULL)
01469     {
01470       /* error in header line, die hard */
01471 #if HAVE_MESSAGES
01472       MHD_DLOG (connection->daemon,
01473                 "Received malformed line (no colon), closing connection.\n");
01474 #endif
01475       connection->state = MHD_CONNECTION_CLOSED;
01476       return MHD_NO;
01477     }
01478   /* zero-terminate header */
01479   colon[0] = '\0';
01480   colon++;                      /* advance to value */
01481   while ((colon[0] != '\0') && ((colon[0] == ' ') || (colon[0] == '\t')))
01482     colon++;
01483   /* we do the actual adding of the connection
01484      header at the beginning of the while
01485      loop since we need to be able to inspect
01486      the *next* header line (in case it starts
01487      with a space...) */
01488   connection->last = line;
01489   connection->colon = colon;
01490   return MHD_YES;
01491 }
01492 
01502 static int
01503 process_broken_line (struct MHD_Connection *connection,
01504                      char *line, enum MHD_ValueKind kind)
01505 {
01506   char *last;
01507   char *tmp;
01508 
01509   last = connection->last;
01510   if ((line[0] == ' ') || (line[0] == '\t'))
01511     {
01512       /* value was continued on the next line, see
01513          http://www.jmarshall.com/easy/http/ */
01514       last = MHD_pool_reallocate (connection->pool,
01515                                   last,
01516                                   strlen (last) + 1,
01517                                   strlen (line) + strlen (last) + 1);
01518       if (last == NULL)
01519         {
01520           transmit_error_response (connection,
01521                                    MHD_HTTP_REQUEST_ENTITY_TOO_LARGE,
01522                                    REQUEST_TOO_BIG);
01523           return MHD_NO;
01524         }
01525       tmp = line;
01526       while ((tmp[0] == ' ') || (tmp[0] == '\t'))
01527         tmp++;                  /* skip whitespace at start of 2nd line */
01528       strcat (last, tmp);
01529       connection->last = last;
01530       return MHD_YES;           /* possibly more than 2 lines... */
01531     }
01532   EXTRA_CHECK ((last != NULL) && (connection->colon != NULL));
01533   if ((MHD_NO == connection_add_header (connection,
01534                                         last, connection->colon, kind)))
01535     {
01536       transmit_error_response (connection, MHD_HTTP_REQUEST_ENTITY_TOO_LARGE,
01537                                REQUEST_TOO_BIG);
01538       return MHD_NO;
01539     }
01540   /* we still have the current line to deal with... */
01541   if (strlen (line) != 0)
01542     {
01543       if (MHD_NO == process_header_line (connection, line))
01544         {
01545           transmit_error_response (connection,
01546                                    MHD_HTTP_BAD_REQUEST, REQUEST_MALFORMED);
01547           return MHD_NO;
01548         }
01549     }
01550   return MHD_YES;
01551 }
01552 
01558 static void
01559 parse_connection_headers (struct MHD_Connection *connection)
01560 {
01561   const char *clen;
01562   unsigned long long cval;
01563   struct MHD_Response *response;
01564 
01565   parse_cookie_header (connection);
01566   if ((0 != (MHD_USE_PEDANTIC_CHECKS & connection->daemon->options))
01567       && (NULL != connection->version)
01568       && (0 == strcasecmp (MHD_HTTP_VERSION_1_1, connection->version))
01569       && (NULL ==
01570           MHD_lookup_connection_value (connection, MHD_HEADER_KIND,
01571                                        MHD_HTTP_HEADER_HOST)))
01572     {
01573       /* die, http 1.1 request without host and we are pedantic */
01574       connection->state = MHD_CONNECTION_FOOTERS_RECEIVED;
01575       connection->read_closed = MHD_YES;
01576 #if HAVE_MESSAGES
01577       MHD_DLOG (connection->daemon,
01578                 "Received `%s' request without `%s' header.\n",
01579                 MHD_HTTP_VERSION_1_1, MHD_HTTP_HEADER_HOST);
01580 #endif
01581       response =
01582         MHD_create_response_from_data (strlen (REQUEST_LACKS_HOST),
01583                                        REQUEST_LACKS_HOST, MHD_NO, MHD_NO);
01584       MHD_queue_response (connection, MHD_HTTP_BAD_REQUEST, response);
01585       MHD_destroy_response (response);
01586       return;
01587     }
01588 
01589   clen = MHD_lookup_connection_value (connection,
01590                                       MHD_HEADER_KIND,
01591                                       MHD_HTTP_HEADER_CONTENT_LENGTH);
01592   if (clen != NULL)
01593     {
01594       if (1 != SSCANF (clen, "%llu", &cval))
01595         {
01596 #if HAVE_MESSAGES
01597           MHD_DLOG (connection->daemon,
01598                     "Failed to parse `%s' header `%s', closing connection.\n",
01599                     MHD_HTTP_HEADER_CONTENT_LENGTH, clen);
01600 #endif
01601           connection->state = MHD_CONNECTION_CLOSED;
01602           return;
01603         }
01604       connection->remaining_upload_size = cval;
01605     }
01606   else
01607     {
01608       if (NULL == MHD_lookup_connection_value (connection,
01609                                                MHD_HEADER_KIND,
01610                                                MHD_HTTP_HEADER_TRANSFER_ENCODING))
01611         {
01612           /* this request does not have a body */
01613           connection->remaining_upload_size = 0;
01614         }
01615       else
01616         {
01617           connection->remaining_upload_size = MHD_SIZE_UNKNOWN;
01618           if (0 ==
01619               strcasecmp (MHD_lookup_connection_value
01620                           (connection, MHD_HEADER_KIND,
01621                            MHD_HTTP_HEADER_TRANSFER_ENCODING), "chunked"))
01622             connection->have_chunked_upload = MHD_YES;
01623         }
01624     }
01625 }
01626 
01636 int
01637 MHD_connection_handle_read (struct MHD_Connection *connection)
01638 {
01639   connection->last_activity = time (NULL);
01640   if (connection->state == MHD_CONNECTION_CLOSED)
01641     return MHD_NO;
01642   /* make sure "read" has a reasonable number of bytes
01643      in buffer to use per system call (if possible) */
01644   if (connection->read_buffer_offset + MHD_BUF_INC_SIZE >
01645       connection->read_buffer_size)
01646     try_grow_read_buffer (connection);
01647   if (MHD_NO == do_read (connection))
01648     return MHD_YES;
01649   while (1)
01650     {
01651 #if DEBUG_STATES
01652       MHD_DLOG (connection->daemon, "%s: state: %s\n",
01653                 __FUNCTION__, MHD_state_to_string (connection->state));
01654 #endif
01655       switch (connection->state)
01656         {
01657         case MHD_CONNECTION_INIT:
01658         case MHD_CONNECTION_URL_RECEIVED:
01659         case MHD_CONNECTION_HEADER_PART_RECEIVED:
01660         case MHD_CONNECTION_HEADERS_RECEIVED:
01661         case MHD_CONNECTION_HEADERS_PROCESSED:
01662         case MHD_CONNECTION_CONTINUE_SENDING:
01663         case MHD_CONNECTION_CONTINUE_SENT:
01664         case MHD_CONNECTION_BODY_RECEIVED:
01665         case MHD_CONNECTION_FOOTER_PART_RECEIVED:
01666           /* nothing to do but default action */
01667           if (MHD_YES == connection->read_closed)
01668             {
01669               connection->state = MHD_CONNECTION_CLOSED;
01670               continue;
01671             }
01672           break;
01673         case MHD_CONNECTION_CLOSED:
01674           if (connection->socket_fd != -1)
01675             connection_close_error (connection);
01676           return MHD_NO;
01677         default:
01678           /* shrink read buffer to how much is actually used */
01679           MHD_pool_reallocate (connection->pool,
01680                                connection->read_buffer,
01681                                connection->read_buffer_size + 1,
01682                                connection->read_buffer_offset);
01683           break;
01684         }
01685       break;
01686     }
01687   return MHD_YES;
01688 }
01689 
01699 int
01700 MHD_connection_handle_write (struct MHD_Connection *connection)
01701 {
01702   struct MHD_Response *response;
01703   int ret;
01704   connection->last_activity = time (NULL);
01705   while (1)
01706     {
01707 #if DEBUG_STATES
01708       MHD_DLOG (connection->daemon, "%s: state: %s\n",
01709                 __FUNCTION__, MHD_state_to_string (connection->state));
01710 #endif
01711       switch (connection->state)
01712         {
01713         case MHD_CONNECTION_INIT:
01714         case MHD_CONNECTION_URL_RECEIVED:
01715         case MHD_CONNECTION_HEADER_PART_RECEIVED:
01716         case MHD_CONNECTION_HEADERS_RECEIVED:
01717           EXTRA_CHECK (0);
01718           break;
01719         case MHD_CONNECTION_HEADERS_PROCESSED:
01720           break;
01721         case MHD_CONNECTION_CONTINUE_SENDING:
01722           ret = connection->send_cls (connection,
01723                                       &HTTP_100_CONTINUE
01724                                       [connection->continue_message_write_offset],
01725                                       strlen (HTTP_100_CONTINUE) -
01726                                       connection->continue_message_write_offset);
01727           if (ret < 0)
01728             {
01729               if (errno == EINTR)
01730                 break;
01731 #if HAVE_MESSAGES
01732               MHD_DLOG (connection->daemon,
01733                         "Failed to send data: %s\n", STRERROR (errno));
01734 #endif
01735               connection_close_error (connection);
01736               return MHD_NO;
01737             }
01738 #if DEBUG_SEND_DATA
01739           FPRINTF (stderr,
01740                    "Sent 100 continue response: `%.*s'\n",
01741                    ret,
01742                    &HTTP_100_CONTINUE
01743                    [connection->continue_message_write_offset]);
01744 #endif
01745           connection->continue_message_write_offset += ret;
01746           break;
01747         case MHD_CONNECTION_CONTINUE_SENT:
01748         case MHD_CONNECTION_BODY_RECEIVED:
01749         case MHD_CONNECTION_FOOTER_PART_RECEIVED:
01750         case MHD_CONNECTION_FOOTERS_RECEIVED:
01751           EXTRA_CHECK (0);
01752           break;
01753         case MHD_CONNECTION_HEADERS_SENDING:
01754           do_write (connection);
01755           check_write_done (connection, MHD_CONNECTION_HEADERS_SENT);
01756           break;
01757         case MHD_CONNECTION_HEADERS_SENT:
01758           EXTRA_CHECK (0);
01759           break;
01760         case MHD_CONNECTION_NORMAL_BODY_READY:
01761           response = connection->response;
01762           if (response->crc != NULL)
01763             pthread_mutex_lock (&response->mutex);
01764           if (MHD_YES != try_ready_normal_body (connection))
01765             {
01766               if (response->crc != NULL)
01767                 pthread_mutex_unlock (&response->mutex);
01768               connection->state = MHD_CONNECTION_NORMAL_BODY_UNREADY;
01769               break;
01770             }
01771 #if HTTPS_SUPPORT
01772           if (connection->daemon->options & MHD_USE_SSL)
01773             {
01774               ret = MHD__gnutls_record_send (connection->tls_session,
01775                                              &connection->response->data
01776                                              [connection->
01777                                               response_write_position -
01778                                               response->data_start],
01779                                              response->data_size -
01780                                              (connection->response_write_position
01781                                               - response->data_start));
01782             }
01783           else
01784 #endif
01785             {
01786               ret = connection->send_cls (connection,
01787                                           &response->data
01788                                           [connection->response_write_position
01789                                            - response->data_start],
01790                                           response->data_size -
01791                                           (connection->response_write_position
01792                                            - response->data_start));
01793             }
01794 #if DEBUG_SEND_DATA
01795           if (ret > 0)
01796             FPRINTF (stderr,
01797                      "Sent DATA response: `%.*s'\n",
01798                      ret,
01799                      &response->data[connection->response_write_position -
01800                                      response->data_start]);
01801 #endif
01802           if (response->crc != NULL)
01803             pthread_mutex_unlock (&response->mutex);
01804           if (ret < 0)
01805             {
01806               if (errno == EINTR)
01807                 return MHD_YES;
01808 #if HAVE_MESSAGES
01809               MHD_DLOG (connection->daemon,
01810                         "Failed to send data: %s\n", STRERROR (errno));
01811 #endif
01812               connection_close_error (connection);
01813               return MHD_NO;
01814             }
01815           connection->response_write_position += ret;
01816           if (connection->response_write_position ==
01817               connection->response->total_size)
01818             connection->state = MHD_CONNECTION_FOOTERS_SENT;    /* have no footers... */
01819           break;
01820         case MHD_CONNECTION_NORMAL_BODY_UNREADY:
01821           EXTRA_CHECK (0);
01822           break;
01823         case MHD_CONNECTION_CHUNKED_BODY_READY:
01824           do_write (connection);
01825           check_write_done (connection,
01826                             (connection->response->total_size ==
01827                              connection->response_write_position) ?
01828                             MHD_CONNECTION_BODY_SENT :
01829                             MHD_CONNECTION_CHUNKED_BODY_UNREADY);
01830           break;
01831         case MHD_CONNECTION_CHUNKED_BODY_UNREADY:
01832         case MHD_CONNECTION_BODY_SENT:
01833           EXTRA_CHECK (0);
01834           break;
01835         case MHD_CONNECTION_FOOTERS_SENDING:
01836           do_write (connection);
01837           check_write_done (connection, MHD_CONNECTION_FOOTERS_SENT);
01838           break;
01839         case MHD_CONNECTION_FOOTERS_SENT:
01840           EXTRA_CHECK (0);
01841           break;
01842         case MHD_CONNECTION_CLOSED:
01843           if (connection->socket_fd != -1)
01844             connection_close_error (connection);
01845           return MHD_NO;
01846         case MHD_TLS_CONNECTION_INIT:
01847         case MHD_TLS_HELLO_REQUEST:
01848         case MHD_TLS_HANDSHAKE_FAILED:
01849           EXTRA_CHECK (0);
01850           break;
01851         default:
01852           EXTRA_CHECK (0);
01853           connection_close_error (connection);
01854           return MHD_NO;
01855         }
01856       break;
01857     }
01858   return MHD_YES;
01859 }
01860 
01870 int
01871 MHD_connection_handle_idle (struct MHD_Connection *connection)
01872 {
01873   unsigned int timeout;
01874   const char *end;
01875   char *line;
01876 
01877   while (1)
01878     {
01879 #if DEBUG_STATES
01880       MHD_DLOG (connection->daemon, "%s: state: %s\n",
01881                 __FUNCTION__, MHD_state_to_string (connection->state));
01882 #endif
01883       switch (connection->state)
01884         {
01885         case MHD_CONNECTION_INIT:
01886           line = get_next_header_line (connection);
01887           if (line == NULL)
01888             {
01889               if (connection->state != MHD_CONNECTION_INIT)
01890                 continue;
01891               if (connection->read_closed)
01892                 {
01893                   connection->state = MHD_CONNECTION_CLOSED;
01894                   continue;
01895                 }
01896               break;
01897             }
01898           if (MHD_NO == parse_initial_message_line (connection, line))
01899             connection->state = MHD_CONNECTION_CLOSED;
01900           else
01901             connection->state = MHD_CONNECTION_URL_RECEIVED;
01902           continue;
01903         case MHD_CONNECTION_URL_RECEIVED:
01904           line = get_next_header_line (connection);
01905           if (line == NULL)
01906             {
01907               if (connection->state != MHD_CONNECTION_URL_RECEIVED)
01908                 continue;
01909               if (connection->read_closed)
01910                 {
01911                   connection->state = MHD_CONNECTION_CLOSED;
01912                   continue;
01913                 }
01914               break;
01915             }
01916           if (strlen (line) == 0)
01917             {
01918               connection->state = MHD_CONNECTION_HEADERS_RECEIVED;
01919               continue;
01920             }
01921           if (MHD_NO == process_header_line (connection, line))
01922             {
01923               transmit_error_response (connection,
01924                                        MHD_HTTP_BAD_REQUEST,
01925                                        REQUEST_MALFORMED);
01926               break;
01927             }
01928           connection->state = MHD_CONNECTION_HEADER_PART_RECEIVED;
01929           continue;
01930         case MHD_CONNECTION_HEADER_PART_RECEIVED:
01931           line = get_next_header_line (connection);
01932           if (line == NULL)
01933             {
01934               if (connection->state != MHD_CONNECTION_HEADER_PART_RECEIVED)
01935                 continue;
01936               if (connection->read_closed)
01937                 {
01938                   connection->state = MHD_CONNECTION_CLOSED;
01939                   continue;
01940                 }
01941               break;
01942             }
01943           if (MHD_NO ==
01944               process_broken_line (connection, line, MHD_HEADER_KIND))
01945             continue;
01946           if (strlen (line) == 0)
01947             {
01948               connection->state = MHD_CONNECTION_HEADERS_RECEIVED;
01949               continue;
01950             }
01951           continue;
01952         case MHD_CONNECTION_HEADERS_RECEIVED:
01953           parse_connection_headers (connection);
01954           if (connection->state == MHD_CONNECTION_CLOSED)
01955             continue;
01956           connection->state = MHD_CONNECTION_HEADERS_PROCESSED;
01957           continue;
01958         case MHD_CONNECTION_HEADERS_PROCESSED:
01959           call_connection_handler (connection); /* first call */
01960           if (connection->state == MHD_CONNECTION_CLOSED)
01961             continue;
01962           if (need_100_continue (connection))
01963             {
01964               connection->state = MHD_CONNECTION_CONTINUE_SENDING;
01965               break;
01966             }
01967           if (connection->response != NULL)
01968             {
01969               /* we refused (no upload allowed!) */
01970               connection->remaining_upload_size = 0;
01971               /* force close, in case client still tries to upload... */
01972               connection->read_closed = MHD_YES;
01973             }
01974           connection->state = (connection->remaining_upload_size == 0)
01975             ? MHD_CONNECTION_FOOTERS_RECEIVED : MHD_CONNECTION_CONTINUE_SENT;
01976           continue;
01977         case MHD_CONNECTION_CONTINUE_SENDING:
01978           if (connection->continue_message_write_offset ==
01979               strlen (HTTP_100_CONTINUE))
01980             {
01981               connection->state = MHD_CONNECTION_CONTINUE_SENT;
01982               continue;
01983             }
01984           break;
01985         case MHD_CONNECTION_CONTINUE_SENT:
01986           if (connection->read_buffer_offset != 0)
01987             {
01988               process_request_body (connection);     /* loop call */
01989               if (connection->state == MHD_CONNECTION_CLOSED)
01990                 continue;
01991             }
01992           if ((connection->remaining_upload_size == 0) ||
01993               ((connection->remaining_upload_size == MHD_SIZE_UNKNOWN) &&
01994                (connection->read_buffer_offset == 0) &&
01995                (MHD_YES == connection->read_closed)))
01996             {
01997               if ((MHD_YES == connection->have_chunked_upload) &&
01998                   (MHD_NO == connection->read_closed))
01999                 connection->state = MHD_CONNECTION_BODY_RECEIVED;
02000               else
02001                 connection->state = MHD_CONNECTION_FOOTERS_RECEIVED;
02002               continue;
02003             }
02004           break;
02005         case MHD_CONNECTION_BODY_RECEIVED:
02006           line = get_next_header_line (connection);
02007           if (line == NULL)
02008             {
02009               if (connection->state != MHD_CONNECTION_BODY_RECEIVED)
02010                 continue;
02011               if (connection->read_closed)
02012                 {
02013                   connection->state = MHD_CONNECTION_CLOSED;
02014                   continue;
02015                 }
02016               break;
02017             }
02018           if (strlen (line) == 0)
02019             {
02020               connection->state = MHD_CONNECTION_FOOTERS_RECEIVED;
02021               continue;
02022             }
02023           if (MHD_NO == process_header_line (connection, line))
02024             {
02025               transmit_error_response (connection,
02026                                        MHD_HTTP_BAD_REQUEST,
02027                                        REQUEST_MALFORMED);
02028               break;
02029             }
02030           connection->state = MHD_CONNECTION_FOOTER_PART_RECEIVED;
02031           continue;
02032         case MHD_CONNECTION_FOOTER_PART_RECEIVED:
02033           line = get_next_header_line (connection);
02034           if (line == NULL)
02035             {
02036               if (connection->state != MHD_CONNECTION_FOOTER_PART_RECEIVED)
02037                 continue;
02038               if (connection->read_closed)
02039                 {
02040                   connection->state = MHD_CONNECTION_CLOSED;
02041                   continue;
02042                 }
02043               break;
02044             }
02045           if (MHD_NO ==
02046               process_broken_line (connection, line, MHD_FOOTER_KIND))
02047             continue;
02048           if (strlen (line) == 0)
02049             {
02050               connection->state = MHD_CONNECTION_FOOTERS_RECEIVED;
02051               continue;
02052             }
02053           continue;
02054         case MHD_CONNECTION_FOOTERS_RECEIVED:
02055           call_connection_handler (connection); /* "final" call */
02056           if (connection->state == MHD_CONNECTION_CLOSED)
02057             continue;
02058           if (connection->response == NULL)
02059             break;              /* try again next time */
02060           if (MHD_NO == build_header_response (connection))
02061             {
02062               /* oops - close! */
02063 #if HAVE_MESSAGES
02064               MHD_DLOG (connection->daemon,
02065                         "Closing connection (failed to create response header)\n");
02066 #endif
02067               connection->state = MHD_CONNECTION_CLOSED;
02068               continue;
02069             }
02070           connection->state = MHD_CONNECTION_HEADERS_SENDING;
02071 
02072 #if HAVE_DECL_TCP_CORK
02073           /* starting header send, set TCP cork */
02074           {
02075             const int val = 1;
02076             setsockopt (connection->socket_fd, IPPROTO_TCP, TCP_CORK, &val,
02077                         sizeof (val));
02078           }
02079 #endif
02080           break;
02081         case MHD_CONNECTION_HEADERS_SENDING:
02082           /* no default action */
02083           break;
02084         case MHD_CONNECTION_HEADERS_SENT:
02085           if (connection->have_chunked_upload)
02086             connection->state = MHD_CONNECTION_CHUNKED_BODY_UNREADY;
02087           else
02088             connection->state = MHD_CONNECTION_NORMAL_BODY_UNREADY;
02089           continue;
02090         case MHD_CONNECTION_NORMAL_BODY_READY:
02091           /* nothing to do here */
02092           break;
02093         case MHD_CONNECTION_NORMAL_BODY_UNREADY:
02094           if (connection->response->crc != NULL)
02095             pthread_mutex_lock (&connection->response->mutex);
02096           if (MHD_YES == try_ready_normal_body (connection))
02097             {
02098               if (connection->response->crc != NULL)
02099                 pthread_mutex_unlock (&connection->response->mutex);
02100               connection->state = MHD_CONNECTION_NORMAL_BODY_READY;
02101               break;
02102             }
02103           if (connection->response->crc != NULL)
02104             pthread_mutex_unlock (&connection->response->mutex);
02105           /* not ready, no socket action */
02106           break;
02107         case MHD_CONNECTION_CHUNKED_BODY_READY:
02108           /* nothing to do here */
02109           break;
02110         case MHD_CONNECTION_CHUNKED_BODY_UNREADY:
02111           if (connection->response->crc != NULL)
02112             pthread_mutex_lock (&connection->response->mutex);
02113           if (MHD_YES == try_ready_chunked_body (connection))
02114             {
02115               if (connection->response->crc != NULL)
02116                 pthread_mutex_unlock (&connection->response->mutex);
02117               connection->state = MHD_CONNECTION_CHUNKED_BODY_READY;
02118               continue;
02119             }
02120           if (connection->response->crc != NULL)
02121             pthread_mutex_unlock (&connection->response->mutex);
02122           break;
02123         case MHD_CONNECTION_BODY_SENT:
02124           build_header_response (connection);
02125           if (connection->write_buffer_send_offset ==
02126               connection->write_buffer_append_offset)
02127             connection->state = MHD_CONNECTION_FOOTERS_SENT;
02128           else
02129             connection->state = MHD_CONNECTION_FOOTERS_SENDING;
02130           continue;
02131         case MHD_CONNECTION_FOOTERS_SENDING:
02132           /* no default action */
02133           break;
02134         case MHD_CONNECTION_FOOTERS_SENT:
02135 #if HAVE_DECL_TCP_CORK
02136           /* done sending, uncork */
02137           {
02138             const int val = 0;
02139             setsockopt (connection->socket_fd, IPPROTO_TCP, TCP_CORK, &val,
02140                         sizeof (val));
02141           }
02142 #endif
02143           MHD_destroy_response (connection->response);
02144           if (connection->daemon->notify_completed != NULL)
02145             {
02146               connection->daemon->notify_completed (connection->daemon->
02147                                                     notify_completed_cls,
02148                                                     connection,
02149                                                     &connection->client_context,
02150                                                     MHD_REQUEST_TERMINATED_COMPLETED_OK);
02151             }
02152           connection->client_aware = MHD_NO;
02153           end =
02154             MHD_lookup_connection_value (connection, MHD_HEADER_KIND,
02155                                          MHD_HTTP_HEADER_CONNECTION);
02156           connection->client_context = NULL;
02157           connection->continue_message_write_offset = 0;
02158           connection->responseCode = 0;
02159           connection->response = NULL;
02160           connection->headers_received = NULL;
02161           connection->response_write_position = 0;
02162           connection->have_chunked_upload = MHD_NO;
02163           connection->method = NULL;
02164           connection->url = NULL;
02165           connection->write_buffer = NULL;
02166           connection->write_buffer_size = 0;
02167           connection->write_buffer_send_offset = 0;
02168           connection->write_buffer_append_offset = 0;
02169           if ((end != NULL) && (0 == strcasecmp (end, "close")))
02170             {
02171               connection->read_closed = MHD_YES;
02172               connection->read_buffer_offset = 0;
02173             }
02174           if (((MHD_YES == connection->read_closed) &&
02175                (0 == connection->read_buffer_offset)) ||
02176               (connection->version == NULL) ||
02177               (0 != strcasecmp (MHD_HTTP_VERSION_1_1, connection->version)))
02178             {
02179               /* http 1.0, version-less requests cannot be pipelined */
02180               connection->state = MHD_CONNECTION_CLOSED;
02181               MHD_pool_destroy (connection->pool);
02182               connection->pool = NULL;
02183               connection->read_buffer = NULL;
02184               connection->read_buffer_size = 0;
02185               connection->read_buffer_offset = 0;
02186             }
02187           else
02188             {
02189               connection->version = NULL;
02190               connection->state = MHD_CONNECTION_INIT;
02191               connection->read_buffer
02192                 = MHD_pool_reset (connection->pool,
02193                                   connection->read_buffer,
02194                                   connection->read_buffer_size);
02195             }
02196           continue;
02197         case MHD_CONNECTION_CLOSED:
02198           if (connection->socket_fd != -1)
02199             connection_close_error (connection);
02200           break;
02201         default:
02202           EXTRA_CHECK (0);
02203           break;
02204         }
02205       break;
02206     }
02207   timeout = connection->daemon->connection_timeout;
02208   if ((connection->socket_fd != -1) &&
02209       (timeout != 0) && (time (NULL) - timeout > connection->last_activity))
02210     {
02211       MHD_connection_close (connection, MHD_REQUEST_TERMINATED_TIMEOUT_REACHED);
02212       return MHD_NO;
02213     }
02214   return MHD_YES;
02215 
02216 }
02217 
02218 void
02219 MHD_set_http_calbacks (struct MHD_Connection *connection)
02220 {
02221   connection->read_handler = &MHD_connection_handle_read;
02222   connection->write_handler = &MHD_connection_handle_write;
02223   connection->idle_handler = &MHD_connection_handle_idle;
02224 }
02225 
02226 #if HTTPS_SUPPORT
02227 #include "gnutls_int.h"
02228 #include "gnutls_record.h"
02229 #endif
02230 
02240 const union MHD_ConnectionInfo *
02241 MHD_get_connection_info (struct MHD_Connection *connection,
02242                          enum MHD_ConnectionInfoType infoType, ...)
02243 {
02244   switch (infoType)
02245     {
02246 #if HTTPS_SUPPORT
02247     case MHD_CONNECTION_INFO_CIPHER_ALGO:
02248       if (connection->tls_session == NULL)
02249         return NULL;
02250       return (const union MHD_ConnectionInfo *) &connection->
02251         tls_session->security_parameters.read_bulk_cipher_algorithm;
02252     case MHD_CONNECTION_INFO_PROTOCOL:
02253       if (connection->tls_session == NULL)
02254         return NULL;
02255       return (const union MHD_ConnectionInfo *) &connection->
02256         tls_session->security_parameters.version;
02257 #endif
02258     case MHD_CONNECTION_INFO_CLIENT_ADDRESS:
02259       return (const union MHD_ConnectionInfo *) &connection->addr;
02260     default:
02261       return NULL;
02262     };
02263 }
02264 
02265 
02266 /* end of connection.c */
Generated by  doxygen 1.6.2-20100208