connection.c

Go to the documentation of this file.
00001 /*
00002     This file is part of libmicrohttpd
00003      (C) 2007, 2008, 2009, 2010, 2011, 2012 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 <limits.h>
00030 #include "connection.h"
00031 #include "memorypool.h"
00032 #include "response.h"
00033 #include "reason_phrase.h"
00034 
00035 #if HAVE_NETINET_TCP_H
00036 /* for TCP_CORK */
00037 #include <netinet/tcp.h>
00038 #endif
00039 
00043 #define HTTP_100_CONTINUE "HTTP/1.1 100 Continue\r\n\r\n"
00044 
00052 #if HAVE_MESSAGES
00053 #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>"
00054 #else
00055 #define REQUEST_TOO_BIG ""
00056 #endif
00057 
00065 #if HAVE_MESSAGES
00066 #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>"
00067 #else
00068 #define REQUEST_LACKS_HOST ""
00069 #endif
00070 
00078 #if HAVE_MESSAGES
00079 #define REQUEST_MALFORMED "<html><head><title>Request malformed</title></head><body>Your HTTP request was syntactically incorrect.</body></html>"
00080 #else
00081 #define REQUEST_MALFORMED ""
00082 #endif
00083 
00090 #if HAVE_MESSAGES
00091 #define INTERNAL_ERROR "<html><head><title>Internal server error</title></head><body>Some programmer needs to study the manual more carefully.</body></html>"
00092 #else
00093 #define INTERNAL_ERROR ""
00094 #endif
00095 
00100 #define DEBUG_CLOSE MHD_NO
00101 
00105 #define DEBUG_SEND_DATA MHD_NO
00106 
00107 
00118 int
00119 MHD_get_connection_values (struct MHD_Connection *connection,
00120                            enum MHD_ValueKind kind,
00121                            MHD_KeyValueIterator iterator, void *iterator_cls)
00122 {
00123   int ret;
00124   struct MHD_HTTP_Header *pos;
00125 
00126   if (NULL == connection)
00127     return -1;
00128   ret = 0;
00129   for (pos = connection->headers_received; NULL != pos; pos = pos->next)
00130     if (0 != (pos->kind & kind))
00131       {
00132         ret++;
00133         if ((NULL != iterator) &&
00134             (MHD_YES != iterator (iterator_cls,
00135                                   kind, pos->header, pos->value)))
00136           return ret;
00137       }
00138   return ret;
00139 }
00140 
00141 
00171 int
00172 MHD_set_connection_value (struct MHD_Connection *connection,
00173                           enum MHD_ValueKind kind,
00174                           const char *key, const char *value)
00175 {
00176   struct MHD_HTTP_Header *pos;
00177 
00178   pos = MHD_pool_allocate (connection->pool,
00179                            sizeof (struct MHD_HTTP_Header), MHD_NO);
00180   if (NULL == pos)
00181     return MHD_NO;
00182   pos->header = (char *) key;
00183   pos->value = (char *) value;
00184   pos->kind = kind;
00185   pos->next = NULL;
00186   /* append 'pos' to the linked list of headers */
00187   if (NULL == connection->headers_received_tail)
00188   {
00189     connection->headers_received = pos;
00190     connection->headers_received_tail = pos;
00191   }
00192   else
00193   {
00194     connection->headers_received_tail->next = pos;
00195     connection->headers_received_tail = pos;
00196   }
00197   return MHD_YES;
00198 }
00199 
00200 
00210 const char *
00211 MHD_lookup_connection_value (struct MHD_Connection *connection,
00212                              enum MHD_ValueKind kind, const char *key)
00213 {
00214   struct MHD_HTTP_Header *pos;
00215 
00216   if (NULL == connection)
00217     return NULL;
00218   for (pos = connection->headers_received; NULL != pos; pos = pos->next)
00219     if ((0 != (pos->kind & kind)) && 
00220         ( (key == pos->header) ||
00221           ( (NULL != pos->header) &&
00222             (NULL != key) &&
00223             (0 == strcasecmp (key, pos->header))) ))
00224       return pos->value;    
00225   return NULL;
00226 }
00227 
00228 
00239 int
00240 MHD_queue_response (struct MHD_Connection *connection,
00241                     unsigned int status_code, struct MHD_Response *response)
00242 {
00243   if ( (NULL == connection) ||
00244        (NULL == response) ||
00245        (NULL != connection->response) ||
00246        ( (MHD_CONNECTION_HEADERS_PROCESSED != connection->state) &&
00247          (MHD_CONNECTION_FOOTERS_RECEIVED != connection->state) ) )
00248     return MHD_NO;
00249   MHD_increment_response_rc (response);
00250   connection->response = response;
00251   connection->responseCode = status_code;
00252   if ( (NULL != connection->method) &&
00253        (0 == strcasecmp (connection->method, MHD_HTTP_METHOD_HEAD)) )
00254     {
00255       /* if this is a "HEAD" request, pretend that we
00256          have already sent the full message body */
00257       connection->response_write_position = response->total_size;
00258     }
00259   if (MHD_CONNECTION_HEADERS_PROCESSED == connection->state)
00260     {
00261       /* response was queued "early",
00262          refuse to read body / footers or further
00263          requests! */
00264       (void) SHUTDOWN (connection->socket_fd, SHUT_RD);
00265       connection->read_closed = MHD_YES;
00266       connection->state = MHD_CONNECTION_FOOTERS_RECEIVED;
00267     }
00268   return MHD_YES;
00269 }
00270 
00271 
00279 static int
00280 need_100_continue (struct MHD_Connection *connection)
00281 {
00282   const char *expect;
00283 
00284   return ( (NULL == connection->response) &&
00285            (NULL != connection->version) &&
00286            (0 == strcasecmp (connection->version,
00287                              MHD_HTTP_VERSION_1_1)) &&
00288            (NULL != (expect = MHD_lookup_connection_value (connection,
00289                                                            MHD_HEADER_KIND,
00290                                                            MHD_HTTP_HEADER_EXPECT))) &&
00291            (0 == strcasecmp (expect, "100-continue")) &&
00292            (connection->continue_message_write_offset <
00293             strlen (HTTP_100_CONTINUE)) );
00294 }
00295 
00296 
00304 void
00305 MHD_connection_close (struct MHD_Connection *connection,
00306                       enum MHD_RequestTerminationCode termination_code)
00307 {
00308   struct MHD_Daemon *daemon;
00309 
00310   daemon = connection->daemon;
00311   SHUTDOWN (connection->socket_fd, 
00312             (connection->read_closed == MHD_YES) ? SHUT_WR : SHUT_RDWR);
00313   connection->state = MHD_CONNECTION_CLOSED;
00314   if ( (NULL != daemon->notify_completed) &&
00315        (MHD_YES == connection->client_aware) )
00316     daemon->notify_completed (daemon->notify_completed_cls, 
00317                               connection,
00318                               &connection->client_context,
00319                               termination_code);
00320   connection->client_aware = MHD_NO;
00321 }
00322 
00323 
00331 static void
00332 connection_close_error (struct MHD_Connection *connection,
00333                         const char *emsg)
00334 {
00335 #if HAVE_MESSAGES
00336   if (NULL != emsg)
00337     MHD_DLOG (connection->daemon, emsg);
00338 #endif
00339   MHD_connection_close (connection, MHD_REQUEST_TERMINATED_WITH_ERROR);
00340 }
00341 
00342 
00347 #if HAVE_MESSAGES
00348 #define CONNECTION_CLOSE_ERROR(c, emsg) connection_close_error (c, emsg)
00349 #else
00350 #define CONNECTION_CLOSE_ERROR(c, emsg) connection_close_error (c, NULL)
00351 #endif
00352 
00353 
00364 static int
00365 try_ready_normal_body (struct MHD_Connection *connection)
00366 {
00367   int ret;
00368   struct MHD_Response *response;
00369 
00370   response = connection->response;
00371   if (NULL == response->crc)
00372     return MHD_YES;
00373   if ( (response->data_start <=
00374         connection->response_write_position) &&
00375        (response->data_size + response->data_start >
00376         connection->response_write_position) )
00377     return MHD_YES; /* response already ready */
00378 #if LINUX
00379   if ( (-1 != response->fd) &&
00380        (0 == (connection->daemon->options & MHD_USE_SSL)) )
00381     {
00382       /* will use sendfile, no need to bother response crc */
00383       return MHD_YES; 
00384     }
00385 #endif
00386   
00387   ret = response->crc (response->crc_cls,
00388                        connection->response_write_position,
00389                        response->data,
00390                        MHD_MIN (response->data_buffer_size,
00391                                 response->total_size -
00392                                 connection->response_write_position));
00393   if ((0 == ret) &&
00394       (0 != (connection->daemon->options & MHD_USE_SELECT_INTERNALLY)))
00395     mhd_panic (mhd_panic_cls, __FILE__, __LINE__, 
00396 #if HAVE_MESSAGES
00397                "API violation"
00398 #else
00399                NULL
00400 #endif
00401                );
00402   if ( (MHD_CONTENT_READER_END_OF_STREAM == ret) ||
00403        (MHD_CONTENT_READER_END_WITH_ERROR == ret) )
00404     {
00405       /* either error or http 1.0 transfer, close socket! */
00406       response->total_size = connection->response_write_position;
00407       CONNECTION_CLOSE_ERROR (connection,
00408                               (ret == MHD_CONTENT_READER_END_OF_STREAM) 
00409                               ? "Closing connection (end of response)\n"
00410                               : "Closing connection (stream error)\n");
00411       return MHD_NO;
00412     }
00413   response->data_start = connection->response_write_position;
00414   response->data_size = ret;
00415   if (0 == ret)
00416     {
00417       connection->state = MHD_CONNECTION_NORMAL_BODY_UNREADY;
00418       return MHD_NO;
00419     }
00420   return MHD_YES;
00421 }
00422 
00423 
00433 static int
00434 try_ready_chunked_body (struct MHD_Connection *connection)
00435 {
00436   int ret;
00437   char *buf;
00438   struct MHD_Response *response;
00439   size_t size;
00440   char cbuf[10];                /* 10: max strlen of "%x\r\n" */
00441   int cblen;
00442 
00443   response = connection->response;
00444   if (0 == connection->write_buffer_size)
00445     {
00446       size = connection->daemon->pool_size;
00447       do
00448         {
00449           size /= 2;
00450           if (size < 128)
00451             {
00452               /* not enough memory */
00453               CONNECTION_CLOSE_ERROR (connection,
00454                                       "Closing connection (out of memory)\n");
00455               return MHD_NO;
00456             }
00457           buf = MHD_pool_allocate (connection->pool, size, MHD_NO);
00458         }
00459       while (NULL == buf);
00460       connection->write_buffer_size = size;
00461       connection->write_buffer = buf;
00462     }
00463 
00464   if ( (response->data_start <=
00465         connection->response_write_position) &&
00466        (response->data_size + response->data_start >
00467         connection->response_write_position) )
00468     {
00469       /* buffer already ready, use what is there for the chunk */
00470       ret = response->data_size + response->data_start - connection->response_write_position;
00471       if (ret > connection->write_buffer_size - sizeof (cbuf) - 2)
00472         ret = connection->write_buffer_size - sizeof (cbuf) - 2;
00473       memcpy (&connection->write_buffer[sizeof (cbuf)],
00474               &response->data[connection->response_write_position - response->data_start],
00475               ret);
00476     }
00477   else
00478     {
00479       /* buffer not in range, try to fill it */
00480       ret = response->crc (response->crc_cls,
00481                            connection->response_write_position,
00482                            &connection->write_buffer[sizeof (cbuf)],
00483                            connection->write_buffer_size - sizeof (cbuf) - 2);
00484     }
00485   if (MHD_CONTENT_READER_END_WITH_ERROR == ret)
00486     {
00487       /* error, close socket! */
00488       response->total_size = connection->response_write_position;
00489       CONNECTION_CLOSE_ERROR (connection,
00490                               "Closing connection (error generating response)\n");
00491       return MHD_NO;
00492     }
00493   if (MHD_CONTENT_READER_END_OF_STREAM == ret) 
00494     {
00495       /* end of message, signal other side! */
00496       strcpy (connection->write_buffer, "0\r\n");
00497       connection->write_buffer_append_offset = 3;
00498       connection->write_buffer_send_offset = 0;
00499       response->total_size = connection->response_write_position;
00500       return MHD_YES;
00501     }
00502   if (0 == ret)
00503     {
00504       connection->state = MHD_CONNECTION_CHUNKED_BODY_UNREADY;
00505       return MHD_NO;
00506     }
00507   if (ret > 0xFFFFFF)
00508     ret = 0xFFFFFF;
00509   snprintf (cbuf, 
00510             sizeof (cbuf),
00511             "%X\r\n", ret);
00512   cblen = strlen (cbuf);
00513   EXTRA_CHECK (cblen <= sizeof (cbuf));
00514   memcpy (&connection->write_buffer[sizeof (cbuf) - cblen], cbuf, cblen);
00515   memcpy (&connection->write_buffer[sizeof (cbuf) + ret], "\r\n", 2);
00516   connection->response_write_position += ret;
00517   connection->write_buffer_send_offset = sizeof (cbuf) - cblen;
00518   connection->write_buffer_append_offset = sizeof (cbuf) + ret + 2;
00519   return MHD_YES;
00520 }
00521 
00522 
00529 static void
00530 add_extra_headers (struct MHD_Connection *connection)
00531 {
00532   const char *have;
00533   char buf[128];
00534 
00535   connection->have_chunked_upload = MHD_NO;
00536   if (MHD_SIZE_UNKNOWN == connection->response->total_size)
00537     {
00538       have = MHD_get_response_header (connection->response,
00539                                       MHD_HTTP_HEADER_CONNECTION);
00540       if ((NULL == have) || (0 != strcasecmp (have, "close")))
00541         {
00542           if ((NULL != connection->version) &&
00543               (0 == strcasecmp (connection->version, MHD_HTTP_VERSION_1_1)))
00544             {
00545               connection->have_chunked_upload = MHD_YES;
00546               have = MHD_get_response_header (connection->response,
00547                                               MHD_HTTP_HEADER_TRANSFER_ENCODING);
00548               if (NULL == have)
00549                 MHD_add_response_header (connection->response,
00550                                          MHD_HTTP_HEADER_TRANSFER_ENCODING,
00551                                          "chunked");
00552             }
00553           else
00554             {
00555               MHD_add_response_header (connection->response,
00556                                        MHD_HTTP_HEADER_CONNECTION, "close");
00557             }
00558         }
00559     }
00560   else if (NULL == MHD_get_response_header (connection->response,
00561                                             MHD_HTTP_HEADER_CONTENT_LENGTH))
00562     {
00563       SPRINTF (buf,
00564                "%" MHD_LONG_LONG_PRINTF "u",
00565                (unsigned MHD_LONG_LONG) connection->response->total_size);
00566       MHD_add_response_header (connection->response,
00567                                MHD_HTTP_HEADER_CONTENT_LENGTH, buf);
00568     }
00569 }
00570 
00571 
00578 static void
00579 get_date_string (char *date)
00580 {
00581   static const char *days[] =
00582     { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" };
00583   static const char *mons[] =
00584     { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct",
00585     "Nov", "Dec"
00586   };
00587   struct tm now;
00588   time_t t;
00589 
00590   time (&t);
00591   gmtime_r (&t, &now);
00592   SPRINTF (date,
00593            "Date: %3s, %02u %3s %04u %02u:%02u:%02u GMT\r\n",
00594            days[now.tm_wday % 7],
00595            now.tm_mday,
00596            mons[now.tm_mon % 12],
00597            1900 + now.tm_year, now.tm_hour, now.tm_min, now.tm_sec);
00598 }
00599 
00600 
00607 static int
00608 try_grow_read_buffer (struct MHD_Connection *connection)
00609 {
00610   void *buf;
00611 
00612   buf = MHD_pool_reallocate (connection->pool,
00613                              connection->read_buffer,
00614                              connection->read_buffer_size,
00615                              connection->read_buffer_size * 2 +
00616                              MHD_BUF_INC_SIZE + 1);
00617   if (NULL == buf)
00618     return MHD_NO;
00619   /* we can actually grow the buffer, do it! */
00620   connection->read_buffer = buf;
00621   connection->read_buffer_size =
00622     connection->read_buffer_size * 2 + MHD_BUF_INC_SIZE;
00623   return MHD_YES;
00624 }
00625 
00626 
00634 static int
00635 build_header_response (struct MHD_Connection *connection)
00636 {
00637   size_t size;
00638   size_t off;
00639   struct MHD_HTTP_Header *pos;
00640   char code[256];
00641   char date[128];
00642   char *data;
00643   enum MHD_ValueKind kind;
00644   const char *reason_phrase;
00645   uint32_t rc;
00646   int must_add_close;
00647 
00648   EXTRA_CHECK (NULL != connection->version);
00649   if (0 == strlen(connection->version))
00650     {
00651       data = MHD_pool_allocate (connection->pool, 0, MHD_YES);
00652       connection->write_buffer = data;
00653       connection->write_buffer_append_offset = 0;
00654       connection->write_buffer_send_offset = 0;
00655       connection->write_buffer_size = 0;
00656       return MHD_YES;
00657     }
00658   if (MHD_CONNECTION_FOOTERS_RECEIVED == connection->state)
00659     {
00660       add_extra_headers (connection);
00661       rc = connection->responseCode & (~MHD_ICY_FLAG);
00662       reason_phrase = MHD_get_reason_phrase_for (rc);
00663       SPRINTF (code,
00664                "%s %u %s\r\n",
00665                (0 != (connection->responseCode & MHD_ICY_FLAG))
00666                ? "ICY" 
00667                : ( (0 == strcasecmp (MHD_HTTP_VERSION_1_0,
00668                                      connection->version)) 
00669                    ? MHD_HTTP_VERSION_1_0 
00670                    : MHD_HTTP_VERSION_1_1),
00671                rc, 
00672                reason_phrase);
00673       off = strlen (code);
00674       /* estimate size */
00675       size = off + 2;           /* extra \r\n at the end */
00676       kind = MHD_HEADER_KIND;
00677       if ( (0 == (connection->daemon->options & MHD_SUPPRESS_DATE_NO_CLOCK)) && 
00678            (NULL == MHD_get_response_header (connection->response,
00679                                              MHD_HTTP_HEADER_DATE)) )
00680         get_date_string (date);
00681       else
00682         date[0] = '\0';
00683       size += strlen (date);
00684     }
00685   else
00686     {
00687       size = 2;
00688       kind = MHD_FOOTER_KIND;
00689       off = 0;
00690     }
00691   must_add_close = ( (connection->state == MHD_CONNECTION_FOOTERS_RECEIVED) &&
00692                      (connection->read_closed == MHD_YES) &&
00693                      (0 == strcasecmp (connection->version,
00694                                        MHD_HTTP_VERSION_1_1)) &&
00695                      (NULL == MHD_get_response_header (connection->response,
00696                                                        MHD_HTTP_HEADER_CONNECTION)) );
00697   if (must_add_close)
00698     size += strlen ("Connection: close\r\n");
00699   for (pos = connection->response->first_header; NULL != pos; pos = pos->next)
00700     if (pos->kind == kind)
00701       size += strlen (pos->header) + strlen (pos->value) + 4; /* colon, space, linefeeds */
00702   /* produce data */
00703   data = MHD_pool_allocate (connection->pool, size + 1, MHD_YES);
00704   if (NULL == data)
00705     {
00706 #if HAVE_MESSAGES
00707       MHD_DLOG (connection->daemon, "Not enough memory for write!\n");
00708 #endif
00709       return MHD_NO;
00710     }
00711   if (MHD_CONNECTION_FOOTERS_RECEIVED == connection->state)
00712     {
00713       memcpy (data, code, off);
00714     }
00715   if (must_add_close)
00716     {
00717       /* we must add the 'close' header because circumstances forced us to
00718          stop reading from the socket; however, we are not adding the header
00719          to the response as the response may be used in a different context
00720          as well */
00721       memcpy (&data[off], "Connection: close\r\n",
00722               strlen ("Connection: close\r\n"));
00723       off += strlen ("Connection: close\r\n");
00724     }
00725   for (pos = connection->response->first_header; NULL != pos; pos = pos->next)
00726     if (pos->kind == kind)
00727       off += SPRINTF (&data[off], 
00728                       "%s: %s\r\n",
00729                       pos->header, 
00730                       pos->value);
00731   if (connection->state == MHD_CONNECTION_FOOTERS_RECEIVED)
00732     {
00733       strcpy (&data[off], date);
00734       off += strlen (date);
00735     }
00736   memcpy (&data[off], "\r\n", 2);
00737   off += 2;
00738 
00739   if (off != size)
00740     mhd_panic (mhd_panic_cls, __FILE__, __LINE__, NULL);
00741   connection->write_buffer = data;
00742   connection->write_buffer_append_offset = size;
00743   connection->write_buffer_send_offset = 0;
00744   connection->write_buffer_size = size + 1;
00745   return MHD_YES;
00746 }
00747 
00748 
00758 static void
00759 transmit_error_response (struct MHD_Connection *connection,
00760                          unsigned int status_code, 
00761                          const char *message)
00762 {
00763   struct MHD_Response *response;
00764 
00765   if (NULL == connection->version)
00766     {
00767       /* we were unable to process the full header line, so we don't
00768          really know what version the client speaks; assume 1.0 */
00769       connection->version = MHD_HTTP_VERSION_1_0;
00770     }
00771   connection->state = MHD_CONNECTION_FOOTERS_RECEIVED;
00772   connection->read_closed = MHD_YES;
00773 #if HAVE_MESSAGES
00774   MHD_DLOG (connection->daemon,
00775             "Error %u (`%s') processing request, closing connection.\n",
00776             status_code, message);
00777 #endif
00778   EXTRA_CHECK (connection->response == NULL);
00779   response = MHD_create_response_from_buffer (strlen (message),
00780                                               (void *) message, 
00781                                               MHD_RESPMEM_PERSISTENT);
00782   MHD_queue_response (connection, status_code, response);
00783   EXTRA_CHECK (connection->response != NULL);
00784   MHD_destroy_response (response);
00785   if (MHD_NO == build_header_response (connection))
00786     {
00787       /* oops - close! */
00788       CONNECTION_CLOSE_ERROR (connection,
00789                               "Closing connection (failed to create response header)\n");
00790     }
00791   else
00792     {
00793       connection->state = MHD_CONNECTION_HEADERS_SENDING;
00794     }
00795 }
00796 
00797 
00806 static void
00807 add_to_fd_set (int fd, 
00808                fd_set *set, 
00809                int *max_fd)
00810 {
00811   FD_SET (fd, set);
00812   if ( (NULL != max_fd) &&
00813        (fd > *max_fd) )
00814     *max_fd = fd;
00815 }
00816 
00817 
00830 int
00831 MHD_connection_get_fdset (struct MHD_Connection *connection,
00832                           fd_set *read_fd_set,
00833                           fd_set *write_fd_set,
00834                           fd_set *except_fd_set, 
00835                           int *max_fd)
00836 {
00837   int ret;
00838   struct MHD_Pollfd p;
00839 
00840   /* we use the 'poll fd' as a convenient way to re-use code 
00841      when determining the select sets */
00842   memset (&p, 0, sizeof(struct MHD_Pollfd));
00843   ret = MHD_connection_get_pollfd (connection, &p);
00844   if ( (MHD_YES == ret) && (p.fd >= 0) ) {
00845     if (0 != (p.events & MHD_POLL_ACTION_IN)) 
00846       add_to_fd_set(p.fd, read_fd_set, max_fd);    
00847     if (0 != (p.events & MHD_POLL_ACTION_OUT)) 
00848       add_to_fd_set(p.fd, write_fd_set, max_fd);    
00849   }
00850   return ret;
00851 }
00852 
00853 
00862 int
00863 MHD_connection_get_pollfd (struct MHD_Connection *connection, 
00864                            struct MHD_Pollfd *p)
00865 {
00866   int fd;
00867 
00868   if (NULL == connection->pool)
00869     connection->pool = MHD_pool_create (connection->daemon->pool_size);
00870   if (NULL == connection->pool)
00871     {
00872       CONNECTION_CLOSE_ERROR (connection,
00873                               "Failed to create memory pool!\n");
00874       return MHD_YES;
00875     }
00876   fd = connection->socket_fd;
00877   p->fd = fd;
00878   if (-1 == fd)
00879     return MHD_YES;
00880   while (1)
00881     {
00882 #if DEBUG_STATES
00883       MHD_DLOG (connection->daemon, "%s: state: %s\n",
00884                 __FUNCTION__, MHD_state_to_string (connection->state));
00885 #endif
00886       switch (connection->state)
00887         {
00888 #if HTTPS_SUPPORT     
00889         case MHD_TLS_CONNECTION_INIT:
00890           if (0 == gnutls_record_get_direction (connection->tls_session))
00891             p->events |= MHD_POLL_ACTION_IN;
00892           else
00893             p->events |= MHD_POLL_ACTION_OUT;
00894           break;
00895 #endif
00896         case MHD_CONNECTION_INIT:
00897         case MHD_CONNECTION_URL_RECEIVED:
00898         case MHD_CONNECTION_HEADER_PART_RECEIVED:
00899           /* while reading headers, we always grow the
00900              read buffer if needed, no size-check required */
00901           if ((connection->read_closed) &&
00902               (0 == connection->read_buffer_offset))
00903             {
00904               CONNECTION_CLOSE_ERROR (connection, 
00905                                       "Connection buffer to small for request\n");
00906               continue;
00907             }
00908           if ((connection->read_buffer_offset == connection->read_buffer_size)
00909               && (MHD_NO == try_grow_read_buffer (connection)))
00910             {
00911               transmit_error_response (connection,
00912                                        (connection->url != NULL)
00913                                        ? MHD_HTTP_REQUEST_ENTITY_TOO_LARGE
00914                                        : MHD_HTTP_REQUEST_URI_TOO_LONG,
00915                                        REQUEST_TOO_BIG);
00916               continue;
00917             }
00918           if (MHD_NO == connection->read_closed)
00919             p->events |= MHD_POLL_ACTION_IN;
00920           break;
00921         case MHD_CONNECTION_HEADERS_RECEIVED:
00922           /* we should never get here */
00923           EXTRA_CHECK (0);
00924           break;
00925         case MHD_CONNECTION_HEADERS_PROCESSED:
00926           EXTRA_CHECK (0);
00927           break;
00928         case MHD_CONNECTION_CONTINUE_SENDING:
00929           p->events |= MHD_POLL_ACTION_OUT;
00930           break;
00931         case MHD_CONNECTION_CONTINUE_SENT:
00932           if (connection->read_buffer_offset == connection->read_buffer_size)
00933             {
00934               if ((MHD_YES != try_grow_read_buffer (connection)) &&
00935                   (0 != (connection->daemon->options &
00936                          (MHD_USE_SELECT_INTERNALLY |
00937                           MHD_USE_THREAD_PER_CONNECTION))))
00938                 {
00939                   /* failed to grow the read buffer, and the
00940                      client which is supposed to handle the
00941                      received data in a *blocking* fashion
00942                      (in this mode) did not handle the data as
00943                      it was supposed to!
00944                      => we would either have to do busy-waiting
00945                      (on the client, which would likely fail),
00946                      or if we do nothing, we would just timeout
00947                      on the connection (if a timeout is even
00948                      set!).
00949                      Solution: we kill the connection with an error */
00950                   transmit_error_response (connection,
00951                                            MHD_HTTP_INTERNAL_SERVER_ERROR,
00952                                            INTERNAL_ERROR);
00953                   continue;
00954                 }
00955             }
00956           if ((connection->read_buffer_offset < connection->read_buffer_size)
00957               && (MHD_NO == connection->read_closed))
00958             p->events |= MHD_POLL_ACTION_IN;
00959           break;
00960         case MHD_CONNECTION_BODY_RECEIVED:
00961         case MHD_CONNECTION_FOOTER_PART_RECEIVED:
00962           /* while reading footers, we always grow the
00963              read buffer if needed, no size-check required */
00964           if (MHD_YES == connection->read_closed)
00965             {
00966               CONNECTION_CLOSE_ERROR (connection, 
00967                                       NULL);
00968               continue;
00969             }
00970           p->events |= MHD_POLL_ACTION_IN;
00971           /* transition to FOOTERS_RECEIVED
00972              happens in read handler */
00973           break;
00974         case MHD_CONNECTION_FOOTERS_RECEIVED:
00975           /* no socket action, wait for client
00976              to provide response */
00977           break;
00978         case MHD_CONNECTION_HEADERS_SENDING:
00979           /* headers in buffer, keep writing */
00980           p->events |= MHD_POLL_ACTION_OUT;
00981           break;
00982         case MHD_CONNECTION_HEADERS_SENT:
00983           EXTRA_CHECK (0);
00984           break;
00985         case MHD_CONNECTION_NORMAL_BODY_READY:
00986           p->events |= MHD_POLL_ACTION_OUT;
00987           break;
00988         case MHD_CONNECTION_NORMAL_BODY_UNREADY:
00989           /* not ready, no socket action */
00990           break;
00991         case MHD_CONNECTION_CHUNKED_BODY_READY:
00992           p->events |= MHD_POLL_ACTION_OUT;
00993           break;
00994         case MHD_CONNECTION_CHUNKED_BODY_UNREADY:
00995           /* not ready, no socket action */
00996           break;
00997         case MHD_CONNECTION_BODY_SENT:
00998           EXTRA_CHECK (0);
00999           break;
01000         case MHD_CONNECTION_FOOTERS_SENDING:
01001           p->events |= MHD_POLL_ACTION_OUT;
01002           break;
01003         case MHD_CONNECTION_FOOTERS_SENT:
01004           EXTRA_CHECK (0);
01005           break;
01006         case MHD_CONNECTION_CLOSED:
01007           return MHD_YES;       /* do nothing, not even reading */
01008         default:
01009           EXTRA_CHECK (0);
01010         }
01011       break;
01012     }
01013   return MHD_YES;
01014 }
01015 
01016 
01025 static char *
01026 get_next_header_line (struct MHD_Connection *connection)
01027 {
01028   char *rbuf;
01029   size_t pos;
01030 
01031   if (0 == connection->read_buffer_offset)
01032     return NULL;
01033   pos = 0;
01034   rbuf = connection->read_buffer;
01035   while ((pos < connection->read_buffer_offset - 1) &&
01036          ('\r' != rbuf[pos]) && ('\n' != rbuf[pos]))
01037     pos++;
01038   if (pos == connection->read_buffer_offset - 1)
01039     {
01040       /* not found, consider growing... */
01041       if (connection->read_buffer_offset == connection->read_buffer_size)
01042         {
01043           rbuf = MHD_pool_reallocate (connection->pool,
01044                                       connection->read_buffer,
01045                                       connection->read_buffer_size,
01046                                       connection->read_buffer_size * 2 +
01047                                       MHD_BUF_INC_SIZE);
01048           if (NULL == rbuf)
01049             {
01050               transmit_error_response (connection,
01051                                        (NULL != connection->url)
01052                                        ? MHD_HTTP_REQUEST_ENTITY_TOO_LARGE
01053                                        : MHD_HTTP_REQUEST_URI_TOO_LONG,
01054                                        REQUEST_TOO_BIG);
01055             }
01056           else
01057             {
01058               connection->read_buffer_size =
01059                 connection->read_buffer_size * 2 + MHD_BUF_INC_SIZE;
01060               connection->read_buffer = rbuf;
01061             }
01062         }
01063       return NULL;
01064     }
01065   /* found, check if we have proper CRLF */
01066   if (('\r' == rbuf[pos]) && ('\n' == rbuf[pos + 1]))
01067     rbuf[pos++] = '\0';         /* skip both r and n */
01068   rbuf[pos++] = '\0';
01069   connection->read_buffer += pos;
01070   connection->read_buffer_size -= pos;
01071   connection->read_buffer_offset -= pos;
01072   return rbuf;
01073 }
01074 
01075 
01087 static int
01088 connection_add_header (struct MHD_Connection *connection,
01089                        char *key, char *value, enum MHD_ValueKind kind)
01090 {
01091   if (MHD_NO == MHD_set_connection_value (connection,
01092                                           kind,
01093                                           key, value))
01094     {
01095 #if HAVE_MESSAGES
01096       MHD_DLOG (connection->daemon,
01097                 "Not enough memory to allocate header record!\n");
01098 #endif
01099       transmit_error_response (connection, MHD_HTTP_REQUEST_ENTITY_TOO_LARGE,
01100                                REQUEST_TOO_BIG);
01101       return MHD_NO;
01102     }
01103   return MHD_YES;
01104 }
01105 
01106 
01116 static int
01117 parse_arguments (enum MHD_ValueKind kind,
01118                  struct MHD_Connection *connection, 
01119                  char *args)
01120 {
01121   char *equals;
01122   char *amper;
01123 
01124   while (NULL != args)
01125     {
01126       equals = strchr (args, '=');
01127       amper = strchr (args, '&');
01128       if (NULL == amper)
01129         {
01130           /* last argument */
01131           if (NULL == equals)
01132             {
01133               /* got 'foo', add key 'foo' with NULL for value */
01134               connection->daemon->unescape_callback (connection->daemon->unescape_callback_cls,
01135                                                      connection,
01136                                                      args);
01137               return connection_add_header (connection,
01138                                             args,
01139                                             NULL,
01140                                             kind);            
01141             }
01142           /* got 'foo=bar' */
01143           equals[0] = '\0';
01144           equals++;
01145           connection->daemon->unescape_callback (connection->daemon->unescape_callback_cls,
01146                                                  connection,
01147                                                  args);
01148           connection->daemon->unescape_callback (connection->daemon->unescape_callback_cls,
01149                                                  connection,
01150                                                  equals);
01151           return connection_add_header (connection, args, equals, kind);
01152         }
01153       /* amper is non-NULL here */
01154       amper[0] = '\0';
01155       amper++;
01156       if ( (NULL == equals) ||
01157            (equals >= amper) )
01158         {
01159           /* got 'foo&bar' or 'foo&bar=val', add key 'foo' with NULL for value */
01160           connection->daemon->unescape_callback (connection->daemon->unescape_callback_cls,
01161                                                  connection,
01162                                                  args);
01163           if (MHD_NO ==
01164               connection_add_header (connection,
01165                                      args,
01166                                      NULL,
01167                                      kind))
01168             return MHD_NO;
01169           /* continue with 'bar' */
01170           args = amper;
01171           continue;
01172 
01173         }
01174       /* equals and amper are non-NULL here, and equals < amper,
01175          so we got regular 'foo=value&bar...'-kind of argument */
01176       equals[0] = '\0';
01177       equals++;
01178       connection->daemon->unescape_callback (connection->daemon->unescape_callback_cls,
01179                                              connection,
01180                                              args);
01181       connection->daemon->unescape_callback (connection->daemon->unescape_callback_cls,
01182                                              connection,
01183                                              equals);
01184       if (MHD_NO == connection_add_header (connection, args, equals, kind))
01185         return MHD_NO;
01186       args = amper;
01187     }
01188   return MHD_YES;
01189 }
01190 
01191 
01197 static int
01198 parse_cookie_header (struct MHD_Connection *connection)
01199 {
01200   const char *hdr;
01201   char *cpy;
01202   char *pos;
01203   char *sce;
01204   char *semicolon;
01205   char *equals;
01206   char *ekill;
01207   char old;
01208   int quotes;
01209 
01210   hdr = MHD_lookup_connection_value (connection,
01211                                      MHD_HEADER_KIND,
01212                                      MHD_HTTP_HEADER_COOKIE);
01213   if (hdr == NULL)
01214     return MHD_YES;
01215   cpy = MHD_pool_allocate (connection->pool, strlen (hdr) + 1, MHD_YES);
01216   if (cpy == NULL)
01217     {
01218 #if HAVE_MESSAGES
01219       MHD_DLOG (connection->daemon, "Not enough memory to parse cookies!\n");
01220 #endif
01221       transmit_error_response (connection, MHD_HTTP_REQUEST_ENTITY_TOO_LARGE,
01222                                REQUEST_TOO_BIG);
01223       return MHD_NO;
01224     }
01225   memcpy (cpy, hdr, strlen (hdr) + 1);
01226   pos = cpy;
01227   while (pos != NULL)
01228     {
01229       while (*pos == ' ')
01230         pos++;                  /* skip spaces */
01231 
01232       sce = pos;
01233       while (((*sce) != '\0') &&
01234              ((*sce) != ',') && ((*sce) != ';') && ((*sce) != '='))
01235         sce++;
01236       /* remove tailing whitespace (if any) from key */
01237       ekill = sce - 1;
01238       while ((*ekill == ' ') && (ekill >= pos))
01239         *(ekill--) = '\0';
01240       old = *sce;
01241       *sce = '\0';
01242       if (old != '=')
01243         {
01244           /* value part omitted, use empty string... */
01245           if (MHD_NO ==
01246               connection_add_header (connection, pos, "", MHD_COOKIE_KIND))
01247             return MHD_NO;
01248           if (old == '\0')
01249             break;
01250           pos = sce + 1;
01251           continue;
01252         }
01253       equals = sce + 1;
01254       quotes = 0;
01255       semicolon = equals;
01256       while ((semicolon[0] != '\0') &&
01257              ((quotes != 0) ||
01258               ((semicolon[0] != ';') && (semicolon[0] != ','))))
01259         {
01260           if (semicolon[0] == '"')
01261             quotes = (quotes + 1) & 1;
01262           semicolon++;
01263         }
01264       if (semicolon[0] == '\0')
01265         semicolon = NULL;
01266       if (semicolon != NULL)
01267         {
01268           semicolon[0] = '\0';
01269           semicolon++;
01270         }
01271       /* remove quotes */
01272       if ((equals[0] == '"') && (equals[strlen (equals) - 1] == '"'))
01273         {
01274           equals[strlen (equals) - 1] = '\0';
01275           equals++;
01276         }
01277       if (MHD_NO == connection_add_header (connection,
01278                                            pos, equals, MHD_COOKIE_KIND))
01279         return MHD_NO;
01280       pos = semicolon;
01281     }
01282   return MHD_YES;
01283 }
01284 
01285 
01293 static int
01294 parse_initial_message_line (struct MHD_Connection *connection, char *line)
01295 {
01296   char *uri;
01297   char *httpVersion;
01298   char *args;
01299 
01300   if (NULL == (uri = strchr (line, ' ')))
01301     return MHD_NO;              /* serious error */
01302   uri[0] = '\0';
01303   connection->method = line;
01304   uri++;
01305   while (uri[0] == ' ')
01306     uri++;
01307   httpVersion = strchr (uri, ' ');
01308   if (httpVersion != NULL)
01309     {
01310       httpVersion[0] = '\0';
01311       httpVersion++;
01312     }
01313   if (connection->daemon->uri_log_callback != NULL)
01314     connection->client_context
01315       =
01316       connection->daemon->uri_log_callback (connection->daemon->
01317                                             uri_log_callback_cls, uri);
01318   args = strchr (uri, '?');
01319   if (NULL != args)
01320     {
01321       args[0] = '\0';
01322       args++;
01323       parse_arguments (MHD_GET_ARGUMENT_KIND, connection, args);
01324     }
01325   connection->daemon->unescape_callback (connection->daemon->unescape_callback_cls,
01326                                          connection,
01327                                          uri);
01328   connection->url = uri;
01329   if (NULL == httpVersion)
01330     connection->version = "";
01331   else
01332     connection->version = httpVersion;
01333   return MHD_YES;
01334 }
01335 
01336 
01342 static void
01343 call_connection_handler (struct MHD_Connection *connection)
01344 {
01345   size_t processed;
01346 
01347   if (NULL != connection->response)
01348     return;                     /* already queued a response */  
01349   processed = 0;
01350   connection->client_aware = MHD_YES;
01351   if (MHD_NO ==
01352       connection->daemon->default_handler (connection->daemon->
01353                                            default_handler_cls,
01354                                            connection, connection->url,
01355                                            connection->method,
01356                                            connection->version,
01357                                            NULL, &processed,
01358                                            &connection->client_context))
01359     {
01360       /* serious internal error, close connection */
01361       CONNECTION_CLOSE_ERROR (connection, 
01362                               "Internal application error, closing connection.\n");
01363       return;
01364     }
01365 }
01366 
01367 
01368 
01374 static void
01375 process_request_body (struct MHD_Connection *connection)
01376 {
01377   size_t processed;
01378   size_t available;
01379   size_t used;
01380   size_t i;
01381   int instant_retry;
01382   int malformed;
01383   char *buffer_head;
01384   char *end;
01385 
01386   if (NULL != connection->response)
01387     return;                     /* already queued a response */
01388 
01389   buffer_head = connection->read_buffer;
01390   available = connection->read_buffer_offset;
01391   do
01392     {
01393       instant_retry = MHD_NO;
01394       if ((connection->have_chunked_upload == MHD_YES) &&
01395           (connection->remaining_upload_size == MHD_SIZE_UNKNOWN))
01396         {
01397           if ((connection->current_chunk_offset ==
01398                connection->current_chunk_size)
01399               && (connection->current_chunk_offset != 0) && (available >= 2))
01400             {
01401               /* skip new line at the *end* of a chunk */
01402               i = 0;
01403               if ((buffer_head[i] == '\r') || (buffer_head[i] == '\n'))
01404                 i++;            /* skip 1st part of line feed */
01405               if ((buffer_head[i] == '\r') || (buffer_head[i] == '\n'))
01406                 i++;            /* skip 2nd part of line feed */
01407               if (i == 0)
01408                 {
01409                   /* malformed encoding */
01410                   CONNECTION_CLOSE_ERROR (connection,
01411                                           "Received malformed HTTP request (bad chunked encoding), closing connection.\n");
01412                   return;
01413                 }
01414               available -= i;
01415               buffer_head += i;
01416               connection->current_chunk_offset = 0;
01417               connection->current_chunk_size = 0;
01418             }
01419           if (connection->current_chunk_offset <
01420               connection->current_chunk_size)
01421             {
01422               /* we are in the middle of a chunk, give
01423                  as much as possible to the client (without
01424                  crossing chunk boundaries) */
01425               processed =
01426                 connection->current_chunk_size -
01427                 connection->current_chunk_offset;
01428               if (processed > available)
01429                 processed = available;
01430               if (available > processed)
01431                 instant_retry = MHD_YES;
01432             }
01433           else
01434             {
01435               /* we need to read chunk boundaries */
01436               i = 0;
01437               while (i < available)
01438                 {
01439                   if ((buffer_head[i] == '\r') || (buffer_head[i] == '\n'))
01440                     break;
01441                   i++;
01442                   if (i >= 6)
01443                     break;
01444                 }
01445               /* take '\n' into account; if '\n'
01446                  is the unavailable character, we
01447                  will need to wait until we have it
01448                  before going further */
01449               if ((i + 1 >= available) &&
01450                   !((i == 1) && (available == 2) && (buffer_head[0] == '0')))
01451                 break;          /* need more data... */
01452               malformed = (i >= 6);
01453               if (!malformed)
01454                 {
01455                   buffer_head[i] = '\0';
01456                   connection->current_chunk_size = strtoul (buffer_head, &end, 16);
01457                   malformed = ('\0' != *end);
01458                 }
01459               if (malformed)
01460                 {
01461                   /* malformed encoding */
01462                   CONNECTION_CLOSE_ERROR (connection,
01463                                           "Received malformed HTTP request (bad chunked encoding), closing connection.\n");
01464                   return;
01465                 }
01466               i++;
01467               if ((i < available) &&
01468                   ((buffer_head[i] == '\r') || (buffer_head[i] == '\n')))
01469                 i++;            /* skip 2nd part of line feed */
01470 
01471               buffer_head += i;
01472               available -= i;
01473               connection->current_chunk_offset = 0;
01474 
01475               if (available > 0)
01476                 instant_retry = MHD_YES;
01477               if (connection->current_chunk_size == 0)
01478                 {
01479                   connection->remaining_upload_size = 0;
01480                   break;
01481                 }
01482               continue;
01483             }
01484         }
01485       else
01486         {
01487           /* no chunked encoding, give all to the client */
01488           if ( (0 != connection->remaining_upload_size) && 
01489                (MHD_SIZE_UNKNOWN != connection->remaining_upload_size) &&
01490                (connection->remaining_upload_size < available) )
01491             {
01492               processed = connection->remaining_upload_size;
01493             }
01494           else
01495             {
01500               processed = available;
01501             }
01502         }
01503       used = processed;
01504       connection->client_aware = MHD_YES;
01505       if (MHD_NO ==
01506           connection->daemon->default_handler (connection->daemon->
01507                                                default_handler_cls,
01508                                                connection, connection->url,
01509                                                connection->method,
01510                                                connection->version,
01511                                                buffer_head, &processed,
01512                                                &connection->client_context))
01513         {
01514           /* serious internal error, close connection */
01515           CONNECTION_CLOSE_ERROR (connection,
01516                                   "Internal application error, closing connection.\n");
01517           return;
01518         }
01519       if (processed > used)
01520         mhd_panic (mhd_panic_cls, __FILE__, __LINE__, 
01521 #if HAVE_MESSAGES
01522                    "API violation"
01523 #else
01524                    NULL
01525 #endif
01526                    );
01527       if (processed != 0)
01528         instant_retry = MHD_NO; /* client did not process everything */
01529       used -= processed;
01530       if (connection->have_chunked_upload == MHD_YES)
01531         connection->current_chunk_offset += used;
01532       /* dh left "processed" bytes in buffer for next time... */
01533       buffer_head += used;
01534       available -= used;
01535       if (connection->remaining_upload_size != MHD_SIZE_UNKNOWN)
01536         connection->remaining_upload_size -= used;
01537     }
01538   while (MHD_YES == instant_retry);
01539   if (available > 0)
01540     memmove (connection->read_buffer, buffer_head, available);
01541   connection->read_buffer_offset = available;
01542 }
01543 
01552 static int
01553 do_read (struct MHD_Connection *connection)
01554 {
01555   int bytes_read;
01556 
01557   if (connection->read_buffer_size == connection->read_buffer_offset)
01558     return MHD_NO;
01559 
01560   bytes_read = connection->recv_cls (connection,
01561                                      &connection->read_buffer
01562                                      [connection->read_buffer_offset],
01563                                      connection->read_buffer_size -
01564                                      connection->read_buffer_offset);
01565   if (bytes_read < 0)
01566     {
01567       if ((EINTR == errno) || (EAGAIN == errno))
01568         return MHD_NO;
01569 #if HAVE_MESSAGES
01570 #if HTTPS_SUPPORT
01571       if (0 != (connection->daemon->options & MHD_USE_SSL))
01572         MHD_DLOG (connection->daemon,
01573                   "Failed to receive data: %s\n",
01574                   gnutls_strerror (bytes_read));
01575       else
01576 #endif      
01577         MHD_DLOG (connection->daemon,
01578                   "Failed to receive data: %s\n", STRERROR (errno));
01579 #endif
01580       CONNECTION_CLOSE_ERROR (connection, NULL);
01581       return MHD_YES;
01582     }
01583   if (0 == bytes_read)
01584     {
01585       /* other side closed connection */
01586       connection->read_closed = MHD_YES;
01587       SHUTDOWN (connection->socket_fd, SHUT_RD);
01588       return MHD_YES;
01589     }
01590   connection->read_buffer_offset += bytes_read;
01591   return MHD_YES;
01592 }
01593 
01601 static int
01602 do_write (struct MHD_Connection *connection)
01603 {
01604   int ret;
01605 
01606   ret = connection->send_cls (connection,
01607                               &connection->write_buffer
01608                               [connection->write_buffer_send_offset],
01609                               connection->write_buffer_append_offset
01610                               - connection->write_buffer_send_offset);
01611 
01612   if (ret < 0)
01613     {
01614       if ((EINTR == errno) || (EAGAIN == errno))
01615         return MHD_NO;
01616 #if HAVE_MESSAGES
01617 #if HTTPS_SUPPORT
01618       if (0 != (connection->daemon->options & MHD_USE_SSL))
01619         MHD_DLOG (connection->daemon,
01620                   "Failed to send data: %s\n",
01621                   gnutls_strerror (ret));
01622       else
01623 #endif      
01624         MHD_DLOG (connection->daemon,
01625                   "Failed to send data: %s\n", STRERROR (errno));
01626 #endif
01627       CONNECTION_CLOSE_ERROR (connection, NULL);
01628       return MHD_YES;
01629     }
01630 #if DEBUG_SEND_DATA
01631   FPRINTF (stderr,
01632            "Sent response: `%.*s'\n",
01633            ret,
01634            &connection->write_buffer[connection->write_buffer_send_offset]);
01635 #endif
01636   connection->write_buffer_send_offset += ret;
01637   return MHD_YES;
01638 }
01639 
01645 static int
01646 check_write_done (struct MHD_Connection *connection,
01647                   enum MHD_CONNECTION_STATE next_state)
01648 {
01649   if (connection->write_buffer_append_offset !=
01650       connection->write_buffer_send_offset)
01651     return MHD_NO;
01652   connection->write_buffer_append_offset = 0;
01653   connection->write_buffer_send_offset = 0;
01654   connection->state = next_state;
01655   MHD_pool_reallocate (connection->pool, connection->write_buffer,
01656                        connection->write_buffer_size, 0);
01657   connection->write_buffer = NULL;
01658   connection->write_buffer_size = 0;
01659   return MHD_YES;
01660 }
01661 
01667 static int
01668 process_header_line (struct MHD_Connection *connection, char *line)
01669 {
01670   char *colon;
01671 
01672   /* line should be normal header line, find colon */
01673   colon = strchr (line, ':');
01674   if (colon == NULL)
01675     {
01676       /* error in header line, die hard */
01677       CONNECTION_CLOSE_ERROR (connection, 
01678                               "Received malformed line (no colon), closing connection.\n");
01679       return MHD_NO;
01680     }
01681   /* zero-terminate header */
01682   colon[0] = '\0';
01683   colon++;                      /* advance to value */
01684   while ((colon[0] != '\0') && ((colon[0] == ' ') || (colon[0] == '\t')))
01685     colon++;
01686   /* we do the actual adding of the connection
01687      header at the beginning of the while
01688      loop since we need to be able to inspect
01689      the *next* header line (in case it starts
01690      with a space...) */
01691   connection->last = line;
01692   connection->colon = colon;
01693   return MHD_YES;
01694 }
01695 
01696 
01706 static int
01707 process_broken_line (struct MHD_Connection *connection,
01708                      char *line, enum MHD_ValueKind kind)
01709 {
01710   char *last;
01711   char *tmp;
01712   size_t last_len;
01713   size_t tmp_len;
01714 
01715   last = connection->last;
01716   if ((line[0] == ' ') || (line[0] == '\t'))
01717     {
01718       /* value was continued on the next line, see
01719          http://www.jmarshall.com/easy/http/ */
01720       last_len = strlen (last);
01721       /* skip whitespace at start of 2nd line */
01722       tmp = line;
01723       while ((tmp[0] == ' ') || (tmp[0] == '\t'))
01724         tmp++;                  
01725       tmp_len = strlen (tmp);
01726       last = MHD_pool_reallocate (connection->pool,
01727                                   last,
01728                                   last_len + 1,
01729                                   last_len + tmp_len + 1);
01730       if (last == NULL)
01731         {
01732           transmit_error_response (connection,
01733                                    MHD_HTTP_REQUEST_ENTITY_TOO_LARGE,
01734                                    REQUEST_TOO_BIG);
01735           return MHD_NO;
01736         }
01737       memcpy (&last[last_len], tmp, tmp_len + 1);
01738       connection->last = last;
01739       return MHD_YES;           /* possibly more than 2 lines... */
01740     }
01741   EXTRA_CHECK ((last != NULL) && (connection->colon != NULL));
01742   if ((MHD_NO == connection_add_header (connection,
01743                                         last, connection->colon, kind)))
01744     {
01745       transmit_error_response (connection, MHD_HTTP_REQUEST_ENTITY_TOO_LARGE,
01746                                REQUEST_TOO_BIG);
01747       return MHD_NO;
01748     }
01749   /* we still have the current line to deal with... */
01750   if (strlen (line) != 0)
01751     {
01752       if (MHD_NO == process_header_line (connection, line))
01753         {
01754           transmit_error_response (connection,
01755                                    MHD_HTTP_BAD_REQUEST, REQUEST_MALFORMED);
01756           return MHD_NO;
01757         }
01758     }
01759   return MHD_YES;
01760 }
01761 
01762 
01768 static void
01769 parse_connection_headers (struct MHD_Connection *connection)
01770 {
01771   const char *clen;
01772   unsigned MHD_LONG_LONG cval;
01773   struct MHD_Response *response;
01774   const char *enc;
01775   char *end;
01776 
01777   parse_cookie_header (connection);
01778   if ((0 != (MHD_USE_PEDANTIC_CHECKS & connection->daemon->options))
01779       && (NULL != connection->version)
01780       && (0 == strcasecmp (MHD_HTTP_VERSION_1_1, connection->version))
01781       && (NULL ==
01782           MHD_lookup_connection_value (connection, MHD_HEADER_KIND,
01783                                        MHD_HTTP_HEADER_HOST)))
01784     {
01785       /* die, http 1.1 request without host and we are pedantic */
01786       connection->state = MHD_CONNECTION_FOOTERS_RECEIVED;
01787       connection->read_closed = MHD_YES;
01788 #if HAVE_MESSAGES
01789       MHD_DLOG (connection->daemon,
01790                 "Received `%s' request without `%s' header.\n",
01791                 MHD_HTTP_VERSION_1_1, MHD_HTTP_HEADER_HOST);
01792 #endif
01793       EXTRA_CHECK (connection->response == NULL);
01794       response =
01795         MHD_create_response_from_buffer (strlen (REQUEST_LACKS_HOST),
01796                                          REQUEST_LACKS_HOST,
01797                                          MHD_RESPMEM_PERSISTENT);
01798       MHD_queue_response (connection, MHD_HTTP_BAD_REQUEST, response);
01799       MHD_destroy_response (response);
01800       return;
01801     }
01802 
01803   clen = MHD_lookup_connection_value (connection,
01804                                       MHD_HEADER_KIND,
01805                                       MHD_HTTP_HEADER_CONTENT_LENGTH);
01806   if (clen != NULL)
01807     {
01808       cval = strtoul (clen, &end, 10);
01809       if ( ('\0' != *end) ||
01810          ( (LONG_MAX == cval) && (errno == ERANGE) ) )
01811         {
01812 #if HAVE_MESSAGES
01813           MHD_DLOG (connection->daemon,
01814                     "Failed to parse `%s' header `%s', closing connection.\n",
01815                     MHD_HTTP_HEADER_CONTENT_LENGTH, clen);
01816 #endif
01817           CONNECTION_CLOSE_ERROR (connection, NULL);
01818           return;
01819         }
01820       connection->remaining_upload_size = cval;
01821     }
01822   else
01823     {
01824       enc = MHD_lookup_connection_value (connection,
01825                                          MHD_HEADER_KIND,
01826                                          MHD_HTTP_HEADER_TRANSFER_ENCODING);
01827       if (NULL == enc)
01828         {
01829           /* this request (better) not have a body */
01830           connection->remaining_upload_size = 0;
01831         }
01832       else
01833         {
01834           connection->remaining_upload_size = MHD_SIZE_UNKNOWN;
01835           if (0 == strcasecmp (enc, "chunked"))
01836             connection->have_chunked_upload = MHD_YES;
01837         }
01838     }
01839 }
01840 
01841 
01852 int
01853 MHD_connection_handle_read (struct MHD_Connection *connection)
01854 {
01855   connection->last_activity = MHD_monotonic_time();
01856   if (connection->state == MHD_CONNECTION_CLOSED)
01857     return MHD_YES;
01858   /* make sure "read" has a reasonable number of bytes
01859      in buffer to use per system call (if possible) */
01860   if (connection->read_buffer_offset + MHD_BUF_INC_SIZE >
01861       connection->read_buffer_size)
01862     try_grow_read_buffer (connection);
01863   if (MHD_NO == do_read (connection))
01864     return MHD_YES;
01865   while (1)
01866     {
01867 #if DEBUG_STATES
01868       MHD_DLOG (connection->daemon, "%s: state: %s\n",
01869                 __FUNCTION__, MHD_state_to_string (connection->state));
01870 #endif
01871       switch (connection->state)
01872         {
01873         case MHD_CONNECTION_INIT:
01874         case MHD_CONNECTION_URL_RECEIVED:
01875         case MHD_CONNECTION_HEADER_PART_RECEIVED:
01876         case MHD_CONNECTION_HEADERS_RECEIVED:
01877         case MHD_CONNECTION_HEADERS_PROCESSED:
01878         case MHD_CONNECTION_CONTINUE_SENDING:
01879         case MHD_CONNECTION_CONTINUE_SENT:
01880         case MHD_CONNECTION_BODY_RECEIVED:
01881         case MHD_CONNECTION_FOOTER_PART_RECEIVED:
01882           /* nothing to do but default action */
01883           if (MHD_YES == connection->read_closed)
01884             {
01885               MHD_connection_close (connection,
01886                                     MHD_REQUEST_TERMINATED_READ_ERROR);
01887               continue;
01888             }
01889           break;
01890         case MHD_CONNECTION_CLOSED:
01891           return MHD_YES;
01892         default:
01893           /* shrink read buffer to how much is actually used */
01894           MHD_pool_reallocate (connection->pool,
01895                                connection->read_buffer,
01896                                connection->read_buffer_size + 1,
01897                                connection->read_buffer_offset);
01898           break;
01899         }
01900       break;
01901     }
01902   return MHD_YES;
01903 }
01904 
01905 
01916 int
01917 MHD_connection_handle_write (struct MHD_Connection *connection)
01918 {
01919   struct MHD_Response *response;
01920   int ret;
01921   connection->last_activity = MHD_monotonic_time();
01922   while (1)
01923     {
01924 #if DEBUG_STATES
01925       MHD_DLOG (connection->daemon, "%s: state: %s\n",
01926                 __FUNCTION__, MHD_state_to_string (connection->state));
01927 #endif
01928       switch (connection->state)
01929         {
01930         case MHD_CONNECTION_INIT:
01931         case MHD_CONNECTION_URL_RECEIVED:
01932         case MHD_CONNECTION_HEADER_PART_RECEIVED:
01933         case MHD_CONNECTION_HEADERS_RECEIVED:
01934           EXTRA_CHECK (0);
01935           break;
01936         case MHD_CONNECTION_HEADERS_PROCESSED:
01937           break;
01938         case MHD_CONNECTION_CONTINUE_SENDING:
01939           ret = connection->send_cls (connection,
01940                                       &HTTP_100_CONTINUE
01941                                       [connection->continue_message_write_offset],
01942                                       strlen (HTTP_100_CONTINUE) -
01943                                       connection->continue_message_write_offset);
01944           if (ret < 0)
01945             {
01946               if ((errno == EINTR) || (errno == EAGAIN))
01947                 break;
01948 #if HAVE_MESSAGES
01949               MHD_DLOG (connection->daemon,
01950                         "Failed to send data: %s\n", STRERROR (errno));
01951 #endif
01952               CONNECTION_CLOSE_ERROR (connection, NULL);
01953               return MHD_YES;
01954             }
01955 #if DEBUG_SEND_DATA
01956           FPRINTF (stderr,
01957                    "Sent 100 continue response: `%.*s'\n",
01958                    ret,
01959                    &HTTP_100_CONTINUE
01960                    [connection->continue_message_write_offset]);
01961 #endif
01962           connection->continue_message_write_offset += ret;
01963           break;
01964         case MHD_CONNECTION_CONTINUE_SENT:
01965         case MHD_CONNECTION_BODY_RECEIVED:
01966         case MHD_CONNECTION_FOOTER_PART_RECEIVED:
01967         case MHD_CONNECTION_FOOTERS_RECEIVED:
01968           EXTRA_CHECK (0);
01969           break;
01970         case MHD_CONNECTION_HEADERS_SENDING:
01971           do_write (connection);
01972           if (connection->state != MHD_CONNECTION_HEADERS_SENDING)
01973              break;
01974           check_write_done (connection, MHD_CONNECTION_HEADERS_SENT);
01975           break;
01976         case MHD_CONNECTION_HEADERS_SENT:
01977           EXTRA_CHECK (0);
01978           break;
01979         case MHD_CONNECTION_NORMAL_BODY_READY:
01980           response = connection->response;
01981           if (response->crc != NULL)
01982             pthread_mutex_lock (&response->mutex);
01983           if (MHD_YES != try_ready_normal_body (connection))
01984             {
01985               if (response->crc != NULL)
01986                 pthread_mutex_unlock (&response->mutex);
01987               break;
01988             }
01989           ret = connection->send_cls (connection,
01990                                       &response->data
01991                                       [connection->response_write_position
01992                                        - response->data_start],
01993                                       response->data_size -
01994                                       (connection->response_write_position
01995                                        - response->data_start));
01996 #if DEBUG_SEND_DATA
01997           if (ret > 0)
01998             FPRINTF (stderr,
01999                      "Sent DATA response: `%.*s'\n",
02000                      ret,
02001                      &response->data[connection->response_write_position -
02002                                      response->data_start]);
02003 #endif
02004           if (response->crc != NULL)
02005             pthread_mutex_unlock (&response->mutex);
02006           if (ret < 0)
02007             {
02008               if ((errno == EINTR) || (errno == EAGAIN))
02009                 return MHD_YES;
02010 #if HAVE_MESSAGES
02011               MHD_DLOG (connection->daemon,
02012                         "Failed to send data: %s\n", STRERROR (errno));
02013 #endif
02014               CONNECTION_CLOSE_ERROR (connection, NULL);
02015               return MHD_YES;
02016             }
02017           connection->response_write_position += ret;
02018           if (connection->response_write_position ==
02019               connection->response->total_size)
02020             connection->state = MHD_CONNECTION_FOOTERS_SENT;    /* have no footers... */
02021           break;
02022         case MHD_CONNECTION_NORMAL_BODY_UNREADY:
02023           EXTRA_CHECK (0);
02024           break;
02025         case MHD_CONNECTION_CHUNKED_BODY_READY:
02026           do_write (connection);
02027           if (connection->state !=  MHD_CONNECTION_CHUNKED_BODY_READY)
02028              break;
02029           check_write_done (connection,
02030                             (connection->response->total_size ==
02031                              connection->response_write_position) ?
02032                             MHD_CONNECTION_BODY_SENT :
02033                             MHD_CONNECTION_CHUNKED_BODY_UNREADY);
02034           break;
02035         case MHD_CONNECTION_CHUNKED_BODY_UNREADY:
02036         case MHD_CONNECTION_BODY_SENT:
02037           EXTRA_CHECK (0);
02038           break;
02039         case MHD_CONNECTION_FOOTERS_SENDING:
02040           do_write (connection);
02041           if (connection->state != MHD_CONNECTION_FOOTERS_SENDING)
02042             break;
02043           check_write_done (connection, MHD_CONNECTION_FOOTERS_SENT);
02044           break;
02045         case MHD_CONNECTION_FOOTERS_SENT:
02046           EXTRA_CHECK (0);
02047           break;
02048         case MHD_CONNECTION_CLOSED:
02049           return MHD_YES;
02050         case MHD_TLS_CONNECTION_INIT:
02051           EXTRA_CHECK (0);
02052           break;
02053         default:
02054           EXTRA_CHECK (0);
02055           CONNECTION_CLOSE_ERROR (connection, "Internal error\n");
02056           return MHD_YES;
02057         }
02058       break;
02059     }
02060   return MHD_YES;
02061 }
02062 
02063 
02074 int
02075 MHD_connection_handle_idle (struct MHD_Connection *connection)
02076 {
02077   struct MHD_Daemon *daemon;
02078   unsigned int timeout;
02079   const char *end;
02080   int rend;
02081   char *line;
02082 
02083   while (1)
02084     {
02085 #if DEBUG_STATES
02086       MHD_DLOG (connection->daemon, "%s: state: %s\n",
02087                 __FUNCTION__, MHD_state_to_string (connection->state));
02088 #endif
02089       switch (connection->state)
02090         {
02091         case MHD_CONNECTION_INIT:
02092           line = get_next_header_line (connection);
02093           if (line == NULL)
02094             {
02095               if (connection->state != MHD_CONNECTION_INIT)
02096                 continue;
02097               if (connection->read_closed)
02098                 {
02099                   CONNECTION_CLOSE_ERROR (connection, 
02100                                           NULL);
02101                   continue;
02102                 }
02103               break;
02104             }
02105           if (MHD_NO == parse_initial_message_line (connection, line))
02106             CONNECTION_CLOSE_ERROR (connection, NULL);
02107           else
02108             connection->state = MHD_CONNECTION_URL_RECEIVED;
02109           continue;
02110         case MHD_CONNECTION_URL_RECEIVED:
02111           line = get_next_header_line (connection);
02112           if (line == NULL)
02113             {
02114               if (connection->state != MHD_CONNECTION_URL_RECEIVED)
02115                 continue;
02116               if (connection->read_closed)
02117                 {
02118                   CONNECTION_CLOSE_ERROR (connection, 
02119                                           NULL);
02120                   continue;
02121                 }
02122               break;
02123             }
02124           if (strlen (line) == 0)
02125             {
02126               connection->state = MHD_CONNECTION_HEADERS_RECEIVED;
02127               continue;
02128             }
02129           if (MHD_NO == process_header_line (connection, line))
02130             {
02131               transmit_error_response (connection,
02132                                        MHD_HTTP_BAD_REQUEST,
02133                                        REQUEST_MALFORMED);
02134               break;
02135             }
02136           connection->state = MHD_CONNECTION_HEADER_PART_RECEIVED;
02137           continue;
02138         case MHD_CONNECTION_HEADER_PART_RECEIVED:
02139           line = get_next_header_line (connection);
02140           if (line == NULL)
02141             {
02142               if (connection->state != MHD_CONNECTION_HEADER_PART_RECEIVED)
02143                 continue;
02144               if (connection->read_closed)
02145                 {
02146                   CONNECTION_CLOSE_ERROR (connection, 
02147                                           NULL);
02148                   continue;
02149                 }
02150               break;
02151             }
02152           if (MHD_NO ==
02153               process_broken_line (connection, line, MHD_HEADER_KIND))
02154             continue;
02155           if (strlen (line) == 0)
02156             {
02157               connection->state = MHD_CONNECTION_HEADERS_RECEIVED;
02158               continue;
02159             }
02160           continue;
02161         case MHD_CONNECTION_HEADERS_RECEIVED:
02162           parse_connection_headers (connection);
02163           if (connection->state == MHD_CONNECTION_CLOSED)
02164             continue;
02165           connection->state = MHD_CONNECTION_HEADERS_PROCESSED;
02166           continue;
02167         case MHD_CONNECTION_HEADERS_PROCESSED:
02168           call_connection_handler (connection); /* first call */
02169           if (connection->state == MHD_CONNECTION_CLOSED)
02170             continue;
02171           if (need_100_continue (connection))
02172             {
02173               connection->state = MHD_CONNECTION_CONTINUE_SENDING;
02174               break;
02175             }
02176           if (connection->response != NULL)
02177             {
02178               /* we refused (no upload allowed!) */
02179               connection->remaining_upload_size = 0;
02180               /* force close, in case client still tries to upload... */
02181               connection->read_closed = MHD_YES;
02182             }
02183           connection->state = (connection->remaining_upload_size == 0)
02184             ? MHD_CONNECTION_FOOTERS_RECEIVED : MHD_CONNECTION_CONTINUE_SENT;
02185           continue;
02186         case MHD_CONNECTION_CONTINUE_SENDING:
02187           if (connection->continue_message_write_offset ==
02188               strlen (HTTP_100_CONTINUE))
02189             {
02190               connection->state = MHD_CONNECTION_CONTINUE_SENT;
02191               continue;
02192             }
02193           break;
02194         case MHD_CONNECTION_CONTINUE_SENT:
02195           if (connection->read_buffer_offset != 0)
02196             {
02197               process_request_body (connection);     /* loop call */
02198               if (connection->state == MHD_CONNECTION_CLOSED)
02199                 continue;
02200             }
02201           if ((connection->remaining_upload_size == 0) ||
02202               ((connection->remaining_upload_size == MHD_SIZE_UNKNOWN) &&
02203                (connection->read_buffer_offset == 0) &&
02204                (MHD_YES == connection->read_closed)))
02205             {
02206               if ((MHD_YES == connection->have_chunked_upload) &&
02207                   (MHD_NO == connection->read_closed))
02208                 connection->state = MHD_CONNECTION_BODY_RECEIVED;
02209               else
02210                 connection->state = MHD_CONNECTION_FOOTERS_RECEIVED;
02211               continue;
02212             }
02213           break;
02214         case MHD_CONNECTION_BODY_RECEIVED:
02215           line = get_next_header_line (connection);
02216           if (line == NULL)
02217             {
02218               if (connection->state != MHD_CONNECTION_BODY_RECEIVED)
02219                 continue;
02220               if (connection->read_closed)
02221                 {
02222                   CONNECTION_CLOSE_ERROR (connection, 
02223                                           NULL);
02224                   continue;
02225                 }
02226               break;
02227             }
02228           if (strlen (line) == 0)
02229             {
02230               connection->state = MHD_CONNECTION_FOOTERS_RECEIVED;
02231               continue;
02232             }
02233           if (MHD_NO == process_header_line (connection, line))
02234             {
02235               transmit_error_response (connection,
02236                                        MHD_HTTP_BAD_REQUEST,
02237                                        REQUEST_MALFORMED);
02238               break;
02239             }
02240           connection->state = MHD_CONNECTION_FOOTER_PART_RECEIVED;
02241           continue;
02242         case MHD_CONNECTION_FOOTER_PART_RECEIVED:
02243           line = get_next_header_line (connection);
02244           if (line == NULL)
02245             {
02246               if (connection->state != MHD_CONNECTION_FOOTER_PART_RECEIVED)
02247                 continue;
02248               if (connection->read_closed)
02249                 {
02250                   CONNECTION_CLOSE_ERROR (connection, 
02251                                           NULL);
02252                   continue;
02253                 }
02254               break;
02255             }
02256           if (MHD_NO ==
02257               process_broken_line (connection, line, MHD_FOOTER_KIND))
02258             continue;
02259           if (strlen (line) == 0)
02260             {
02261               connection->state = MHD_CONNECTION_FOOTERS_RECEIVED;
02262               continue;
02263             }
02264           continue;
02265         case MHD_CONNECTION_FOOTERS_RECEIVED:
02266           call_connection_handler (connection); /* "final" call */
02267           if (connection->state == MHD_CONNECTION_CLOSED)
02268             continue;
02269           if (connection->response == NULL)
02270             break;              /* try again next time */
02271           if (MHD_NO == build_header_response (connection))
02272             {
02273               /* oops - close! */
02274               CONNECTION_CLOSE_ERROR (connection, 
02275                                       "Closing connection (failed to create response header)\n");
02276               continue;
02277             }
02278           connection->state = MHD_CONNECTION_HEADERS_SENDING;
02279 
02280 #if HAVE_DECL_TCP_CORK
02281           /* starting header send, set TCP cork */
02282           {
02283             const int val = 1;
02284             setsockopt (connection->socket_fd, IPPROTO_TCP, TCP_CORK, &val,
02285                         sizeof (val));
02286           }
02287 #endif
02288           break;
02289         case MHD_CONNECTION_HEADERS_SENDING:
02290           /* no default action */
02291           break;
02292         case MHD_CONNECTION_HEADERS_SENT:
02293           if (connection->have_chunked_upload)
02294             connection->state = MHD_CONNECTION_CHUNKED_BODY_UNREADY;
02295           else
02296             connection->state = MHD_CONNECTION_NORMAL_BODY_UNREADY;
02297           continue;
02298         case MHD_CONNECTION_NORMAL_BODY_READY:
02299           /* nothing to do here */
02300           break;
02301         case MHD_CONNECTION_NORMAL_BODY_UNREADY:
02302           if (connection->response->crc != NULL)
02303             pthread_mutex_lock (&connection->response->mutex);
02304           if (MHD_YES == try_ready_normal_body (connection))
02305             {
02306               if (connection->response->crc != NULL)
02307                 pthread_mutex_unlock (&connection->response->mutex);
02308               connection->state = MHD_CONNECTION_NORMAL_BODY_READY;
02309               break;
02310             }
02311           if (connection->response->crc != NULL)
02312             pthread_mutex_unlock (&connection->response->mutex);
02313           /* not ready, no socket action */
02314           break;
02315         case MHD_CONNECTION_CHUNKED_BODY_READY:
02316           /* nothing to do here */
02317           break;
02318         case MHD_CONNECTION_CHUNKED_BODY_UNREADY:
02319           if (connection->response->crc != NULL)
02320             pthread_mutex_lock (&connection->response->mutex);
02321           if (MHD_YES == try_ready_chunked_body (connection))
02322             {
02323               if (connection->response->crc != NULL)
02324                 pthread_mutex_unlock (&connection->response->mutex);
02325               connection->state = MHD_CONNECTION_CHUNKED_BODY_READY;
02326               continue;
02327             }
02328           if (connection->response->crc != NULL)
02329             pthread_mutex_unlock (&connection->response->mutex);
02330           break;
02331         case MHD_CONNECTION_BODY_SENT:
02332           build_header_response (connection);
02333           if (connection->write_buffer_send_offset ==
02334               connection->write_buffer_append_offset)
02335             connection->state = MHD_CONNECTION_FOOTERS_SENT;
02336           else
02337             connection->state = MHD_CONNECTION_FOOTERS_SENDING;
02338           continue;
02339         case MHD_CONNECTION_FOOTERS_SENDING:
02340           /* no default action */
02341           break;
02342         case MHD_CONNECTION_FOOTERS_SENT:
02343 #if HAVE_DECL_TCP_CORK
02344           /* done sending, uncork */
02345           {
02346             const int val = 0;
02347             setsockopt (connection->socket_fd, IPPROTO_TCP, TCP_CORK, &val,
02348                         sizeof (val));
02349           }
02350 #endif
02351           end =
02352             MHD_get_response_header (connection->response, 
02353                                      MHD_HTTP_HEADER_CONNECTION);
02354           rend = ( (end != NULL) && (0 == strcasecmp (end, "close")) );
02355           MHD_destroy_response (connection->response);
02356           connection->response = NULL;
02357           if (connection->daemon->notify_completed != NULL)
02358             connection->daemon->notify_completed (connection->daemon->
02359                                                   notify_completed_cls,
02360                                                   connection,
02361                                                   &connection->client_context,
02362                                                   MHD_REQUEST_TERMINATED_COMPLETED_OK);     
02363           connection->client_aware = MHD_NO;
02364           end =
02365             MHD_lookup_connection_value (connection, MHD_HEADER_KIND,
02366                                          MHD_HTTP_HEADER_CONNECTION);
02367           connection->client_context = NULL;
02368           connection->continue_message_write_offset = 0;
02369           connection->responseCode = 0;
02370           connection->headers_received = NULL;
02371           connection->headers_received_tail = NULL;
02372           connection->response_write_position = 0;
02373           connection->have_chunked_upload = MHD_NO;
02374           connection->method = NULL;
02375           connection->url = NULL;
02376           connection->write_buffer = NULL;
02377           connection->write_buffer_size = 0;
02378           connection->write_buffer_send_offset = 0;
02379           connection->write_buffer_append_offset = 0;
02380           if ( (rend) || ((end != NULL) && (0 == strcasecmp (end, "close"))) )
02381             {
02382               connection->read_closed = MHD_YES;
02383               connection->read_buffer_offset = 0;
02384             }
02385           if (((MHD_YES == connection->read_closed) &&
02386                (0 == connection->read_buffer_offset)) ||
02387               (connection->version == NULL) ||
02388               (0 != strcasecmp (MHD_HTTP_VERSION_1_1, connection->version)))
02389             {
02390               /* http 1.0, version-less requests cannot be pipelined */
02391               MHD_connection_close (connection, MHD_REQUEST_TERMINATED_COMPLETED_OK);
02392               MHD_pool_destroy (connection->pool);
02393               connection->pool = NULL;
02394               connection->read_buffer = NULL;
02395               connection->read_buffer_size = 0;
02396               connection->read_buffer_offset = 0;
02397             }
02398           else
02399             {
02400               connection->version = NULL;
02401               connection->state = MHD_CONNECTION_INIT;
02402               connection->read_buffer
02403                 = MHD_pool_reset (connection->pool,
02404                                   connection->read_buffer,
02405                                   connection->read_buffer_size);
02406             }
02407           continue;
02408         case MHD_CONNECTION_CLOSED:
02409           if (connection->response != NULL)
02410             {
02411               MHD_destroy_response (connection->response);
02412               connection->response = NULL;
02413             }
02414           daemon = connection->daemon;
02415           if (0 != pthread_mutex_lock(&daemon->cleanup_connection_mutex))
02416             {
02417               MHD_PANIC ("Failed to acquire cleanup mutex\n");
02418             }
02419           DLL_remove (daemon->connections_head,
02420                       daemon->connections_tail,
02421                       connection);
02422           DLL_insert (daemon->cleanup_head,
02423                       daemon->cleanup_tail,
02424                       connection);
02425           if (0 != pthread_mutex_unlock(&daemon->cleanup_connection_mutex))
02426             {
02427               MHD_PANIC ("Failed to release cleanup mutex\n");
02428             }
02429           return MHD_NO;
02430         default:
02431           EXTRA_CHECK (0);
02432           break;
02433         }
02434       break;
02435     }
02436   timeout = connection->connection_timeout;
02437   if ( (timeout != 0) &&
02438        (timeout <= (MHD_monotonic_time() - connection->last_activity)) )
02439     {
02440       MHD_connection_close (connection, MHD_REQUEST_TERMINATED_TIMEOUT_REACHED);
02441       return MHD_YES;
02442     }
02443   return MHD_YES;
02444 }
02445 
02446 
02452 void
02453 MHD_set_http_callbacks_ (struct MHD_Connection *connection)
02454 {
02455   connection->read_handler = &MHD_connection_handle_read;
02456   connection->write_handler = &MHD_connection_handle_write;
02457   connection->idle_handler = &MHD_connection_handle_idle;
02458 }
02459 
02460 
02470 const union MHD_ConnectionInfo *
02471 MHD_get_connection_info (struct MHD_Connection *connection,
02472                          enum MHD_ConnectionInfoType infoType, ...)
02473 {
02474   switch (infoType)
02475     {
02476 #if HTTPS_SUPPORT
02477     case MHD_CONNECTION_INFO_CIPHER_ALGO:
02478       if (connection->tls_session == NULL)
02479         return NULL;
02480       connection->cipher = gnutls_cipher_get (connection->tls_session);
02481       return (const union MHD_ConnectionInfo *) &connection->cipher;
02482     case MHD_CONNECTION_INFO_PROTOCOL:
02483       if (connection->tls_session == NULL)
02484         return NULL;
02485       connection->protocol = gnutls_protocol_get_version (connection->tls_session);
02486       return (const union MHD_ConnectionInfo *) &connection->protocol;
02487     case MHD_CONNECTION_INFO_GNUTLS_SESSION:
02488       if (connection->tls_session == NULL)
02489         return NULL;
02490       return (const union MHD_ConnectionInfo *) &connection->tls_session;
02491 #endif
02492     case MHD_CONNECTION_INFO_CLIENT_ADDRESS:
02493       return (const union MHD_ConnectionInfo *) &connection->addr;
02494     case MHD_CONNECTION_INFO_DAEMON:
02495       return (const union MHD_ConnectionInfo *) &connection->daemon;
02496     default:
02497       return NULL;
02498     };
02499 }
02500 
02501 
02510 int 
02511 MHD_set_connection_option (struct MHD_Connection *connection,
02512                            enum MHD_CONNECTION_OPTION option,
02513                            ...)
02514 {
02515   va_list ap;
02516 
02517   switch (option)
02518     {
02519     case MHD_CONNECTION_OPTION_TIMEOUT:
02520       va_start (ap, option);
02521       connection->connection_timeout = va_arg (ap, unsigned int);
02522       va_end (ap);
02523       return MHD_YES;
02524     default:
02525       return MHD_NO;
02526     }
02527 }
02528 
02529 
02530 /* end of connection.c */

Generated on 27 Sep 2012 for GNU libmicrohttpd by  doxygen 1.6.1