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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 54 - (hide annotations) (download)
Fri Apr 27 08:42:17 2007 UTC (17 years, 2 months ago) by hedin
File MIME type: text/plain
File size: 48930 byte(s)
Added basic project
1 hedin 54 /*********************************************************************
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