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

📄 http.c

📁 RTL8019以太网开发板资料
💻 C
字号:
//-----------------------------------------------------------------------------
// Net HTTP.C
//
// This module is the Web Server
// It currently serves a html text page and a jpeg image, or handles
// a POST message to turn an LED on or off.
// The HTTP protocol specification is at http://www.w3.org/Protocols/ 
//-----------------------------------------------------------------------------
#include <string.h>
#include <stdlib.h>
#include <ctype.h>		// toupper
#include "main.h"		// toupper
#include "rs232.h"		// toupper
#include "tcp.h"		// toupper
#include "http.h"		// toupper
#include "ip.h"		// toupper
#include "WebData.h"
// These structures keep track of connection information
 
bit CONTROL_LED;

void LightONOFF(bit b);

/*********************************************************************
函数名:       void ResetSystem(void)
功能:         复位系统
输入:         None 
输出:         None
返回:         TRUE or FALSE
日期:         2004/02/09
*********************************************************************/

void LightONOFF(bit b)
{
	if (b)
	{
		TEST_LED = 0;
	}
	else
	{
		TEST_LED = 1;
	}
}
/*********************************************************************
函数名:       void ResetSystem(void)
功能:         复位系统
输入:         None 
输出:         None
返回:         TRUE or FALSE
日期:         2004/02/09
*********************************************************************/
void init_http(void)
{
  CONTROL_LED = 0;
  LightONOFF(CONTROL_LED);
}
/*********************************************************************
函数名:       UWORK8 FlashCheck(void)
功能:         把整形转成ASCII的字符串
输入:         none
输出:         None
返回:         none
日期:         2005/11/19
注意:最少为12个字节
*********************************************************************/
char *itoa(UWORK16 value, char * buf, UWORK8 radix)
{
	UWORK16 i;
	char * ptr;
	char * temphold;
	
	temphold = buf;
	ptr = buf + 12;
	*--ptr = 0;		// Insert NULL char
	do
	{
		i = (value % radix) + 0x30;		   // First create string in reverse order
		if(i > 0x39) i += 7;
		*--ptr = i;
		value = value / radix;
	} while(value != 0);
	for( ; (*buf++ = *ptr++); );	  // Next, move the string 6 places to the left Include NULL character
	return(temphold);
}


//------------------------------------------------------------------------
// This function is the standard string search. The Keil library
// does not provide it.  It looks for one string in another string
// and returns a pointer to it if found, otherwise returns NULL. 
//------------------------------------------------------------------------
char * strstr(char * haystack, char * needle)
{
	char *ptr1, *ptr2;
	
	// Protect against NULL pointer
	if (*needle == 0) return(haystack);
	for( ; *haystack; haystack++ )
	{
		// Look for needle in haystack.  If there is a
      // match then this will continue all the way
      // until ptr1 reaches the NULL at the end of needle 
		for(ptr1 = needle, ptr2 = haystack; *ptr1 && (*ptr1 == *ptr2); ++ptr1, ++ptr2);
							
		// If there is a match then return pointer to needle in haystack
		if(*ptr1 == 0) return(haystack);	
	}
	return NULL;			// no matching string found
}



//------------------------------------------------------------------------
// This sends an TCP segment to the ip layer.  The segment is 
// is normally either a web page or a graphic.
// See "TCP/IP Illustrated, Volume 1" Sect 17.3
//------------------------------------------------------------------------

void http_send(UWORK16 flags,  UWORK8 *TData, UWORK16 TLen, UWORK8 nr)
{
   ST_TCP_FORMAT *strTcp;
   UWORK8 destIP_buf[4];
   UWORK16 TCPHead_len;

   UWORK8 *TempD;
   TempD = TData; 
   TCPHead_len = 20;
   strTcp = (ST_TCP_FORMAT *)&NetSend_buf[20];
  strTcp->usSourcePort = SourcePort;				//源端口
  strTcp->usDesPort = StrConnection_buf[nr].usDesPort;			//目标端口,在接收TCP时已附值


  strTcp->ucSERIESNUM = StrConnection_buf[nr].ucSERIESNUM;	 //序号为0
  strTcp->ucTRUECODE = StrConnection_buf[nr].ucTRUECODE;	 //确认号为0

  memcpy(destIP_buf,(UWORK8 *)&StrConnection_buf[nr].ipaddr, 4);	//发送的目标IP地址在TCP接收中已附值

   strTcp->ucMOVENUM = (TCPHead_len << 10) | flags;		  //记算TCP的头长度及相关的标志位
   strTcp->ucWINDOWBIG = 1024;						  //设置窗口大小
   strTcp->ucTCPCHECK = 0;							  //先设置校验位为0
   strTcp->ucMUSGPOINT = 0;							  //紧急指针为0
   
   memcpy((UWORK8 *)&NetSend_buf[(20 + TCPHead_len)], TData, TLen);		//把发送的数据传到发送缓存中 
   //下面是给IP打包头
    gstIphead.ucVerAndLen = 0x45;                       //版本号和长度,各占4位
    gstIphead.ucDs = 0;                        //区分服务
    gstIphead.usTotalLen = IP_HEAD_LEN + TCPHead_len + TLen;                        //头加后面的数据
    gstIphead.usID = ++LocalIpID;
    gstIphead.usSegOffset = 0;

    gstIphead.ucTTL = 0;										 // max hops
    gstIphead.ucprotocol = TCP;
    gstIphead.usCheckSum = TCPHead_len + TLen;                                   //在计算TCP的校验位时,TCP的长度要算两次,此时是借IP的校验位来做第二个TCP的长度
    memcpy(&gstIphead.ucDestIP[0],&IPDestAddress_buf[0],IP_LEN);          // 目的IP 
    memcpy(&gstIphead.ucSourceIP[0],&IPLocalAddress_buf[0],IP_LEN);                // 源IP    
    memcpy(&NetSend_buf[0],&gstIphead,20);										  //把IP的头传给发送缓存区
	strTcp->ucTCPCHECK = 0;
	strTcp->ucTCPCHECK = CheckSum((UWORK16 *)&NetSend_buf[8],TCPHead_len + TLen + 12);   // 20 = 12个字节伪头 + 8个字节UDP头 

    gstIphead.ucTTL = 0x20;                                                   //校验和计算完毕,重赋TTL值 
    memcpy(&MAC_Remote_buf[0],&gstaRevEthernet.ucaSourceNodID[0],MAC_LEN);    // 目的MAC 
//    memcpy((UWORK8 *)&MAC_Remote_buf[4],&gstaRevEthernet.ucaDestNodID[0],MAC_LEN);    // 目的MAC 
//	memcpy(&MAC_Remote_buf[0],&ArpCache_Buf[0].ucaMAC[0],MAC_LEN);          // 远程MAC 
	IpSend();
   // (Re)start TCP retransmit timer
    StrConnection_buf[nr].timer = TCP_TIMEOUT;
	StrConnection_buf[nr].ucRESERIESNUM = StrConnection_buf[nr].ucSERIESNUM;
}



//------------------------------------------------------------------------
// This searches a web page looking for a specified tag.  If found,
// it replaces the tag with the text in * sub.  Tags are fixed length -
// The first 4 chars of the tag is always "TAG:" and the rest of it
// is always 4 chars for a total of 8 chars. 
//------------------------------------------------------------------------
void replace_tag(UWORK8 xdata * start, char * tag, char * sub) 
{ 
   UWORK8 idata i, flg;
   UWORK8 xdata * ptr;
   
   // Find tag.  If not found - just return
   ptr = strstr(start, tag);
	if (ptr == NULL) return;
   
	flg = TRUE;

   // Replace the 8 char tag with the substitute text
	// Pad on the right with spaces
   for (i=0; i < 8; i++)
	{
   	if (sub[i] == 0) flg = FALSE;
   	if (flg) ptr[i] = sub[i]; else ptr[i] = SPACE;
	}
}



//------------------------------------------------------------------------
//	This serves up either a HTML page, a JPEG image, or controls an 
// LED,  depending what it gets from the browser.  The received header
// must contain the word "GET" or "POST" to be considered a valid request.
// With HTTP 1.1 where the connection is left open, the header I send
// should include content length. With HTTP 1.0 you can just close the
// connection after sending the page and the browser knows its done. 
//
// The HTTP protocol specification is at http://www.w3.org/Protocols/ 
//------------------------------------------------------------------------
//------------------------------------------------------------------------
//	This serves up either a HTML page, a JPEG image, or controls an 
// LED,  depending what it gets from the browser.  The received header
// must contain the word "GET" or "POST" to be considered a valid request.
// With HTTP 1.1 where the connection is left open, the header I send
// should include content length. With HTTP 1.0 you can just close the
// connection after sending the page and the browser knows its done. 
//
// The HTTP protocol specification is at http://www.w3.org/Protocols/ 
//------------------------------------------------------------------------
UWORK16 http_server(UWORK8 nr, UWORK8 reSendFlag)
{
	UWORK16 idata body_len, hhdr_len, jhdr_len, page_len, jpeg_len;
	UWORK16 idata sent, remaining;
	UWORK8 xdata * outbuf;
	UWORK8 xdata * ptr;
	UWORK8 xdata * tcp_data;
	UWORK8 idata request;
	UWORK16 TCPheader_len, data_len, Total_len;
	ST_IP_HEAD_FORMAT StrIp;
	ST_TCP_FORMAT strTcp;
	static UWORK8 idata post_flg = FALSE;

    if(FALSE == gbHaveFragment)
    {                             // 没有分片的数据 
	   memcpy((UWORK8 *)&StrIp.ucVerAndLen, (UWORK8 *)&gstaRevEthernet.ucaPacket[0], 20);	  //读取IP头数据
       memcpy((UWORK8 *)&strTcp.usSourcePort, (UWORK8 *)&gstaRevEthernet.ucaPacket[20], 20);  //读取TCP头数据
	}
    else
    {                             // 分片的数据 
		memcpy((UWORK8 *)&StrIp.ucVerAndLen, (UWORK8 *)&gucaSegTemp[0], 20);	  //读取IP头数据
        memcpy((UWORK8 *)&strTcp.usSourcePort, (UWORK8 *)&gucaSegTemp[20], 20);  //读取TCP头数据
	}
	Total_len = StrIp.usTotalLen;
	Total_len -= 20;		 //长度是IC的总数据长度减去IP头的长度。其实就是IP数据包的长度.
    TCPheader_len =  (strTcp.ucMOVENUM & 0xF000) >> 10;	 //记算TCP头的长度    data_len = Total_len - TCPheader_len;						 //len在上面已算过是总个TCP的长度
	tcp_data = &gstaRevEthernet.ucaPacket[20 + TCPheader_len];

	if (nr == NO_CONNECTION) return 0;			  //表示没有连上
	if (!reSendFlag)				  //发果不是重复发送
	{
		StrConnection_buf[nr].ucRESERIESNUM = StrConnection_buf[nr].ucSERIESNUM;
	}
	else
	{
		StrConnection_buf[nr].ucSERIESNUM = StrConnection_buf[nr].ucRESERIESNUM;   
	}
	request = NONE;
	
	if (strstr(tcp_data, "POST") != NULL)
	{
		post_flg = TRUE; 
	}
	else if (strstr(tcp_data, "GET") != NULL)	//See if this is a GET message
	{
		post_flg = FALSE;
		if (strstr(tcp_data, "photo1") != NULL)
		{
			request = GET_JPEG;
		}
		else if (strstr(tcp_data, "index") != NULL)
		{ 
			request = GET_PAGE;
		}
		else if(strstr(tcp_data, "/ ") != NULL)
		{
			request = GET_PAGE;
		}
	}

	// If POST flag is "armed" then look for the "switch=" string
	// and if found, turn the LED on or off according to whether 
	// the browser is sending a 1 or a 0.
	if (post_flg)
	{
		ptr = strstr(tcp_data, "switch=");
		if (ptr != NULL)
		{
			// Move to space after equals sign
			// Set control indicator accordingly
			post_flg = FALSE;
			request = POST_PAGE;
			ptr += 7;
			if (*ptr == '1')
			{
				CONTROL_LED=0x0;
			}   
			else if (*ptr == '0')
			{
				CONTROL_LED=0x1;
			}
			LightONOFF(CONTROL_LED);
		}
	}

	if ((request == GET_PAGE) || (request == POST_PAGE))
	{
		// Figure out sizes
		hhdr_len = strlen(html_header);
		page_len = strlen(web_page);
		body_len = hhdr_len + page_len;
		
		memcpy(&NetSend_buf[40], html_header, hhdr_len);
		memcpy(&NetSend_buf[40 + hhdr_len], web_page, page_len);
		NetSend_buf[40 + body_len] = 0;		// Append NULL 
		
		// Replace length tag with actual value
		itoa(page_len, text, 10);
		replace_tag(&NetSend_buf[40], "TAG:LEN1", text);
		
		// Insert the word CHECKED into the html so the browser will
		// check the correct LED state indicator box 
		if (CONTROL_LED == ON)
		{
			replace_tag(&NetSend_buf[40], "TAG:CHK1", "CHECKED");
		}
		else
		{
			replace_tag(&NetSend_buf[40], "TAG:CHK2", "CHECKED");
		}
		http_send(FLG_ACK | FLG_PSH, &NetSend_buf[40], body_len, nr);
//	    StrConnection_buf[nr].ucSERIESNUM += body_len;
	}
	else if (request == GET_JPEG)
	{
		// Ths browser has requested the jpeg image.  First figure out
		// sizes - cannot use sizeof() for jpeg here because it is in
		// another module.  Just directly specify length of it
		jhdr_len = strlen(jpeg_header);
		jpeg_len = 5705;//6194;
		body_len = jhdr_len + jpeg_len;
		
		// Free memory holding received message.  The message from the
		// browser can be 500+ bytes long so this is a significant 
		// chunk out of the available malloc space of 1500 bytes
		
		// First send the header and enough of the jpeg to make 1000 bytes.
		// The value of 1000 is arbitrary, but must be stay under 1500. 
		if (body_len < 1000) 		  //数据长度大于1000要分片
		{
			remaining = body_len;
		} 
		else
		{
			remaining = 1000; 
		}
		memcpy(&NetSend_buf[40], jpeg_header, jhdr_len);
		memcpy(&NetSend_buf[40 + jhdr_len], photo1_jpeg, remaining - jhdr_len);
		
		NetSend_buf[40 + remaining] = 0;		// Append NULL
		
		itoa(jpeg_len, text, 10);			      // Replace jpeg length tag with actual value
		replace_tag(outbuf + 54, "TAG:LEN2", text);
		
		http_send(FLG_ACK | FLG_PSH, &NetSend_buf[40], remaining, nr);
		sent = remaining - jhdr_len;
		StrConnection_buf[nr].ucSERIESNUM += remaining;
		
		// Send the rest of the jpeg file in 1000 byte chunks.  This sends about
		// 6 segments of 1000 bytes back to back, but we should actually process
		// acks from the other end to make sure we are not sending more than the
		// other end can receive.  Most systems can handle 6K
		while (sent < jpeg_len)			//如发送的数据小于图片长度
		{
			remaining = jpeg_len - sent;
			if (remaining > 1000) remaining = 1000;
			
			memcpy(&NetSend_buf[40], photo1_jpeg + sent, remaining);
			
			NetSend_buf[40 + remaining] = 0;		// Append NULL
			http_send(FLG_ACK | FLG_PSH, &NetSend_buf[40], remaining, nr);
			sent += remaining;
			StrConnection_buf[nr].ucSERIESNUM += remaining;
		}
	}
	StrConnection_buf[nr].HttpFlag = TCP_HTTP;
	return(body_len);		 // Return number of bytes sent, not including TCP header
}





⌨️ 快捷键说明

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