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

📄 httpd.c

📁 基于凌阳系列单片机的以太网驱动程序
💻 C
字号:
/*
 * Copyright (c) 2001-2003 Swedish Institute of Computer Science.
 * All rights reserved. 
 * 
 * Redistribution and use in source and binary forms, with or without modification, 
 * are permitted provided that the following conditions are met:
 *
 * 1. Redistributions of source code must retain the above copyright notice,
 *    this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright notice,
 *    this list of conditions and the following disclaimer in the documentation
 *    and/or other materials provided with the distribution.
 * 3. The name of the author may not be used to endorse or promote products
 *    derived from this software without specific prior written permission. 
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED 
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 
 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT 
 * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT 
 * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 
 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY 
 * OF SUCH DAMAGE.
 *
 * This file is part of the lwIP TCP/IP stack.
 * 
 * Author: Adam Dunkels <adam@sics.se>
 *
 * Modify by zhigang.
 */
 
 
/*
#include "lwip/debug.h"
#include "lwip/stats.h"
#include "lwip/tcp.h"*/
#include "config.h"
#include "httpd.h"
#include "web.h"
//#include "fs.h"




extern struct webdata * CGI_Callback(char *tempdata);

/*-----------------------------------------------------------------------------------*/
 void
conn_err(void *arg, err_t err)
{
  struct http_state *hs;
  hs = arg;
  if (hs!=NULL)
  {
  web_free(hs->web);
  mem_free(hs);
  }
}
/*-----------------------------------------------------------------------------------*/
static void
close_conn(struct tcp_pcb *pcb, struct http_state *hs)
{
  tcp_arg(pcb, NULL);
  tcp_sent(pcb, NULL);
  tcp_recv(pcb, NULL);
  tcp_poll(pcb,NULL,10);
  if (hs!=NULL)
  {
  web_free(hs->web);
  mem_free(hs);
}
  tcp_close(pcb);
}
/*-----------------------------------------------------------------------------------*/
static err_t
send_data(struct tcp_pcb *pcb, struct http_state *hs)
{
  err_t err;
  u16_t len,*data,copy;

  /* We cannot send more data than space available in the send
     buffer. */

while ((tcp_sndbuf(pcb)>2)&&(hs->web!=NULL))
{     
    len = hs->web->len - hs->web->offset;
	if(tcp_sndbuf(pcb) < len) {
    len = (tcp_sndbuf(pcb)-1)/2;
    len *= 2;            //保证len为偶数
  }
  
  data = (u16_t *)(hs->web->payload + (hs->web->offset / 2));

  do {
    if (hs->web->attr == STATIC) copy = 0;
     else copy = 1;
    err = tcp_write(pcb, data, len, copy); //对于动态部分,拷贝到协议栈内部
    if(err == ERR_MEM) {
        close_conn(pcb,hs);
        return err;
    }
  } while(err == ERR_MEM && len > 0);  
  
  if(err == ERR_OK) {
    hs->web->offset += len;
    if (hs->web->offset == hs->web->len)
      {
       if (hs->web->attr == DYNAMIC)  //释放动态网页所占空间,因为动态部分已经拷贝
       mem_free(hs->web->payload);       //到协议栈内部,因此不再需要了。
       data = (u16_t *)hs->web;
       hs->web = hs->web->next;
       mem_free(data);            //对于已经发送完毕的web,已经不再需要
       }     
     }
 }//while((tcp
 return ERR_OK;
}
/*-----------------------------------------------------------------------------------*/
err_t
http_poll(void *arg, struct tcp_pcb *pcb)
{
  err_t err;
  struct http_state *hs;

  hs = arg;
  
  if(hs ->web == NULL) {
    close_conn(pcb,hs);
    return ERR_OK;
  } else {
    ++hs->retries;
    if(hs->retries >= 30) {   //anyway some error happend: no mem or the remote client down
      tcp_abort(pcb);
      return ERR_ABRT;
    }
   err = send_data(pcb, hs);
   return err;
  }
  return ERR_OK;
}

/*-----------------------------------------------------------------------------------*/
 err_t
http_sent(void *arg, struct tcp_pcb *pcb, u16_t len)
{
  struct http_state *hs;
  hs = arg;  
  hs->retries = 0;
  if (hs->web != NULL) 
   {    
    send_data(pcb, hs);
  } else {
    close_conn(pcb, hs);
  }
  return ERR_OK;
}
/*-----------------------------------------------------------------------------------*/
err_t
http_recv(void *arg, struct tcp_pcb *pcb, struct pbuf *p, err_t err)
{
  int i;
  u16_t *data;
  struct http_state *hs;
  u16_t * tempdata;
  hs = arg;
  tcp_recved(pcb, p->tot_len);     /* Inform TCP that we have taken the data. */
  if(err == ERR_OK && p != NULL) {
        
    if(hs->web == NULL) {    
     tempdata = mem_malloc(58);
      data = p->payload;
      for(i=0;i<50;i++)
      tempdata[i] = getbyte(data, i);
      
	  pbuf_free(p);     
      if(strncmp(tempdata, "GET ", 4) == 0) {
	for(i = 0; i < 50; i++) {
	  if(((char *)tempdata + 4)[i] == ' ' ||
	     ((char *)tempdata + 4)[i] == '\r' ||
	     ((char *)tempdata + 4)[i] == '\n' ||
	     ((char *)tempdata + 4)[i] == '=' ||
	     ((char *)tempdata + 4)[i] == '&' ||
	     ((char *)tempdata + 4)[i] == '?' ) {
	    ((char *)tempdata + 4)[i] = 0;
	  }
	}
	hs->web = Web_Request((char *)&tempdata[4]);
	send_data(pcb, hs);
	/* 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);
      }  
    mem_free(tempdata);
    }
    pbuf_free(p);
  }

 else if(err == ERR_OK && p == NULL) {
    close_conn(pcb, hs);    //remote host close the connection
  }
  else
  {
  tcp_abort(pcb);    // some error  happen reset the connection
  return ERR_ABRT;
  }
  return ERR_OK;    //all ok resume the connection
}


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

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

  if(hs == NULL) {
    return ERR_MEM;
  }
  
  /* Initialize the structure. */
  hs->retries = 0;
  hs->web = NULL;  
  /* 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, 10);
  return ERR_OK;
}
/*-----------------------------------------------------------------------------------*/
void
httpd_init(void)
{
  struct tcp_pcb *pcb;
  pcb = tcp_new();
  tcp_bind(pcb, IP_ADDR_ANY, 80);
  pcb = tcp_listen(pcb);
  tcp_accept(pcb, http_accept);
}

⌨️ 快捷键说明

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