gnunet-svn
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[GNUnet-SVN] r5280 - libmicrohttpd/src/daemon


From: gnunet
Subject: [GNUnet-SVN] r5280 - libmicrohttpd/src/daemon
Date: Sun, 8 Jul 2007 21:20:59 -0600 (MDT)

Author: grothoff
Date: 2007-07-08 21:20:57 -0600 (Sun, 08 Jul 2007)
New Revision: 5280

Added:
   libmicrohttpd/src/daemon/connection.c
   libmicrohttpd/src/daemon/connection.h
Removed:
   libmicrohttpd/src/daemon/session.c
   libmicrohttpd/src/daemon/session.h
Log:
rename

Copied: libmicrohttpd/src/daemon/connection.c (from rev 5279, 
libmicrohttpd/src/daemon/session.c)
===================================================================
--- libmicrohttpd/src/daemon/connection.c                               (rev 0)
+++ libmicrohttpd/src/daemon/connection.c       2007-07-09 03:20:57 UTC (rev 
5280)
@@ -0,0 +1,831 @@
+/*
+     This file is part of libmicrohttpd
+     (C) 2007 Daniel Pittman
+
+     libmicrohttpd is free software; you can redistribute it and/or modify
+     it under the terms of the GNU General Public License as published
+     by the Free Software Foundation; either version 2, or (at your
+     option) any later version.
+
+     libmicrohttpd is distributed in the hope that it will be useful, but
+     WITHOUT ANY WARRANTY; without even the implied warranty of
+     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+     General Public License for more details.
+
+     You should have received a copy of the GNU General Public License
+     along with libmicrohttpd; see the file COPYING.  If not, write to the
+     Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+     Boston, MA 02111-1307, USA.
+*/
+
+/**
+ * @file connection.c
+ * @brief  Methods for managing connections
+ * @author Daniel Pittman
+ * @author Christian Grothoff
+ */
+
+#include "internal.h"
+#include "connection.h"
+#include "response.h"
+
+
+/**
+ * Get all of the headers from the request.
+ *
+ * @param iterator callback to call on each header;
+ *        maybe NULL (then just count headers)
+ * @param iterator_cls extra argument to iterator
+ * @return number of entries iterated over
+ */
+int
+MHD_get_connection_values(struct MHD_Connection * connection,
+                      enum MHD_ValueKind kind,
+                      MHD_KeyValueIterator iterator,
+                      void * iterator_cls) {
+  int ret;
+  struct MHD_HTTP_Header * pos;
+
+  if (connection == NULL)
+    return -1;
+  ret = 0;
+  pos = connection->headers_received;
+  while (pos != NULL) {
+    if (0 != (pos->kind & kind)) {
+      ret++;
+      if ( (iterator != NULL) &&
+          (MHD_YES != iterator(iterator_cls,
+                               kind,
+                               pos->header,
+                               pos->value)) )
+       return ret;
+    }
+    pos = pos->next;
+  }
+  return ret;
+}
+
+
+/**
+ * Get a particular header value.  If multiple
+ * values match the kind, return any one of them.
+ *
+ * @param key the header to look for
+ * @return NULL if no such item was found
+ */
+const char *
+MHD_lookup_connection_value(struct MHD_Connection * connection,
+                        enum MHD_ValueKind kind,
+                        const char * key) {
+  struct MHD_HTTP_Header * pos;
+
+  if (connection == NULL)
+    return NULL;
+  pos = connection->headers_received;
+  while (pos != NULL) {
+    if ( (0 != (pos->kind & kind)) &&
+        (0 == strcasecmp(key,
+                         pos->header)) )
+      return pos->value;
+    pos = pos->next;
+  }
+  return NULL;
+}
+
+/**
+ * Queue a response to be transmitted to the client (as soon as
+ * possible).
+ *
+ * @param connection the connection identifying the client
+ * @param status_code HTTP status code (i.e. 200 for OK)
+ * @param response response to transmit
+ * @return MHD_NO on error (i.e. reply already sent),
+ *         MHD_YES on success or if message has been queued
+ */
+int
+MHD_queue_response(struct MHD_Connection * connection,
+                  unsigned int status_code,
+                  struct MHD_Response * response) {
+  if ( (connection == NULL) ||
+       (response == NULL) ||
+       (connection->response != NULL) ||
+       (connection->bodyReceived == 0) ||
+       (connection->headersReceived == 0) )
+    return MHD_NO;     
+  MHD_increment_response_rc(response);
+  connection->response = response;
+  connection->responseCode = status_code;
+  return MHD_YES;
+}
+
+
+/**
+ * Obtain the select sets for this connection
+ *
+ * @return MHD_YES on success
+ */
+int
+MHD_connection_get_fdset(struct MHD_Connection * connection,
+                     fd_set * read_fd_set,
+                     fd_set * write_fd_set,
+                     fd_set * except_fd_set,
+                     int * max_fd) {
+  int fd;
+
+  fd = connection->socket_fd;
+  if (fd == -1)
+    return MHD_YES;
+  if ( (connection->read_close == 0) &&
+       ( (connection->headersReceived == 0) ||
+        (connection->readLoc < connection->read_buffer_size) ) )
+    FD_SET(fd, read_fd_set);
+  if (connection->response != NULL)
+    FD_SET(fd, write_fd_set);
+  if ( (fd > *max_fd) &&
+       ( (connection->headersReceived == 0) ||
+        (connection->readLoc < connection->read_buffer_size) ||
+        (connection->response != NULL) ) )
+    *max_fd = fd;
+  return MHD_YES;
+}
+
+/**
+ * Parse a single line of the HTTP header.  Remove it
+ * from the read buffer.  If the current line does not
+ * fit, consider growing the buffer.  If the line is
+ * far too long, close the connection.  If no line is
+ * found (incomplete, buffer too small, line too long),
+ * return NULL.  Otherwise return a copy of the line.
+ */
+static char *
+MHD_get_next_header_line(struct MHD_Connection * connection) {
+  char * rbuf;
+  size_t pos;
+  size_t start;
+
+  if (connection->readLoc == 0)
+    return NULL;
+  start = 0;
+  pos = 0;
+  rbuf = connection->read_buffer;
+  while ( (pos < connection->readLoc - 1) &&
+         (rbuf[pos] != '\r') &&
+         (rbuf[pos] != '\n') )
+    pos++;
+  if (pos == connection->readLoc - 1) {
+    /* not found, consider growing... */
+    if (connection->readLoc == connection->read_buffer_size) {
+      /* grow buffer to read larger header or die... */
+      if (connection->read_buffer_size < 4 * MHD_MAX_BUF_SIZE) {
+       rbuf = malloc(connection->read_buffer_size * 2);
+       memcpy(rbuf,
+              connection->read_buffer,
+              connection->readLoc);
+       free(connection->read_buffer);
+       connection->read_buffer = rbuf;
+       connection->read_buffer_size *= 2;
+      } else {
+       /* die, header far too long to be reasonable */
+       MHD_DLOG(connection->daemon,
+                "Received excessively long header line (>%u), closing 
connection.\n",
+                4 * MHD_MAX_BUF_SIZE);
+       CLOSE(connection->socket_fd);
+       connection->socket_fd = -1;
+      }
+    }
+    return NULL;
+  }
+  /* found, check if we have proper CRLF */
+  rbuf = malloc(pos + 1);
+  memcpy(rbuf,
+        connection->read_buffer,
+        pos);
+  rbuf[pos] = '\0';
+  if ( (connection->read_buffer[pos] == '\r') &&
+       (connection->read_buffer[pos+1] == '\n') )
+    pos++; /* skip both r and n */
+  pos++;
+  memmove(connection->read_buffer,
+         &connection->read_buffer[pos],
+         connection->readLoc - pos);
+  connection->readLoc -= pos;
+  return rbuf;
+}
+
+static void
+MHD_connection_add_header(struct MHD_Connection * connection,
+                      const char * key,
+                      const char * value,
+                      enum MHD_ValueKind kind) {
+  struct MHD_HTTP_Header * hdr;
+
+  hdr = malloc(sizeof(struct MHD_HTTP_Header));
+  hdr->next = connection->headers_received;
+  hdr->header = strdup(key);
+  hdr->value = strdup(value);
+  hdr->kind = kind;
+  connection->headers_received = hdr;
+}
+
+/**
+ * Process escape sequences ('+'=space, %HH)
+ */ 
+static void
+MHD_http_unescape(char * val) {
+  char * esc;
+  unsigned int num;
+
+  while (NULL != (esc = strstr(val, "+"))) 
+    *esc = ' ';  
+  while (NULL != (esc = strstr(val, "%"))) {
+    if ( (1 == sscanf(&esc[1],
+                   "%2x",
+                   &num)) ||
+        (1 == sscanf(&esc[1],
+                     "%2X",
+                     &num)) ) {
+      esc[0] = (unsigned char) num;
+      memmove(&esc[1],
+             &esc[3],
+             strlen(&esc[3]));
+    }
+    val = esc+1;
+  }
+}
+
+static void
+MHD_parse_arguments(struct MHD_Connection * connection,
+                   char * args) {
+  char * equals;
+  char * amper;
+
+  while (args != NULL) {
+    equals = strstr(args, "=");
+    if (equals == NULL)
+      return; /* invalid, ignore */
+    equals[0] = '\0';
+    equals++;
+    amper = strstr(equals, "&");
+    if (amper != NULL) {
+      amper[0] = '\0';
+      amper++;
+    }
+    MHD_http_unescape(args);
+    MHD_http_unescape(equals);
+    MHD_connection_add_header(connection,
+                          args,
+                          equals,
+                          MHD_GET_ARGUMENT_KIND);
+    args = amper;
+  }
+}
+
+/**
+ * Parse the cookie header (see RFC 2109).
+ */
+static void
+MHD_parse_cookie_header(struct MHD_Connection * connection) {
+  const char * hdr;
+  char * cpy;
+  char * pos;
+  char * semicolon;
+  char * equals;
+  int quotes;
+
+  hdr = MHD_lookup_connection_value(connection,
+                                MHD_HEADER_KIND,
+                                "Cookie");
+  if (hdr == NULL)
+    return;
+  cpy = strdup(hdr);
+  pos = cpy;
+  while (pos != NULL) {
+    equals = strstr(pos, "=");
+    if (equals == NULL)
+      break;
+    equals[0] = '\0';
+    equals++;
+    quotes = 0;
+    semicolon = equals;
+    while ( (semicolon[0] != '\0') &&
+           ( (quotes != 0) ||
+             ( (semicolon[0] != ';') &&
+               (semicolon[0] != ',') ) ) ) {
+      if (semicolon[0] == '"')
+       quotes = (quotes + 1) & 1;
+      semicolon++;
+    }
+    if (semicolon[0] == '\0')
+      semicolon = NULL;
+    if (semicolon != NULL) {
+      semicolon[0] = '\0';
+      semicolon++;
+    }
+    /* remove quotes */
+    if ( (equals[0] == '"') &&
+        (equals[strlen(equals)-1] == '"') ) {
+      equals[strlen(equals)-1] = '\0';
+      equals++;
+    }
+    MHD_connection_add_header(connection,
+                          pos,
+                          equals,
+                          MHD_COOKIE_KIND);
+    pos = semicolon;
+  }
+  free(cpy);
+}
+
+
+/**
+ * This function is designed to parse the input buffer of a given connection.
+ *
+ * Once the header is complete, it should have set the
+ * headers_received, url and method values and set
+ * headersReceived to 1.  If no body is expected, it should
+ * also set "bodyReceived" to 1.  Otherwise, it should
+ * set "uploadSize" to the expected size of the body.  If the
+ * size of the body is unknown, it should be set to -1.
+ */
+static void
+MHD_parse_connection_headers(struct MHD_Connection * connection) {
+  char * last;
+  char * line;
+  char * colon;
+  char * uri;
+  char * httpType;
+  char * args;
+  char * tmp;
+  const char * clen;
+  unsigned long long cval;
+
+  if (connection->bodyReceived == 1)
+    abort();
+  last = NULL;
+  while (NULL != (line = MHD_get_next_header_line(connection))) {
+    if (last != NULL) {
+      if ( (line[0] == ' ') ||
+          (line[0] == '\t') ) {
+       /* value was continued on the next line, see
+          http://www.jmarshall.com/easy/http/ */
+       if ( (strlen(line) + strlen(last) >
+             4 * MHD_MAX_BUF_SIZE) ) {
+         free(line);
+         free(last);
+         last = NULL;
+         MHD_DLOG(connection->daemon,
+                  "Received excessively long header line (>%u), closing 
connection.\n",
+                  4 * MHD_MAX_BUF_SIZE);
+         CLOSE(connection->socket_fd);
+         connection->socket_fd = -1;
+         break;
+       }
+       tmp = malloc(strlen(line) + strlen(last) + 1);
+       strcpy(tmp, last);
+       free(last);
+       last = tmp;
+       tmp = line;
+       while ( (tmp[0] == ' ') ||
+               (tmp[0] == '\t') )
+         tmp++; /* skip whitespace at start of 2nd line */
+       strcat(last, tmp);
+       free(line);
+       continue; /* possibly more than 2 lines... */
+      } else {
+       MHD_connection_add_header(connection,
+                              last,
+                              colon,
+                              MHD_HEADER_KIND);
+       free(last);
+       last = NULL;    
+      }
+    }
+    if (connection->url == NULL) {
+      /* line must be request line */
+      uri = strstr(line, " ");
+      if (uri == NULL)
+       goto DIE;
+      uri[0] = '\0';
+      connection->method = strdup(line);
+      uri++;
+      httpType = strstr(uri, " ");
+      if (httpType != NULL) {
+       httpType[0] = '\0';
+       httpType++;
+      }
+      args = strstr(uri, "?");
+      if (args != NULL) {
+       args[0] = '\0';
+       args++;
+       MHD_parse_arguments(connection,
+                           args);
+      }
+      connection->url = strdup(uri);
+      if (httpType == NULL)
+       connection->version = strdup("");
+      else
+       connection->version = strdup(httpType);
+      free(line);
+      continue;
+    }
+    /* check if this is the end of the header */
+    if (strlen(line) == 0) {
+      free(line);
+      /* end of header */
+      connection->headersReceived = 1;
+      clen = MHD_lookup_connection_value(connection,
+                                     MHD_HEADER_KIND,
+                                     "Content-Length");
+      if (clen != NULL) {
+       if (1 != sscanf(clen,
+                       "%llu",
+                       &cval)) {
+         MHD_DLOG(connection->daemon,
+                  "Failed to parse Content-Length header `%s', closing 
connection.\n",
+                  clen);
+         goto DIE;
+       }
+       connection->uploadSize = cval;
+       connection->bodyReceived = cval == 0 ? 1 : 0;
+      } else {
+       if (NULL == MHD_lookup_connection_value(connection,
+                                            MHD_HEADER_KIND,
+                                            "Transfer-Encoding")) {
+         /* this request does not have a body */
+         connection->uploadSize = 0;
+         connection->bodyReceived = 1;
+       } else {
+         connection->uploadSize = -1; /* unknown size */
+         connection->bodyReceived = 0;
+       }
+      }
+      break;
+    }
+    /* line should be normal header line, find colon */
+    colon = strstr(line, ":");
+    if (colon == NULL) {
+      /* error in header line, die hard */
+      MHD_DLOG(connection->daemon,
+              "Received malformed line (no colon), closing connection.\n");
+      goto DIE;
+    }
+    /* zero-terminate header */
+    colon[0] = '\0';
+    colon++; /* advance to value */
+    while ( (colon[0] != '\0') &&
+           ( (colon[0] == ' ') ||
+             (colon[0] == '\t') ) )
+      colon++;
+    /* we do the actual adding of the connection
+       header at the beginning of the while
+       loop since we need to be able to inspect
+       the *next* header line (in case it starts
+       with a space...) */
+  }
+  if (last != NULL) {
+    MHD_connection_add_header(connection,
+                          last,
+                          colon,
+                          MHD_HEADER_KIND);
+    free(last);
+  }
+  MHD_parse_cookie_header(connection);
+  return;
+ DIE:
+  CLOSE(connection->socket_fd);
+  connection->socket_fd = -1;
+}
+
+
+/**
+ * Find the handler responsible for this request.
+ */
+static struct MHD_Access_Handler *
+MHD_find_access_handler(struct MHD_Connection * connection) {
+  struct MHD_Access_Handler * pos;
+
+  pos = connection->daemon->handlers;
+  while (pos != NULL) {
+    if (0 == strcmp(connection->url,
+                   pos->uri_prefix))
+      return pos;
+    pos = pos->next;
+  }
+  return &connection->daemon->default_handler;
+}
+
+/**
+ * Call the handler of the application for this
+ * connection.
+ */
+void
+MHD_call_connection_handler(struct MHD_Connection * connection) {
+  struct MHD_Access_Handler * ah;
+  unsigned int processed;
+
+  if (connection->headersReceived == 0)
+    abort(); /* bad timing... */
+  ah = MHD_find_access_handler(connection);
+  processed = connection->readLoc;
+  if (MHD_NO == ah->dh(ah->dh_cls,
+                      connection,
+                      connection->url,
+                      connection->method,
+                      connection->read_buffer,
+                      &processed)) {
+    /* serios internal error, close connection */
+    MHD_DLOG(connection->daemon,
+            "Internal application error, closing connection.");
+    CLOSE(connection->socket_fd);
+    connection->socket_fd = -1;
+    return;
+  }
+  /* dh left "processed" bytes in buffer for next time... */
+  memmove(connection->read_buffer,
+         &connection->read_buffer[connection->readLoc - processed],
+         processed);
+  if (connection->uploadSize != -1)
+    connection->uploadSize -= (connection->readLoc - processed);
+  connection->readLoc = processed;
+  if ( (connection->uploadSize == 0) ||
+       ( (connection->readLoc == 0) &&
+        (connection->uploadSize == -1) &&
+        (connection->socket_fd == -1) ) ) {
+    connection->bodyReceived = 1;
+    connection->readLoc = 0;
+    connection->read_buffer_size = 0;
+    free(connection->read_buffer);
+    connection->read_buffer = NULL;
+  }
+}
+
+
+/**
+ * This function handles a particular connection when it has been
+ * determined that there is data to be read off a socket. All implementations
+ * (multithreaded, external select, internal select) call this function
+ * to handle reads.
+ */
+int
+MHD_connection_handle_read(struct MHD_Connection * connection) {
+  int bytes_read;
+  void * tmp;
+
+  if ( (connection->readLoc >= connection->read_buffer_size) &&
+       (connection->headersReceived == 0) ) {
+    /* need to grow read buffer */
+    tmp = malloc(connection->read_buffer_size * 2 + MHD_MAX_BUF_SIZE);
+    memcpy(tmp,
+          connection->read_buffer,
+          connection->read_buffer_size);
+    connection->read_buffer_size = connection->read_buffer_size * 2 + 
MHD_MAX_BUF_SIZE;
+    if (connection->read_buffer != NULL)
+      free(connection->read_buffer);
+    connection->read_buffer = tmp;
+  }
+  if (connection->readLoc >= connection->read_buffer_size) {
+    MHD_DLOG(connection->daemon,
+            "Unexpected call to %s.\n",
+            __FUNCTION__);
+    return MHD_NO;
+  }
+  bytes_read = RECV(connection->socket_fd,
+                   &connection->read_buffer[connection->readLoc],
+                   connection->read_buffer_size - connection->readLoc,
+                   0);
+  if (bytes_read < 0) {
+    if (errno == EINTR)
+      return MHD_NO;
+    MHD_DLOG(connection->daemon,
+            "Failed to receive data: %s\n",
+            STRERROR(errno));
+    CLOSE(connection->socket_fd);
+    connection->socket_fd = -1;
+    return MHD_YES;
+  }
+  if (bytes_read == 0) {
+    /* other side closed connection */
+    if (connection->readLoc > 0)
+      MHD_call_connection_handler(connection);
+    shutdown(connection->socket_fd, SHUT_RD);
+    return MHD_YES;
+  }
+  connection->readLoc += bytes_read;
+  if (connection->headersReceived == 0)
+    MHD_parse_connection_headers(connection);
+  if (connection->headersReceived == 1)
+    MHD_call_connection_handler(connection);
+  return MHD_YES;
+}
+
+/**
+ * Check if we need to set some additional headers
+ * for http-compiliance.
+ */
+static void
+MHD_add_extra_headers(struct MHD_Connection * connection) {
+  const char * have;
+  char buf[128];
+
+  if (connection->response->total_size == -1) {
+    have = MHD_get_response_header(connection->response,
+                                  "Connection");
+    if (have == NULL)
+      MHD_add_response_header(connection->response,
+                             "Connection",
+                             "close");
+  } else if (NULL == MHD_get_response_header(connection->response,
+                                            "Content-Length")) {
+    _REAL_SNPRINTF(buf,
+            128,
+            "%llu",
+            (unsigned long long) connection->response->total_size);
+    MHD_add_response_header(connection->response,
+                           "Content-Length",
+                           buf);
+  }
+}
+
+/**
+ * Allocate the connection's write buffer and
+ * fill it with all of the headers from the
+ * HTTPd's response.
+ */
+static void
+MHD_build_header_response(struct MHD_Connection * connection) {
+  size_t size;
+  size_t off;
+  struct MHD_HTTP_Header * pos;
+  char code[32];
+  char * data;
+
+  MHD_add_extra_headers(connection);
+  SPRINTF(code,
+         "HTTP/1.1 %u\r\n",
+         connection->responseCode);
+  off = strlen(code);
+  /* estimate size */
+  size = off + 2; /* extra \r\n at the end */
+  pos = connection->response->first_header;
+  while (pos != NULL) {
+    size += strlen(pos->header) + strlen(pos->value) + 4; /* colon, space, 
linefeeds */
+    pos = pos->next;
+  }
+  /* produce data */
+  data = malloc(size + 1);
+  memcpy(data,
+        code,
+        off);
+  pos = connection->response->first_header;
+  while (pos != NULL) {
+    SPRINTF(&data[off],
+           "%s: %s\r\n",
+           pos->header,
+           pos->value);
+    off += strlen(pos->header) + strlen(pos->value) + 4;
+    pos = pos->next;
+  }
+  sprintf(&data[off],
+         "\r\n");
+  off += 2;
+  if (off != size)
+    abort();
+  connection->write_buffer = data;
+  connection->write_buffer_size = size;
+}
+
+/**
+ * This function was created to handle writes to sockets when it has
+ * been determined that the socket can be written to. All
+ * implementations (multithreaded, external select, internal select)
+ * call this function
+ */
+int
+MHD_connection_handle_write(struct MHD_Connection * connection) {
+  struct MHD_Response * response;
+  int ret;
+
+  response = connection->response;
+  if(response == NULL) {
+    MHD_DLOG(connection->daemon,
+            "Unexpected call to %s.\n",
+            __FUNCTION__);
+    return MHD_NO;
+  }
+  if (! connection->headersSent) {
+    if (connection->write_buffer == NULL)
+      MHD_build_header_response(connection);
+    ret = SEND(connection->socket_fd,
+              &connection->write_buffer[connection->writeLoc],
+              connection->write_buffer_size - connection->writeLoc,
+              0);
+    if (ret < 0) {
+      if (errno == EINTR)
+       return MHD_YES;
+      MHD_DLOG(connection->daemon,
+              "Failed to send data: %s\n",
+              STRERROR(errno));
+      CLOSE(connection->socket_fd);
+      connection->socket_fd = -1;
+      return MHD_YES;
+    }
+    connection->writeLoc += ret;
+    if (connection->writeLoc == connection->write_buffer_size) {
+      connection->writeLoc = 0;
+      free(connection->write_buffer);
+      connection->write_buffer = NULL;
+      connection->write_buffer_size = 0;
+      connection->headersSent = 1;
+    }
+    return MHD_YES;
+  }
+  if (response->total_size <= connection->messagePos)
+    abort(); /* internal error */
+  if (response->crc != NULL)
+    pthread_mutex_lock(&response->mutex);
+
+  /* prepare send buffer */
+  if ( (response->data == NULL) ||
+       (response->data_start > connection->messagePos) ||
+       (response->data_start + response->data_size < connection->messagePos) ) 
{
+    if (response->data_size == 0) {
+      if (response->data != NULL)
+       free(response->data);
+      response->data = malloc(MHD_MAX_BUF_SIZE);
+      response->data_size = MHD_MAX_BUF_SIZE;
+    }
+    ret = response->crc(response->crc_cls,
+                       connection->messagePos,
+                       response->data,
+                       MAX(MHD_MAX_BUF_SIZE,
+                           response->data_size - connection->messagePos));
+    if (ret == -1) {
+      /* end of message, signal other side by closing! */
+      response->data_size = connection->messagePos;
+      CLOSE(connection->socket_fd);
+      connection->socket_fd = -1;
+      if (response->crc != NULL)
+       pthread_mutex_unlock(&response->mutex);
+      return MHD_YES;
+    }
+    response->data_start = connection->messagePos;
+    response->data_size = ret;
+    if (ret == 0) {
+      if (response->crc != NULL)
+       pthread_mutex_unlock(&response->mutex);
+      return MHD_YES;
+    }
+  }
+
+  /* transmit */
+  ret = SEND(connection->socket_fd,
+            &response->data[connection->messagePos - response->data_start],
+            response->data_size - (connection->messagePos - 
response->data_start),
+            0);
+  if (response->crc != NULL)
+    pthread_mutex_unlock(&response->mutex);
+  if (ret < 0) {
+    if (errno == EINTR)
+      return MHD_YES;
+    MHD_DLOG(connection->daemon,
+            "Failed to send data: %s\n",
+            STRERROR(errno));
+    CLOSE(connection->socket_fd);
+    connection->socket_fd = -1;
+    return MHD_YES;
+  }
+  connection->messagePos += ret;
+  if (connection->messagePos > response->data_size)
+    abort(); /* internal error */
+  if (connection->messagePos == response->data_size) {
+    if ( (connection->bodyReceived == 0) ||
+        (connection->headersReceived == 0) )
+      abort(); /* internal error */
+    MHD_destroy_response(response);
+    connection->responseCode = 0;
+    connection->response = NULL;
+    connection->headersReceived = 0;
+    connection->headersSent = 0;
+    connection->bodyReceived = 0;
+    connection->messagePos = 0;
+    free(connection->method);
+    connection->method = NULL;
+    free(connection->url);
+    connection->url = NULL;
+    free(connection->version);
+    connection->version = NULL;
+    free(connection->write_buffer);
+    connection->write_buffer = NULL;
+    connection->write_buffer_size = 0;
+    if (connection->read_close != 0) {
+      /* closed for reading => close for good! */
+      CLOSE(connection->socket_fd);
+      connection->socket_fd = -1;
+    }
+  }
+  return MHD_YES;
+}
+
+/* end of connection.c */
+
+

Copied: libmicrohttpd/src/daemon/connection.h (from rev 5279, 
libmicrohttpd/src/daemon/session.h)
===================================================================
--- libmicrohttpd/src/daemon/connection.h                               (rev 0)
+++ libmicrohttpd/src/daemon/connection.h       2007-07-09 03:20:57 UTC (rev 
5280)
@@ -0,0 +1,72 @@
+/*
+     This file is part of libmicrohttpd
+     (C) 2007 Daniel Pittman
+
+     libmicrohttpd is free software; you can redistribute it and/or modify
+     it under the terms of the GNU General Public License as published
+     by the Free Software Foundation; either version 2, or (at your
+     option) any later version.
+
+     libmicrohttpd is distributed in the hope that it will be useful, but
+     WITHOUT ANY WARRANTY; without even the implied warranty of
+     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+     General Public License for more details.
+
+     You should have received a copy of the GNU General Public License
+     along with libmicrohttpd; see the file COPYING.  If not, write to the
+     Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+     Boston, MA 02111-1307, USA.
+*/
+
+/**
+ * @file connection.h
+ * @brief  Methods for managing connections
+ * @author Daniel Pittman
+ * @author Christian Grothoff
+ */
+
+#ifndef CONNECTION_H
+#define CONNECTION_H
+
+
+/**
+ * Obtain the select sets for this connection.
+ *
+ * @return MHD_YES on success
+ */
+int
+MHD_connection_get_fdset(struct MHD_Connection * connection,
+                     fd_set * read_fd_set,
+                     fd_set * write_fd_set,
+                     fd_set * except_fd_set,
+                     int * max_fd);
+
+
+/**
+ * Call the handler of the application for this
+ * connection.
+ */
+void
+MHD_call_connection_handler(struct MHD_Connection * connection);
+
+/**
+ * This function handles a particular connection when it has been
+ * determined that there is data to be read off a socket. All implementations
+ * (multithreaded, external select, internal select) call this function
+ * to handle reads.
+ */
+int
+MHD_connection_handle_read(struct MHD_Connection * connection);
+
+
+/**
+ * This function was created to handle writes to sockets when it has been
+ * determined that the socket can be written to. If there is no data
+ * to be written, however, the function call does nothing. All implementations
+ * (multithreaded, external select, internal select) call this function
+ */
+int
+MHD_connection_handle_write(struct MHD_Connection * connection);
+
+
+#endif

Deleted: libmicrohttpd/src/daemon/session.c
===================================================================
--- libmicrohttpd/src/daemon/session.c  2007-07-09 03:20:40 UTC (rev 5279)
+++ libmicrohttpd/src/daemon/session.c  2007-07-09 03:20:57 UTC (rev 5280)
@@ -1,831 +0,0 @@
-/*
-     This file is part of libmicrohttpd
-     (C) 2007 Daniel Pittman
-
-     libmicrohttpd is free software; you can redistribute it and/or modify
-     it under the terms of the GNU General Public License as published
-     by the Free Software Foundation; either version 2, or (at your
-     option) any later version.
-
-     libmicrohttpd is distributed in the hope that it will be useful, but
-     WITHOUT ANY WARRANTY; without even the implied warranty of
-     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-     General Public License for more details.
-
-     You should have received a copy of the GNU General Public License
-     along with libmicrohttpd; see the file COPYING.  If not, write to the
-     Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-     Boston, MA 02111-1307, USA.
-*/
-
-/**
- * @file connection.c
- * @brief  Methods for managing connections
- * @author Daniel Pittman
- * @author Christian Grothoff
- */
-
-#include "internal.h"
-#include "connection.h"
-#include "response.h"
-
-
-/**
- * Get all of the headers from the request.
- *
- * @param iterator callback to call on each header;
- *        maybe NULL (then just count headers)
- * @param iterator_cls extra argument to iterator
- * @return number of entries iterated over
- */
-int
-MHD_get_connection_values(struct MHD_Connection * connection,
-                      enum MHD_ValueKind kind,
-                      MHD_KeyValueIterator iterator,
-                      void * iterator_cls) {
-  int ret;
-  struct MHD_HTTP_Header * pos;
-
-  if (connection == NULL)
-    return -1;
-  ret = 0;
-  pos = connection->headers_received;
-  while (pos != NULL) {
-    if (0 != (pos->kind & kind)) {
-      ret++;
-      if ( (iterator != NULL) &&
-          (MHD_YES != iterator(iterator_cls,
-                               kind,
-                               pos->header,
-                               pos->value)) )
-       return ret;
-    }
-    pos = pos->next;
-  }
-  return ret;
-}
-
-
-/**
- * Get a particular header value.  If multiple
- * values match the kind, return any one of them.
- *
- * @param key the header to look for
- * @return NULL if no such item was found
- */
-const char *
-MHD_lookup_connection_value(struct MHD_Connection * connection,
-                        enum MHD_ValueKind kind,
-                        const char * key) {
-  struct MHD_HTTP_Header * pos;
-
-  if (connection == NULL)
-    return NULL;
-  pos = connection->headers_received;
-  while (pos != NULL) {
-    if ( (0 != (pos->kind & kind)) &&
-        (0 == strcasecmp(key,
-                         pos->header)) )
-      return pos->value;
-    pos = pos->next;
-  }
-  return NULL;
-}
-
-/**
- * Queue a response to be transmitted to the client (as soon as
- * possible).
- *
- * @param connection the connection identifying the client
- * @param status_code HTTP status code (i.e. 200 for OK)
- * @param response response to transmit
- * @return MHD_NO on error (i.e. reply already sent),
- *         MHD_YES on success or if message has been queued
- */
-int
-MHD_queue_response(struct MHD_Connection * connection,
-                  unsigned int status_code,
-                  struct MHD_Response * response) {
-  if ( (connection == NULL) ||
-       (response == NULL) ||
-       (connection->response != NULL) ||
-       (connection->bodyReceived == 0) ||
-       (connection->headersReceived == 0) )
-    return MHD_NO;     
-  MHD_increment_response_rc(response);
-  connection->response = response;
-  connection->responseCode = status_code;
-  return MHD_YES;
-}
-
-
-/**
- * Obtain the select sets for this connection
- *
- * @return MHD_YES on success
- */
-int
-MHD_connection_get_fdset(struct MHD_Connection * connection,
-                     fd_set * read_fd_set,
-                     fd_set * write_fd_set,
-                     fd_set * except_fd_set,
-                     int * max_fd) {
-  int fd;
-
-  fd = connection->socket_fd;
-  if (fd == -1)
-    return MHD_YES;
-  if ( (connection->read_close == 0) &&
-       ( (connection->headersReceived == 0) ||
-        (connection->readLoc < connection->read_buffer_size) ) )
-    FD_SET(fd, read_fd_set);
-  if (connection->response != NULL)
-    FD_SET(fd, write_fd_set);
-  if ( (fd > *max_fd) &&
-       ( (connection->headersReceived == 0) ||
-        (connection->readLoc < connection->read_buffer_size) ||
-        (connection->response != NULL) ) )
-    *max_fd = fd;
-  return MHD_YES;
-}
-
-/**
- * Parse a single line of the HTTP header.  Remove it
- * from the read buffer.  If the current line does not
- * fit, consider growing the buffer.  If the line is
- * far too long, close the connection.  If no line is
- * found (incomplete, buffer too small, line too long),
- * return NULL.  Otherwise return a copy of the line.
- */
-static char *
-MHD_get_next_header_line(struct MHD_Connection * connection) {
-  char * rbuf;
-  size_t pos;
-  size_t start;
-
-  if (connection->readLoc == 0)
-    return NULL;
-  start = 0;
-  pos = 0;
-  rbuf = connection->read_buffer;
-  while ( (pos < connection->readLoc - 1) &&
-         (rbuf[pos] != '\r') &&
-         (rbuf[pos] != '\n') )
-    pos++;
-  if (pos == connection->readLoc - 1) {
-    /* not found, consider growing... */
-    if (connection->readLoc == connection->read_buffer_size) {
-      /* grow buffer to read larger header or die... */
-      if (connection->read_buffer_size < 4 * MHD_MAX_BUF_SIZE) {
-       rbuf = malloc(connection->read_buffer_size * 2);
-       memcpy(rbuf,
-              connection->read_buffer,
-              connection->readLoc);
-       free(connection->read_buffer);
-       connection->read_buffer = rbuf;
-       connection->read_buffer_size *= 2;
-      } else {
-       /* die, header far too long to be reasonable */
-       MHD_DLOG(connection->daemon,
-                "Received excessively long header line (>%u), closing 
connection.\n",
-                4 * MHD_MAX_BUF_SIZE);
-       CLOSE(connection->socket_fd);
-       connection->socket_fd = -1;
-      }
-    }
-    return NULL;
-  }
-  /* found, check if we have proper CRLF */
-  rbuf = malloc(pos + 1);
-  memcpy(rbuf,
-        connection->read_buffer,
-        pos);
-  rbuf[pos] = '\0';
-  if ( (connection->read_buffer[pos] == '\r') &&
-       (connection->read_buffer[pos+1] == '\n') )
-    pos++; /* skip both r and n */
-  pos++;
-  memmove(connection->read_buffer,
-         &connection->read_buffer[pos],
-         connection->readLoc - pos);
-  connection->readLoc -= pos;
-  return rbuf;
-}
-
-static void
-MHD_connection_add_header(struct MHD_Connection * connection,
-                      const char * key,
-                      const char * value,
-                      enum MHD_ValueKind kind) {
-  struct MHD_HTTP_Header * hdr;
-
-  hdr = malloc(sizeof(struct MHD_HTTP_Header));
-  hdr->next = connection->headers_received;
-  hdr->header = strdup(key);
-  hdr->value = strdup(value);
-  hdr->kind = kind;
-  connection->headers_received = hdr;
-}
-
-/**
- * Process escape sequences ('+'=space, %HH)
- */ 
-static void
-MHD_http_unescape(char * val) {
-  char * esc;
-  unsigned int num;
-
-  while (NULL != (esc = strstr(val, "+"))) 
-    *esc = ' ';  
-  while (NULL != (esc = strstr(val, "%"))) {
-    if ( (1 == sscanf(&esc[1],
-                   "%2x",
-                   &num)) ||
-        (1 == sscanf(&esc[1],
-                     "%2X",
-                     &num)) ) {
-      esc[0] = (unsigned char) num;
-      memmove(&esc[1],
-             &esc[3],
-             strlen(&esc[3]));
-    }
-    val = esc+1;
-  }
-}
-
-static void
-MHD_parse_arguments(struct MHD_Connection * connection,
-                   char * args) {
-  char * equals;
-  char * amper;
-
-  while (args != NULL) {
-    equals = strstr(args, "=");
-    if (equals == NULL)
-      return; /* invalid, ignore */
-    equals[0] = '\0';
-    equals++;
-    amper = strstr(equals, "&");
-    if (amper != NULL) {
-      amper[0] = '\0';
-      amper++;
-    }
-    MHD_http_unescape(args);
-    MHD_http_unescape(equals);
-    MHD_connection_add_header(connection,
-                          args,
-                          equals,
-                          MHD_GET_ARGUMENT_KIND);
-    args = amper;
-  }
-}
-
-/**
- * Parse the cookie header (see RFC 2109).
- */
-static void
-MHD_parse_cookie_header(struct MHD_Connection * connection) {
-  const char * hdr;
-  char * cpy;
-  char * pos;
-  char * semicolon;
-  char * equals;
-  int quotes;
-
-  hdr = MHD_lookup_connection_value(connection,
-                                MHD_HEADER_KIND,
-                                "Cookie");
-  if (hdr == NULL)
-    return;
-  cpy = strdup(hdr);
-  pos = cpy;
-  while (pos != NULL) {
-    equals = strstr(pos, "=");
-    if (equals == NULL)
-      break;
-    equals[0] = '\0';
-    equals++;
-    quotes = 0;
-    semicolon = equals;
-    while ( (semicolon[0] != '\0') &&
-           ( (quotes != 0) ||
-             ( (semicolon[0] != ';') &&
-               (semicolon[0] != ',') ) ) ) {
-      if (semicolon[0] == '"')
-       quotes = (quotes + 1) & 1;
-      semicolon++;
-    }
-    if (semicolon[0] == '\0')
-      semicolon = NULL;
-    if (semicolon != NULL) {
-      semicolon[0] = '\0';
-      semicolon++;
-    }
-    /* remove quotes */
-    if ( (equals[0] == '"') &&
-        (equals[strlen(equals)-1] == '"') ) {
-      equals[strlen(equals)-1] = '\0';
-      equals++;
-    }
-    MHD_connection_add_header(connection,
-                          pos,
-                          equals,
-                          MHD_COOKIE_KIND);
-    pos = semicolon;
-  }
-  free(cpy);
-}
-
-
-/**
- * This function is designed to parse the input buffer of a given connection.
- *
- * Once the header is complete, it should have set the
- * headers_received, url and method values and set
- * headersReceived to 1.  If no body is expected, it should
- * also set "bodyReceived" to 1.  Otherwise, it should
- * set "uploadSize" to the expected size of the body.  If the
- * size of the body is unknown, it should be set to -1.
- */
-static void
-MHD_parse_connection_headers(struct MHD_Connection * connection) {
-  char * last;
-  char * line;
-  char * colon;
-  char * uri;
-  char * httpType;
-  char * args;
-  char * tmp;
-  const char * clen;
-  unsigned long long cval;
-
-  if (connection->bodyReceived == 1)
-    abort();
-  last = NULL;
-  while (NULL != (line = MHD_get_next_header_line(connection))) {
-    if (last != NULL) {
-      if ( (line[0] == ' ') ||
-          (line[0] == '\t') ) {
-       /* value was continued on the next line, see
-          http://www.jmarshall.com/easy/http/ */
-       if ( (strlen(line) + strlen(last) >
-             4 * MHD_MAX_BUF_SIZE) ) {
-         free(line);
-         free(last);
-         last = NULL;
-         MHD_DLOG(connection->daemon,
-                  "Received excessively long header line (>%u), closing 
connection.\n",
-                  4 * MHD_MAX_BUF_SIZE);
-         CLOSE(connection->socket_fd);
-         connection->socket_fd = -1;
-         break;
-       }
-       tmp = malloc(strlen(line) + strlen(last) + 1);
-       strcpy(tmp, last);
-       free(last);
-       last = tmp;
-       tmp = line;
-       while ( (tmp[0] == ' ') ||
-               (tmp[0] == '\t') )
-         tmp++; /* skip whitespace at start of 2nd line */
-       strcat(last, tmp);
-       free(line);
-       continue; /* possibly more than 2 lines... */
-      } else {
-       MHD_connection_add_header(connection,
-                              last,
-                              colon,
-                              MHD_HEADER_KIND);
-       free(last);
-       last = NULL;    
-      }
-    }
-    if (connection->url == NULL) {
-      /* line must be request line */
-      uri = strstr(line, " ");
-      if (uri == NULL)
-       goto DIE;
-      uri[0] = '\0';
-      connection->method = strdup(line);
-      uri++;
-      httpType = strstr(uri, " ");
-      if (httpType != NULL) {
-       httpType[0] = '\0';
-       httpType++;
-      }
-      args = strstr(uri, "?");
-      if (args != NULL) {
-       args[0] = '\0';
-       args++;
-       MHD_parse_arguments(connection,
-                           args);
-      }
-      connection->url = strdup(uri);
-      if (httpType == NULL)
-       connection->version = strdup("");
-      else
-       connection->version = strdup(httpType);
-      free(line);
-      continue;
-    }
-    /* check if this is the end of the header */
-    if (strlen(line) == 0) {
-      free(line);
-      /* end of header */
-      connection->headersReceived = 1;
-      clen = MHD_lookup_connection_value(connection,
-                                     MHD_HEADER_KIND,
-                                     "Content-Length");
-      if (clen != NULL) {
-       if (1 != sscanf(clen,
-                       "%llu",
-                       &cval)) {
-         MHD_DLOG(connection->daemon,
-                  "Failed to parse Content-Length header `%s', closing 
connection.\n",
-                  clen);
-         goto DIE;
-       }
-       connection->uploadSize = cval;
-       connection->bodyReceived = cval == 0 ? 1 : 0;
-      } else {
-       if (NULL == MHD_lookup_connection_value(connection,
-                                            MHD_HEADER_KIND,
-                                            "Transfer-Encoding")) {
-         /* this request does not have a body */
-         connection->uploadSize = 0;
-         connection->bodyReceived = 1;
-       } else {
-         connection->uploadSize = -1; /* unknown size */
-         connection->bodyReceived = 0;
-       }
-      }
-      break;
-    }
-    /* line should be normal header line, find colon */
-    colon = strstr(line, ":");
-    if (colon == NULL) {
-      /* error in header line, die hard */
-      MHD_DLOG(connection->daemon,
-              "Received malformed line (no colon), closing connection.\n");
-      goto DIE;
-    }
-    /* zero-terminate header */
-    colon[0] = '\0';
-    colon++; /* advance to value */
-    while ( (colon[0] != '\0') &&
-           ( (colon[0] == ' ') ||
-             (colon[0] == '\t') ) )
-      colon++;
-    /* we do the actual adding of the connection
-       header at the beginning of the while
-       loop since we need to be able to inspect
-       the *next* header line (in case it starts
-       with a space...) */
-  }
-  if (last != NULL) {
-    MHD_connection_add_header(connection,
-                          last,
-                          colon,
-                          MHD_HEADER_KIND);
-    free(last);
-  }
-  MHD_parse_cookie_header(connection);
-  return;
- DIE:
-  CLOSE(connection->socket_fd);
-  connection->socket_fd = -1;
-}
-
-
-/**
- * Find the handler responsible for this request.
- */
-static struct MHD_Access_Handler *
-MHD_find_access_handler(struct MHD_Connection * connection) {
-  struct MHD_Access_Handler * pos;
-
-  pos = connection->daemon->handlers;
-  while (pos != NULL) {
-    if (0 == strcmp(connection->url,
-                   pos->uri_prefix))
-      return pos;
-    pos = pos->next;
-  }
-  return &connection->daemon->default_handler;
-}
-
-/**
- * Call the handler of the application for this
- * connection.
- */
-void
-MHD_call_connection_handler(struct MHD_Connection * connection) {
-  struct MHD_Access_Handler * ah;
-  unsigned int processed;
-
-  if (connection->headersReceived == 0)
-    abort(); /* bad timing... */
-  ah = MHD_find_access_handler(connection);
-  processed = connection->readLoc;
-  if (MHD_NO == ah->dh(ah->dh_cls,
-                      connection,
-                      connection->url,
-                      connection->method,
-                      connection->read_buffer,
-                      &processed)) {
-    /* serios internal error, close connection */
-    MHD_DLOG(connection->daemon,
-            "Internal application error, closing connection.");
-    CLOSE(connection->socket_fd);
-    connection->socket_fd = -1;
-    return;
-  }
-  /* dh left "processed" bytes in buffer for next time... */
-  memmove(connection->read_buffer,
-         &connection->read_buffer[connection->readLoc - processed],
-         processed);
-  if (connection->uploadSize != -1)
-    connection->uploadSize -= (connection->readLoc - processed);
-  connection->readLoc = processed;
-  if ( (connection->uploadSize == 0) ||
-       ( (connection->readLoc == 0) &&
-        (connection->uploadSize == -1) &&
-        (connection->socket_fd == -1) ) ) {
-    connection->bodyReceived = 1;
-    connection->readLoc = 0;
-    connection->read_buffer_size = 0;
-    free(connection->read_buffer);
-    connection->read_buffer = NULL;
-  }
-}
-
-
-/**
- * This function handles a particular connection when it has been
- * determined that there is data to be read off a socket. All implementations
- * (multithreaded, external select, internal select) call this function
- * to handle reads.
- */
-int
-MHD_connection_handle_read(struct MHD_Connection * connection) {
-  int bytes_read;
-  void * tmp;
-
-  if ( (connection->readLoc >= connection->read_buffer_size) &&
-       (connection->headersReceived == 0) ) {
-    /* need to grow read buffer */
-    tmp = malloc(connection->read_buffer_size * 2 + MHD_MAX_BUF_SIZE);
-    memcpy(tmp,
-          connection->read_buffer,
-          connection->read_buffer_size);
-    connection->read_buffer_size = connection->read_buffer_size * 2 + 
MHD_MAX_BUF_SIZE;
-    if (connection->read_buffer != NULL)
-      free(connection->read_buffer);
-    connection->read_buffer = tmp;
-  }
-  if (connection->readLoc >= connection->read_buffer_size) {
-    MHD_DLOG(connection->daemon,
-            "Unexpected call to %s.\n",
-            __FUNCTION__);
-    return MHD_NO;
-  }
-  bytes_read = RECV(connection->socket_fd,
-                   &connection->read_buffer[connection->readLoc],
-                   connection->read_buffer_size - connection->readLoc,
-                   0);
-  if (bytes_read < 0) {
-    if (errno == EINTR)
-      return MHD_NO;
-    MHD_DLOG(connection->daemon,
-            "Failed to receive data: %s\n",
-            STRERROR(errno));
-    CLOSE(connection->socket_fd);
-    connection->socket_fd = -1;
-    return MHD_YES;
-  }
-  if (bytes_read == 0) {
-    /* other side closed connection */
-    if (connection->readLoc > 0)
-      MHD_call_connection_handler(connection);
-    shutdown(connection->socket_fd, SHUT_RD);
-    return MHD_YES;
-  }
-  connection->readLoc += bytes_read;
-  if (connection->headersReceived == 0)
-    MHD_parse_connection_headers(connection);
-  if (connection->headersReceived == 1)
-    MHD_call_connection_handler(connection);
-  return MHD_YES;
-}
-
-/**
- * Check if we need to set some additional headers
- * for http-compiliance.
- */
-static void
-MHD_add_extra_headers(struct MHD_Connection * connection) {
-  const char * have;
-  char buf[128];
-
-  if (connection->response->total_size == -1) {
-    have = MHD_get_response_header(connection->response,
-                                  "Connection");
-    if (have == NULL)
-      MHD_add_response_header(connection->response,
-                             "Connection",
-                             "close");
-  } else if (NULL == MHD_get_response_header(connection->response,
-                                            "Content-Length")) {
-    _REAL_SNPRINTF(buf,
-            128,
-            "%llu",
-            (unsigned long long) connection->response->total_size);
-    MHD_add_response_header(connection->response,
-                           "Content-Length",
-                           buf);
-  }
-}
-
-/**
- * Allocate the connection's write buffer and
- * fill it with all of the headers from the
- * HTTPd's response.
- */
-static void
-MHD_build_header_response(struct MHD_Connection * connection) {
-  size_t size;
-  size_t off;
-  struct MHD_HTTP_Header * pos;
-  char code[32];
-  char * data;
-
-  MHD_add_extra_headers(connection);
-  SPRINTF(code,
-         "HTTP/1.1 %u\r\n",
-         connection->responseCode);
-  off = strlen(code);
-  /* estimate size */
-  size = off + 2; /* extra \r\n at the end */
-  pos = connection->response->first_header;
-  while (pos != NULL) {
-    size += strlen(pos->header) + strlen(pos->value) + 4; /* colon, space, 
linefeeds */
-    pos = pos->next;
-  }
-  /* produce data */
-  data = malloc(size + 1);
-  memcpy(data,
-        code,
-        off);
-  pos = connection->response->first_header;
-  while (pos != NULL) {
-    SPRINTF(&data[off],
-           "%s: %s\r\n",
-           pos->header,
-           pos->value);
-    off += strlen(pos->header) + strlen(pos->value) + 4;
-    pos = pos->next;
-  }
-  sprintf(&data[off],
-         "\r\n");
-  off += 2;
-  if (off != size)
-    abort();
-  connection->write_buffer = data;
-  connection->write_buffer_size = size;
-}
-
-/**
- * This function was created to handle writes to sockets when it has
- * been determined that the socket can be written to. All
- * implementations (multithreaded, external select, internal select)
- * call this function
- */
-int
-MHD_connection_handle_write(struct MHD_Connection * connection) {
-  struct MHD_Response * response;
-  int ret;
-
-  response = connection->response;
-  if(response == NULL) {
-    MHD_DLOG(connection->daemon,
-            "Unexpected call to %s.\n",
-            __FUNCTION__);
-    return MHD_NO;
-  }
-  if (! connection->headersSent) {
-    if (connection->write_buffer == NULL)
-      MHD_build_header_response(connection);
-    ret = SEND(connection->socket_fd,
-              &connection->write_buffer[connection->writeLoc],
-              connection->write_buffer_size - connection->writeLoc,
-              0);
-    if (ret < 0) {
-      if (errno == EINTR)
-       return MHD_YES;
-      MHD_DLOG(connection->daemon,
-              "Failed to send data: %s\n",
-              STRERROR(errno));
-      CLOSE(connection->socket_fd);
-      connection->socket_fd = -1;
-      return MHD_YES;
-    }
-    connection->writeLoc += ret;
-    if (connection->writeLoc == connection->write_buffer_size) {
-      connection->writeLoc = 0;
-      free(connection->write_buffer);
-      connection->write_buffer = NULL;
-      connection->write_buffer_size = 0;
-      connection->headersSent = 1;
-    }
-    return MHD_YES;
-  }
-  if (response->total_size <= connection->messagePos)
-    abort(); /* internal error */
-  if (response->crc != NULL)
-    pthread_mutex_lock(&response->mutex);
-
-  /* prepare send buffer */
-  if ( (response->data == NULL) ||
-       (response->data_start > connection->messagePos) ||
-       (response->data_start + response->data_size < connection->messagePos) ) 
{
-    if (response->data_size == 0) {
-      if (response->data != NULL)
-       free(response->data);
-      response->data = malloc(MHD_MAX_BUF_SIZE);
-      response->data_size = MHD_MAX_BUF_SIZE;
-    }
-    ret = response->crc(response->crc_cls,
-                       connection->messagePos,
-                       response->data,
-                       MAX(MHD_MAX_BUF_SIZE,
-                           response->data_size - connection->messagePos));
-    if (ret == -1) {
-      /* end of message, signal other side by closing! */
-      response->data_size = connection->messagePos;
-      CLOSE(connection->socket_fd);
-      connection->socket_fd = -1;
-      if (response->crc != NULL)
-       pthread_mutex_unlock(&response->mutex);
-      return MHD_YES;
-    }
-    response->data_start = connection->messagePos;
-    response->data_size = ret;
-    if (ret == 0) {
-      if (response->crc != NULL)
-       pthread_mutex_unlock(&response->mutex);
-      return MHD_YES;
-    }
-  }
-
-  /* transmit */
-  ret = SEND(connection->socket_fd,
-            &response->data[connection->messagePos - response->data_start],
-            response->data_size - (connection->messagePos - 
response->data_start),
-            0);
-  if (response->crc != NULL)
-    pthread_mutex_unlock(&response->mutex);
-  if (ret < 0) {
-    if (errno == EINTR)
-      return MHD_YES;
-    MHD_DLOG(connection->daemon,
-            "Failed to send data: %s\n",
-            STRERROR(errno));
-    CLOSE(connection->socket_fd);
-    connection->socket_fd = -1;
-    return MHD_YES;
-  }
-  connection->messagePos += ret;
-  if (connection->messagePos > response->data_size)
-    abort(); /* internal error */
-  if (connection->messagePos == response->data_size) {
-    if ( (connection->bodyReceived == 0) ||
-        (connection->headersReceived == 0) )
-      abort(); /* internal error */
-    MHD_destroy_response(response);
-    connection->responseCode = 0;
-    connection->response = NULL;
-    connection->headersReceived = 0;
-    connection->headersSent = 0;
-    connection->bodyReceived = 0;
-    connection->messagePos = 0;
-    free(connection->method);
-    connection->method = NULL;
-    free(connection->url);
-    connection->url = NULL;
-    free(connection->version);
-    connection->version = NULL;
-    free(connection->write_buffer);
-    connection->write_buffer = NULL;
-    connection->write_buffer_size = 0;
-    if (connection->read_close != 0) {
-      /* closed for reading => close for good! */
-      CLOSE(connection->socket_fd);
-      connection->socket_fd = -1;
-    }
-  }
-  return MHD_YES;
-}
-
-/* end of connection.c */
-
-

Deleted: libmicrohttpd/src/daemon/session.h
===================================================================
--- libmicrohttpd/src/daemon/session.h  2007-07-09 03:20:40 UTC (rev 5279)
+++ libmicrohttpd/src/daemon/session.h  2007-07-09 03:20:57 UTC (rev 5280)
@@ -1,72 +0,0 @@
-/*
-     This file is part of libmicrohttpd
-     (C) 2007 Daniel Pittman
-
-     libmicrohttpd is free software; you can redistribute it and/or modify
-     it under the terms of the GNU General Public License as published
-     by the Free Software Foundation; either version 2, or (at your
-     option) any later version.
-
-     libmicrohttpd is distributed in the hope that it will be useful, but
-     WITHOUT ANY WARRANTY; without even the implied warranty of
-     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-     General Public License for more details.
-
-     You should have received a copy of the GNU General Public License
-     along with libmicrohttpd; see the file COPYING.  If not, write to the
-     Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-     Boston, MA 02111-1307, USA.
-*/
-
-/**
- * @file connection.h
- * @brief  Methods for managing connections
- * @author Daniel Pittman
- * @author Christian Grothoff
- */
-
-#ifndef CONNECTION_H
-#define CONNECTION_H
-
-
-/**
- * Obtain the select sets for this connection.
- *
- * @return MHD_YES on success
- */
-int
-MHD_connection_get_fdset(struct MHD_Connection * connection,
-                     fd_set * read_fd_set,
-                     fd_set * write_fd_set,
-                     fd_set * except_fd_set,
-                     int * max_fd);
-
-
-/**
- * Call the handler of the application for this
- * connection.
- */
-void
-MHD_call_connection_handler(struct MHD_Connection * connection);
-
-/**
- * This function handles a particular connection when it has been
- * determined that there is data to be read off a socket. All implementations
- * (multithreaded, external select, internal select) call this function
- * to handle reads.
- */
-int
-MHD_connection_handle_read(struct MHD_Connection * connection);
-
-
-/**
- * This function was created to handle writes to sockets when it has been
- * determined that the socket can be written to. If there is no data
- * to be written, however, the function call does nothing. All implementations
- * (multithreaded, external select, internal select) call this function
- */
-int
-MHD_connection_handle_write(struct MHD_Connection * connection);
-
-
-#endif





reply via email to

[Prev in Thread] Current Thread [Next in Thread]