Subversion Repositories HomeAutomation

Rev

Rev 363 | Blame | Compare with Previous | Last modification | View Log | SVN | RSS feed

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