Aktuální adresář: FITkit /
trunk /
mcu /
libs /
enc28j60 /
enc28j60_tcp.c
1 /*******************************************************************************
2
3 Copyright (C) 2010 Brno University of Technology,
4 Faculty of Information Technology
5 Author(s): Martin Musil <xmusil34 AT fit.vutbr.cz>
6
7 LICENSE TERMS
8
9 Redistribution and use in source and binary forms, with or without
10 modification, are permitted provided that the following conditions
11 are met:
12 1. Redistributions of source code must retain the above copyright
13 notice, this list of conditions and the following disclaimer.
14 2. Redistributions in binary form must reproduce the above copyright
15 notice, this list of conditions and the following disclaimer in
16 the documentation and/or other materials provided with the
17 distribution.
18 3. All advertising materials mentioning features or use of this software
19 or firmware must display the following acknowledgement:
20
21 This product includes software developed by the University of
22 Technology, Faculty of Information Technology, Brno and its
23 contributors.
24
25 4. Neither the name of the Company nor the names of its contributors
26 may be used to endorse or promote products derived from this
27 software without specific prior written permission.
28
29 This software or firmware is provided ``as is'', and any express or implied
30 warranties, including, but not limited to, the implied warranties of
31 merchantability and fitness for a particular purpose are disclaimed.
32 In no event shall the company or contributors be liable for any
33 direct, indirect, incidental, special, exemplary, or consequential
34 damages (including, but not limited to, procurement of substitute
35 goods or services; loss of use, data, or profits; or business
36 interruption) however caused and on any theory of liability, whether
37 in contract, strict liability, or tort (including negligence or
38 otherwise) arising in any way out of the use of this software, even
39 if advised of the possibility of such damage.
40
41 $Id$
42
43 *******************************************************************************/
44
45 #include "enc28j60_spi.h"
46 #include "enc28j60_eth.h"
47 #include "enc28j60_ip.h"
48 #include "enc28j60_tcp.h"
49
50
51 unsigned long dest_seq_num = 0;
52 unsigned long local_seq_num = 0;
53 unsigned long expected_ack_num = 0;
54
55 struct ip_h* ip_header_ptr;
56
57 extern unsigned long local_ip;
58 extern unsigned int tcp_fsm_timer;
59
60 struct tcp_socket socket;
61
62
63 /**
64
65 **/
66 void tcp_recv(struct ip_h* ip_header){
67
68 struct tcp_h tcp_header;
69
70 if(rx_read(&tcp_header, TCP_HEADER_LEN) != TCP_HEADER_LEN)
71 return;
72
73 //port filtr
74 if( HTONS(tcp_header.dest_port) != socket.src_port)
75 return;
76
77 //IP filtr
78 if(socket.state != FSM_LISTEN){
79
80 if(socket.dest_port != NTOHS(tcp_header.src_port))
81 return;
82
83 if(socket.dest_ip != NTOHL(ip_header->src_ip))
84 return;
85 }
86
87 //pokud je hlavicka delsi nez obvyklych 20B (volitelne polozky), zahodime je
88 if( ( ((unsigned char)tcp_header.data_offset) <<2) > TCP_HEADER_LEN){ //header_len *4
89 rx_skip ( ( ((unsigned char)tcp_header.data_offset) <<2) - TCP_HEADER_LEN);
90 }
91
92 ip_header_ptr = ip_header;
93
94 //volani konecneho automatu
95 tcp_fsm(&tcp_header);
96
97 return;
98 }
99
100
101
102 /**
103
104 **/
105 char tcp_send(){
106
107 if(tcp_connected()){
108 tx_seek(TCP_HEADER);
109 tx_save(TX3);
110 expected_ack_num = local_seq_num + tx_data_len() - TCP_HEADER_LEN;
111
112 if(tcp_fsm(NULL) == -1){
113 return -1;
114 }
115 else{
116 return 0;
117 }
118 }
119 return -1;
120 }
121
122
123 /**
124
125 **/
126 char tcp_out(unsigned long seq, unsigned long ack, unsigned char flags){
127 /*
128 if(!link_up()) //kabel odpojen,nebudeme odesilat
129 return -1;
130 */
131 struct tcp_h tcp_header;
132
133 tcp_header.src_port = HTONS(socket.src_port);
134 tcp_header.dest_port = HTONS(socket.dest_port);
135 tcp_header.seq_num = HTONL(seq);
136
137 if((flags & TCP_ACK) != 0)
138 tcp_header.ack_num = HTONL(ack);
139 else
140 tcp_header.ack_num = 0;
141
142 tcp_header.reserved = 0;
143 tcp_header.data_offset = TCP_HEADER_LEN >> 2;
144 tcp_header.flags = flags;
145 tcp_header.window_size = HTONS(WINDOW_SIZE);
146 tcp_header.checksum = 0;
147 tcp_header.urgent_ptr = 0;
148
149 tx_seek(TCP_HEADER);
150 tx_write(&tcp_header, TCP_HEADER_LEN);
151
152 tx_seek(TCP_HEADER);
153 tcp_header.checksum = HTONS(tcp_checksum(socket.dest_ip, tx_data_len()));
154
155 tx_write(&tcp_header, TCP_HEADER_LEN);
156
157
158
159 return ip_send(socket.dest_ip,IP_PROTO_TCP);
160 }
161
162
163 /**
164
165 **/
166 unsigned int tcp_checksum(unsigned long dest_ip,unsigned int length){
167
168 unsigned long sum = 0;
169 unsigned int* ptr;
170
171 ptr = (unsigned int*)&local_ip;
172 sum += *ptr;
173 ptr++;
174 sum += *ptr;
175
176 ptr = (unsigned int*)&dest_ip;
177 sum += *ptr;
178 ptr++;
179 sum += *ptr;
180
181 sum += IP_PROTO_TCP;
182 sum += length;
183
184 sum += (unsigned int) ~tx_checksum();
185
186 while(sum >>16)
187 sum = (sum & 0xFFFF) + (sum >> 16);
188
189 return (unsigned int) ~sum;
190 }
191
192 /**
193
194 **/
195 char tcp_send_header(unsigned char flags){
196
197 if( tx_init(TCP_PROTO_HEADER_ONLY) < 0)
198 return -1;
199 tx_close();
200
201 return tcp_out(local_seq_num,dest_seq_num, flags);
202 }
203
204 /**
205
206 **/
207 void tcp_fsm_reset(){
208
209 tx_unlock(TX3);
210
211 if(socket.type == TCP_SERVER)
212 socket.state = FSM_LISTEN;
213 else
214 socket.state = FSM_IDLE;
215 }
216
217 /**
218
219
220 **/
221 unsigned char create_tcp_socket(unsigned int src_port, void* handler){
222
223 if(src_port != 0){
224 socket.src_port = src_port;
225 socket.app_handler = handler;
226 socket.state = FSM_IDLE;
227 return src_port;
228 }
229 else
230 return 0;
231 }
232
233 /**
234
235
236
237 **/
238 char delete_tcp_socket(){
239
240 if(tcp_is_idle()){
241 socket.src_port = 0;
242 socket.app_handler = NULL;
243 socket.state = FSM_IDLE;
244 return 0;
245 }
246 else
247 return -1;
248 }
249
250
251 /**
252
253 **/
254 void change_tcp_handler(void* new_handler){
255
256 socket.app_handler = new_handler;
257
258 return;
259 }
260
261 /**
262
263 **/
264 char tcp_connect(unsigned long ip, unsigned int port){
265
266 if(socket.state == FSM_IDLE){
267 socket.dest_ip = ip;
268 socket.dest_port = port;
269 socket.state = FSM_NOT_CONNECTED;
270 socket.type = TCP_CLIENT;
271 tcp_fsm(NULL);
272 return 0;
273 }
274 else return -1;
275 }
276
277 /**
278
279 **/
280 char tcp_bind(){
281
282 if((socket.state == FSM_IDLE) | ( socket.state == FSM_LISTEN)){
283 socket.state = FSM_LISTEN;
284 socket.type = TCP_SERVER;
285 return 1;
286 }
287
288 return 0;
289 }
290
291 /**
292
293 **/
294 char tcp_unbind(){
295 if(( socket.state == FSM_LISTEN)){
296 socket.dest_port = 0;
297 socket.state = FSM_IDLE;
298 socket.type = TCP_SERVER;
299 return 1;
300 }
301 return 0;
302 }
303
304 /**
305
306 **/
307 inline void tcp_disconnect(){
308 if(socket.state == FSM_ESTABILISHED){
309 tcp_fsm_timer = FIN_WAIT1_TIMEOUT;
310 socket.state = FSM_HALF_OPEN;
311 expected_ack_num++; //+1 za FIN
312 tcp_fsm(NULL);
313 }
314 }
315
316 /**
317
318 **/
319 char tcp_connected(){
320
321 if(socket.state == FSM_ESTABILISHED)
322 return 1;
323
324 else return 0;
325 }
326
327 /**
328
329 **/
330 char tcp_is_idle(){
331
332 if((socket.state == FSM_IDLE) | ( socket.state == FSM_LISTEN)){
333 return 1;
334 }
335
336 return 0;
337
338 }
339 /**
340
341
342 **/
343 inline void tcp_timer(){
344
345 tcp_fsm(NULL);
346 }
347