/[H8]/trunk/PIC/TCP-IP stack/tcp.c
ViewVC logotype

Contents of /trunk/PIC/TCP-IP stack/tcp.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 54 - (show annotations) (download)
Fri Apr 27 08:42:17 2007 UTC (17 years, 1 month ago) by hedin
File MIME type: text/plain
File size: 48930 byte(s)
Added basic project
1 /*********************************************************************
2 *
3 * TCP Module for Microchip TCP/IP Stack
4 *
5 *********************************************************************
6 * FileName: TCP.C
7 * Dependencies: string.h
8 * StackTsk.h
9 * Helpers.h
10 * IP.h
11 * MAC.h
12 * ARP.h
13 * Tick.h
14 * TCP.h
15 * Processor: PIC18
16 * Complier: MCC18 v1.00.50 or higher
17 * HITECH PICC-18 V8.10PL1 or higher
18 * Company: Microchip Technology, Inc.
19 *
20 * Software License Agreement
21 *
22 * The software supplied herewith by Microchip Technology Incorporated
23 * (the “Company”) for its PICmicro® Microcontroller is intended and
24 * supplied to you, the Company’s customer, for use solely and
25 * exclusively on Microchip PICmicro Microcontroller products. The
26 * software is owned by the Company and/or its supplier, and is
27 * protected under applicable copyright laws. All rights are reserved.
28 * Any use in violation of the foregoing restrictions may subject the
29 * user to criminal sanctions under applicable laws, as well as to
30 * civil liability for the breach of the terms and conditions of this
31 * license.
32 *
33 * THIS SOFTWARE IS PROVIDED IN AN “AS IS” CONDITION. NO WARRANTIES,
34 * WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING, BUT NOT LIMITED
35 * TO, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
36 * PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. THE COMPANY SHALL NOT,
37 * IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL OR
38 * CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER.
39 *
40 * HiTech PICC18 Compiler Options excluding device selection:
41 * -FAKELOCAL -G -O -Zg -E -C
42 *
43 *
44 *
45 *
46 * Author Date Comment
47 *~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
48 * Nilesh Rajbharti 5/8/01 Original (Rev 1.0)
49 * Nilesh Rajbharti 5/22/02 Rev 2.0 (See version.log for detail)
50 * Nilesh Rajbharti 11/1/02 Fixed TCPTick() SYN Retry bug.
51 ********************************************************************/
52 #define THIS_IS_TCP
53
54 #include <string.h>
55
56 #include "stacktsk.h"
57 #include "helpers.h"
58 #include "ip.h"
59 #include "mac.h"
60 #include "tick.h"
61 #include "tcp.h"
62
63
64 /*
65 * Max TCP data length is MAC_TX_BUFFER_SIZE - sizeof(TCP_HEADER) -
66 * sizeof(IP_HEADER) - sizeof(ETHER_HEADER)
67 */
68 #define MAX_TCP_DATA_LEN (MAC_TX_BUFFER_SIZE - 54)
69
70
71 /*
72 * TCP Timeout value to begin with.
73 */
74 #define TCP_START_TIMEOUT_VAL ((TICK)TICK_SECOND * (TICK)60)
75
76 /*
77 * TCP Flags as defined by rfc793
78 */
79 #define FIN (0x01)
80 #define SYN (0x02)
81 #define RST (0x04)
82 #define PSH (0x08)
83 #define ACK (0x10)
84 #define URG (0x20)
85
86
87 /*
88 * TCP Header def. as per rfc 793.
89 */
90
91 typedef struct _TCP_HEADER
92 {
93 WORD SourcePort;
94 WORD DestPort;
95 DWORD SeqNumber;
96 DWORD AckNumber;
97
98 struct
99 {
100 unsigned int Reserved3 : 4;
101 unsigned int Val : 4;
102 } DataOffset;
103
104
105 union
106 {
107 struct
108 {
109 unsigned int flagFIN : 1;
110 unsigned int flagSYN : 1;
111 unsigned int flagRST : 1;
112 unsigned int flagPSH : 1;
113 unsigned int flagACK : 1;
114 unsigned int flagURG : 1;
115 unsigned int Reserved2 : 2;
116 } bits;
117 BYTE byte;
118 } Flags;
119
120 WORD Window;
121 WORD Checksum;
122 WORD UrgentPointer;
123
124 } TCP_HEADER;
125
126
127 /*
128 * TCP Options as defined by rfc 793
129 */
130 #define TCP_OPTIONS_END_OF_LIST (0x00)
131 #define TCP_OPTIONS_NO_OP (0x01)
132 #define TCP_OPTIONS_MAX_SEG_SIZE (0x02)
133 typedef struct _TCP_OPTIONS
134 {
135 BYTE Kind;
136 BYTE Length;
137 WORD_VAL MaxSegSize;
138 } TCP_OPTIONS;
139
140 #define SwapPseudoTCPHeader(h) (h.TCPLength = swaps(h.TCPLength))
141
142 /*
143 * Pseudo header as defined by rfc 793.
144 */
145 typedef struct _PSEUDO_HEADER
146 {
147 IP_ADDR SourceAddress;
148 IP_ADDR DestAddress;
149 BYTE Zero;
150 BYTE Protocol;
151 WORD TCPLength;
152 } PSEUDO_HEADER;
153
154 /*
155 * These are all sockets supported by this TCP.
156 */
157 SOCKET_INFO TCB[MAX_SOCKETS];
158
159 /*
160 * Local temp port numbers.
161 */
162 static WORD _NextPort;
163
164 /*
165 * Starting segment sequence number for each new connection.
166 */
167 static DWORD ISS;
168
169
170 static void HandleTCPSeg(TCP_SOCKET s,
171 NODE_INFO *remote,
172 TCP_HEADER *h,
173 WORD len);
174
175 static void TransmitTCP(NODE_INFO *remote,
176 TCP_PORT localPort,
177 TCP_PORT remotePort,
178 DWORD seq,
179 DWORD ack,
180 BYTE flags,
181 BUFFER buffer,
182 WORD len);
183
184 static TCP_SOCKET FindMatchingSocket(TCP_HEADER *h,
185 NODE_INFO *remote);
186 static void SwapTCPHeader(TCP_HEADER* header);
187 static WORD CalcTCPChecksum(WORD len);
188 static void CloseSocket(SOCKET_INFO* ps);
189
190 #define SendTCP(remote, localPort, remotePort, seq, ack, flags) \
191 TransmitTCP(remote, localPort, remotePort, seq, ack, flags, \
192 INVALID_BUFFER, 0)
193
194 #define LOCAL_PORT_START_NUMBER (1024)
195 #define LOCAL_PORT_END_NUMBER (5000)
196
197
198
199 /*********************************************************************
200 * Function: void TCPInit(void)
201 *
202 * PreCondition: None
203 *
204 * Input: None
205 *
206 * Output: TCP is initialized.
207 *
208 * Side Effects: None
209 *
210 * Overview: Initialize all socket info.
211 *
212 * Note: This function is called only one during lifetime
213 * of the application.
214 ********************************************************************/
215 void TCPInit(void)
216 {
217 TCP_SOCKET s;
218 SOCKET_INFO* ps;
219
220
221 // Initialize all sockets.
222 for ( s = 0; s < MAX_SOCKETS; s++ )
223 {
224 ps = &TCB[s];
225
226 ps->smState = TCP_CLOSED;
227 ps->Flags.bServer = FALSE;
228 ps->Flags.bIsPutReady = TRUE;
229 ps->Flags.bFirstRead = TRUE;
230 ps->Flags.bIsTxInProgress = FALSE;
231 ps->Flags.bIsGetReady = FALSE;
232 ps->TxBuffer = INVALID_BUFFER;
233 ps->TimeOut = TCP_START_TIMEOUT_VAL;
234 }
235
236 _NextPort = LOCAL_PORT_START_NUMBER;
237 ISS = 0;
238 }
239
240
241
242 /*********************************************************************
243 * Function: TCP_SOCKET TCPListen(TCP_PORT port)
244 *
245 * PreCondition: TCPInit() is already called.
246 *
247 * Input: port - A TCP port to be opened.
248 *
249 * Output: Given port is opened and returned on success
250 * INVALID_SOCKET if no more sockets left.
251 *
252 * Side Effects: None
253 *
254 * Overview: None
255 *
256 * Note: None
257 ********************************************************************/
258 TCP_SOCKET TCPListen(TCP_PORT port)
259 {
260 TCP_SOCKET s;
261 SOCKET_INFO* ps;
262
263 for ( s = 0; s < MAX_SOCKETS; s++ )
264 {
265 ps = &TCB[s];
266
267 if ( ps->smState == TCP_CLOSED )
268 {
269 /*
270 * We have a CLOSED socket.
271 * Initialize it with LISTENing state info.
272 */
273 ps->smState = TCP_LISTEN;
274 ps->localPort = port;
275 ps->remotePort = 0;
276
277 /*
278 * There is no remote node IP address info yet.
279 */
280 ps->remote.IPAddr.Val = 0x00;
281
282 /*
283 * If a socket is listened on, it is a SERVER.
284 */
285 ps->Flags.bServer = TRUE;
286
287 ps->Flags.bIsGetReady = FALSE;
288 ps->TxBuffer = INVALID_BUFFER;
289 ps->Flags.bIsPutReady = TRUE;
290
291 return s;
292 }
293 }
294 return INVALID_SOCKET;
295 }
296
297
298
299 /*********************************************************************
300 * Function: TCP_SOCKET TCPConnect(NODE_INFO* remote,
301 * TCP_PORT remotePort)
302 *
303 * PreCondition: TCPInit() is already called.
304 *
305 * Input: remote - Remote node address info
306 * remotePort - remote port to be connected.
307 *
308 * Output: A new socket is created, connection request is
309 * sent and socket handle is returned.
310 *
311 * Side Effects: None
312 *
313 * Overview: None
314 *
315 * Note: By default this function is not included in
316 * source. You must define STACK_CLIENT_MODE to
317 * be able to use this function.
318 ********************************************************************/
319 #ifdef STACK_CLIENT_MODE
320 TCP_SOCKET TCPConnect(NODE_INFO *remote, TCP_PORT remotePort)
321 {
322 TCP_SOCKET s;
323 SOCKET_INFO* ps;
324 BOOL lbFound;
325
326
327 lbFound = FALSE;
328 /*
329 * Find an available socket
330 */
331 for ( s = 0; s < MAX_SOCKETS; s++ )
332 {
333 ps = &TCB[s];
334 if ( ps->smState == TCP_CLOSED )
335 {
336 lbFound = TRUE;
337 break;
338 }
339 }
340
341 /*
342 * If there is no socket available, return error.
343 */
344 if ( lbFound == FALSE )
345 return INVALID_SOCKET;
346
347 /*
348 * Each new socket that is opened by this node, gets
349 * next sequential port number.
350 */
351 ps->localPort = ++_NextPort;
352 if ( _NextPort > LOCAL_PORT_END_NUMBER )
353 _NextPort = LOCAL_PORT_START_NUMBER;
354
355 /*
356 * This is a client socket.
357 */
358 ps->Flags.bServer = FALSE;
359
360 /*
361 * This is the port, we are trying to connect to.
362 */
363 ps->remotePort = remotePort;
364
365 /*
366 * Each new socket that is opened by this node, will
367 * start with next segment seqeuence number.
368 */
369 ps->SND_SEQ = ++ISS;
370 ps->SND_ACK = 0;
371
372 memcpy((BYTE*)&ps->remote, (const void*)remote, sizeof(ps->remote));
373
374 /*
375 * Send SYN message.
376 */
377 SendTCP(&ps->remote,
378 ps->localPort,
379 ps->remotePort,
380 ps->SND_SEQ,
381 ps->SND_ACK,
382 SYN);
383
384 ps->smState = TCP_SYN_SENT;
385 ps->SND_SEQ++;
386
387 return s;
388 }
389 #endif
390
391
392
393 /*********************************************************************
394 * Function: BOOL TCPIsConnected(TCP_SOCKET s)
395 *
396 * PreCondition: TCPInit() is already called.
397 *
398 * Input: s - Socket to be checked for connection.
399 *
400 * Output: TRUE if given socket is connected
401 * FALSE if given socket is not connected.
402 *
403 * Side Effects: None
404 *
405 * Overview: None
406 *
407 * Note: A socket is said to be connected if it is not
408 * in LISTEN and CLOSED mode. Socket may be in
409 * SYN_RCVD or FIN_WAIT_1 and may contain socket
410 * data.
411 ********************************************************************/
412 BOOL TCPIsConnected(TCP_SOCKET s)
413 {
414 return ( TCB[s].smState == TCP_EST );
415 }
416
417
418
419 /*********************************************************************
420 * Function: void TCPDisconnect(TCP_SOCKET s)
421 *
422 * PreCondition: TCPInit() is already called AND
423 * TCPIsPutReady(s) == TRUE
424 *
425 * Input: s - Socket to be disconnected.
426 *
427 * Output: A disconnect request is sent for given socket.
428 *
429 * Side Effects: None
430 *
431 * Overview: None
432 *
433 * Note: None
434 ********************************************************************/
435 void TCPDisconnect(TCP_SOCKET s)
436 {
437 SOCKET_INFO *ps;
438
439 ps = &TCB[s];
440
441 /*
442 * If socket is not connected, may be it is already closed
443 * or in process of closing. Since user has called this
444 * explicitly, close it forcefully.
445 */
446 if ( ps->smState != TCP_EST )
447 {
448 CloseSocket(ps);
449 return;
450 }
451
452
453 /*
454 * Discard any outstand data that is to be read.
455 */
456 TCPDiscard(s);
457
458 /*
459 * Send FIN message.
460 */
461 SendTCP(&ps->remote,
462 ps->localPort,
463 ps->remotePort,
464 ps->SND_SEQ,
465 ps->SND_ACK,
466 FIN | ACK);
467
468 ps->SND_SEQ++;
469
470 ps->smState = TCP_FIN_WAIT_1;
471
472 return;
473 }
474
475 /*********************************************************************
476 * Function: BOOL TCPFlush(TCP_SOCKET s)
477 *
478 * PreCondition: TCPInit() is already called.
479 *
480 * Input: s - Socket whose data is to be transmitted.
481 *
482 * Output: All and any data associated with this socket
483 * is marked as ready for transmission.
484 *
485 * Side Effects: None
486 *
487 * Overview: None
488 *
489 * Note: None
490 ********************************************************************/
491 BOOL TCPFlush(TCP_SOCKET s)
492 {
493 SOCKET_INFO *ps;
494
495 ps = &TCB[s];
496
497 // Make sure that this already a TxBuffer assigned to this
498 // socket.
499 if ( ps->TxBuffer == INVALID_BUFFER )
500 return FALSE;
501
502 if ( ps->Flags.bIsPutReady == FALSE )
503 return FALSE;
504
505 TransmitTCP(&ps->remote,
506 ps->localPort,
507 ps->remotePort,
508 ps->SND_SEQ,
509 ps->SND_ACK,
510 ACK,
511 ps->TxBuffer,
512 ps->TxCount);
513 ps->SND_SEQ += (DWORD)ps->TxCount;
514 ps->Flags.bIsPutReady = FALSE;
515 ps->Flags.bIsTxInProgress = FALSE;
516
517 #ifdef TCP_NO_WAIT_FOR_ACK
518 MACDiscardTx(ps->TxBuffer);
519 ps->TxBuffer = INVALID_BUFFER;
520 ps->Flags.bIsPutReady = TRUE;
521 #endif
522
523 return TRUE;
524 }
525
526
527
528 /*********************************************************************
529 * Function: BOOL TCPIsPutReady(TCP_SOCKET s)
530 *
531 * PreCondition: TCPInit() is already called.
532 *
533 * Input: s - socket to test
534 *
535 * Output: TRUE if socket 's' is free to transmit
536 * FALSE if socket 's' is not free to transmit.
537 *
538 * Side Effects: None
539 *
540 * Overview: None
541 *
542 * Note: Each socket maintains only transmit buffer.
543 * Hence until a data packet is acknowledeged by
544 * remote node, socket will not be ready for
545 * next transmission.
546 * All control transmission such as Connect,
547 * Disconnect do not consume/reserve any transmit
548 * buffer.
549 ********************************************************************/
550 BOOL TCPIsPutReady(TCP_SOCKET s)
551 {
552 if ( TCB[s].TxBuffer == INVALID_BUFFER )
553 return IPIsTxReady();
554 else
555 return TCB[s].Flags.bIsPutReady;
556 }
557
558
559
560
561 /*********************************************************************
562 * Function: BOOL TCPPut(TCP_SOCKET s, BYTE byte)
563 *
564 * PreCondition: TCPIsPutReady() == TRUE
565 *
566 * Input: s - socket to use
567 * byte - a data byte to send
568 *
569 * Output: TRUE if given byte was put in transmit buffer
570 * FALSE if transmit buffer is full.
571 *
572 * Side Effects: None
573 *
574 * Overview: None
575 *
576 * Note: None
577 ********************************************************************/
578 BOOL TCPPut(TCP_SOCKET s, BYTE byte)
579 {
580 WORD tempTxCount; // This is a fix for HITECH bug
581 SOCKET_INFO* ps;
582
583 ps = &TCB[s];
584
585 if ( ps->TxBuffer == INVALID_BUFFER )
586 {
587 ps->TxBuffer = MACGetTxBuffer();
588
589 // This function is used to transmit data only. And every data packet
590 // must be ack'ed by remote node. Until this packet is ack'ed by
591 // remote node, we must preserve its content so that we can retransmit
592 // if we need to.
593 MACReserveTxBuffer(ps->TxBuffer);
594
595 ps->TxCount = 0;
596
597 IPSetTxBuffer(ps->TxBuffer, sizeof(TCP_HEADER));
598 }
599
600 /*
601 * HITECH does not seem to compare ps->TxCount as it is.
602 * Copying it to local variable and then comparing seems to work.
603 */
604 tempTxCount = ps->TxCount;
605 if ( tempTxCount >= MAX_TCP_DATA_LEN )
606 return FALSE;
607
608 ps->Flags.bIsTxInProgress = TRUE;
609
610 MACPut(byte);
611
612 // REMOVE
613 //tempTxCount = ps->TxCount;
614 tempTxCount++;
615 ps->TxCount = tempTxCount;
616
617 //ps->TxCount++;
618 //tempTxCount = ps->TxCount;
619 if ( tempTxCount >= MAX_TCP_DATA_LEN )
620 TCPFlush(s);
621 //if ( TCB[s].TxCount >= MAX_TCP_DATA_LEN )
622 // TCPFlush(s);
623
624 return TRUE;
625 }
626
627
628
629 /*********************************************************************
630 * Function: BOOL TCPDiscard(TCP_SOCKET s)
631 *
632 * PreCondition: TCPInit() is already called.
633 *
634 * Input: s - socket
635 *
636 * Output: TRUE if socket received data was discarded
637 * FALSE if socket received data was already
638 * discarded.
639 *
640 * Side Effects: None
641 *
642 * Overview: None
643 *
644 * Note: None
645 ********************************************************************/
646 BOOL TCPDiscard(TCP_SOCKET s)
647 {
648 SOCKET_INFO* ps;
649
650 ps = &TCB[s];
651
652 /*
653 * This socket must contain data for it to be discarded.
654 */
655 if ( !ps->Flags.bIsGetReady )
656 return FALSE;
657
658 MACDiscardRx();
659 ps->Flags.bIsGetReady = FALSE;
660
661 return TRUE;
662 }
663
664
665
666
667 /*********************************************************************
668 * Function: WORD TCPGetArray(TCP_SOCKET s, BYTE *buffer,
669 * WORD count)
670 *
671 * PreCondition: TCPInit() is already called AND
672 * TCPIsGetReady(s) == TRUE
673 *
674 * Input: s - socket
675 * buffer - Buffer to hold received data.
676 * count - Buffer length
677 *
678 * Output: Number of bytes loaded into buffer.
679 *
680 * Side Effects: None
681 *
682 * Overview: None
683 *
684 * Note: None
685 ********************************************************************/
686 WORD TCPGetArray(TCP_SOCKET s, BYTE *buffer, WORD count)
687 {
688 SOCKET_INFO *ps;
689
690 ps = &TCB[s];
691
692 if ( ps->Flags.bIsGetReady )
693 {
694 if ( ps->Flags.bFirstRead )
695 {
696 // Position read pointer to begining of correct
697 // buffer.
698 IPSetRxBuffer(sizeof(TCP_HEADER));
699
700 ps->Flags.bFirstRead = FALSE;
701 }
702
703 ps->Flags.bIsTxInProgress = TRUE;
704
705 return MACGetArray(buffer, count);
706 }
707 else
708 return 0;
709 }
710
711
712
713 /*********************************************************************
714 * Function: BOOL TCPGet(TCP_SOCKET s, BYTE *byte)
715 *
716 * PreCondition: TCPInit() is already called AND
717 * TCPIsGetReady(s) == TRUE
718 *
719 * Input: s - socket
720 * byte - Pointer to a byte.
721 *
722 * Output: TRUE if a byte was read.
723 * FALSE if byte was not read.
724 *
725 * Side Effects: None
726 *
727 * Overview: None
728 *
729 * Note: None
730 ********************************************************************/
731 BOOL TCPGet(TCP_SOCKET s, BYTE *byte)
732 {
733 SOCKET_INFO* ps;
734
735 ps = &TCB[s];
736
737 if ( ps->Flags.bIsGetReady )
738 {
739 if ( ps->Flags.bFirstRead )
740 {
741 // Position read pointer to begining of correct
742 // buffer.
743 IPSetRxBuffer(sizeof(TCP_HEADER));
744
745 ps->Flags.bFirstRead = FALSE;
746
747 }
748
749 if ( ps->RxCount == 0 )
750 {
751 MACDiscardRx();
752 ps->Flags.bIsGetReady = FALSE;
753 return FALSE;
754 }
755
756 ps->RxCount--;
757 *byte = MACGet();
758 return TRUE;
759 }
760 return FALSE;
761 }
762
763
764
765 /*********************************************************************
766 * Function: BOOL TCPIsGetReady(TCP_SOCKET s)
767 *
768 * PreCondition: TCPInit() is already called.
769 *
770 * Input: s - socket to test
771 *
772 * Output: TRUE if socket 's' contains any data.
773 * FALSE if socket 's' does not contain any data.
774 *
775 * Side Effects: None
776 *
777 * Overview: None
778 *
779 * Note: None
780 ********************************************************************/
781 BOOL TCPIsGetReady(TCP_SOCKET s)
782 {
783 /*
784 * A socket is said to be "Get" ready when it has already
785 * received some data. Sometime, a socket may be closed,
786 * but it still may contain data. Thus in order to ensure
787 * reuse of a socket, caller must make sure that it reads
788 * a socket, if is ready.
789 */
790 return (TCB[s].Flags.bIsGetReady );
791 }
792
793
794
795 /*********************************************************************
796 * Function: void TCPTick(void)
797 *
798 * PreCondition: TCPInit() is already called.
799 *
800 * Input: None
801 *
802 * Output: Each socket FSM is executed for any timeout
803 * situation.
804 *
805 * Side Effects: None
806 *
807 * Overview: None
808 *
809 * Note: None
810 ********************************************************************/
811 void TCPTick(void)
812 {
813 #if 1 //!defined(TCP_NO_WAIT_FOR_ACK)
814 TCP_SOCKET s;
815 TICK diffTicks;
816 TICK tick;
817 SOCKET_INFO* ps;
818 DWORD seq;
819 BYTE flags;
820
821 flags = 0x00;
822 /*
823 * Periodically all "not closed" sockets must perform timed operation.
824 */
825 for ( s = 0; s < MAX_SOCKETS; s++ )
826 {
827 ps = &TCB[s];
828
829 if ( ps->Flags.bIsGetReady || ps->Flags.bIsTxInProgress )
830 continue;
831
832
833 /*
834 * Closed or Passively Listening socket do not care
835 * about timeout conditions.
836 */
837 if ( (ps->smState == TCP_CLOSED) ||
838 (ps->smState == TCP_LISTEN &&
839 ps->Flags.bServer == TRUE) )
840 continue;
841
842 tick = TickGet();
843
844 // Calculate timeout value for this socket.
845 diffTicks = TickGetDiff(tick, ps->startTick);
846
847 // If timeout has not occured, do not do anything.
848 if ( diffTicks <= ps->TimeOut )
849 continue;
850
851 /*
852 * All states require retransmission, so check for transmitter
853 * availability right here - common for all.
854 */
855 if ( !IPIsTxReady() )
856 return;
857
858 // Restart timeout reference.
859 ps->startTick = TickGet();
860
861 // Update timeout value if there is need to wait longer.
862 ps->TimeOut++;
863
864 // This will be one more attempt.
865 ps->RetryCount++;
866
867 /*
868 * A timeout has occured. Respond to this timeout condition
869 * depending on what state this socket is in.
870 */
871 switch(ps->smState)
872 {
873 case TCP_SYN_SENT:
874 /*
875 * Keep sending SYN until we hear from remote node.
876 * This may be for infinite time, in that case
877 * caller must detect it and do something.
878 * Bug Fix: 11/1/02
879 */
880 flags = SYN;
881 break;
882
883 case TCP_SYN_RCVD:
884 /*
885 * We must receive ACK before timeout expires.
886 * If not, resend SYN+ACK.
887 * Abort, if maximum attempts counts are reached.
888 */
889 if ( ps->RetryCount < MAX_RETRY_COUNTS )
890 {
891 flags = SYN | ACK;
892 }
893 else
894 CloseSocket(ps);
895 break;
896
897 case TCP_EST:
898 #if !defined(TCP_NO_WAIT_FOR_ACK)
899 /*
900 * Don't let this connection idle for very long time.
901 * If we did not receive or send any message before timeout
902 * expires, close this connection.
903 */
904 if ( ps->RetryCount <= MAX_RETRY_COUNTS )
905 {
906 if ( ps->TxBuffer != INVALID_BUFFER )
907 {
908 MACSetTxBuffer(ps->TxBuffer, 0);
909 MACFlush();
910 }
911 else
912 flags = ACK;
913 }
914 else
915 {
916 // Forget about previous transmission.
917 if ( ps->TxBuffer != INVALID_BUFFER )
918 MACDiscardTx(ps->TxBuffer);
919 ps->TxBuffer = INVALID_BUFFER;
920
921 #endif
922 // Request closure.
923 flags = FIN | ACK;
924
925 ps->smState = TCP_FIN_WAIT_1;
926 #if !defined(TCP_NO_WAIT_FOR_ACK)
927 }
928 #endif
929 break;
930
931 case TCP_FIN_WAIT_1:
932 case TCP_LAST_ACK:
933 /*
934 * If we do not receive any response to out close request,
935 * close it outselves.
936 */
937 if ( ps->RetryCount > MAX_RETRY_COUNTS )
938 CloseSocket(ps);
939 else
940 flags = FIN;
941 break;
942
943 case TCP_CLOSING:
944 case TCP_TIMED_WAIT:
945 /*
946 * If we do not receive any response to out close request,
947 * close it outselves.
948 */
949 if ( ps->RetryCount > MAX_RETRY_COUNTS )
950 CloseSocket(ps);
951 else
952 flags = ACK;
953 break;
954 }
955
956 if ( flags > 0x00 )
957 {
958 if ( flags != ACK )
959 seq = ps->SND_SEQ++;
960 else
961 seq = ps->SND_SEQ;
962
963 SendTCP(&ps->remote,
964 ps->localPort,
965 ps->remotePort,
966 seq,
967 ps->SND_ACK,
968 flags);
969 }
970 }
971 #else
972 return;
973 #endif
974 }
975
976
977
978 /*********************************************************************
979 * Function: BOOL TCPProcess(NODE_INFO* remote,
980 * WORD len)
981 *
982 * PreCondition: TCPInit() is already called AND
983 * TCP segment is ready in MAC buffer
984 *
985 * Input: remote - Remote node info
986 * len - Total length of TCP semgent.
987 *
988 * Output: TRUE if this function has completed its task
989 * FALSE otherwise
990 *
991 * Side Effects: None
992 *
993 * Overview: None
994 *
995 * Note: None
996 ********************************************************************/
997 BOOL TCPProcess(NODE_INFO *remote, WORD len)
998 {
999 TCP_HEADER TCPHeader;
1000 PSEUDO_HEADER pseudoHeader;
1001 TCP_SOCKET socket;
1002 WORD_VAL checksum;
1003 BYTE optionsSize;
1004
1005
1006 // Retrieve TCP header.
1007 MACGetArray((BYTE*)&TCPHeader, sizeof(TCPHeader));
1008
1009 SwapTCPHeader(&TCPHeader);
1010
1011 // Calculate IP pseudoheader checksum.
1012 pseudoHeader.SourceAddress = remote->IPAddr;
1013 pseudoHeader.DestAddress.v[0] = MY_IP_BYTE1;
1014 pseudoHeader.DestAddress.v[1] = MY_IP_BYTE2;
1015 pseudoHeader.DestAddress.v[2] = MY_IP_BYTE3;
1016 pseudoHeader.DestAddress.v[3] = MY_IP_BYTE4;
1017 pseudoHeader.Zero = 0x0;
1018 pseudoHeader.Protocol = IP_PROT_TCP;
1019 pseudoHeader.TCPLength = len;
1020
1021 SwapPseudoTCPHeader(pseudoHeader);
1022
1023
1024 checksum.Val = ~CalcIPChecksum((BYTE*)&pseudoHeader,
1025 sizeof(pseudoHeader));
1026
1027
1028 // Set TCP packet checksum = pseudo header checksum in MAC RAM.
1029 IPSetRxBuffer(16);
1030 MACPut(checksum.v[0]);
1031 MACPut(checksum.v[1]);
1032 IPSetRxBuffer(0);
1033
1034 // Now calculate TCP packet checksum in NIC RAM - including
1035 // pesudo header.
1036 checksum.Val = CalcTCPChecksum(len);
1037
1038 if ( checksum.Val != TCPHeader.Checksum )
1039 {
1040 MACDiscardRx();
1041 return TRUE;
1042 }
1043
1044 // Skip over options and retrieve all data bytes.
1045 optionsSize = (BYTE)((TCPHeader.DataOffset.Val << 2)-
1046 sizeof(TCPHeader));
1047 len = len - optionsSize - sizeof(TCPHeader);
1048
1049 // Position packet read pointer to start of data area.
1050 IPSetRxBuffer((TCPHeader.DataOffset.Val << 2));
1051
1052 // Find matching socket.
1053 socket = FindMatchingSocket(&TCPHeader, remote);
1054 if ( socket < INVALID_SOCKET )
1055 {
1056 HandleTCPSeg(socket, remote, &TCPHeader, len);
1057 }
1058 else
1059 {
1060 /*
1061 * If this is an unknown socket, discard it and
1062 * send RESET to remote node.
1063 */
1064 MACDiscardRx();
1065
1066 if ( socket == UNKNOWN_SOCKET )
1067 {
1068
1069 TCPHeader.AckNumber += len;
1070 if ( TCPHeader.Flags.bits.flagSYN ||
1071 TCPHeader.Flags.bits.flagFIN )
1072 TCPHeader.AckNumber++;
1073
1074 SendTCP(remote,
1075 TCPHeader.DestPort,
1076 TCPHeader.SourcePort,
1077 TCPHeader.AckNumber,
1078 TCPHeader.SeqNumber,
1079 RST);
1080 }
1081
1082 }
1083
1084 return TRUE;
1085 }
1086
1087
1088 /*********************************************************************
1089 * Function: static void TransmitTCP(NODE_INFO* remote
1090 * TCP_PORT localPort,
1091 * TCP_PORT remotePort,
1092 * DWORD seq,
1093 * DWORD ack,
1094 * BYTE flags,
1095 * BUFFER buffer,
1096 * WORD len)
1097 *
1098 * PreCondition: TCPInit() is already called AND
1099 * TCPIsPutReady() == TRUE
1100 *
1101 * Input: remote - Remote node info
1102 * localPort - Source port number
1103 * remotePort - Destination port number
1104 * seq - Segment sequence number
1105 * ack - Segment acknowledge number
1106 * flags - Segment flags
1107 * buffer - Buffer to which this segment
1108 * is to be transmitted
1109 * len - Total data length for this segment.
1110 *
1111 * Output: A TCP segment is assembled and put to transmit.
1112 *
1113 * Side Effects: None
1114 *
1115 * Overview: None
1116 *
1117 * Note: None
1118 ********************************************************************/
1119 static void TransmitTCP(NODE_INFO *remote,
1120 TCP_PORT localPort,
1121 TCP_PORT remotePort,
1122 DWORD tseq,
1123 DWORD tack,
1124 BYTE flags,
1125 BUFFER buffer,
1126 WORD len)
1127 {
1128 WORD_VAL checkSum;
1129 TCP_HEADER header;
1130 TCP_OPTIONS options;
1131 PSEUDO_HEADER pseudoHeader;
1132
1133 /*
1134 * When using SLIP (USART), packet transmission takes some time
1135 * and hence before sending another packet, we must make sure
1136 * that, last packet is transmitted.
1137 * When using ethernet controller, transmission occurs very fast
1138 * and by the time next packet is transmitted, previous is
1139 * transmitted and we do not need to check for last packet.
1140 */
1141 while( !IPIsTxReady() );
1142
1143 header.SourcePort = localPort;
1144 header.DestPort = remotePort;
1145 header.SeqNumber = tseq;
1146 header.AckNumber = tack;
1147 header.Flags.bits.Reserved2 = 0;
1148 header.DataOffset.Reserved3 = 0;
1149 header.Flags.byte = flags;
1150 // Receive window = MAC Free buffer size - TCP header (20) - IP header (20)
1151 // - ETHERNET header (14 if using NIC) .
1152 header.Window = MACGetFreeRxSize();
1153 #if !defined(STACK_USE_SLIP)
1154 /*
1155 * Limit one segment at a time from remote host.
1156 * This limit increases overall throughput as remote host does not
1157 * flood us with packets and later retry with significant delay.
1158 */
1159 if ( header.Window >= MAC_RX_BUFFER_SIZE )
1160 header.Window = MAC_RX_BUFFER_SIZE;
1161
1162 else if ( header.Window > 54 )
1163 {
1164 header.Window -= 54;
1165 }
1166 else
1167 header.Window = 0;
1168 #else
1169 if ( header.Window > 40 )
1170 {
1171 header.Window -= 40;
1172 }
1173 else
1174 header.Window = 0;
1175 #endif
1176
1177 header.Checksum = 0;
1178 header.UrgentPointer = 0;
1179
1180 SwapTCPHeader(&header);
1181
1182 len += sizeof(header);
1183
1184 if ( flags & SYN )
1185 {
1186 len += sizeof(options);
1187 options.Kind = TCP_OPTIONS_MAX_SEG_SIZE;
1188 options.Length = 0x04;
1189
1190 // Load MSS in already swapped order.
1191 options.MaxSegSize.v[0] = (MAC_RX_BUFFER_SIZE >> 8); // 0x05;
1192 options.MaxSegSize.v[1] = (MAC_RX_BUFFER_SIZE & 0xff); // 0xb4;
1193
1194 header.DataOffset.Val = (sizeof(header) + sizeof(options)) >> 2;
1195 }
1196 else
1197 header.DataOffset.Val = sizeof(header) >> 2;
1198
1199
1200 // Calculate IP pseudoheader checksum.
1201 pseudoHeader.SourceAddress.v[0] = MY_IP_BYTE1;
1202 pseudoHeader.SourceAddress.v[1] = MY_IP_BYTE2;
1203 pseudoHeader.SourceAddress.v[2] = MY_IP_BYTE3;
1204 pseudoHeader.SourceAddress.v[3] = MY_IP_BYTE4;
1205 pseudoHeader.DestAddress = remote->IPAddr;
1206 pseudoHeader.Zero = 0x0;
1207 pseudoHeader.Protocol = IP_PROT_TCP;
1208 pseudoHeader.TCPLength = len;
1209
1210 SwapPseudoTCPHeader(pseudoHeader);
1211
1212 header.Checksum = ~CalcIPChecksum((BYTE*)&pseudoHeader,
1213 sizeof(pseudoHeader));
1214 checkSum.Val = header.Checksum;
1215
1216 if ( buffer == INVALID_BUFFER )
1217 buffer = MACGetTxBuffer();
1218
1219 IPSetTxBuffer(buffer, 0);
1220
1221 // Write IP header.
1222 IPPutHeader(remote, IP_PROT_TCP, len);
1223 IPPutArray((BYTE*)&header, sizeof(header));
1224
1225 if ( flags & SYN )
1226 IPPutArray((BYTE*)&options, sizeof(options));
1227
1228 IPSetTxBuffer(buffer, 0);
1229
1230 checkSum.Val = CalcTCPChecksum(len);
1231
1232 // Update the checksum.
1233 IPSetTxBuffer(buffer, 16);
1234 MACPut(checkSum.v[1]);
1235 MACPut(checkSum.v[0]);
1236 MACSetTxBuffer(buffer, 0);
1237
1238 MACFlush();
1239 }
1240
1241
1242
1243 /*********************************************************************
1244 * Function: static WORD CalcTCPChecksum(WORD len)
1245 *
1246 * PreCondition: TCPInit() is already called AND
1247 * MAC buffer pointer set to starting of buffer
1248 *
1249 * Input: len - Total number of bytes to calculate
1250 * checksum for.
1251 *
1252 * Output: 16-bit checksum as defined by rfc 793.
1253 *
1254 * Side Effects: None
1255 *
1256 * Overview: This function performs checksum calculation in
1257 * MAC buffer itself.
1258 *
1259 * Note: None
1260 ********************************************************************/
1261 static WORD CalcTCPChecksum(WORD len)
1262 {
1263 BOOL lbMSB;
1264 WORD_VAL checkSum;
1265 BYTE Checkbyte;
1266
1267 lbMSB = TRUE;
1268 checkSum.Val = 0;
1269
1270 while( len-- )
1271 {
1272 Checkbyte = MACGet();
1273
1274 if ( !lbMSB )
1275 {
1276 if ( (checkSum.v[0] = Checkbyte+checkSum.v[0]) < Checkbyte)
1277 {
1278 if ( ++checkSum.v[1] == 0 )
1279 checkSum.v[0]++;
1280 }
1281 }
1282 else
1283 {
1284 if ( (checkSum.v[1] = Checkbyte+checkSum.v[1]) < Checkbyte)
1285 {
1286 if ( ++checkSum.v[0] == 0 )
1287 checkSum.v[1]++;
1288 }
1289 }
1290
1291 lbMSB = !lbMSB;
1292 }
1293
1294 checkSum.v[1] = ~checkSum.v[1];
1295 checkSum.v[0] = ~checkSum.v[0];
1296 return checkSum.Val;
1297 }
1298
1299
1300
1301 /*********************************************************************
1302 * Function: static TCP_SOCKET FindMatchingSocket(TCP_HEADER *h,
1303 * NODE_INFO* remote)
1304 *
1305 * PreCondition: TCPInit() is already called
1306 *
1307 * Input: h - TCP Header to be matched against.
1308 * remote - Node who sent this header.
1309 *
1310 * Output: A socket that matches with given header and remote
1311 * node is searched.
1312 * If such socket is found, its index is returned
1313 * else INVALID_SOCKET is returned.
1314 *
1315 * Side Effects: None
1316 *
1317 * Overview: None
1318 *
1319 * Note: None
1320 ********************************************************************/
1321 static TCP_SOCKET FindMatchingSocket(TCP_HEADER *h, NODE_INFO *remote)
1322 {
1323 SOCKET_INFO *ps;
1324 TCP_SOCKET s;
1325 TCP_SOCKET partialMatch;
1326
1327 partialMatch = INVALID_SOCKET;
1328
1329 for ( s = 0; s < MAX_SOCKETS; s++ )
1330 {
1331 ps = &TCB[s];
1332
1333 if ( ps->smState != TCP_CLOSED )
1334 {
1335 if ( ps->localPort == h->DestPort )
1336 {
1337 if ( ps->smState == TCP_LISTEN )
1338 partialMatch = s;
1339
1340 if ( ps->remotePort == h->SourcePort &&
1341 ps->remote.IPAddr.Val == remote->IPAddr.Val )
1342 {
1343 return s;
1344 }
1345 }
1346 }
1347 }
1348
1349 ps = &TCB[partialMatch];
1350
1351 if ( partialMatch != INVALID_SOCKET &&
1352 ps->smState == TCP_LISTEN )
1353 {
1354 memcpy((void*)&ps->remote, (void*)remote, sizeof(*remote));
1355 //ps->remote = *remote;
1356 ps->localPort = h->DestPort;
1357 ps->remotePort = h->SourcePort;
1358 ps->Flags.bIsGetReady = FALSE;
1359 ps->TxBuffer = INVALID_BUFFER;
1360 ps->Flags.bIsPutReady = TRUE;
1361
1362 return partialMatch;
1363 }
1364
1365 if ( partialMatch == INVALID_SOCKET )
1366 return UNKNOWN_SOCKET;
1367 else
1368 return INVALID_SOCKET;
1369 }
1370
1371
1372
1373
1374
1375
1376 /*********************************************************************
1377 * Function: static void SwapTCPHeader(TCP_HEADER* header)
1378 *
1379 * PreCondition: None
1380 *
1381 * Input: header - TCP Header to be swapped.
1382 *
1383 * Output: Given header is swapped.
1384 *
1385 * Side Effects: None
1386 *
1387 * Overview: None
1388 *
1389 * Note: None
1390 ********************************************************************/
1391 static void SwapTCPHeader(TCP_HEADER* header)
1392 {
1393 header->SourcePort = swaps(header->SourcePort);
1394 header->DestPort = swaps(header->DestPort);
1395 header->SeqNumber = swapl(header->SeqNumber);
1396 header->AckNumber = swapl(header->AckNumber);
1397 header->Window = swaps(header->Window);
1398 header->Checksum = swaps(header->Checksum);
1399 header->UrgentPointer = swaps(header->UrgentPointer);
1400 }
1401
1402
1403
1404 /*********************************************************************
1405 * Function: static void CloseSocket(SOCKET_INFO* ps)
1406 *
1407 * PreCondition: TCPInit() is already called
1408 *
1409 * Input: ps - Pointer to a socket info that is to be
1410 * closed.
1411 *
1412 * Output: Given socket information is reset and any
1413 * buffer held by this socket is discarded.
1414 *
1415 * Side Effects: None
1416 *
1417 * Overview: None
1418 *
1419 * Note: None
1420 ********************************************************************/
1421 static void CloseSocket(SOCKET_INFO* ps)
1422 {
1423 if ( ps->TxBuffer != INVALID_BUFFER )
1424 {
1425 MACDiscardTx(ps->TxBuffer);
1426 ps->TxBuffer = INVALID_BUFFER;
1427 ps->Flags.bIsPutReady = TRUE;
1428 }
1429
1430 ps->remote.IPAddr.Val = 0x00;
1431 ps->remotePort = 0x00;
1432 if ( ps->Flags.bIsGetReady )
1433 {
1434 MACDiscardRx();
1435 }
1436 ps->Flags.bIsGetReady = FALSE;
1437 ps->TimeOut = TCP_START_TIMEOUT_VAL;
1438
1439 ps->Flags.bIsTxInProgress = FALSE;
1440
1441 if ( ps->Flags.bServer )
1442 ps->smState = TCP_LISTEN;
1443 else
1444 ps->smState = TCP_CLOSED;
1445 return;
1446 }
1447
1448
1449
1450 /*********************************************************************
1451 * Function: static void HandleTCPSeg(TCP_SOCKET s,
1452 * NODE_INFO *remote,
1453 * TCP_HEADER* h,
1454 * WORD len)
1455 *
1456 * PreCondition: TCPInit() is already called AND
1457 * TCPProcess() is the caller.
1458 *
1459 * Input: s - Socket that owns this segment
1460 * remote - Remote node info
1461 * h - TCP Header
1462 * len - Total buffer length.
1463 *
1464 * Output: TCP FSM is executed on given socket with
1465 * given TCP segment.
1466 *
1467 * Side Effects: None
1468 *
1469 * Overview: None
1470 *
1471 * Note: None
1472 ********************************************************************/
1473 static void HandleTCPSeg(TCP_SOCKET s,
1474 NODE_INFO *remote,
1475 TCP_HEADER *h,
1476 WORD len)
1477 {
1478 DWORD ack;
1479 DWORD seq;
1480 DWORD prevAck, prevSeq;
1481 SOCKET_INFO *ps;
1482 BYTE flags;
1483
1484
1485 flags = 0x00;
1486 ps = &TCB[s];
1487
1488 /*
1489 * Remember current seq and ack for our connection so that if
1490 * we have to silently discard this packet, we can go back to
1491 * previous ack and seq numbers.
1492 */
1493 prevAck = ps->SND_ACK;
1494 prevSeq = ps->SND_SEQ;
1495
1496 ack = h->SeqNumber ;
1497 ack += (DWORD)len;
1498 seq = ps->SND_SEQ;
1499
1500 /*
1501 * Clear retry counts and timeout tick counter.
1502 */
1503 ps->RetryCount = 0;
1504 ps->startTick = TickGet();
1505 ps->TimeOut = TCP_START_TIMEOUT_VAL;
1506
1507 if ( ps->smState == TCP_LISTEN )
1508 {
1509 MACDiscardRx();
1510
1511 ps->SND_SEQ = ++ISS;
1512 ps->SND_ACK = ++ack;
1513 seq = ps->SND_SEQ;
1514 ++ps->SND_SEQ;
1515 if ( h->Flags.bits.flagSYN )
1516 {
1517 /*
1518 * This socket has received connection request.
1519 * Remember calling node, assign next segment seq. number
1520 * for this potential connection.
1521 */
1522 memcpy((void*)&ps->remote, (const void*)remote, sizeof(*remote));
1523 ps->remotePort = h->SourcePort;
1524
1525 /*
1526 * Grant connection request.
1527 */
1528 flags = SYN | ACK;
1529 ps->smState = TCP_SYN_RCVD;
1530
1531 }
1532 else
1533 {
1534 /*
1535 * Anything other than connection request is ignored in
1536 * LISTEN state.
1537 */
1538 flags = RST;
1539 seq = ack;
1540 ack = h->SeqNumber;
1541 ps->remote.IPAddr.Val = 0x00;
1542 }
1543
1544 }
1545 else
1546 {
1547 /*
1548 * Reset FSM, if RST is received.
1549 */
1550 if ( h->Flags.bits.flagRST )
1551 {
1552 MACDiscardRx();
1553
1554 CloseSocket(ps);
1555
1556 return;
1557
1558 }
1559
1560 else if ( seq == h->AckNumber )
1561 {
1562 if ( ps->smState == TCP_SYN_RCVD )
1563 {
1564 if ( h->Flags.bits.flagACK )
1565 {
1566 ps->SND_ACK = ack;
1567 ps->RetryCount = 0;
1568 ps->startTick = TickGet();
1569 ps->smState = TCP_EST;
1570
1571 if ( len > 0 )
1572 {
1573 ps->Flags.bIsGetReady = TRUE;
1574 ps->RxCount = len;
1575 ps->Flags.bFirstRead = TRUE;
1576 }
1577 else
1578 MACDiscardRx();
1579 }
1580 else
1581 {
1582 MACDiscardRx();
1583 }
1584 }
1585 else if ( ps->smState == TCP_SYN_SENT )
1586 {
1587 if ( h->Flags.bits.flagSYN )
1588 {
1589 ps->SND_ACK = ++ack;
1590 if ( h->Flags.bits.flagACK )
1591 {
1592 flags = ACK;
1593 ps->smState = TCP_EST;
1594 }
1595 else
1596 {
1597 flags = SYN | ACK;
1598 ps->smState = TCP_SYN_RCVD;
1599 ps->SND_SEQ = ++seq;
1600 }
1601
1602 if ( len > 0 )
1603 {
1604 ps->Flags.bIsGetReady = TRUE;
1605 ps->RxCount = len;
1606 ps->Flags.bFirstRead = TRUE;
1607 }
1608 else
1609 MACDiscardRx();
1610 }
1611 else
1612 {
1613 MACDiscardRx();
1614 }
1615 }
1616 else
1617 {
1618 if ( h->SeqNumber != ps->SND_ACK )
1619 {
1620 // Discard buffer.
1621 MACDiscardRx();
1622 return;
1623 }
1624
1625 ps->SND_ACK = ack;
1626
1627 if ( ps->smState == TCP_EST )
1628 {
1629 if ( h->Flags.bits.flagACK )
1630 {
1631 if ( ps->TxBuffer != INVALID_BUFFER )
1632 {
1633 MACDiscardTx(ps->TxBuffer);
1634 ps->TxBuffer = INVALID_BUFFER;
1635 ps->Flags.bIsPutReady = TRUE;
1636 }
1637 }
1638
1639 if ( h->Flags.bits.flagFIN )
1640 {
1641 flags = FIN | ACK;
1642 seq = ps->SND_SEQ++;
1643 ack = ++ps->SND_ACK;
1644 ps->smState = TCP_LAST_ACK;
1645 }
1646
1647
1648 if ( len > 0 )
1649 {
1650 if ( !ps->Flags.bIsGetReady )
1651 {
1652 ps->Flags.bIsGetReady = TRUE;
1653 ps->RxCount = len;
1654 ps->Flags.bFirstRead = TRUE;
1655
1656 // 4/1/02
1657 flags = ACK;
1658 }
1659 else
1660 {
1661 /*
1662 * Since we cannot accept this packet,
1663 * restore to previous seq and ack.
1664 * and do not send anything back.
1665 * Host has to resend this packet when
1666 * we are ready.
1667 */
1668 flags = 0x00;
1669 ps->SND_SEQ = prevSeq;
1670 ps->SND_ACK = prevAck;
1671
1672 MACDiscardRx();
1673 }
1674 }
1675 else
1676 {
1677 MACDiscardRx();
1678 }
1679
1680
1681 }
1682 else if ( ps->smState == TCP_LAST_ACK )
1683 {
1684 MACDiscardRx();
1685
1686 if ( h->Flags.bits.flagACK )
1687 {
1688 CloseSocket(ps);
1689 }
1690 }
1691 else if ( ps->smState == TCP_FIN_WAIT_1 )
1692 {
1693 MACDiscardRx();
1694
1695 if ( h->Flags.bits.flagFIN )
1696 {
1697 flags = ACK;
1698 ack = ++ps->SND_ACK;
1699 if ( h->Flags.bits.flagACK )
1700 {
1701 CloseSocket(ps);
1702 }
1703 else
1704 {
1705 ps->smState = TCP_CLOSING;
1706 }
1707 }
1708 }
1709 else if ( ps->smState == TCP_CLOSING )
1710 {
1711 MACDiscardRx();
1712
1713 if ( h->Flags.bits.flagACK )
1714 {
1715 CloseSocket(ps);
1716 }
1717 }
1718 }
1719 }
1720 else
1721 {
1722 MACDiscardRx();
1723 }
1724 }
1725
1726 if ( flags > 0x00 )
1727 {
1728 SendTCP(remote,
1729 h->DestPort,
1730 h->SourcePort,
1731 seq,
1732 ack,
1733 flags);
1734 }
1735 }
1736
1737
1738

  ViewVC Help
Powered by ViewVC 1.1.20