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

📄 tcp.c

📁 ENC28J60 System HTTP
💻 C
📖 第 1 页 / 共 2 页
字号:
/*,-----------------------------------------------------------------------------------------.| net/tcp|-----------------------------------------------------------------------------------------| this file implements a very basic tcp protocol| - very basic|| KNOWN PROBLEMS:| - it does not yet check the tcp checksum of incoming packets!!| - something with the seq/ack calc might be buggy|   -> must be checked by sending bad tcp packets/re-request etc [[TODO!]]|| Author   : {{removed according to contest rules}}|            -> circuitcellar.com avr design contest 2006|            -> Entry #AT2616||-----------------------------------------------------------------------------------------| License:| This program is free software; you can redistribute it and/or modify it under| the terms of the GNU General Public License as published by the Free Software| Foundation; either version 2 of the License, or (at your option) any later| version.| This program is distributed in the hope that it will be useful, but|| WITHOUT ANY WARRANTY;|| without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR| PURPOSE. See the GNU General Public License for more details.|| You should have received a copy of the GNU General Public License along with| this program; if not, write to the Free Software Foundation, Inc., 51| Franklin St, Fifth Floor, Boston, MA 02110, USA|| http://www.gnu.de/gpl-ger.html`-----------------------------------------------------------------------------------------*/#include "tcp.h"//ACTIVATE DEBUG by editing this file:#include "debug.h"struct tcp_socket tcp_sockets[TCP_SOCKET_COUNT];//initialise all sockets to closed state:void tcp_init(){	unsigned char i = 0;	for(i=0; i<TCP_SOCKET_COUNT; i++){		tcp_close_socket(i);	}}unsigned char tcp_find_free_socket(){	unsigned char i;	for(i=0; i<TCP_SOCKET_COUNT; i++){		if (tcp_sockets[i].state == TCP_STATE_CLOSED)			return i;	}	//no free closed socket fount! -> kick an TIMED_WAIT socket	for(i=0; i<TCP_SOCKET_COUNT; i++){		if (tcp_sockets[i].state == TCP_STATE_TIMED_WAIT){			tcp_close_socket(i);			return i;		}	}	//no more free sockets ... return invalid val		return(TCP_SOCKET_COUNT);}void tcp_packet_in(unsigned char *buffer, unsigned int len){	unsigned char tcp_header_flags;	unsigned int  source_port;	unsigned int  dest_port;	unsigned int  datalen;	unsigned int  datapos;	unsigned long source_ip;	unsigned long longtmp;	unsigned char socketnum;	//unsigned char i;	//read header:	//source ip:	source_ip   = nic_buffer_to_ip(&buffer[IP_POS_SRC_IP]);	//source port:	source_port = (buffer[TCP_POS_SRC_PORT]<<8) | buffer[TCP_POS_SRC_PORT+1];	//dest port	dest_port   = (buffer[TCP_POS_DST_PORT]<<8) | buffer[TCP_POS_DST_PORT+1];	//flags:	tcp_header_flags = buffer[TCP_POS_HEADERFLAGS] & 0x3F;	//check if target ip matches:	if (nic_buffer_to_ip(&buffer[IP_POS_DST_IP]) != nic_ip){		#if TCP_DEBUG		softuart_puts_progmem("TCP : ignoring packet for ip ");		softuart_put_ip(nic_buffer_to_ip(&buffer[IP_POS_DST_IP]));		softuart_putnewline();		#endif		return; //no, not for us !	}	//do we have an open socket for this connection ?!	for(socketnum=0; socketnum<TCP_SOCKET_COUNT; socketnum++){		//check every not closed socket		if (tcp_sockets[socketnum].state != TCP_STATE_CLOSED){			//compare source port (faster check than source ip			if(tcp_sockets[socketnum].source_port == source_port){				//now compare the source ip:				if(tcp_sockets[socketnum].source_ip == source_ip){					/// yes, this is for us !					//handle packet					#if TCP_DEBUG					softuart_puts_progmem("TCP : socket[");					softuart_put_uint8(socketnum);					softuart_puts_progmem("] ACK: ");					softuart_put_uint16(nic_buffer_to_seq(&buffer[TCP_POS_ACK])&0xFFFF);					softuart_puts_progmem(" SEQ: ");					softuart_put_uint16(nic_buffer_to_seq(&buffer[TCP_POS_SEQ])&0xFFFF);					softuart_puts_progmem(" -> ");					#endif					//reset TTL:					tcp_sockets[socketnum].ttl = TCP_TTL_TIMEOUT;					//check for connection abort (RST flag)					if (tcp_header_flags & TCP_RST_FLAG){						//client wants to terminate ! accept this...						tcp_close_socket(socketnum);						//tcp_sockets[socketnum].ack = nic_buffer_to_seq(&buffer[TCP_POS_SEQ]) + 1;						//tcp_sockets[socketnum].seq = nic_buffer_to_seq(&buffer[TCP_POS_ACK]);						//FIXME: what is the correct response to an RST packet ?!						#if TCP_DEBUG						softuart_puts_progmem(" RST FLAG received -> socket CLOSED.\r\n");						#endif						return;					}					switch (tcp_sockets[socketnum].state){						///SNY_RECEIVED						case(TCP_STATE_SYN_RECEIVED):							if (tcp_header_flags == TCP_ACK_FLAG){								//ok, this connection is established:								//we do not need to send any data now)								tcp_sockets[socketnum].state = TCP_STATE_ESTABLISHED;								#if TCP_DEBUG								softuart_puts_progmem("ESTABLISHED");								#endif							}else{								//invalid packet or TCP_RST_FLAG for example ...								//connection reset -> close socket								tcp_close_socket(socketnum);								#if TCP_DEBUG								softuart_puts_progmem("CLOSED");								#endif							}							break;							///ESTABLISHED						case(TCP_STATE_ESTABLISHED):							if (tcp_header_flags & TCP_FIN_FLAG){								//connection close request								//-------send ACK & goto CLOSE_WAIT---- no do this:								//send ACK+FIN and goto LAST ACK:								tcp_sockets[socketnum].state = TCP_STATE_LAST_ACK;								tcp_sockets[socketnum].ack = nic_buffer_to_seq(&buffer[TCP_POS_SEQ]) + 1;								tcp_sockets[socketnum].seq = nic_buffer_to_seq(&buffer[TCP_POS_ACK]);								tcp_send_packet(buffer, socketnum, (TCP_FIN_FLAG|TCP_ACK_FLAG), 0);								#if TCP_DEBUG								softuart_puts_progmem("LAST_ACK");								#endif							}else{								//this is data for application!								//check for error & send packet to correct application								///OUTGOING DATA HANDLING:								//which databyte was acked ?								longtmp = nic_buffer_to_seq(&buffer[TCP_POS_ACK]);								//the last packet we have sent was tcp_sockets[socketnum].seq,								//check it:								if ((longtmp != tcp_sockets[socketnum].seq) && (longtmp != 1)){									#if TCP_DEBUG									softuart_puts_progmem("TCP : ack != last seqnum! retransmit : ");									softuart_put_uint16(longtmp&0xFFFF);									softuart_putc(' ');									softuart_put_uint16(tcp_sockets[socketnum].seq&0xFFFF);									softuart_putc(' ');									softuart_putnewline();									#endif									//overwrite seq num -> send acked data !									tcp_sockets[socketnum].seq = longtmp;								}								//update our seq counter, we should send now								//databyte longtmp-1 (1 = initval of seq counter)								//tcp_sockets[socketnum].seq = longtmp;								///INCOMING DATA HANDLING:								//check if this is the data we expect:								longtmp = nic_buffer_to_seq(&buffer[TCP_POS_SEQ]);								//extract data pos:								datapos = (14 + ((buffer[IP_POS_VERSION] & 0x0F) << 2) + ((buffer[TCP_POS_DATA_OFFSET] & 0xF0) >>2));								datalen = ((buffer[IP_POS_PKTLEN+0]<<8) | buffer[IP_POS_PKTLEN+1])-datapos+14;								//we are waiting for a packet with seq = <tcp_sockets[socketnum].ack>								//-> we sent an ack for packet byte n, now the seq counter of incoming								//   packet has to be <n>								if ((longtmp != tcp_sockets[socketnum].ack) && (tcp_sockets[socketnum].ack != 0)){									//there was an error, check what to do next:									if (longtmp < tcp_sockets[socketnum].ack){										//we expected data x to y but we got (x-n) to y										//we onlny need x to y, so discard n bytes:										longtmp = (tcp_sockets[socketnum].ack - longtmp);										datapos = datapos + longtmp;										datalen = datalen - longtmp;										#if TCP_DEBUG										softuart_puts_progmem(" WARN: tcp data dup! ignoring duplicate data. ");										#endif									}else{ //longtmp > tcp....										//uups one packet was lost during transfer !										//re request this packet, send an ack for expected <seq>:										#if TCP_DEBUG										softuart_puts_progmem(" ERR : tcp packet lost! re-requesting. ");										#endif										tcp_send_packet(buffer, socketnum, (TCP_ACK_FLAG), 0);										return;									}								}								//protect buffer:								if (datapos > NIC_BUFFERSIZE)									datapos = NIC_BUFFERSIZE;								if ((datapos + datalen) > NIC_BUFFERSIZE)									datalen = 0;								//limit datalength to length that fits into our buffer:								if (datalen > (NIC_BUFFERSIZE-datapos))									datalen = (NIC_BUFFERSIZE-datapos);								//next ack packet we will send must ack data byte n+datalen:								tcp_sockets[socketnum].ack = tcp_sockets[socketnum].ack + (datalen);								#if TCP_DEBUG								softuart_put_uint16(datalen);								softuart_puts_progmem(" bytes in ");								/*if (datalen>0)									softuart_putnewline();								for(int d=datapos; d<datapos+datalen; d++){									softuart_putc(buffer[d]);								}*/								softuart_putnewline();								#endif								//now call the application								unsigned char appstate = TCP_APPSTATE_NONE;								unsigned int  data_tx_count = 0;								if ((tcp_sockets[socketnum].dest_port == IP_PORT_HTTPD)||(tcp_sockets[socketnum].dest_port == 3333)){									data_tx_count = httpd_data_in(buffer, datapos, datalen, socketnum, &appstate);								//}else{								//	data_tx_count = http_client_data_in(buffer, datapos, datalen, socketnum, &appstate);								}								//application modified appstate								switch(appstate){									case (TCP_APPSTATE_EMPTYACK):										tcp_send_packet(buffer, socketnum, (TCP_ACK_FLAG), 0);										tcp_sockets[socketnum].seq = tcp_sockets[socketnum].seq;										break;									case (TCP_APPSTATE_HAS_TXDATA):										//send data										tcp_send_packet(buffer, socketnum, (TCP_ACK_FLAG), data_tx_count);										//seq counter update:										tcp_sockets[socketnum].seq = tcp_sockets[socketnum].seq + data_tx_count;										#if TCP_DEBUG										softuart_puts_progmem("TCP : last byte sent = ");										softuart_put_uint16(tcp_sockets[socketnum].seq&0xFFFF);										softuart_putc(' ');										#endif																			break;									case (TCP_APPSTATE_FINISHED):										#if TCP_DEBUG										softuart_puts_progmem("TCP : app closed socket ");										softuart_put_uint8(socketnum);										#endif										tcp_sockets[socketnum].state = TCP_STATE_FIN_WAIT1;										tcp_send_packet(buffer, socketnum, (TCP_FIN_FLAG|TCP_PSH_FLAG|TCP_ACK_FLAG), 0);										//seq counter update:										tcp_sockets[socketnum].seq = tcp_sockets[socketnum].seq + 1;										break;									default:										//do nothing... should not happen!										break;								}							}							break;						///CLOSE WAIT						case(TCP_STATE_CLOSE_WAIT):							//goto last_ack & send FIN packet							tcp_sockets[socketnum].state = TCP_STATE_LAST_ACK;							tcp_sockets[socketnum].ack = nic_buffer_to_seq(&buffer[TCP_POS_SEQ])+1;

⌨️ 快捷键说明

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