⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 connection.c

📁 一个 http 服务器的框架实现
💻 C
📖 第 1 页 / 共 3 页
字号:
  char *semicolon;  char *equals;  int quotes;  hdr = MHD_lookup_connection_value (connection, MHD_HEADER_KIND, "Cookie");  if (hdr == NULL)    return MHD_YES;  cpy = MHD_pool_allocate (connection->pool, strlen (hdr) + 1, MHD_YES);  if (cpy == NULL)    {      MHD_DLOG (connection->daemon, "Not enough memory to parse cookies!\n");      MHD_excessive_data_handler (connection,                                  MHD_HTTP_REQUEST_ENTITY_TOO_LARGE);      return MHD_NO;    }  memcpy (cpy, hdr, strlen (hdr) + 1);  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++;        }      if (MHD_NO == MHD_connection_add_header (connection,                                               pos, equals, MHD_COOKIE_KIND))        return MHD_NO;      pos = semicolon;    }  return MHD_YES;}/** * Parse the first line of the HTTP HEADER. * * @param connection the connection (updated) * @param line the first line * @return MHD_YES if the line is ok, MHD_NO if it is malformed */static intparse_initial_message_line (struct MHD_Connection *connection, char *line){  char *uri;  char *httpVersion;  char *args;  uri = strstr (line, " ");  if (uri == NULL)    return MHD_NO;              /* serious error */  uri[0] = '\0';  connection->method = line;  uri++;  while (uri[0] == ' ')    uri++;  httpVersion = strstr (uri, " ");  if (httpVersion != NULL)    {      httpVersion[0] = '\0';      httpVersion++;    }  args = strstr (uri, "?");  if (args != NULL)    {      args[0] = '\0';      args++;      parse_arguments (MHD_GET_ARGUMENT_KIND, connection, args);    }  connection->url = uri;  if (httpVersion == NULL)    connection->version = "";  else    connection->version = httpVersion;  return MHD_YES;}/** * 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 voidMHD_parse_connection_headers (struct MHD_Connection *connection){  char *last;  char *line;  char *colon;  char *tmp;  const char *clen;  const char *end;  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/ */              last = MHD_pool_reallocate (connection->pool,                                          last,                                          strlen (last) + 1,                                          strlen (line) + strlen (last) + 1);              if (last == NULL)                {                  MHD_excessive_data_handler (connection,                                              MHD_HTTP_REQUEST_ENTITY_TOO_LARGE);                  break;                }              tmp = line;              while ((tmp[0] == ' ') || (tmp[0] == '\t'))                tmp++;          /* skip whitespace at start of 2nd line */              strcat (last, tmp);              continue;         /* possibly more than 2 lines... */            }          else            {              if (MHD_NO == MHD_connection_add_header (connection,                                                       last,                                                       colon,                                                       MHD_HEADER_KIND))                return;              last = NULL;            }        }      if (connection->url == NULL)        {          /* line must be request line (first line of header) */          if (MHD_NO == parse_initial_message_line (connection, line))            goto DIE;          continue;        }      /* check if this is the end of the header */      if (strlen (line) == 0)        {          /* end of header */          connection->headersReceived = 1;          clen = MHD_lookup_connection_value (connection,                                              MHD_HEADER_KIND,                                              MHD_HTTP_HEADER_CONTENT_LENGTH);          if (clen != NULL)            {              if (1 != sscanf (clen, "%llu", &cval))                {                  MHD_DLOG (connection->daemon,                            "Failed to parse `%s' header `%s', closing connection.\n",                            MHD_HTTP_HEADER_CONTENT_LENGTH, clen);                  goto DIE;                }              connection->uploadSize = cval;              connection->bodyReceived = cval == 0 ? 1 : 0;            }          else            {              if (NULL == MHD_lookup_connection_value (connection,                                                       MHD_HEADER_KIND,                                                       MHD_HTTP_HEADER_TRANSFER_ENCODING))                {                  /* this request does not have a body */                  connection->uploadSize = 0;                  connection->bodyReceived = 1;                }              else                {                  connection->uploadSize = -1;  /* unknown size */                  connection->bodyReceived = 0;                }            }          end = MHD_lookup_connection_value (connection,                                             MHD_HEADER_KIND,                                             MHD_HTTP_HEADER_CONNECTION);          if ((end != NULL) && (0 == strcasecmp (end, "close")))            {              /* other side explicitly requested                  that we close the connection after                 this request */              connection->read_close = MHD_YES;            }          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...) */      last = line;    }  if ((last != NULL) &&      (MHD_NO == MHD_connection_add_header (connection,                                            last, colon, MHD_HEADER_KIND)))    return;                     /* error */  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;}/** * Test if we are able to process the POST data. * This depends on available memory (enough to load * all of the POST data into the pool) and the * content encoding of the POST data.  And of course, * this requires that the request is actually a * POST request. *  * @return MHD_YES if so */static intMHD_test_post_data (struct MHD_Connection *connection){  const char *encoding;  void *buf;  if ((connection->method == NULL) ||      (connection->response != NULL) ||      (0 != strcasecmp (connection->method, MHD_HTTP_METHOD_POST)))    return MHD_NO;  encoding = MHD_lookup_connection_value (connection,                                          MHD_HEADER_KIND,                                          MHD_HTTP_HEADER_CONTENT_TYPE);  if (encoding == NULL)    return MHD_NO;  if ((0 == strcasecmp (MHD_HTTP_POST_ENCODING_FORM_URLENCODED,                        encoding)) && (connection->uploadSize != -1))    {      buf = MHD_pool_reallocate (connection->pool,                                 connection->read_buffer,                                 connection->read_buffer_size,                                 connection->uploadSize + 1);      if (buf == NULL)        return MHD_NO;      connection->read_buffer_size = connection->uploadSize + 1;      connection->read_buffer = buf;      return MHD_YES;    }  return MHD_NO;}/** * Process the POST data here (adding to headers). * * Needs to first check POST encoding and then do * the right thing (TM).  The POST data is in the * connection's post_data buffer between the postPos  * and postLoc offsets.  The POST message maybe * incomplete.  The existing buffer (allocated from * the pool) can be used and modified but must then * be properly removed from the struct. *  * @return MHD_YES on success, MHD_NO on error (i.e. out of *         memory). */static intMHD_parse_post_data (struct MHD_Connection *connection){  const char *encoding;  int ret;  encoding = MHD_lookup_connection_value (connection,                                          MHD_HEADER_KIND,                                          MHD_HTTP_HEADER_CONTENT_TYPE);  if (encoding == NULL)    return MHD_NO;  if (0 == strcasecmp (MHD_HTTP_POST_ENCODING_FORM_URLENCODED, encoding))    {      ret = parse_arguments (MHD_POSTDATA_KIND,                             connection, connection->read_buffer);      /* invalidate read buffer for other uses --         in particular, do not give it to the         client; if this were to be needed, we would         have to make a copy, which would double memory          requirements */      connection->read_buffer_size = 0;      connection->readLoc = 0;      connection->uploadSize = 0;      connection->read_buffer = NULL;      return ret;    }  if (0 == strcasecmp (MHD_HTTP_POST_ENCODING_MULTIPART_FORMDATA, encoding))    {      /* this code should never been reached right now,         since the test_post_data function would already         return MHD_NO; code is here only for future         extensions... */      /* see http://www.w3.org/TR/html4/interact/forms.html#h-17.13.4 */      MHD_DLOG (connection->daemon,                "Unsupported multipart encoding of POST data specified, not processing POST data.\n");      return MHD_NO;    }  /* this should never be reached, just here for     error checking */  MHD_DLOG (connection->daemon,            "Unknown encoding of POST data specified, not processing POST data.\n");  return MHD_NO;}/** * Call the handler of the application for this * connection. */voidMHD_call_connection_handler (struct MHD_Connection *connection){  struct MHD_Access_Handler *ah;  unsigned int processed;  if (connection->response != NULL)    return;                     /* already queued a response */  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->version,                        connection->read_buffer, &processed))    {      /* serios internal error, close connection */      MHD_DLOG (connection->daemon,                "Internal application error, closing connection.\n");      CLOSE (connection->socket_fd);      connection->socket_fd = -1;      return;    }  /* dh left "processed" bytes in buffer for next time... */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -