RTL8019以太网开发板资料

源代码在线查看: http.c

软件大小: 5070 K
上传用户: sunzhe
关键词: 8019 RTL 以太网 开发板
下载地址: 免注册下载 普通下载 VIP

相关代码

				//-----------------------------------------------------------------------------
				// 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 
				#include 
				#include 		// 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 				   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
				}
				
				
				
				
				
							

相关资源