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

📄 httpd.c

📁 在luminary平台下移植lwip到freertos,集成开发环境KEIL
💻 C
📖 第 1 页 / 共 3 页
字号:
              hs->parse_left--;
              hs->parsed++;
              hs->tag_state = TAG_NONE;
          }
          break;

        /*
         * We have found a valid tag and are in the process of sending
         * data as a result of that discovery. We send either remaining data
         * from the file prior to the insert point or the insert string itself.
         */
        case TAG_SENDING:
          /* Do we have any remaining file data to send from the buffer prior
           * to the tag?
           */
          if(hs->tag_end > hs->file)
          {
            /* How much of the data can we send? */
            if(len > hs->tag_end - hs->file) {
              len = hs->tag_end - hs->file;
            }

            do {
              DEBUG_PRINT("Sending %d bytes\n", len);
              err = tcp_write(pcb, hs->file, len, 0);
              if (err == ERR_MEM) {
                len /= 2;
              }
            } while (err == ERR_MEM && (len > 1));

            if (err == ERR_OK) {
              data_to_send = true;
              hs->file += len;
              hs->left -= len;
            }
          } else {
            /* Do we still have insert data left to send? */
            if(hs->tag_index < hs->tag_insert_len) {
              /* We are sending the insert string itself. How much of the
               * insert can we send? */
              if(len > (hs->tag_insert_len - hs->tag_index)) {
                len = (hs->tag_insert_len - hs->tag_index);
              }

              do {
                DEBUG_PRINT("Sending %d bytes\n", len);
                /*
                 * Note that we set the copy flag here since we only have a
                 * single tag insert buffer per connection. If we don't do
                 * this, insert corruption can occur if more than one insert
                 * is processed before we call tcp_output.
                 */
                err = tcp_write(pcb, &(hs->tag_insert[hs->tag_index]), len, 1);
                if (err == ERR_MEM) {
                  len /= 2;
                }
              } while (err == ERR_MEM && (len > 1));

              if (err == ERR_OK) {
                data_to_send = true;
                hs->tag_index += len;
                return;
              }
            } else {
              /* We have sent all the insert data so go back to looking for
               * a new tag.
               */
              DEBUG_PRINT("Everything sent.\n");
              hs->tag_index = 0;
              hs->tag_state = TAG_NONE;
          }
        }
      }
    }

    /*
     * If we drop out of the end of the for loop, this implies we must have
     * file data to send so send it now. In TAG_SENDING state, we've already
     * handled this so skip the send if that's the case.
     */
    if((hs->tag_state != TAG_SENDING) && (hs->parsed > hs->file)) {
      /* We cannot send more data than space available in the send
         buffer. */
      if (tcp_sndbuf(pcb) < (hs->parsed - hs->file)) {
        len = tcp_sndbuf(pcb);
      } else {
        len = (hs->parsed - hs->file);
        LWIP_ASSERT("Data size did not fit into u16_t!",
                    (hs->parsed - hs->file));
      }
      if(len > (2*pcb->mss)) {
        len = 2*pcb->mss;
      }

      do {
        DEBUG_PRINT("Sending %d bytes\n", len);
        err = tcp_write(pcb, hs->file, len, 0);
        if (err == ERR_MEM) {
          len /= 2;
        }
      } while (err == ERR_MEM && len > 1);

      if (err == ERR_OK) {
        data_to_send = true;
        hs->file += len;
        hs->left -= len;
      }
    }
  }
#endif /* INCLUDE_HTTPD_SSI */

  /* If we wrote anything to be sent, go ahead and send it now. */
  if(data_to_send) {
    DEBUG_PRINT("tcp_output\n");
    tcp_output(pcb);
  }

  DEBUG_PRINT("send_data end.\n");
}

/*-----------------------------------------------------------------------------------*/
static err_t
http_poll(void *arg, struct tcp_pcb *pcb)
{
  struct http_state *hs;

  hs = arg;

  DEBUG_PRINT("http_poll 0x%08x\n", pcb);

  /*  printf("Polll\n");*/
  if (hs == NULL) {
    /*    printf("Null, close\n");*/
    tcp_abort(pcb);
    return ERR_ABRT;
  } else {
    ++hs->retries;
    if (hs->retries == 4) {
      tcp_abort(pcb);
      return ERR_ABRT;
    }

    /* If this connection has a file open, try to send some more data. If
     * it has not yet received a GET request, don't do this since it will
     * cause the connection to close immediately. */
    if(hs->handle) {
      send_data(pcb, hs);
    }
  }

  return ERR_OK;
}
/*-----------------------------------------------------------------------------------*/
static err_t
http_sent(void *arg, struct tcp_pcb *pcb, u16_t len)
{
  struct http_state *hs;

  DEBUG_PRINT("http_sent 0x%08x\n", pcb);

  LWIP_UNUSED_ARG(len);

  hs = arg;

  hs->retries = 0;

  /* Temporarily disable send notifications */
  tcp_sent(pcb, NULL);

  send_data(pcb, hs);

  /* Reenable notifications. */
  tcp_sent(pcb, http_sent);

  return ERR_OK;
}

/*-----------------------------------------------------------------------------------*/
static struct fs_file *
get_404_file(char **ppURI)
{
  struct fs_file *file;

  *ppURI = "/404.html";
  file = fs_open(*ppURI);
  if(file == NULL) {
    /* 404.html doesn't exist. Try 404.htm instead. */
    *ppURI = "/404.htm";
    file = fs_open(*ppURI);
    if(file == NULL) {
      /* 404.htm doesn't exist either. Indicate to the caller that it should
       * send back a default 404 page.
       */
      *ppURI = NULL;
    }
  }

  return(file);
}

/*-----------------------------------------------------------------------------------*/
static err_t
http_recv(void *arg, struct tcp_pcb *pcb, struct pbuf *p, err_t err)
{
  int i;
  int loop;
  char *data;
  char *uri;
  struct fs_file *file;
  struct http_state *hs;
#ifdef INCLUDE_HTTPD_CGI
  int count;
  char *params;
#endif

  DEBUG_PRINT("http_recv 0x%08x\n", pcb);

  hs = arg;

  if (err == ERR_OK && p != NULL) {

    /* Inform TCP that we have taken the data. */
    tcp_recved(pcb, p->tot_len);

    if (hs->handle == NULL) {
      data = p->payload;
      uri = &data[4];
      DEBUG_PRINT("Request:\n%s\n", data);
      if (strncmp(data, "GET ", 4) == 0) {
        /*
         * We have a GET request. Find the end of the URI by looking for the
         * HTTP marker. We can't just use strstr to find this since the request
         * came from an outside source and we can't be sure that it is
         * correctly formed. We need to make sure that our search is bounded
         * by the packet length so we do it manually. If we don't find " HTTP",
         * assume the request is invalid and close the connection.
         */
        for(i = 4; i < (p->len - 5); i++) {
          if ((data[i] == ' ') && (data[i + 1] == 'H') &&
              (data[i + 2] == 'T') && (data[i + 3] == 'T') &&
              (data[i + 4] == 'P')) {
            data[i] = 0;
            break;
          }
        }
        if(i == (p->len - 5)) {
          /* We failed to find " HTTP" in the request so assume it is invalid */
          DEBUG_PRINT("Invalid GET request. Closing.\n");
          pbuf_free(p);
          close_conn(pcb, hs);
          return(ERR_OK);
        }

#ifdef INCLUDE_HTTPD_SSI
        /*
         * By default, assume we will not be processing server-side-includes
         * tags
         */
        hs->tag_check = false;
#endif

        /*
         * Have we been asked for the default root file?
         */
        if((uri[0] == '/') &&  (uri[1] == 0)) {
          /*
           * Try each of the configured default filenames until we find one
           * that exists.
           */
          for(loop = 0; loop < NUM_DEFAULT_FILENAMES; loop++) {
            DEBUG_PRINT("Looking for %s...\n", g_psDefaultFilenames[loop].name);
            file = fs_open((char *)g_psDefaultFilenames[loop].name);
            uri = (char *)g_psDefaultFilenames[loop].name;
            if(file != NULL) {
              DEBUG_PRINT("Opened.\n");
#ifdef INCLUDE_HTTPD_SSI
              hs->tag_check = g_psDefaultFilenames[loop].shtml;
#endif
              break;
            }
          }
          if(file == NULL) {
            /* None of the default filenames exist so send back a 404 page */
            file = get_404_file(&uri);
#ifdef INCLUDE_HTTPD_SSI
            hs->tag_check = false;
#endif
          }
        } else {
          /* No - we've been asked for a specific file. */
#ifdef INCLUDE_HTTPD_CGI
          /* First, isolate the base URI (without any parameters) */
          params = strchr(uri, '?');
          if(params) {
            *params = '\0';
            params++;
          }

          /* Does the base URI we have isolated correspond to a CGI handler? */
          if(g_iNumCGIs && g_pCGIs) {
            for(i = 0; i < g_iNumCGIs; i++) {
              if(strcmp(uri, g_pCGIs[i].pcCGIName) == 0) {
                /*
                 * We found a CGI that handles this URI so extract the
                 * parameters and call the handler.
                 */
                 count = extract_uri_parameters(hs, params);
                 uri = g_pCGIs[i].pfnCGIHandler(i, count, hs->params,
                                                hs->param_vals);
                 break;
              }
            }

            /* Did we handle this URL as a CGI? If not, reinstate the
             * original URL and pass it to the file system directly. */
            if(i == g_iNumCGIs)
            {
              /* Replace the ? marker at the beginning of the parameters */
              if(params) {
                 params--;
                *params = '?';
              }
            }
          }
#endif

          DEBUG_PRINT("Opening %s\n", uri);

          file = fs_open(uri);
          if(file == NULL) {
            file = get_404_file(&uri);
          }
#ifdef INCLUDE_HTTPD_SSI
          else {
            /*
             * See if we have been asked for an shtml file and, if so,
             * enable tag checking.
             */
            hs->tag_check = false;
            for(loop = 0; loop < NUM_SHTML_EXTENSIONS; loop++) {
              if(ustrstr(uri, g_pcSSIExtensions[loop])) {
                hs->tag_check = true;
                break;
              }
            }
          }
#endif /* INCLUDE_HTTP_SSI */
        }

        if(file) {
#ifdef INCLUDE_HTTPD_SSI
          hs->tag_index = 0;
          hs->tag_state = TAG_NONE;
          hs->parsed = file->data;
          hs->parse_left = file->len;
          hs->tag_end = file->data;
#endif
          hs->handle = file;
          hs->file = file->data;
          LWIP_ASSERT("File length must be positive!", (file->len >= 0));
          hs->left = file->len;
          hs->retries = 0;
          pbuf_free(p);
        } else {
          hs->handle = NULL;
          hs->file = NULL;
          hs->left = 0;
          hs->retries = 0;
        }

#ifdef DYNAMIC_HTTP_HEADERS
        /* Determine the HTTP headers to send based on the file extension of
         * the requested URI. */
        get_http_headers(hs, uri);
#endif

        /* Tell TCP that we wish be to informed of data that has been
           successfully sent by a call to the http_sent() function. */
        tcp_sent(pcb, http_sent);

        /* Start sending the headers and file data. */
        send_data(pcb, hs);
      } else {
        pbuf_free(p);
        close_conn(pcb, hs);
      }
    } else {
      pbuf_free(p);
    }
  }

  if (err == ERR_OK && p == NULL) {
    close_conn(pcb, hs);
  }
  return ERR_OK;
}
/*-----------------------------------------------------------------------------------*/
static err_t
http_accept(void *arg, struct tcp_pcb *pcb, err_t err)
{
  struct http_state *hs;

  LWIP_UNUSED_ARG(arg);
  LWIP_UNUSED_ARG(err);

  DEBUG_PRINT("http_accept 0x%08x\n", pcb);

  /* Allocate memory for the structure that holds the state of the
     connection. */
  hs = (struct http_state *)mem_malloc(sizeof(struct http_state));

  if (hs == NULL) {
    DEBUG_PRINT("http_accept: Out of memory\n");
    return ERR_MEM;
  }

  /* Initialize the structure. */
  hs->handle = NULL;
  hs->file = NULL;
  hs->buf = NULL;
  hs->buf_len = 0;
  hs->left = 0;
  hs->retries = 0;
#ifdef DYNAMIC_HTTP_HEADERS
  /* Indicate that the headers are not yet valid */
  hs->hdr_index = NUM_FILE_HDR_STRINGS;
#endif

  /* Tell TCP that this is the structure we wish to be passed for our
     callbacks. */
  tcp_arg(pcb, hs);

  /* Tell TCP that we wish to be informed of incoming data by a call
     to the http_recv() function. */
  tcp_recv(pcb, http_recv);

  tcp_err(pcb, conn_err);

  tcp_poll(pcb, http_poll, 4);
  return ERR_OK;
}
/*-----------------------------------------------------------------------------------*/
void
httpd_init(void)
{
  struct tcp_pcb *pcb;

  DEBUG_PRINT("httpd_init\n");

  pcb = tcp_new();
  tcp_bind(pcb, IP_ADDR_ANY, 80);
  pcb = tcp_listen(pcb);
  tcp_accept(pcb, http_accept);
}

#ifdef INCLUDE_HTTPD_SSI
/*-----------------------------------------------------------------------------------*/
void
http_set_ssi_handler(tSSIHandler pfnSSIHandler, const char **ppcTags,
                     int iNumTags)
{
    DEBUG_PRINT("http_set_ssi_handler\n");

    g_pfnSSIHandler = pfnSSIHandler;
    g_ppcTags = ppcTags;
    g_iNumTags = iNumTags;
}
#endif

#ifdef INCLUDE_HTTPD_CGI
/*-----------------------------------------------------------------------------------*/
void
http_set_cgi_handlers(const tCGI *pCGIs, int iNumHandlers)
{
    g_pCGIs = pCGIs;
    g_iNumCGIs = iNumHandlers;
}
#endif

/*-----------------------------------------------------------------------------------*/

⌨️ 快捷键说明

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