?? tcp.lst
字號:
1 .file "tcp.c"
2 __SREG__ = 0x3f
3 __SP_H__ = 0x3e
4 __SP_L__ = 0x3d
5 __CCP__ = 0x34
6 __tmp_reg__ = 0
7 __zero_reg__ = 1
8 .global __do_copy_data
9 .global __do_clear_bss
11 .text
12 .Ltext0:
120 .global tcp_send_packet
122 tcp_send_packet:
1:net/tcp.c **** /*
2:net/tcp.c **** ,-----------------------------------------------------------------------------------------.
3:net/tcp.c **** | net/tcp
4:net/tcp.c **** |-----------------------------------------------------------------------------------------
5:net/tcp.c **** | this file implements a very basic tcp protocol
6:net/tcp.c **** | - very basic
7:net/tcp.c **** |
8:net/tcp.c **** | KNOWN PROBLEMS:
9:net/tcp.c **** | - it does not yet check the tcp checksum of incoming packets!!
10:net/tcp.c **** | - something with the seq/ack calc might be buggy
11:net/tcp.c **** | -> must be checked by sending bad tcp packets/re-request etc [[TODO!]]
12:net/tcp.c **** |
13:net/tcp.c **** | Author : {{removed according to contest rules}}
14:net/tcp.c **** | -> circuitcellar.com avr design contest 2006
15:net/tcp.c **** | -> Entry #AT2616
16:net/tcp.c **** |
17:net/tcp.c **** |-----------------------------------------------------------------------------------------
18:net/tcp.c **** | License:
19:net/tcp.c **** | This program is free software; you can redistribute it and/or modify it under
20:net/tcp.c **** | the terms of the GNU General Public License as published by the Free Software
21:net/tcp.c **** | Foundation; either version 2 of the License, or (at your option) any later
22:net/tcp.c **** | version.
23:net/tcp.c **** | This program is distributed in the hope that it will be useful, but
24:net/tcp.c **** |
25:net/tcp.c **** | WITHOUT ANY WARRANTY;
26:net/tcp.c **** |
27:net/tcp.c **** | without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
28:net/tcp.c **** | PURPOSE. See the GNU General Public License for more details.
29:net/tcp.c **** |
30:net/tcp.c **** | You should have received a copy of the GNU General Public License along with
31:net/tcp.c **** | this program; if not, write to the Free Software Foundation, Inc., 51
32:net/tcp.c **** | Franklin St, Fifth Floor, Boston, MA 02110, USA
33:net/tcp.c **** |
34:net/tcp.c **** | http://www.gnu.de/gpl-ger.html
35:net/tcp.c **** `-----------------------------------------------------------------------------------------*/
36:net/tcp.c ****
37:net/tcp.c **** #include "tcp.h"
38:net/tcp.c ****
39:net/tcp.c **** //ACTIVATE DEBUG by editing this file:
40:net/tcp.c **** #include "debug.h"
41:net/tcp.c ****
42:net/tcp.c **** struct tcp_socket tcp_sockets[TCP_SOCKET_COUNT];
43:net/tcp.c ****
44:net/tcp.c **** //initialise all sockets to closed state:
45:net/tcp.c **** void tcp_init(){
46:net/tcp.c **** unsigned char i = 0;
47:net/tcp.c **** for(i=0; i<TCP_SOCKET_COUNT; i++){
48:net/tcp.c **** tcp_close_socket(i);
49:net/tcp.c **** }
50:net/tcp.c **** }
51:net/tcp.c ****
52:net/tcp.c **** unsigned char tcp_find_free_socket(){
53:net/tcp.c **** unsigned char i;
54:net/tcp.c **** for(i=0; i<TCP_SOCKET_COUNT; i++){
55:net/tcp.c **** if (tcp_sockets[i].state == TCP_STATE_CLOSED)
56:net/tcp.c **** return i;
57:net/tcp.c **** }
58:net/tcp.c ****
59:net/tcp.c **** //no free closed socket fount! -> kick an TIMED_WAIT socket
60:net/tcp.c **** for(i=0; i<TCP_SOCKET_COUNT; i++){
61:net/tcp.c **** if (tcp_sockets[i].state == TCP_STATE_TIMED_WAIT){
62:net/tcp.c **** tcp_close_socket(i);
63:net/tcp.c **** return i;
64:net/tcp.c **** }
65:net/tcp.c **** }
66:net/tcp.c ****
67:net/tcp.c **** //no more free sockets ... return invalid val
68:net/tcp.c **** return(TCP_SOCKET_COUNT);
69:net/tcp.c **** }
70:net/tcp.c ****
71:net/tcp.c **** void tcp_packet_in(unsigned char *buffer, unsigned int len){
72:net/tcp.c **** unsigned char tcp_header_flags;
73:net/tcp.c **** unsigned int source_port;
74:net/tcp.c **** unsigned int dest_port;
75:net/tcp.c **** unsigned int datalen;
76:net/tcp.c **** unsigned int datapos;
77:net/tcp.c **** unsigned long source_ip;
78:net/tcp.c **** unsigned long longtmp;
79:net/tcp.c **** unsigned char socketnum;
80:net/tcp.c **** //unsigned char i;
81:net/tcp.c ****
82:net/tcp.c **** //read header:
83:net/tcp.c **** //source ip:
84:net/tcp.c **** source_ip = nic_buffer_to_ip(&buffer[IP_POS_SRC_IP]);
85:net/tcp.c **** //source port:
86:net/tcp.c **** source_port = (buffer[TCP_POS_SRC_PORT]<<8) | buffer[TCP_POS_SRC_PORT+1];
87:net/tcp.c **** //dest port
88:net/tcp.c **** dest_port = (buffer[TCP_POS_DST_PORT]<<8) | buffer[TCP_POS_DST_PORT+1];
89:net/tcp.c **** //flags:
90:net/tcp.c **** tcp_header_flags = buffer[TCP_POS_HEADERFLAGS] & 0x3F;
91:net/tcp.c ****
92:net/tcp.c **** //check if target ip matches:
93:net/tcp.c **** if (nic_buffer_to_ip(&buffer[IP_POS_DST_IP]) != nic_ip){
94:net/tcp.c **** #if TCP_DEBUG
95:net/tcp.c **** softuart_puts_progmem("TCP : ignoring packet for ip ");
96:net/tcp.c **** softuart_put_ip(nic_buffer_to_ip(&buffer[IP_POS_DST_IP]));
97:net/tcp.c **** softuart_putnewline();
98:net/tcp.c **** #endif
99:net/tcp.c **** return; //no, not for us !
100:net/tcp.c **** }
101:net/tcp.c ****
102:net/tcp.c **** //do we have an open socket for this connection ?!
103:net/tcp.c **** for(socketnum=0; socketnum<TCP_SOCKET_COUNT; socketnum++){
104:net/tcp.c **** //check every not closed socket
105:net/tcp.c **** if (tcp_sockets[socketnum].state != TCP_STATE_CLOSED){
106:net/tcp.c **** //compare source port (faster check than source ip
107:net/tcp.c **** if(tcp_sockets[socketnum].source_port == source_port){
108:net/tcp.c **** //now compare the source ip:
109:net/tcp.c **** if(tcp_sockets[socketnum].source_ip == source_ip){
110:net/tcp.c **** /// yes, this is for us !
111:net/tcp.c **** //handle packet
112:net/tcp.c **** #if TCP_DEBUG
113:net/tcp.c **** softuart_puts_progmem("TCP : socket[");
114:net/tcp.c **** softuart_put_uint8(socketnum);
115:net/tcp.c **** softuart_puts_progmem("] ACK: ");
116:net/tcp.c **** softuart_put_uint16(nic_buffer_to_seq(&buffer[TCP_POS_ACK])&0xFFFF);
117:net/tcp.c **** softuart_puts_progmem(" SEQ: ");
118:net/tcp.c **** softuart_put_uint16(nic_buffer_to_seq(&buffer[TCP_POS_SEQ])&0xFFFF);
119:net/tcp.c **** softuart_puts_progmem(" -> ");
120:net/tcp.c **** #endif
121:net/tcp.c ****
122:net/tcp.c **** //reset TTL:
123:net/tcp.c **** tcp_sockets[socketnum].ttl = TCP_TTL_TIMEOUT;
124:net/tcp.c ****
125:net/tcp.c **** //check for connection abort (RST flag)
126:net/tcp.c **** if (tcp_header_flags & TCP_RST_FLAG){
127:net/tcp.c **** //client wants to terminate ! accept this...
128:net/tcp.c **** tcp_close_socket(socketnum);
129:net/tcp.c **** //tcp_sockets[socketnum].ack = nic_buffer_to_seq(&buffer[TCP_POS_SEQ]) + 1;
130:net/tcp.c **** //tcp_sockets[socketnum].seq = nic_buffer_to_seq(&buffer[TCP_POS_ACK]);
131:net/tcp.c **** //FIXME: what is the correct response to an RST packet ?!
132:net/tcp.c ****
133:net/tcp.c **** #if TCP_DEBUG
134:net/tcp.c **** softuart_puts_progmem(" RST FLAG received -> socket CLOSED.\r\n");
135:net/tcp.c **** #endif
136:net/tcp.c **** return;
137:net/tcp.c **** }
138:net/tcp.c ****
139:net/tcp.c **** switch (tcp_sockets[socketnum].state){
140:net/tcp.c **** ///SNY_RECEIVED
141:net/tcp.c **** case(TCP_STATE_SYN_RECEIVED):
142:net/tcp.c **** if (tcp_header_flags == TCP_ACK_FLAG){
143:net/tcp.c **** //ok, this connection is established:
144:net/tcp.c **** //we do not need to send any data now)
145:net/tcp.c **** tcp_sockets[socketnum].state = TCP_STATE_ESTABLISHED;
146:net/tcp.c ****
147:net/tcp.c **** #if TCP_DEBUG
148:net/tcp.c **** softuart_puts_progmem("ESTABLISHED");
149:net/tcp.c **** #endif
150:net/tcp.c **** }else{
151:net/tcp.c **** //invalid packet or TCP_RST_FLAG for example ...
152:net/tcp.c **** //connection reset -> close socket
153:net/tcp.c **** tcp_close_socket(socketnum);
154:net/tcp.c **** #if TCP_DEBUG
155:net/tcp.c **** softuart_puts_progmem("CLOSED");
156:net/tcp.c **** #endif
157:net/tcp.c **** }
158:net/tcp.c **** break;
159:net/tcp.c ****
160:net/tcp.c **** ///ESTABLISHED
161:net/tcp.c **** case(TCP_STATE_ESTABLISHED):
162:net/tcp.c **** if (tcp_header_flags & TCP_FIN_FLAG){
163:net/tcp.c **** //connection close request
164:net/tcp.c **** //-------send ACK & goto CLOSE_WAIT---- no do this:
165:net/tcp.c **** //send ACK+FIN and goto LAST ACK:
166:net/tcp.c **** tcp_sockets[socketnum].state = TCP_STATE_LAST_ACK;
167:net/tcp.c **** tcp_sockets[socketnum].ack = nic_buffer_to_seq(&buffer[TCP_POS_SEQ]) + 1;
168:net/tcp.c **** tcp_sockets[socketnum].seq = nic_buffer_to_seq(&buffer[TCP_POS_ACK]);
169:net/tcp.c ****
170:net/tcp.c **** tcp_send_packet(buffer, socketnum, (TCP_FIN_FLAG|TCP_ACK_FLAG), 0);
171:net/tcp.c **** #if TCP_DEBUG
172:net/tcp.c **** softuart_puts_progmem("LAST_ACK");
173:net/tcp.c **** #endif
174:net/tcp.c **** }else{
175:net/tcp.c **** //this is data for application!
176:net/tcp.c **** //check for error & send packet to correct application
177:net/tcp.c ****
178:net/tcp.c **** ///OUTGOING DATA HANDLING:
179:net/tcp.c **** //which databyte was acked ?
180:net/tcp.c **** longtmp = nic_buffer_to_seq(&buffer[TCP_POS_ACK]);
181:net/tcp.c **** //the last packet we have sent was tcp_sockets[socketnum].seq,
182:net/tcp.c **** //check it:
183:net/tcp.c **** if ((longtmp != tcp_sockets[socketnum].seq) && (longtmp != 1)){
184:net/tcp.c **** #if TCP_DEBUG
185:net/tcp.c **** softuart_puts_progmem("TCP : ack != last seqnum! retransmit : ");
186:net/tcp.c **** softuart_put_uint16(longtmp&0xFFFF);
187:net/tcp.c **** softuart_putc(' ');
188:net/tcp.c **** softuart_put_uint16(tcp_sockets[socketnum].seq&0xFFFF);
189:net/tcp.c **** softuart_putc(' ');
190:net/tcp.c **** softuart_putnewline();
191:net/tcp.c **** #endif
192:net/tcp.c **** //overwrite seq num -> send acked data !
193:net/tcp.c **** tcp_sockets[socketnum].seq = longtmp;
194:net/tcp.c **** }
195:net/tcp.c ****
196:net/tcp.c **** //update our seq counter, we should send now
197:net/tcp.c **** //databyte longtmp-1 (1 = initval of seq counter)
198:net/tcp.c **** //tcp_sockets[socketnum].seq = longtmp;
199:net/tcp.c ****
200:net/tcp.c ****
201:net/tcp.c **** ///INCOMING DATA HANDLING:
202:net/tcp.c **** //check if this is the data we expect:
203:net/tcp.c **** longtmp = nic_buffer_to_seq(&buffer[TCP_POS_SEQ]);
204:net/tcp.c ****
205:net/tcp.c **** //extract data pos:
206:net/tcp.c **** datapos = (14 + ((buffer[IP_POS_VERSION] & 0x0F) << 2) + ((buffer[TCP_POS_DATA_OFFSET] & 0x
207:net/tcp.c **** datalen = ((buffer[IP_POS_PKTLEN+0]<<8) | buffer[IP_POS_PKTLEN+1])-datapos+14;
208:net/tcp.c ****
209:net/tcp.c **** //we are waiting for a packet with seq = <tcp_sockets[socketnum].ack>
210:net/tcp.c **** //-> we sent an ack for packet byte n, now the seq counter of incoming
211:net/tcp.c **** // packet has to be <n>
212:net/tcp.c **** if ((longtmp != tcp_sockets[socketnum].ack) && (tcp_sockets[socketnum].ack != 0)){
213:net/tcp.c **** //there was an error, check what to do next:
214:net/tcp.c **** if (longtmp < tcp_sockets[socketnum].ack){
215:net/tcp.c **** //we expected data x to y but we got (x-n) to y
216:net/tcp.c **** //we onlny need x to y, so discard n bytes:
217:net/tcp.c **** longtmp = (tcp_sockets[socketnum].ack - longtmp);
218:net/tcp.c **** datapos = datapos + longtmp;
219:net/tcp.c **** datalen = datalen - longtmp;
220:net/tcp.c **** #if TCP_DEBUG
221:net/tcp.c **** softuart_puts_progmem(" WARN: tcp data dup! ignoring duplicate data. ");
222:net/tcp.c **** #endif
223:net/tcp.c **** }else{ //longtmp > tcp....
224:net/tcp.c **** //uups one packet was lost during transfer !
225:net/tcp.c **** //re request this packet, send an ack for expected <seq>:
226:net/tcp.c **** #if TCP_DEBUG
227:net/tcp.c **** softuart_puts_progmem(" ERR : tcp packet lost! re-requesting. ");
228:net/tcp.c **** #endif
229:net/tcp.c **** tcp_send_packet(buffer, socketnum, (TCP_ACK_FLAG), 0);
230:net/tcp.c **** return;
231:net/tcp.c **** }
232:net/tcp.c **** }
233:net/tcp.c ****
234:net/tcp.c **** //protect buffer:
235:net/tcp.c **** if (datapos > NIC_BUFFERSIZE)
236:net/tcp.c **** datapos = NIC_BUFFERSIZE;
237:net/tcp.c **** if ((datapos + datalen) > NIC_BUFFERSIZE)
238:net/tcp.c **** datalen = 0;
239:net/tcp.c ****
240:net/tcp.c **** //limit datalength to length that fits into our buffer:
241:net/tcp.c **** if (datalen > (NIC_BUFFERSIZE-datapos))
242:net/tcp.c **** datalen = (NIC_BUFFERSIZE-datapos);
243:net/tcp.c ****
244:net/tcp.c **** //next ack packet we will send must ack data byte n+datalen:
245:net/tcp.c **** tcp_sockets[socketnum].ack = tcp_sockets[socketnum].ack + (datalen);
246:net/tcp.c ****
247:net/tcp.c **** #if TCP_DEBUG
248:net/tcp.c **** softuart_put_uint16(datalen);
249:net/tcp.c **** softuart_puts_progmem(" bytes in ");
250:net/tcp.c **** /*if (datalen>0)
251:net/tcp.c **** softuart_putnewline();
252:net/tcp.c **** for(int d=datapos; d<datapos+datalen; d++){
253:net/tcp.c **** softuart_putc(buffer[d]);
254:net/tcp.c **** }*/
255:net/tcp.c **** softuart_putnewline();
256:net/tcp.c **** #endif
257:net/tcp.c ****
258:net/tcp.c **** //now call the application
259:net/tcp.c **** unsigned char appstate = TCP_APPSTATE_NONE;
260:net/tcp.c **** unsigned int data_tx_count = 0;
261:net/tcp.c **** if ((tcp_sockets[socketnum].dest_port == IP_PORT_HTTPD)||(tcp_sockets[socketnum].dest_port
262:net/tcp.c **** data_tx_count = httpd_data_in(buffer, datapos, datalen, socketnum, &appstate);
263:net/tcp.c **** //}else{
264:net/tcp.c **** // data_tx_count = http_client_data_in(buffer, datapos, datalen, socketnum, &appstate);
265:net/tcp.c **** }
266:net/tcp.c ****
267:net/tcp.c **** //application modified appstate
268:net/tcp.c **** switch(appstate){
269:net/tcp.c **** case (TCP_APPSTATE_EMPTYACK):
270:net/tcp.c **** tcp_send_packet(buffer, socketnum, (TCP_ACK_FLAG), 0);
271:net/tcp.c **** tcp_sockets[socketnum].seq = tcp_sockets[socketnum].seq;
272:net/tcp.c ****
273:net/tcp.c **** break;
274:net/tcp.c **** case (TCP_APPSTATE_HAS_TXDATA):
275:net/tcp.c **** //send data
276:net/tcp.c **** tcp_send_packet(buffer, socketnum, (TCP_ACK_FLAG), data_tx_count);
277:net/tcp.c **** //seq counter update:
278:net/tcp.c **** tcp_sockets[socketnum].seq = tcp_sockets[socketnum].seq + data_tx_count;
279:net/tcp.c **** #if TCP_DEBUG
280:net/tcp.c **** softuart_puts_progmem("TCP : last byte sent = ");
281:net/tcp.c **** softuart_put_uint16(tcp_sockets[socketnum].seq&0xFFFF);
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -