/*
*********************************************************************************************************
*                                              uC/TCP-IP
*                                      The Embedded TCP/IP Suite
*
*                          (c) Copyright 2003-2007; Micrium, Inc.; Weston, FL
*
*               All rights reserved.  Protected by international copyright laws.
*
*               uC/TCP-IP is provided in source form for FREE evaluation, for educational
*               use or peaceful research.  If you plan on using uC/TCP-IP in a commercial
*               product you need to contact Micrium to properly license its use in your
*               product.  We provide ALL the source code for your convenience and to help
*               you experience uC/TCP-IP.  The fact that the source code is provided does
*               NOT mean that you can use it without paying a licensing fee.
*
*               Knowledge of the source code may NOT be used to develop a similar product.
*
*               Please help us continue to provide the Embedded community with the finest
*               software available.  Your honesty is greatly appreciated.
*********************************************************************************************************
*/

/*
*********************************************************************************************************
*
*                                          NETWORK TCP LAYER
*                                   (TRANSMISSION CONTROL PROTOCOL)
*
* Filename      : net_tcp.c
* Version       : V1.89
* Programmer(s) : ITJ
*********************************************************************************************************
* Note(s)       : (1) Supports Transmission Control Protocol as described in RFC #793 with the following
*                     restrictions/constraints :
*
*                     (a) TCP Security & Precedence NOT supported               RFC # 793, Section 3.6
*
*                     (b) TCP Urgent Data           NOT supported               RFC # 793, Section 3.7
*                                                                                'The Communication of
*                                                                                  Urgent Information'
*
*                     (c) The following TCP options NOT supported :
*
*                         (1) Window Scale                                      RFC #1072, Section 2
*                                                                               RFC #1323, Section 2
*                         (2) Selective Acknowledgement (SACK)                  RFC #1072, Section 3
*                                                                               RFC #2018
*                                                                               RFC #2883
*                         (3) TCP Echo                                          RFC #1072, Section 4
*                         (4) Timestamp                                         RFC #1323, Section 3.2
*                         (5) Protection Against Wrapped Sequences (PAWS)       RFC #1323, Section 4
*
*                     (d) #### IP-Options-to-TCP-Connection                     RFC #1122, Section 4.2.3.8
*                                Handling NOT           supported
*
*                     (e) #### ICMP-Error-Message-to-TCP-Connection             RFC #1122, Section 4.2.3.9
*                                Handling NOT currently supported
*
*                 (2) TCP Layer assumes/requires Network Socket Layer (see 'net_sock.h  MODULE  Note #1a2').
*********************************************************************************************************
*/

/*
*********************************************************************************************************
*                                            INCLUDE FILES
*********************************************************************************************************
*/

#define    NET_TCP_MODULE
#include  <net.h>


/*
*********************************************************************************************************
*                                               MODULE
*
* Note(s) : (1) See 'net_tcp.h  MODULE'.
*********************************************************************************************************
*/

#ifdef  NET_TCP_MODULE_PRESENT


/*$PAGE*/
/*
*********************************************************************************************************
*                                            LOCAL DEFINES
*********************************************************************************************************
*/

/*
*********************************************************************************************************
*                              TCP CONNECTION CONFIGURATION CODE DEFINES
*
* Note(s) : (1) (a) TCP connection configuration codes used as arguments for various NetTCP_ConnCfg() functions.
*
*               (b) TCP connection configuration codes bit-field flags logically OR'd.
*********************************************************************************************************
*/

#define  NET_TCP_CONN_CFG_NONE                           DEF_BIT_NONE


#define  NET_TCP_CONN_CFG_MAX_SEG_SIZE_LOCAL             DEF_BIT_00
#define  NET_TCP_CONN_CFG_MAX_SEG_SIZE_REMOTE            DEF_BIT_01
#define  NET_TCP_CONN_CFG_MAX_SEG_SIZE_CONN              DEF_BIT_02
#define  NET_TCP_CONN_CFG_MAX_SEG_SIZE_ALL              (NET_TCP_CONN_CFG_MAX_SEG_SIZE_LOCAL  | \
                                                         NET_TCP_CONN_CFG_MAX_SEG_SIZE_REMOTE | \
                                                         NET_TCP_CONN_CFG_MAX_SEG_SIZE_CONN   )

#define  NET_TCP_CONN_CFG_MAX_SEG_SIZE_MASK              NET_TCP_CONN_CFG_MAX_SEG_SIZE_ALL


#define  NET_TCP_CONN_CFG_WIN_SIZE_RX                    DEF_BIT_02
#define  NET_TCP_CONN_CFG_WIN_SIZE_TX                    DEF_BIT_03
#define  NET_TCP_CONN_CFG_WIN_SIZE_CONN                 (NET_TCP_CONN_CFG_WIN_SIZE_RX | \
                                                         NET_TCP_CONN_CFG_WIN_SIZE_TX )
#define  NET_TCP_CONN_CFG_WIN_SIZE_ALL                   NET_TCP_CONN_CFG_WIN_SIZE_CONN

#define  NET_TCP_CONN_CFG_WIN_SIZE_MASK                  NET_TCP_CONN_CFG_WIN_SIZE_ALL


#define  NET_TCP_CONN_CFG_TX_RTT_RTO                     DEF_BIT_04



#define  NET_TCP_CONN_CFG_ALL                           (NET_TCP_CONN_CFG_NONE             | \
                                                         NET_TCP_CONN_CFG_MAX_SEG_SIZE_ALL | \
                                                         NET_TCP_CONN_CFG_WIN_SIZE_ALL     | \
                                                         NET_TCP_CONN_CFG_TX_RTT_RTO       )

/*$PAGE*/
/*
*********************************************************************************************************
*                               TCP CONNECTION CLOSE/FREE CODE DEFINES
*
* Note(s) : (1) (a) TCP connection close codes used as arguments for various NetTCP_ConnClose() functions.
*
*               (b) TCP connection close codes bit-field flags logically OR'd.
*
*           (2) Available TCP connection free codes are identical to TCP connection close codes.
*********************************************************************************************************
*/

#define  NET_TCP_CONN_CLOSE_NONE                         DEF_BIT_NONE


#define  NET_TCP_CONN_CLOSE_CONN_NONE                    DEF_BIT_NONE
#define  NET_TCP_CONN_CLOSE_CONN_TX_RESET                DEF_BIT_00
#define  NET_TCP_CONN_CLOSE_CONN_ALL                    (NET_TCP_CONN_CLOSE_CONN_NONE    | \
                                                         NET_TCP_CONN_CLOSE_CONN_TX_RESET)

#define  NET_TCP_CONN_CLOSE_CONN_MASK                    NET_TCP_CONN_CLOSE_CONN_ALL


#define  NET_TCP_CONN_CLOSE_TMR_NONE                     DEF_BIT_NONE
#define  NET_TCP_CONN_CLOSE_TMR_TX_IDLE                  DEF_BIT_04
#define  NET_TCP_CONN_CLOSE_TMR_TX_SILLY_WIN             DEF_BIT_05
#define  NET_TCP_CONN_CLOSE_TMR_TX_ZERO_WIN              DEF_BIT_06
#define  NET_TCP_CONN_CLOSE_TMR_TX_ACK_DLY               DEF_BIT_07
#define  NET_TCP_CONN_CLOSE_TMR_RE_TX                    DEF_BIT_08
#define  NET_TCP_CONN_CLOSE_TMR_KEEP_ALIVE               DEF_BIT_09
#define  NET_TCP_CONN_CLOSE_TMR_TIMEOUT                  DEF_BIT_10

#define  NET_TCP_CONN_CLOSE_TMR_ALL                     (NET_TCP_CONN_CLOSE_TMR_NONE         | \
                                                         NET_TCP_CONN_CLOSE_TMR_TX_IDLE      | \
                                                         NET_TCP_CONN_CLOSE_TMR_TX_SILLY_WIN | \
                                                         NET_TCP_CONN_CLOSE_TMR_TX_ZERO_WIN  | \
                                                         NET_TCP_CONN_CLOSE_TMR_TX_ACK_DLY   | \
                                                         NET_TCP_CONN_CLOSE_TMR_RE_TX        | \
                                                         NET_TCP_CONN_CLOSE_TMR_KEEP_ALIVE   | \
                                                         NET_TCP_CONN_CLOSE_TMR_TIMEOUT      )

#define  NET_TCP_CONN_CLOSE_TMR_MASK                     NET_TCP_CONN_CLOSE_TMR_ALL


#define  NET_TCP_CONN_CLOSE_ALL                         (NET_TCP_CONN_CLOSE_NONE     | \
                                                         NET_TCP_CONN_CLOSE_CONN_ALL | \
                                                         NET_TCP_CONN_CLOSE_TMR_ALL  )



#define  NET_TCP_CONN_FREE_NONE                          NET_TCP_CONN_CLOSE_NONE

#define  NET_TCP_CONN_FREE_TMR_NONE                      NET_TCP_CONN_CLOSE_TMR_NONE
#define  NET_TCP_CONN_FREE_TMR_TX_IDLE                   NET_TCP_CONN_CLOSE_TMR_TX_IDLE
#define  NET_TCP_CONN_FREE_TMR_TX_SILLY_WIN              NET_TCP_CONN_CLOSE_TMR_TX_SILLY_WIN
#define  NET_TCP_CONN_FREE_TMR_TX_ZERO_WIN               NET_TCP_CONN_CLOSE_TMR_TX_ZERO_WIN
#define  NET_TCP_CONN_FREE_TMR_TX_ACK_DLY                NET_TCP_CONN_CLOSE_TMR_TX_ACK_DLY
#define  NET_TCP_CONN_FREE_TMR_RE_TX                     NET_TCP_CONN_CLOSE_TMR_RE_TX
#define  NET_TCP_CONN_FREE_TMR_KEEP_ALIVE                NET_TCP_CONN_CLOSE_TMR_KEEP_ALIVE
#define  NET_TCP_CONN_FREE_TMR_TIMEOUT                   NET_TCP_CONN_CLOSE_TMR_TIMEOUT
#define  NET_TCP_CONN_FREE_TMR_ALL                       NET_TCP_CONN_CLOSE_TMR_ALL
#define  NET_TCP_CONN_FREE_TMR_MASK                      NET_TCP_CONN_CLOSE_TMR_MASK

#define  NET_TCP_CONN_FREE_ALL                           NET_TCP_CONN_CLOSE_ALL


/*
*********************************************************************************************************
*                                           LOCAL CONSTANTS
*********************************************************************************************************
*/


/*$PAGE*/
/*
*********************************************************************************************************
*                                          LOCAL DATA TYPES
*********************************************************************************************************
*/

/*
*********************************************************************************************************
*                                     TCP SEQUENCE CODE DATA TYPE
*********************************************************************************************************
*/

typedef  CPU_INT08U          NET_TCP_SEQ_CODE;


/*
*********************************************************************************************************
*                                 TCP ACKNOWLEDGEMENT CODE DATA TYPE
*********************************************************************************************************
*/

typedef  CPU_INT08U          NET_TCP_ACK_CODE;


/*
*********************************************************************************************************
*                                 TCP CONNECTION RESET CODE DATA TYPE
*********************************************************************************************************
*/

typedef  CPU_INT08U          NET_TCP_RESET_CODE;


/*
*********************************************************************************************************
*                                      TCP WINDOW CODE DATA TYPE
*********************************************************************************************************
*/

typedef  CPU_INT08U          NET_TCP_WIN_CODE;


/*
*********************************************************************************************************
*                                   TCP CALCULATION CODE DATA TYPE
*********************************************************************************************************
*/

typedef  CPU_INT08U          NET_TCP_CALC_CODE;


/*
*********************************************************************************************************
*                                  TCP CONFIGURATION CODE DATA TYPE
*********************************************************************************************************
*/

typedef  CPU_INT08U          NET_TCP_CFG_CODE;


/*
*********************************************************************************************************
*                                      TCP CLOSE CODE DATA TYPE
*********************************************************************************************************
*/

typedef  CPU_INT16U          NET_TCP_CLOSE_CODE;


/*
*********************************************************************************************************
*                                       TCP FREE CODE DATA TYPE
*********************************************************************************************************
*/

typedef  NET_TCP_CLOSE_CODE  NET_TCP_FREE_CODE;


/*
*********************************************************************************************************
*                                            LOCAL TABLES
*********************************************************************************************************
*/


/*
*********************************************************************************************************
*                                       LOCAL GLOBAL VARIABLES
*********************************************************************************************************
*/


/*$PAGE*/
/*
*********************************************************************************************************
*                                      LOCAL FUNCTION PROTOTYPES
*********************************************************************************************************
*/

                                                                                        /* --------- RX FNCTS --------- */

#if (NET_ERR_CFG_ARG_CHK_DBG_EN == DEF_ENABLED)
static  void                NetTCP_RxPktValidateBuf               (NET_BUF_HDR           *pbuf_hdr,
                                                                   NET_ERR               *perr);
#endif

static  void                NetTCP_RxPktValidate                  (NET_BUF               *pbuf,
                                                                   NET_BUF_HDR           *pbuf_hdr,
                                                                   NET_TCP_HDR           *ptcp_hdr,
                                                                   NET_ERR               *perr);

static  void                NetTCP_RxPktValidateOpt               (NET_BUF_HDR           *pbuf_hdr,
                                                                   NET_TCP_HDR           *ptcp_hdr,
                                                                   CPU_INT08U             tcp_hdr_len_size,
                                                                   NET_ERR               *perr);

static  CPU_BOOLEAN         NetTCP_RxPktValidateOptMaxSegSize     (NET_BUF_HDR           *pbuf_hdr,
                                                                   CPU_INT08U            *popt,
                                                                   CPU_INT08U            *popt_len,
                                                                   NET_ERR               *perr);



static  void                NetTCP_RxPktDemuxSeg                  (NET_BUF               *pbuf,
                                                                   NET_BUF_HDR           *pbuf_hdr,
                                                                   NET_ERR               *perr);



static  void                NetTCP_RxPktConnHandler               (NET_BUF               *pbuf,
                                                                   NET_BUF_HDR           *pbuf_hdr,
                                                                   NET_ERR               *perr);


static  void                NetTCP_RxPktConnHandlerListen         (NET_TCP_CONN          *pconn,
                                                                   NET_BUF               *pbuf,
                                                                   NET_BUF_HDR           *pbuf_hdr,
                                                                   NET_ERR               *perr);

static  void                NetTCP_RxPktConnHandlerSyncRxd        (NET_TCP_CONN          *pconn,
                                                                   NET_BUF               *pbuf,
                                                                   NET_BUF_HDR           *pbuf_hdr,
                                                                   NET_ERR               *perr);

static  void                NetTCP_RxPktConnHandlerSyncTxd        (NET_TCP_CONN          *pconn,
                                                                   NET_BUF               *pbuf,
                                                                   NET_BUF_HDR           *pbuf_hdr,
                                                                   NET_ERR               *perr);

static  void                NetTCP_RxPktConnHandlerConn           (NET_TCP_CONN          *pconn,
                                                                   NET_BUF               *pbuf,
                                                                   NET_BUF_HDR           *pbuf_hdr,
                                                                   NET_ERR               *perr);

static  void                NetTCP_RxPktConnHandlerFinWait1       (NET_TCP_CONN          *pconn,
                                                                   NET_BUF               *pbuf,
                                                                   NET_BUF_HDR           *pbuf_hdr,
                                                                   NET_ERR               *perr);

static  void                NetTCP_RxPktConnHandlerFinWait2       (NET_TCP_CONN          *pconn,
                                                                   NET_BUF               *pbuf,
                                                                   NET_BUF_HDR           *pbuf_hdr,
                                                                   NET_ERR               *perr);

static  void                NetTCP_RxPktConnHandlerClosing        (NET_TCP_CONN          *pconn,
                                                                   NET_BUF               *pbuf,
                                                                   NET_BUF_HDR           *pbuf_hdr,
                                                                   NET_ERR               *perr);

static  void                NetTCP_RxPktConnHandlerTimeWait       (NET_TCP_CONN          *pconn,
                                                                   NET_BUF               *pbuf,
                                                                   NET_BUF_HDR           *pbuf_hdr,
                                                                   NET_ERR               *perr);

static  void                NetTCP_RxPktConnHandlerCloseWait      (NET_TCP_CONN          *pconn,
                                                                   NET_BUF               *pbuf,
                                                                   NET_BUF_HDR           *pbuf_hdr,
                                                                   NET_ERR               *perr);

static  void                NetTCP_RxPktConnHandlerLastAck        (NET_TCP_CONN          *pconn,
                                                                   NET_BUF               *pbuf,
                                                                   NET_BUF_HDR           *pbuf_hdr,
                                                                   NET_ERR               *perr);


/*$PAGE*/
static  void                NetTCP_RxPktConnHandlerSeg            (NET_TCP_CONN          *pconn,
                                                                   NET_TCP_ACK_CODE       ack_code,
                                                                   NET_BUF               *pbuf,
                                                                   NET_BUF_HDR           *pbuf_hdr,
                                                                   NET_ERR               *perr);



static  void                NetTCP_RxPktConnHandlerCfgConn        (NET_TCP_CONN          *pconn);



static  void                NetTCP_RxPktConnHandlerRxQ_Sync       (NET_TCP_CONN          *pconn,
                                                                   NET_BUF               *pbuf,
                                                                   NET_BUF_HDR           *pbuf_hdr,
                                                                   NET_ERR               *perr);

static  void                NetTCP_RxPktConnHandlerRxQ_Conn       (NET_TCP_CONN          *pconn,
                                                                   NET_BUF               *pbuf,
                                                                   NET_BUF_HDR           *pbuf_hdr,
                                                                   NET_ERR               *perr);

static  void                NetTCP_RxPktConnHandlerRxQ_AppData    (NET_TCP_CONN          *pconn,
                                                                   NET_ERR               *perr);



static  void                NetTCP_RxPktConnHandlerTxWinRemote    (NET_TCP_CONN          *pconn,
                                                                   NET_TCP_ACK_CODE       ack_code,
                                                                   NET_BUF_HDR           *pbuf_hdr,
                                                                   NET_ERR               *perr);


static  void                NetTCP_RxPktConnHandlerReTxQ          (NET_TCP_CONN          *pconn,
                                                                   NET_TCP_ACK_CODE       ack_code,
                                                                   NET_BUF_HDR           *pbuf_hdr,
                                                                   NET_ERR               *perr);



static  CPU_BOOLEAN         NetTCP_RxPktConnHandlerListenQ_IsAvail(NET_TCP_CONN          *pconn,
                                                                   NET_ERR               *perr);


static  void                NetTCP_RxPktConnHandlerSignalConn     (NET_TCP_CONN          *pconn,
                                                                   NET_TCP_CONN_STATE     state,
                                                                   NET_ERR               *perr);

static  void                NetTCP_RxPktConnHandlerSignalClose    (NET_TCP_CONN          *pconn,
                                                                   CPU_BOOLEAN            data_avail,
                                                                   NET_ERR               *perr);



static  NET_TCP_SEQ_CODE    NetTCP_RxPktConnIsValidSeq            (NET_TCP_CONN          *pconn,
                                                                   NET_BUF_HDR           *pbuf_hdr,
                                                                   NET_ERR               *perr);

static  NET_TCP_ACK_CODE    NetTCP_RxPktConnIsValidAck            (NET_TCP_CONN          *pconn,
                                                                   NET_BUF_HDR           *pbuf_hdr,
                                                                   NET_ERR               *perr);

static  NET_TCP_RESET_CODE  NetTCP_RxPktConnIsValidReset          (NET_TCP_CONN          *pconn,
                                                                   NET_BUF_HDR           *pbuf_hdr,
                                                                   NET_ERR               *perr);



static  void                NetTCP_RxPktFree                      (NET_BUF               *pbuf_q);

static  void                NetTCP_RxPktDiscard                   (NET_BUF               *pbuf,
                                                                   NET_ERR               *perr);



static  void                NetTCP_RxConnWinSizeCfg               (NET_TCP_CONN          *pconn);

static  void                NetTCP_RxConnWinSizeCfgUpdateTh       (NET_TCP_CONN          *pconn);


static  void                NetTCP_RxConnWinSizeHandler           (NET_TCP_CONN          *pconn,
                                                                   NET_BUF_HDR           *pbuf_hdr,
                                                                   NET_TCP_WIN_SIZE       win_update_size,
                                                                   NET_TCP_WIN_CODE       win_update_code);



/*$PAGE*/
                                                                                        /* --------- TX FNCTS --------- */

static  void                NetTCP_TxConnWinSizeCfg               (NET_TCP_CONN          *pconn);

static  void                NetTCP_TxConnWinSizeCfgCongCtrl       (NET_TCP_CONN          *pconn);

static  void                NetTCP_TxConnWinSizeCfgMinTh          (NET_TCP_CONN          *pconn);


static  void                NetTCP_TxConnWinSizeHandlerCfgd       (NET_TCP_CONN          *pconn,
                                                                   NET_TCP_WIN_SIZE       win_update_size,
                                                                   NET_TCP_WIN_CODE       win_update_code,
                                                                   NET_ERR               *perr);

static  void                NetTCP_TxConnWinSizeHandlerCongCtrl   (NET_TCP_CONN          *pconn,
                                                                   NET_BUF_HDR           *pbuf_hdr,
                                                                   NET_TCP_ACK_CODE       ack_code,
                                                                   NET_TCP_WIN_SIZE       win_update_size,
                                                                   NET_TCP_WIN_CODE       win_update_code,
                                                                   NET_ERR               *perr);


static  void                NetTCP_TxConnWinSizeCalcSlowStartTh   (NET_TCP_CONN          *pconn);


static  void                NetTCP_TxConnWinSizeCongSet           (NET_TCP_CONN          *pconn,
                                                                   NET_TCP_WIN_CODE       win_inc_code);

static  void                NetTCP_TxConnWinSizeCongInc           (NET_TCP_CONN          *pconn,
                                                                   NET_BUF_HDR           *pbuf_hdr,
                                                                   NET_TCP_WIN_SIZE       win_update_size,
                                                                   NET_TCP_WIN_CODE       win_inc_code);


static  void                NetTCP_TxConnWinSizeUpdateAvail       (NET_TCP_CONN          *pconn);


static  void                NetTCP_TxConnWinSizeDupAckCtrlReset   (NET_TCP_CONN          *pconn);

static  void                NetTCP_TxConnWinSizeDupAckCtrlUpdate  (NET_TCP_CONN          *pconn,
                                                                   NET_BUF_HDR           *pbuf_hdr,
                                                                   CPU_BOOLEAN            reset_ctr);


static  void                NetTCP_TxConnWinSizeZeroWinHandler    (NET_TCP_CONN          *pconn,
                                                                   NET_TCP_WIN_CODE       win_update_code,
                                                                   NET_TCP_CLOSE_CODE     close_code);

static  void                NetTCP_TxConnWinSizeZeroWinTimeout    (void                  *pconn_timeout);



/*$PAGE*/
static  void                NetTCP_TxConnSync                     (NET_TCP_CONN          *pconn,
                                                                   NET_BUF_HDR           *pbuf_hdr,
                                                                   NET_ERR               *perr);

static  void                NetTCP_TxConnClose                    (NET_TCP_CONN          *pconn,
                                                                   NET_ERR               *perr);


static  void                NetTCP_TxConnAck                      (NET_TCP_CONN          *pconn,
                                                                   NET_BUF_HDR           *pbuf_hdr,
                                                                   NET_TCP_ACK_CODE       tx_ack_code,
                                                                   NET_TCP_CLOSE_CODE     close_code,
                                                                   NET_ERR               *perr);

static  void                NetTCP_TxConnAckDlyReset              (NET_TCP_CONN          *pconn,
                                                                   CPU_BOOLEAN            tmr_free);

static  void                NetTCP_TxConnAckDlyTimeout            (void                  *pconn_timeout);


static  void                NetTCP_TxConnReset                    (NET_TCP_CONN          *pconn,
                                                                   NET_BUF_HDR           *pbuf_hdr,
                                                                   NET_TCP_RESET_CODE     tx_reset_code,
                                                                   NET_TCP_CLOSE_CODE     close_code,
                                                                   NET_ERR               *perr);


static  void                NetTCP_TxConnProbe                    (NET_TCP_CONN          *pconn,
                                                                   CPU_BOOLEAN            tx_probe_data_octet,
                                                                   NET_TCP_CLOSE_CODE     close_code,
                                                                   NET_ERR               *perr);



static  void                NetTCP_TxConnTxQ                      (NET_TCP_CONN          *pconn,
                                                                   NET_BUF_HDR           *pbuf_hdr,
                                                                   NET_TCP_ACK_CODE       tx_ack_code,
                                                                   CPU_BOOLEAN            tx_q_timeout,
                                                                   NET_TCP_CLOSE_CODE     close_code,
                                                                   NET_ERR               *perr);


static  void                NetTCP_TxConnTxQ_TimeoutIdle          (void                  *pconn_timeout);

static  void                NetTCP_TxConnTxQ_TimeoutIdleSet       (NET_TCP_CONN          *pconn);

static  void                NetTCP_TxConnTxQ_TimeoutIdleClr       (NET_TCP_CONN          *pconn);


static  void                NetTCP_TxConnTxQ_TimeoutSillyWin      (void                  *pconn_timeout);



static  void                NetTCP_TxConnReTxQ                    (NET_TCP_CONN          *pconn,
                                                                   CPU_BOOLEAN            re_tx_q_timeout,
                                                                   NET_TCP_CLOSE_CODE     close_code,
                                                                   NET_ERR               *perr);


static  void                NetTCP_TxConnReTxQ_Timeout            (void                  *pconn_timeout);

static  void                NetTCP_TxConnReTxQ_TimeoutSet         (NET_TCP_CONN          *pconn,
                                                                   CPU_BOOLEAN            re_tx_q_timeout,
                                                                   NET_TCP_CLOSE_CODE     close_code,
                                                                   NET_ERR               *perr);



static  void                NetTCP_TxConnPrepareSegAddrs          (NET_TCP_CONN          *pconn,
                                                                   CPU_INT08U            *psrc_port,
                                                                   CPU_INT08U            *psrc_addr,
                                                                   CPU_INT16U             src_port_len,
                                                                   CPU_INT16U             src_addr_len,
                                                                   CPU_INT08U            *pdest_port,
                                                                   CPU_INT08U            *pdest_addr,
                                                                   CPU_INT16U             dest_port_len,
                                                                   CPU_INT16U             dest_addr_len,
                                                                   NET_ERR               *perr);


/*$PAGE*/
static  void                NetTCP_TxConnRTT_Init                 (NET_TCP_CONN          *pconn);

static  void                NetTCP_TxConnRTT_Reset                (NET_TCP_CONN          *pconn);

static  void                NetTCP_TxConnRTT_CalcUpdate           (NET_TCP_CONN          *pconn);


static  void                NetTCP_TxConnRTO_Init                 (NET_TCP_CONN          *pconn);

static  void                NetTCP_TxConnRTO_CfgMaxTimeout        (NET_TCP_CONN          *pconn);

static  void                NetTCP_TxConnRTO_CalcUpdate           (NET_TCP_CONN          *pconn);

static  NET_TCP_TIMEOUT_MS  NetTCP_TxConnRTO_CalcBackOff          (NET_TCP_CONN          *pconn,
                                                                   NET_TCP_TIMEOUT_MS     rto_ms);


static  void                NetTCP_TxConnRTT_RTO_Init             (NET_TCP_CONN          *pconn);

static  void                NetTCP_TxConnRTT_RTO_Calc             (NET_TCP_CONN          *pconn,
                                                                   NET_TCP_CALC_CODE      calc_code,
                                                                   NET_TCP_TX_RTT_TS_MS   rtt_ts_txd_ms,
                                                                   NET_TCP_TX_RTT_TS_MS   rtt_ts_rxd_ms);



static  void                NetTCP_TxPktHandler                   (NET_BUF               *pbuf,
                                                                   NET_IP_ADDR            src_addr,
                                                                   NET_TCP_PORT_NBR       src_port,
                                                                   NET_IP_ADDR            dest_addr,
                                                                   NET_TCP_PORT_NBR       dest_port,
                                                                   NET_TCP_SEQ_NBR        seq_nbr,
                                                                   NET_TCP_SEQ_NBR        ack_nbr,
                                                                   NET_TCP_WIN_SIZE       win_size,
                                                                   NET_IP_TOS             TOS,
                                                                   NET_IP_TTL             TTL,
                                                                   CPU_INT16U             flags_tcp,
                                                                   CPU_INT16U             flags_ip,
                                                                   void                  *popts_tcp,
                                                                   void                  *popts_ip,
                                                                   NET_ERR               *perr);

#if (NET_ERR_CFG_ARG_CHK_DBG_EN == DEF_ENABLED)
static  void                NetTCP_TxPktValidate                  (NET_BUF               *pbuf,
                                                                   NET_BUF_HDR           *pbuf_hdr,
                                                                   NET_TCP_PORT_NBR       src_port,
                                                                   NET_TCP_PORT_NBR       dest_port,
                                                                   NET_TCP_SEQ_NBR        seq_nbr,
                                                                   NET_TCP_SEQ_NBR        ack_nbr,
                                                                   NET_TCP_WIN_SIZE       win_size,
                                                                   CPU_INT16U             flags_tcp,
                                                                   void                  *popts_tcp,
                                                                   NET_ERR               *perr);

static  void                NetTCP_TxPktValidateOpt               (void                  *popts_tcp,
                                                                   CPU_INT16U             flags_tcp,
                                                                   NET_ERR               *perr);

static  void                NetTCP_TxPktValidateOptMaxSegSize     (void                  *popt_tcp,
                                                                   CPU_INT08U            *popt_len,
                                                                   void                 **popt_next,
                                                                   CPU_INT16U             flags_tcp,
                                                                   NET_ERR               *perr);
#endif


/*$PAGE*/
static  void                NetTCP_TxPkt                          (NET_BUF               *pbuf,
                                                                   NET_BUF_HDR           *pbuf_hdr,
                                                                   NET_IP_ADDR            src_addr,
                                                                   NET_TCP_PORT_NBR       src_port,
                                                                   NET_IP_ADDR            dest_addr,
                                                                   NET_TCP_PORT_NBR       dest_port,
                                                                   NET_TCP_SEQ_NBR        seq_nbr,
                                                                   NET_TCP_SEQ_NBR        ack_nbr,
                                                                   NET_TCP_WIN_SIZE       win_size,
                                                                   NET_IP_TOS             TOS,
                                                                   NET_IP_TTL             TTL,
                                                                   CPU_INT16U             flags_tcp,
                                                                   CPU_INT16U             flags_ip,
                                                                   void                  *popts_tcp,
                                                                   void                  *popts_ip,
                                                                   NET_ERR               *perr);


static  CPU_INT08U          NetTCP_TxPktPrepareOpt                (void                  *popts_tcp,
                                                                   CPU_INT08U            *popt_hdr,
                                                                   NET_ERR               *perr);

static  void                NetTCP_TxPktPrepareOptMaxSegSize      (void                  *popts_tcp,
                                                                   CPU_INT08U            *popt_hdr,
                                                                   CPU_INT08U            *popt_len,
                                                                   void                 **popt_next,
                                                                   NET_ERR               *perr);

static  void                NetTCP_TxPktPrepareHdr                (NET_BUF               *pbuf,
                                                                   NET_BUF_HDR           *pbuf_hdr,
                                                                   CPU_INT16U             tcp_hdr_len_tot,
                                                                   CPU_INT08U             tcp_opt_len_tot,
                                                                   NET_IP_ADDR            src_addr,
                                                                   NET_TCP_PORT_NBR       src_port,
                                                                   NET_IP_ADDR            dest_addr,
                                                                   NET_TCP_PORT_NBR       dest_port,
                                                                   NET_TCP_SEQ_NBR        seq_nbr,
                                                                   NET_TCP_SEQ_NBR        ack_nbr,
                                                                   NET_TCP_WIN_SIZE       win_size,
                                                                   CPU_INT16U             flags_tcp,
                                                                   CPU_INT32U            *ptcp_hdr_opts,
                                                                   NET_ERR               *perr);



static  void                NetTCP_TxPktFree                      (NET_BUF               *pbuf_q);

static  void                NetTCP_TxPktDiscard                   (NET_BUF               *pbuf,
                                                                   NET_ERR               *perr);




/*$PAGE*/
                                                                                        /* ------ TCP CONN FNCTS ------ */

static  void                NetTCP_ConnCfg                        (NET_TCP_CONN          *pconn,
                                                                   NET_TCP_CFG_CODE       cfg_code);

static  void                NetTCP_ConnCfgMaxSegSize              (NET_TCP_CONN          *pconn);



static  void                NetTCP_ConnClose                      (NET_TCP_CONN          *pconn,
                                                                   NET_BUF_HDR           *pbuf_hdr,
                                                                   CPU_BOOLEAN            close_conn_app,
                                                                   NET_TCP_CLOSE_CODE     close_code);

static  void                NetTCP_ConnCloseHandler               (NET_TCP_CONN          *pconn,
                                                                   CPU_BOOLEAN            close_conn_app,
                                                                   NET_TCP_CLOSE_CODE     close_code);

static  void                NetTCP_ConnCloseTimeout               (void                  *pconn_timeout);

static  void                NetTCP_ConnClosingTimeoutDataAvail    (void                  *pconn_timeout);



static  void                NetTCP_ConnFreeHandler                (NET_TCP_CONN          *pconn,
                                                                   NET_TCP_FREE_CODE      free_code);

static  void                NetTCP_ConnFreeTmr                    (NET_TCP_CONN          *pconn,
                                                                   NET_TCP_FREE_CODE      free_code);

static  void                NetTCP_ConnFreeBufQ                   (NET_BUF              **pbuf_q_head,
                                                                   NET_BUF              **pbuf_q_tail);



static  void                NetTCP_ConnClr                        (NET_TCP_CONN          *pconn);

static  void                NetTCP_ConnCopy                       (NET_TCP_CONN          *pconn_dest,
                                                                   NET_TCP_CONN          *pconn_src);


static  void                NetTCP_ConnDiscard                    (NET_TCP_CONN          *pconn);


/*
*********************************************************************************************************
*                                     LOCAL CONFIGURATION ERRORS
*********************************************************************************************************
*/


/*$PAGE*/
/*
*********************************************************************************************************
*                                            NetTCP_Init()
*
* Description : (1) Initialize Transmission Control Protocol Layer :
*
*                   (a) Perform TCP Module/OS  initialization
*                   (b) Perform TCP Module/BSP initialization
*                   (c) Initialize TCP connection pool
*                   (d) Initialize TCP connection table
*                   (e) Initialize TCP statistics & error counters
*
*
* Argument(s) : perr        Pointer to variable that will receive the return error code from this function :
*
*                               NET_TCP_ERR_NONE                    TCP layer successfully initialized.
*
*                                                                   - RETURNED BY NetOS_TCP_Init() : --
*                               NET_OS_ERR_INIT_TCP_RX_Q            TCP receive  queue(s)         NOT
*                                                                       successfully initialized.
*                               NET_OS_ERR_INIT_TCP_RX_Q_TIMEOUT    TCP receive  queue timeout(s) NOT
*                                                                       successfully configured.
*                               NET_OS_ERR_INIT_TCP_TX_Q            TCP transmit queue(s)         NOT
*                                                                       successfully initialized.
*                               NET_OS_ERR_INIT_TCP_TX_Q_TIMEOUT    TCP transmit queue timeout(s) NOT
*                                                                       successfully configured.
*
* Return(s)   : none.
*
* Caller(s)   : Net_Init().
*
*               This function is an INTERNAL network protocol suite function & MUST NOT be called by 
*               application function(s).
*
* Note(s)     : (2) TCP connection pool MUST be initialized PRIOR to initializing the pool with pointers to
*                   TCP connections.
*********************************************************************************************************
*/

void  NetTCP_Init (NET_ERR  *perr)
{
    NET_TCP_CONN      *pconn;
    NET_TCP_CONN_QTY   i;
    NET_ERR            stat_err;


                                                                /* --------------- PERFORM TCP/OS  INIT --------------- */
    NetOS_TCP_Init(perr);                                       /* Create TCP obj(s).                                   */
    if (*perr != NET_OS_ERR_NONE) {
         return;
    }

                                                                /* --------------- PERFORM TCP/BSP INIT --------------- */
    NetTCP_InitTxSeqNbr();                                      /* Init tx seq nbr ctr.                                 */


                                                                /* ------------- INIT TCP CONN POOL/STATS ------------- */
    NetTCP_ConnPoolPtr = (NET_TCP_CONN *)0;                     /* Init-clr TCP conn pool (see Note #2).                */

    NetStat_PoolInit((NET_STAT_POOL   *)&NetTCP_ConnPoolStat,
                     (NET_STAT_POOL_QTY) NET_TCP_CFG_NBR_CONN,
                     (NET_ERR         *)&stat_err);


                                                                /* ---------------- INIT TCP CONN TBL ----------------- */
    pconn = &NetTCP_ConnTbl[0];
    for (i = 0; i < NET_TCP_CFG_NBR_CONN; i++) {
        pconn->Type      =  NET_TCP_TYPE_CONN;                  /* Init each TCP conn type/id--NEVER modify.            */
        pconn->ID        = (NET_TCP_CONN_ID)i;

        pconn->ConnState =  NET_TCP_CONN_STATE_FREE;            /* Init each TCP conn as free/NOT used.                 */
        pconn->Flags     =  NET_TCP_FLAG_NONE;

#if (NET_DBG_CFG_MEM_CLR_EN == DEF_ENABLED)
        NetTCP_ConnClr(pconn);
#endif
                                                                /* Free each TCP conn to TCP conn pool (see Note #2).   */
        pconn->NextPtr     = (void         *)NetTCP_ConnPoolPtr;
        NetTCP_ConnPoolPtr = (NET_TCP_CONN *)pconn;

        pconn++;
    }


/*$PAGE*/
                                                                /* ------------- INIT TCP STAT & ERR CTRS ------------- */
#if (NET_CTR_CFG_STAT_EN           == DEF_ENABLED)
    NetTCP_StatRxPktCtr            =  0;
    NetTCP_StatRxSegProcessedCtr   =  0;

    NetTCP_StatTxSegCtr            =  0;
    NetTCP_StatTxSegConnSyncCtr    =  0;
    NetTCP_StatTxSegConnCloseCtr   =  0;
    NetTCP_StatTxSegConnAckCtr     =  0;
    NetTCP_StatTxSegConnResetCtr   =  0;
    NetTCP_StatTxSegConnProbeCtr   =  0;
    NetTCP_StatTxSegConnTxQ_Ctr    =  0;
    NetTCP_StatTxSegConnReTxQ_Ctr  =  0;
#endif


#if (NET_CTR_CFG_ERR_EN            == DEF_ENABLED)
    NetTCP_ErrNullPtrCtr           =  0;

    NetTCP_ErrNoneAvailCtr         =  0;
    NetTCP_ErrNotUsedCtr           =  0;


    NetTCP_ErrRxHdrLenCtr          =  0;
    NetTCP_ErrRxHdrSegLenCtr       =  0;
    NetTCP_ErrRxHdrPortSrcCtr      =  0;
    NetTCP_ErrRxHdrPortDestCtr     =  0;
    NetTCP_ErrRxHdrFlagsCtr        =  0;
    NetTCP_ErrRxHdrChkSumCtr       =  0;
    NetTCP_ErrRxHdrOptsCtr         =  0;

    NetTCP_ErrRxDestCtr            =  0;

    NetTCP_ErrRxPktDiscardedCtr    =  0;


    NetTCP_ErrTxOptTypeCtr         =  0;

    NetTCP_ErrTxPktDiscardedCtr    =  0;


    NetTCP_ErrConnInvalidCtr       =  0;
    NetTCP_ErrConnInvalidOpCtr     =  0;
    NetTCP_ErrConnInvalidStateCtr  =  0;
    NetTCP_ErrConnCloseCtr         =  0;


#if (NET_ERR_CFG_ARG_CHK_DBG_EN    == DEF_ENABLED)
    NetTCP_ErrRxInvalidBufIxCtr    =  0;

    NetTCP_ErrRxHdrDataLenCtr      =  0;


    NetTCP_ErrTxInvalidProtocolCtr =  0;
    NetTCP_ErrTxInvalidSizeCtr     =  0;
    NetTCP_ErrTxInvalidBufIxCtr    =  0;

    NetTCP_ErrTxHdrDataLenCtr      =  0;
    NetTCP_ErrTxHdrPortSrcCtr      =  0;
    NetTCP_ErrTxHdrPortDestCtr     =  0;
    NetTCP_ErrTxHdrFlagsCtr        =  0;
    NetTCP_ErrTxHdrOptLenCtr       =  0;
    NetTCP_ErrTxHdrOptCfgCtr       =  0;


    NetTCP_ErrConnInvalidTypeCtr   =  0;
#endif
#endif


   *perr = NET_TCP_ERR_NONE;
}


/*$PAGE*/
/*
*********************************************************************************************************
*                                             NetTCP_Rx()
*
* Description : (1) Process received segments & demultiplex to socket or application layer connection :
*
*                   (a) Validate    TCP packet
*                   (b) Demultiplex TCP packet to TCP connection
*                   (c) Handle/Process TCP segment
*                   (d) Return TCP error code(s)
*
*               (2) Although TCP data units are typically referred to as 'segments' (see RFC #793, Section 3.1),
*                   the term 'TCP packet' (see RFC #1983, 'packet') is used for TCP Receive until the packet is
*                   validated as a TCP segment.
*
*
* Argument(s) : pbuf        Pointer to network buffer that received TCP packet.
*
*               perr        Pointer to variable that will receive the return error code from this function :
*
*                               NET_TCP_ERR_NONE                TCP segment successfully received & processed.
*                               NET_ERR_INIT_INCOMPLETE         Network initialization NOT complete.
*
*                                                               ---- RETURNED BY NetTCP_RxPktDiscard() : -----
*                               NET_ERR_RX                      Receive error; packet discarded.
*
* Return(s)   : none.
*
* Caller(s)   : NetIP_RxPktDemuxDatagram().
*
*               This function is an INTERNAL network protocol suite function & MUST NOT be called by 
*               application function(s).
*
* Note(s)     : (3) NetTCP_Rx() blocked until network initialization completes.
*
*               (4) TCP receive statistics updated in NetTCP_RxPktConnHandler(); do NOT re-update.
*
*                   (a) Network buffer already freed & error counter already incremented in previous
*                       function(s).
*
*                   See also 'NetTCP_RxPktConnHandler()  Note #2'.
*********************************************************************************************************
*/
/*$PAGE*/
void  NetTCP_Rx (NET_BUF  *pbuf,
                 NET_ERR  *perr)
{
#if ((((NET_ERR_CFG_ARG_CHK_DBG_EN == DEF_ENABLED)                    && \
       (NET_CTR_CFG_ERR_EN         == DEF_ENABLED))                   || \
       (NET_CTR_CFG_STAT_EN        == DEF_ENABLED))                   && \
       (CPU_CFG_CRITICAL_METHOD    == CPU_CRITICAL_METHOD_STATUS_LOCAL))
    CPU_SR        cpu_sr;
#endif
    NET_BUF_HDR  *pbuf_hdr;
    NET_TCP_HDR  *ptcp_hdr;


#if (NET_ERR_CFG_ARG_CHK_EXT_EN == DEF_ENABLED)
    if (Net_InitDone != DEF_YES) {                              /* If init NOT complete, exit rx (see Note #3).         */
       *perr = NET_ERR_INIT_INCOMPLETE;
        return;
    }
#endif


#if (NET_ERR_CFG_ARG_CHK_DBG_EN == DEF_ENABLED)                 /* ------------------- VALIDATE PTR ------------------- */
    if (pbuf == (NET_BUF *)0) {
        NetTCP_RxPktDiscard(pbuf, perr);
        NET_CTR_ERR_INC(NetTCP_ErrNullPtrCtr);
        return;
    }
#endif


    NET_CTR_STAT_INC(NetTCP_StatRxPktCtr);


                                                                /* ----------------- VALIDATE TCP PKT ----------------- */
    pbuf_hdr = &pbuf->Hdr;
#if (NET_ERR_CFG_ARG_CHK_DBG_EN == DEF_ENABLED)
    NetTCP_RxPktValidateBuf(pbuf_hdr, perr);                    /* Validate rx'd buf.                                   */
    switch (*perr) {
        case NET_TCP_ERR_NONE:
             break;


        case NET_ERR_INVALID_PROTOCOL:
        case NET_BUF_ERR_INVALID_IX:
        default:
             NetTCP_RxPktDiscard(pbuf, perr);
             return;                                            /* Prevent 'break NOT reachable' compiler warning.      */
    }
#endif
    ptcp_hdr = (NET_TCP_HDR *)&pbuf->Data[pbuf_hdr->TCP_UDP_HdrDataIx];
    NetTCP_RxPktValidate(pbuf, pbuf_hdr, ptcp_hdr, perr);       /* Validate rx'd pkt.                                   */


                                                                /* -------------- DEMUX PKT TO TCP CONN --------------- */
    switch (*perr) {
        case NET_TCP_ERR_NONE:
             NetTCP_RxPktDemuxSeg(pbuf, pbuf_hdr, perr);
             break;


        case NET_TCP_ERR_INVALID_PORT_NBR:
        case NET_TCP_ERR_INVALID_LEN_HDR:
        case NET_TCP_ERR_INVALID_LEN_SEG:
        case NET_TCP_ERR_INVALID_LEN_DATA:
        case NET_TCP_ERR_INVALID_FLAG:
        case NET_TCP_ERR_INVALID_CHK_SUM:
        case NET_TCP_ERR_INVALID_OPT_LEN:
        case NET_TCP_ERR_INVALID_OPT_END:
        case NET_TCP_ERR_INVALID_OPT_NBR:
        default:
             NetTCP_RxPktDiscard(pbuf, perr);
             return;                                            /* Prevent 'break NOT reachable' compiler warning.      */
    }


                                                                /* --------------- HANDLE TCP PKT/CONN ---------------- */
    switch (*perr) {                                            /* Chk err from NetTCP_RxPktDemuxSeg().                 */
        case NET_TCP_ERR_NONE:
             NetTCP_RxPktConnHandler(pbuf, pbuf_hdr, perr);
             break;


        case NET_CONN_ERR_INVALID_FAMILY:
        case NET_CONN_ERR_INVALID_CONN:
        case NET_ERR_RX_DEST:
        default:
             NetTCP_RxPktDiscard(pbuf, perr);
             return;                                            /* Prevent 'break NOT reachable' compiler warning.      */
    }


/*$PAGE*/
                                                                /* ---------------- RTN TCP ERR CODES ----------------- */
    switch (*perr) {                                            /* Chk err from NetTCP_RxPktConnHandler().              */
        case NET_TCP_ERR_NONE:
                                                                /* See Note #4.                                         */
             break;


        case NET_TCP_ERR_CONN_DATA_NONE:
        case NET_TCP_ERR_CONN_DATA_VALID:
        case NET_TCP_ERR_CONN_CLOSED:
        case NET_TCP_ERR_CONN_RESET_VALID:
            *perr = NET_TCP_ERR_NONE;
             break;


        case NET_ERR_RX:
                                                                /* See Note #4a.                                        */
             return;                                            /* Prevent 'break NOT reachable' compiler warning.      */


        case NET_ERR_INIT_INCOMPLETE:
        case NET_TCP_ERR_INVALID_CONN:
        case NET_TCP_ERR_CONN_NOT_USED:
        case NET_TCP_ERR_INVALID_CONN_STATE:
        default:
             NetTCP_RxPktDiscard(pbuf, perr);
             return;                                            /* Prevent 'break NOT reachable' compiler warning.      */
    }
}


/*$PAGE*/
/*
*********************************************************************************************************
*                                         NetTCP_RxAppData()
*
* Description : (1) Deframe application data from TCP connection's enqueued TCP segment(s) :
*
*                   (a) Wait on TCP connection application receive queue for packet buffer(s)
*                   (b) Deframe application data from enqueued TCP segment(s)
*                   (c) Update  TCP connection application receive queue
*                       (1) Free TCP packet buffer(s)
*                   (d) Update TCP connection receive window
*
*
* Argument(s) : conn_id_tcp     Handle identifier of TCP connection to receive application data.
*
*               pdata_buf       Pointer to application buffer to receive application data.
*               ---------       Argument validated in NetSock_RxDataHandlerStream().
*
*               data_buf_len    Size    of application receive buffer (in octets).
*               ------------    Argument validated in NetSock_RxDataHandlerStream().
*
*               flags           Flags to select receive options; bit-field flags logically OR'd :
*               -----
*                                   NET_TCP_FLAG_NONE               No      TCP receive flags selected.
*                                   NET_TCP_FLAG_RX_DATA_PEEK       Receive TCP application data without consuming
*                                                                       the data; i.e. data NOT removed from TCP
*                                                                       connection's application receive queue(s).
*                                   NET_TCP_FLAG_RX_BLOCK           Receive TCP application data with blocking,
*                                                                       if flag set; without blocking, if clear.
*
*                               Argument validated in NetSock_RxDataHandlerStream().
*
*               perr        Pointer to variable that will receive the return error code from this function :
*
*                               NET_TCP_ERR_NONE                    TCP connection application data successfully
*                                                                       deframed; check return value for number of
*                                                                       data octets received.
*                               NET_TCP_ERR_INVALID_CONN_STATE      Invalid TCP connection state.
*                               NET_TCP_ERR_INVALID_CONN_OP         Invalid TCP connection operation.
*                               NET_TCP_ERR_CONN_NOT_USED           TCP connection NOT currently used.
*                               NET_TCP_ERR_CONN_FAIL               TCP connection operation(s) failed.
*                               NET_TCP_ERR_CONN_DATA_INVALID       TCP connection application receive queue contains
*                                                                       invalid or improperly sequenced data.
*
*                               NET_TCP_ERR_RX_Q_CLOSED             TCP connection application receive queue closed
*                                                                       (see Note #3e3B).
*                               NET_TCP_ERR_RX_Q_EMPTY              TCP connection application receive queue empty
*                                                                       (see Note #3e2B).
*
*                                                                   ------- RETURNED BY NetTCP_ConnIsUsed() : -------
*                               NET_ERR_INIT_INCOMPLETE             Network initialization NOT complete.
*                               NET_TCP_ERR_INVALID_CONN            Invalid TCP connection number.
*
*                                                                   ------ RETURNED BY NetOS_TCP_RxQ_Wait() : -------
*                               NET_TCP_ERR_RX_Q_SIGNAL_ABORT       TCP connection receive queue signal aborted;
*                                                                       TCP connection closed/aborted.
*                               NET_TCP_ERR_RX_Q_SIGNAL_FAULT       TCP connection receive queue signal fault.
*
*                                                                   ---------- RETURNED BY NetOS_Lock() : -----------
*                               NET_OS_ERR_LOCK                     Network access NOT acquired.
*
* Return(s)   : Total application data octets deframed into receive buffer, if NO errors.
*
*               0,                                                          otherwise.
*
* Caller(s)   : NetSock_RxDataHandlerStream().
*
*               This function is an INTERNAL network protocol suite function & SHOULD NOT be called by 
*               application function(s).
*$PAGE*
* Note(s)     : (2) NetTCP_RxAppData() blocked until network initialization completes.
*
*                   See 'NetTCP_ConnIsUsed()  Note #1'.
*
*               (3) RFC #793, Section 3.9 'Event Processing : RECEIVE Call' specifies how to handle receive
*                   data requests from the application layer :
*
*                   (a) For the "CLOSED STATE ... return 'error: connection does not exist'".
*
*                   (b) (1) For the "LISTEN STATE, SYN-SENT STATE, SYN-RECEIVED STATE ... queue for processing
*                           after entering ESTABLISHED state".
*
*                       (2) The application layer may request to receive application data before the TCP
*                           connection enters the connected state.  Such requests will block or return
*                           no data.
*
*                           See also 'NetTCP_RxPktConnHandlerRxQ_AppData()  Note #1bA'
*                                  &  Note #5b2.
*
*                   (c) For the "ESTABLISHED STATE, FIN-WAIT-1 STATE, FIN-WAIT-2 STATE" ...
*
*                       (1) ... that "if insufficient incoming segments are queued to satisfy the request,
*                           queue the request".
*
*                       (2) "Reassemble queued incoming segments into receive buffer and return to user."
*
*                   (d) For the "CLOSE-WAIT STATE ... since the remote side has already sent FIN, RECEIVEs
*                       must be satisfied by the text already on hand, but not yet delivered to the user.
*                       If no text is awaiting delivery, the RECEIVE will get a 'error: connection closing'
*                       response.  Otherwise, any remaining text can be used to satisfy the RECEIVE".
*
*                   (e) (1) For the "CLOSING STATE, LAST-ACK STATE, TIME-WAIT STATE ... return 'error:
*                           connection closing'".
*
*                       (2) Typically, these states will have already received ALL remainining closing
*                           data from the closing remote host.
*
*                           (A) However, in case all receive data from the remote host has NOT yet been
*                               received, application layer receives from these states are permitted until
*                               the TCP connection's sequence receive state is closed & the TCP connection's
*                               application receive queue is empty.
*
*                           (B) If all receive data from the remote host has NOT yet been received but the
*                               application receive queue is currently empty, return application receive
*                               queue empty error(s).
*
*                       (3) Once a TCP connection has closed & ALL receive data has been received by the
*                           application layer :
*
*                           (A) Close the TCP connection;
*                           (B) Return application receive queue closed error.
*$PAGE*
*               (4) (a) RFC #793, Section 3.3 states that :
*
*                       (1) "Every octet of data sent over a TCP connection has a sequence number."
*                       (2) In addition, "SYN and FIN ... control information ... [is] implicitly assign[ed] 
*                           sequence numbers ... [but] is not physically carried in the segment data space".
*
*                           (A) "For sequence number purposes, the SYN is considered to occur before the 
*                                first actual data octet of the segment in which it occurs," ...
*                           (B) "While the FIN is considered to occur after the last actual data octet in 
*                                a segment in which it occurs."
*
*                       (3) "The segment length (SEG.LEN) includes both data and sequence space occupying
*                            controls.
*
*
*                                  -----          ------------------------        Synchronization
*                                    ^            |  Initial SEQ # (SYN) |  <---  Sequence Number
*                                    |            ------------------------        (see Note #4a2A)
*                                    |            |    Data Octet # 1    |  ---
*                                    |            |    Data Octet # 2    |   ^
*                                                 |    Data Octet # 3    |   |
*                              TCP Connection     |           .          |   |       Data Octet
*                                Sequences        |           .          |   |   Sequence Number(s)
*                              (see Note #4a)     |           .          |   |    (see Note #4a1)
*                                                 | Data Octet # (N - 2) |   |
*                                    |            | Data Octet # (N - 1) |   v
*                                    |            | Data Octet #    N    |  ---       Closing
*                                    |            ------------------------        Sequence Number
*                                    v            |  Close SEQ # (FIN)   |  <---  (see Note #4a2B)
*                                  -----          ------------------------
*
*
*                       See also 'NetTCP_TxConnSync()   Note #3'
*                              & 'NetTCP_TxConnClose()  Note #2'.
*
*                   (b) Therefore, since TCP synchronization or close sequence numbers are NOT actual data
*                       sequences or octets that are transmitted or received; segments which include these
*                       TCP control sequence numbers MUST adjust TCP data sequence numbers & TCP segment
*                       lengths by these TCP control sequence numbers.
*
*                       (1) A TCP data segment MUST adjust its data index by the possible synchronization
*                           control sequence.
*
*                           (A) On a received TCP segment's first data read, the segment's base data index 
*                               is NOT offset -- even though for a synchronization segment, this base data
*                               index starts on the sequence number following the synchronization control
*                               sequence.
*
*                           (B) On any additional received TCP segment data reads, the segment's base data 
*                               index MUST be offset by possible synchronization control sequence.
*
*                       (2) TCP connections & TCP data segments MUST advance their sequence numbers & adjust 
*                           their segment lengths by possible TCP control sequences.
*
*                           (A) A TCP connection MUST advance its sequence numbers by :
*
*                               (1) Possible synchronization sequence; but only on the first, initial access
*                                   to a TCP synchronization segment; ...
*                               (2) All accessed data sequence(s);    ...
*                               (3) Possible closing         sequence; which SHOULD only occur once on the
*                                   last access to a TCP closing segment.
*
*                           (B) (1) A received TCP segment MUST advance its sequence numbers by :
*
*                                   (a) Possible synchronization sequence; but only on the first, initial 
*                                       access to a TCP synchronization segment; ...
*                                   (b) All accessed data sequence(s).
*
*                               (2) (a) A received TCP segment MUST adjust its total segment length by :
*
*                                       (1) Possible synchronization sequence; but only on the first, initial 
*                                           access to a TCP synchronization segment; ...
*                                       (2) All accessed data sequence(s).
*
*                                       (3) Possible closing         sequence adjustment MAY be ignored since 
*                                           all effective segment data handling occurs prior to accessing any
*                                           trailing closing sequence.
*
*                                   (b) A received TCP segment MUST adjust its data  segment length ONLY by :
*
*                                       (b) All accessed data sequence(s).
*$PAGE*
*               (5) (a) Stream-type connections receive all data octets in one or more non-distinct packets.  
*                       In other words, the application data is NOT bounded by any specific packet(s); rather,
*                       it is contiguous & sequenced from one packet to the next.
*
*                   (b) Therefore, the TCP connection receive queue is signaled ONLY when data is received for
*                       a connection where data was previously unavailable.
*
*                   (c) Consequently, it is typical -- but NOT absolutely required -- that a single application
*                       task only receive or request to receive application data from a TCP connection.
*
*                   See also 'net_sock.c  NetSock_RxDataHandlerStream()  Note #2'.
*
*               (6) Since pointer arithmetic is based on the specific pointer data type & inherent pointer
*                   data type size, pointer arithmetic operands :
*
*                   (a) MUST be in terms of the specific pointer data type & data type size; ...
*                   (b) SHOULD NOT & in some cases MUST NOT be cast to other data types or data type sizes.
*
*               (7) RFC #793, Section 3.7 'Data Communication : Managing the Window' states that "the window 
*                   sent in each segment indicates the range of sequence numbers the sender of the window 
*                   (the data receiver) is currently prepared to accept.  There is an assumption that this 
*                   is related to the currently available data buffer space available for this connection
*                   ... One strategy would be to ... [update the] information when the window is larger".
*
*                   See also 'NetTCP_RxPktConnHandlerRxQ_Sync()  Note #5',
*                            'NetTCP_RxPktConnHandlerRxQ_Conn()  Note #6',
*                          & 'NetTCP_RxConnWinSizeHandler()      Note #2a'.
*
*               (8) (a) #### Since segments enqueued to a TCP connection's application receive queue have
*                       already been acknowledged to the remote host & since no mechanism exists for a TCP
*                       connection to re-request previously acknowledged segments, any TCP connection whose
*                       application receive queue becomes corrupted MUST be closed to prevent the application
*                       layer from receiving the corrupted data.
*
*                   (b) For any internal errors where the TCP connection's application receive queue is NOT
*                       corrupted, the TCP connection is NOT closed.  Thus, the application layer may try to
*                       re-receive the application data.
*
*                       However, a TCP connection may deadlock due to persistant internal errors -- i.e. the
*                       internal errors prevent the TCP connection from deframing application data from the
*                       application receive queue which also prevents the TCP connection from receiving
*                       additional application data (see Note ####).  Thus, exception handling code in the
*                       application layer SHOULD eventually detect & close any TCP connection deadlocked due
*                       to internal errors.
*********************************************************************************************************
*/
/*$PAGE*/
CPU_INT16U  NetTCP_RxAppData (NET_TCP_CONN_ID   conn_id_tcp,
                              void             *pdata_buf,
                              CPU_INT16U        data_buf_len,
                              CPU_INT16U        flags,
                              NET_ERR          *perr)
{
#if ((NET_CTR_CFG_ERR_EN      == DEF_ENABLED)                    && \
     (CPU_CFG_CRITICAL_METHOD == CPU_CRITICAL_METHOD_STATUS_LOCAL))
    CPU_SR            cpu_sr;
#endif
#if (NET_ERR_CFG_ARG_CHK_DBG_EN == DEF_ENABLED)
    CPU_INT16U        seg_len_close;
    NET_TCP_SEQ_NBR   seq_nbr_cur;
#endif
    CPU_BOOLEAN       block;
    CPU_BOOLEAN       conn_closed;
    CPU_BOOLEAN       q_prevly_empty;
    CPU_BOOLEAN       peek;
    CPU_BOOLEAN       frag_adv;
    NET_TCP_CONN     *pconn;
    NET_BUF          *pbuf_head;
    NET_BUF          *pbuf_seg;
    NET_BUF          *pbuf_seg_prev;
    NET_BUF          *pbuf_seg_next;
    NET_BUF          *pbuf_frag;
    NET_BUF          *pbuf_frag_next;
    NET_BUF_HDR      *pbuf_seg_hdr;
    NET_BUF_HDR      *pbuf_seg_prev_hdr;
    NET_BUF_HDR      *pbuf_seg_next_hdr;
    NET_BUF_HDR      *pbuf_frag_hdr;
    NET_BUF_SIZE      seg_len_avail;
    NET_BUF_SIZE      data_ix_frag;
    NET_BUF_SIZE      data_ix_pkt;
    NET_BUF_SIZE      data_len_pkt;
    CPU_INT16U        data_len_buf_rem;
    CPU_INT16U        data_len_tot;
    CPU_INT16U        seg_len_data;
    CPU_INT16U        seg_len_data_rem;
    CPU_INT16U        seg_len_data_tot;
    CPU_INT16U        seg_len_sync;
    CPU_INT16U        seg_len_sync_init;
    CPU_INT08U       *p_data;
    NET_TCP_SEQ_NBR   seq_nbr_init;
    NET_TCP_SEQ_NBR   seq_nbr_ix;
    NET_ERR           err;



/*$PAGE*/
#if (NET_ERR_CFG_ARG_CHK_DBG_EN == DEF_ENABLED)                 /* -------------- VALIDATE TCP CONN USED -------------- */
   (void)NetTCP_ConnIsUsed(conn_id_tcp, perr);
    if (*perr != NET_TCP_ERR_NONE) {
         return (0);
    }
#endif

                                                                /* ---------------- VALIDATE TCP CONN ----------------- */
    pconn       = &NetTCP_ConnTbl[conn_id_tcp];
    conn_closed =  DEF_NO;

    switch (pconn->ConnState) {
        case NET_TCP_CONN_STATE_FREE:
             NET_CTR_ERR_INC(NetTCP_ErrNotUsedCtr);
            *perr =  NET_TCP_ERR_CONN_NOT_USED;
             return (0);                                        /* Prevent 'break NOT reachable' compiler warning.      */


        case NET_TCP_CONN_STATE_CLOSED:                         /* See Note #3a.                                        */
             NET_CTR_ERR_INC(NetTCP_ErrConnInvalidOpCtr);
            *perr =  NET_TCP_ERR_INVALID_CONN_OP;
             return (0);                                        /* Prevent 'break NOT reachable' compiler warning.      */


        case NET_TCP_CONN_STATE_LISTEN:                         /* See Note #3b.                                        */
        case NET_TCP_CONN_STATE_SYNC_RXD:
        case NET_TCP_CONN_STATE_SYNC_RXD_PASSIVE:
        case NET_TCP_CONN_STATE_SYNC_RXD_ACTIVE:
        case NET_TCP_CONN_STATE_SYNC_TXD:
        case NET_TCP_CONN_STATE_CONN:                           /* See Note #3c.                                        */
        case NET_TCP_CONN_STATE_FIN_WAIT_1:
        case NET_TCP_CONN_STATE_FIN_WAIT_2:
             break;


        case NET_TCP_CONN_STATE_CLOSE_WAIT:                     /* See Note #3d.                                        */
        case NET_TCP_CONN_STATE_CLOSING:                        /* See Note #3e.                                        */
        case NET_TCP_CONN_STATE_TIME_WAIT:
        case NET_TCP_CONN_STATE_LAST_ACK:
        case NET_TCP_CONN_STATE_CLOSING_DATA_AVAIL:             /* See Note #3e3.                                       */
             if (pconn->RxQ_State == NET_TCP_RX_Q_STATE_CONN_CLOSED) {
                 conn_closed = DEF_YES;
             }
             break;


        case NET_TCP_CONN_STATE_NONE:
        default:
             NetTCP_ConnClose((NET_TCP_CONN     *)pconn,
                              (NET_BUF_HDR      *)0,
                              (CPU_BOOLEAN       )DEF_YES,
                              (NET_TCP_CLOSE_CODE)NET_TCP_CONN_CLOSE_ALL);
             NET_CTR_ERR_INC(NetTCP_ErrConnInvalidStateCtr);
            *perr =  NET_TCP_ERR_INVALID_CONN_STATE;
             return (0);                                        /* Prevent 'break NOT reachable' compiler warning.      */
    }



/*$PAGE*/
                                                                /* ------------ WAIT ON TCP CONN APP RX Q ------------- */
    if (pconn->RxQ_App_Head == (NET_BUF *)0) {                  /* If no rx'd data pkts; ...                            */
        if (conn_closed != DEF_NO) {                            /* ... & conn closed  (see Note #3e3),         ...      */
            if (pconn->ConnState == NET_TCP_CONN_STATE_CLOSING_DATA_AVAIL) {
                                                                /* ... close TCP conn (see Note #3e3A)         ...      */
                NetTCP_ConnCloseHandler(pconn, pconn->ConnCloseAppFlag, NET_TCP_CONN_CLOSE_ALL);
            }

           *perr =  NET_TCP_ERR_RX_Q_CLOSED;                    /* ... & rtn rx Q closed err (see Note #3e3B); ...      */
            return (0);
        }

        block = DEF_BIT_IS_SET(flags, NET_TCP_FLAG_RX_BLOCK);
        if (block != DEF_YES) {                                 /* ... & non-blocking rx                       ...      */
           *perr =  NET_TCP_ERR_RX_Q_EMPTY;                     /* ... rtn rx Q empty err.                              */
            return (0);
        }

        NetOS_Unlock();
        NetOS_TCP_RxQ_Wait(conn_id_tcp, perr);
        NetOS_Lock(&err);
        if (  err != NET_OS_ERR_NONE) {
            *perr  = err;                                       /* Rtn err from NetOS_Lock().                           */
             return (0);
        }
        if (*perr != NET_TCP_ERR_NONE) {
             return (0);                                        /* Rtn err from NetOS_TCP_RxQ_Wait().                   */
        }

        if (pconn->RxQ_App_Head == (NET_BUF *)0) {              /* If still NO rx'd data pkts, ...                      */
           *perr =  NET_TCP_ERR_RX_Q_EMPTY;                     /* ... rtn rx Q empty err.                              */
            return (0);
        }

        q_prevly_empty = DEF_YES;

    } else {
        NetOS_TCP_RxQ_Clr(conn_id_tcp, &err);                   /* Clr any possible async rx Q signal.                  */
        q_prevly_empty = DEF_NO;
    }



/*$PAGE*/
                                                                /* ----------- DEFRAME TCP CONN RX APP DATA ----------- */
    pbuf_head         = (NET_BUF       *) pconn->RxQ_App_Head;
    pbuf_seg          = (NET_BUF       *) pbuf_head;
    pbuf_seg_prev     = (NET_BUF       *) 0;
    p_data            = (CPU_INT08U    *) pdata_buf;
    data_len_buf_rem  = (CPU_INT16U     ) data_buf_len;
    data_len_tot      = (CPU_INT16U     ) 0;
#if (NET_ERR_CFG_ARG_CHK_DBG_EN == DEF_ENABLED)
    pbuf_seg_hdr      = (NET_BUF_HDR   *)&pbuf_seg->Hdr;
    seq_nbr_cur       = (NET_TCP_SEQ_NBR) pbuf_seg_hdr->TCP_SeqNbr;
#endif

    while ((pbuf_seg != (NET_BUF *)0) &&                        /* Copy app rx data from TCP conn q'd seg(s).           */
           (data_len_buf_rem     > 0)) {

        pbuf_seg_hdr  = (NET_BUF_HDR *)&pbuf_seg->Hdr;
        pbuf_seg_next = (NET_BUF     *) pbuf_seg_hdr->NextPrimListPtr;
        pbuf_frag     = (NET_BUF     *) pbuf_seg;

#if (NET_ERR_CFG_ARG_CHK_DBG_EN == DEF_ENABLED)
        if (seq_nbr_cur != pbuf_seg_hdr->TCP_SeqNbr) {          /* If next q'd seg's seq nbr NOT consecutive, ...       */
                                                                /* ... close TCP conn (see Note #8a).                   */
            NetTCP_ConnClose((NET_TCP_CONN     *)pconn,
                             (NET_BUF_HDR      *)0,
                             (CPU_BOOLEAN       )DEF_YES,
                             (NET_TCP_CLOSE_CODE)NET_TCP_CONN_CLOSE_ALL);
           *perr =  NET_TCP_ERR_CONN_DATA_INVALID;
            return (0);
        }
#endif
                                                                /* Init seg lens.                                       */
        seg_len_data      = pbuf_seg_hdr->TCP_SegLenData;
        seg_len_data_rem  = seg_len_data;
        seg_len_data_tot  = 0;

        seg_len_sync      = 0;
        seg_len_sync_init = 0;
        if (pbuf_seg_hdr->TCP_SegSync  == DEF_YES) {
            seg_len_sync  = NET_TCP_SEG_LEN_SYNC;
        }
                                                                /* If still init seg len, cfg init sync seg len.        */
        if (pbuf_seg_hdr->TCP_SegLen == pbuf_seg_hdr->TCP_SegLenInit) {
            seg_len_sync_init = seg_len_sync;
        }

#if (NET_ERR_CFG_ARG_CHK_DBG_EN == DEF_ENABLED)
        seg_len_close     = 0;
        if (pbuf_seg_hdr->TCP_SegClose == DEF_YES) {
            seg_len_close = NET_TCP_SEG_LEN_CLOSE;
        }
#endif
                                                                /* Calc start seq nbr ix into seg data (see Note #4b1). */
        seq_nbr_init = (NET_TCP_SEQ_NBR)(pbuf_seg_hdr->TCP_SeqNbrInit + seg_len_sync - seg_len_sync_init);
        seq_nbr_ix   = (NET_TCP_SEQ_NBR)(pbuf_seg_hdr->TCP_SeqNbr     - seq_nbr_init);
        data_ix_frag = (NET_BUF_SIZE   ) seq_nbr_ix;

        frag_adv     =  DEF_YES;

        while ((pbuf_frag != (NET_BUF *)0) &&
               (frag_adv  ==  DEF_YES)) {

            pbuf_frag_hdr  = (NET_BUF_HDR *)&pbuf_frag->Hdr;
                                                                /* While seg's frag data ix >= cur frag data len ...    */
            if (data_ix_frag  >= (NET_BUF_SIZE)pbuf_frag_hdr->DataLen) {
                data_ix_frag  -= (NET_BUF_SIZE)pbuf_frag_hdr->DataLen;
                pbuf_frag_next = (NET_BUF    *)pbuf_frag_hdr->NextBufPtr;
                pbuf_frag      = (NET_BUF    *)pbuf_frag_next;  /* ... adv to next seg frag.                            */

            } else {
                frag_adv       =  DEF_NO;
            }
        }

/*$PAGE*/
        while ((pbuf_frag != (NET_BUF *)0) &&                   /* Copy app rx data from avail seg pkt buf(s).          */
               (data_len_buf_rem      > 0) &&
               (seg_len_data_rem      > 0)) {

            pbuf_frag_hdr  = (NET_BUF_HDR *)&pbuf_frag->Hdr;
            pbuf_frag_next = (NET_BUF     *) pbuf_frag_hdr->NextBufPtr;

            seg_len_avail  =  pbuf_frag_hdr->DataLen - data_ix_frag;
            if (seg_len_avail > (NET_BUF_SIZE)seg_len_data_rem) {    /* If seg frag pkt data len > rem seg len, ...     */
                seg_len_avail = (NET_BUF_SIZE)seg_len_data_rem;      /* ... limit copy to rem seg len.                  */
            }
            if (data_len_buf_rem > seg_len_avail) {             /* If rem data buf len > seg frag pkt data len, ...     */
                data_len_pkt  = (NET_BUF_SIZE)seg_len_avail;    /* ... copy all pkt buf data len.                       */
            } else {
                data_len_pkt  = (NET_BUF_SIZE)data_len_buf_rem; /* Else limit copy to rem data buf len.                 */
            }
                                                                /* Calc ix into seg frag's data.                        */
            data_ix_pkt  = (NET_BUF_SIZE)pbuf_frag_hdr->DataIx + data_ix_frag;
            data_ix_frag =  0;

            NetBuf_DataRd((NET_BUF    *) pbuf_frag,
                          (NET_BUF_SIZE) data_ix_pkt,
                          (NET_BUF_SIZE) data_len_pkt,
                          (CPU_INT08U *) p_data,
                          (NET_ERR    *)&err);
            if ( err != NET_BUF_ERR_NONE) {                     /* See Note #7b.                                        */
               *perr  = NET_TCP_ERR_CONN_FAIL;
                return (0);
            }
                                                                /* Update data ptr & lens.                              */
            p_data           +=             data_len_pkt;       /* MUST NOT cast ptr operand (see Note #6b).            */
            data_len_tot     += (CPU_INT16U)data_len_pkt;
            data_len_buf_rem -= (CPU_INT16U)data_len_pkt;
            seg_len_data_tot += (CPU_INT16U)data_len_pkt;
            seg_len_data_rem -= (CPU_INT16U)data_len_pkt;

            pbuf_frag         =  pbuf_frag_next;
        }

        if (data_len_buf_rem > 0) {                             /* If rem data buf len > 0, adv to next q'd seg.        */
            pbuf_seg_prev = pbuf_seg;
            pbuf_seg      = pbuf_seg_next;

#if (NET_ERR_CFG_ARG_CHK_DBG_EN == DEF_ENABLED)
            if (seg_len_data_tot != seg_len_data) {             /* If calc'd seg data len != actual seg data len, ...   */
                                                                /* ... close TCP conn (see Note #8a).                   */
                NetTCP_ConnClose((NET_TCP_CONN     *)pconn,
                                 (NET_BUF_HDR      *)0,
                                 (CPU_BOOLEAN       )DEF_YES,
                                 (NET_TCP_CLOSE_CODE)NET_TCP_CONN_CLOSE_ALL);
               *perr =  NET_TCP_ERR_CONN_DATA_INVALID;
                return (0);
            }
                                                                /* Adv seq nbr by cur seg's :                ...        */
            seq_nbr_cur += (NET_TCP_SEQ_NBR)seg_len_sync_init;  /* ... init sync  seg len (see Note #4b2A1), ...        */
            seq_nbr_cur += (NET_TCP_SEQ_NBR)seg_len_data;       /* ...      data  seg len (see Note #4b2A2), ...        */
            seq_nbr_cur += (NET_TCP_SEQ_NBR)seg_len_close;      /* ...    & close seg len (see Note #4b2A3).            */
#endif
        }
    }



/*$PAGE*/
                                                                    /* ----------- UPDATE TCP CONN APP RX Q ----------- */
    peek = DEF_BIT_IS_SET(flags, NET_TCP_FLAG_RX_DATA_PEEK);
    if (peek == DEF_YES) {                                          /* If peek opt req'd                      ...       */
        if (q_prevly_empty == DEF_YES) {                            /* ... & TCP conn app rx Q prev'ly empty, ...       */
            NetOS_TCP_RxQ_Signal(conn_id_tcp, &err);                /* ...     signal app rx Q                ...       */
                                                                    /* ... to negate non-consuming peek (see Note #5b). */
            if (err != NET_TCP_ERR_NONE) {                          /* If app rx Q signal failed, ...                   */
                peek = DEF_NO;                                      /* ... consume pkt buf(s).                          */
            }
        }
    }

    if (peek != DEF_YES) {                                          /* If peek opt NOT req'd, unlink ALL seg pkt buf(s) */
                                                                    /* .. whose data was entirely consumed.             */
        if (pbuf_seg != (NET_BUF *)0) {                             /* If TCP conn app rx Q NOT empty after data rd(s)  */
            if (seg_len_data_rem > 0) {                             /* .. & cur seg's rem data len > 0;              .. */
                pbuf_seg_hdr->PrevPrimListPtr = (void    *)0;       /* ..   unlink from prev q'd seg(s),             .. */
                pconn->RxQ_App_Head           = (NET_BUF *)pbuf_seg;/* ..   set new TCP conn app rx Q head,          .. */
                                                                    /* .. & update seg's seq nbr  (see Note #4b2B1)  .. */
                pbuf_seg_hdr->TCP_SeqNbr     += (CPU_INT32U)(seg_len_data_tot + seg_len_sync_init);
                                                                    /* ..        & seg's seg lens (see Note #4b2B2).    */
                pbuf_seg_hdr->TCP_SegLen     -= (CPU_INT16U)(seg_len_data_tot + seg_len_sync_init);
                pbuf_seg_hdr->TCP_SegLenData -= (CPU_INT16U) seg_len_data_tot;

                if (pbuf_seg_prev != (NET_BUF *)0) {                /* If prev q'd seg(s) avail, ...                    */
                    pbuf_seg_prev_hdr                  = &pbuf_seg_prev->Hdr;
                    pbuf_seg_prev_hdr->NextPrimListPtr = (void *)0; /* ... unlink from app rx Q  ...                    */
                    NetTCP_RxPktFree(pbuf_head);                    /* ... & free ALL rd seg pkt buf(s).                */
                }

            } else {                                                /* Else if cur seg's rem data len = 0     ...       */
                if (pbuf_seg_next != (NET_BUF *)0) {                /* ... &    rem rx q'd seg(s) avail,      ...       */
                                                                    /* ... unlink cur seg from rem q'd seg(s) ...       */
                    pbuf_seg_next_hdr                  = &pbuf_seg_next->Hdr;
                    pbuf_seg_next_hdr->PrevPrimListPtr = (void    *)0;
                    pbuf_seg_hdr->NextPrimListPtr      = (void    *)0;
                                                                    /* ... set new TCP conn app rx Q head;    ...       */
                    pconn->RxQ_App_Head                = (NET_BUF *)pbuf_seg_next;


                } else {                                            /* ... & NO rem rx q'd seg(s) avail,      ...       */
                                                                    /* ... unlink  ALL q'd seg(s);            ...       */
                    pconn->RxQ_App_Head                = (NET_BUF *)0;
                    pconn->RxQ_App_Tail                = (NET_BUF *)0;
                }

                NetTCP_RxPktFree(pbuf_head);                        /* ... & free rd  seg pkt buf(s) from app rx Q.     */
            }

        } else {                                                    /* Else clr app rx Q ...                            */
            pconn->RxQ_App_Head = (NET_BUF *)0;
            pconn->RxQ_App_Tail = (NET_BUF *)0;

            NetTCP_RxPktFree(pbuf_head);                            /* ... & free ALL seg pkt buf(s) from app rx Q.     */
        }


                                                                    /* --------- UPDATE TCP CONN RX WIN SIZE ---------- */
                                                                    /* Inc TCP conn's rx win size (see Note #7).        */
        NetTCP_RxConnWinSizeHandler((NET_TCP_CONN   *)pconn,
                                    (NET_BUF_HDR    *)0,
                                    (NET_TCP_WIN_SIZE)data_len_tot,
                                    (NET_TCP_WIN_CODE)NET_TCP_CONN_RX_WIN_INC);
    }



   *perr =  NET_TCP_ERR_NONE;

    return (data_len_tot);
}


/*$PAGE*/
/*
*********************************************************************************************************
*                                         NetTCP_TxConnReq()
*
* Description : (1) Transmit TCP connection request :
*
*                   (a) Configure TCP connections' IP parameters
*                   (b) Transmit  TCP connection request
*                   (c) Update    TCP connection state
*
*
* Argument(s) : conn_id_tcp     Handle identifier of TCP connection to transmit connection request.
*
*               TOS             Specific TOS to transmit TCP/IP packet
*                                   (see 'net_ip.h  IP HEADER TYPE OF SERVICE (TOS) DEFINES').
*
*               TTL             Specific TTL to transmit TCP/IP packet (see RFC #1122, Section 3.2.1.7) :
*
*                                   NET_IP_HDR_TTL_MIN        1     minimum TTL transmit value
*                                   NET_IP_HDR_TTL_MAX      255     maximum TTL transmit value
*                                   NET_IP_HDR_TTL_DFLT             default TTL transmit value
*                                   NET_IP_HDR_TTL_NONE       0     replace with default TTL
*
*               flags_ip        Flags to select IP  transmit options; bit-field flags logically OR'd :
*
*                                   NET_IP_FLAG_NONE                No  IP transmit flags selected.
*                                   NET_IP_FLAG_TX_DONT_FRAG        Set IP 'Don't Frag' flag.
*
*               popts_ip        Pointer to one or more IP  options configuration data structures :
*
*                                   NULL                            NO IP transmit options configuration.
*                                   NET_IP_OPT_CFG_ROUTE_TS         Route &/or Internet Timestamp options
*                                                                       configuration.
*                                   NET_IP_OPT_CFG_SECURITY         Security options configuration
*                                                                       (see 'net_ip.c  Note #1f').
*
*               perr            Pointer to variable that will receive the return error code from this function :
*
*                                   NET_TCP_ERR_CONN_NOT_USED           TCP connection NOT currently used.
*                                   NET_TCP_ERR_INVALID_CONN_STATE      Invalid TCP connection state.
*                                   NET_TCP_ERR_INVALID_CONN_OP         Invalid TCP connection operation.
*
*                                                                       ---- RETURNED BY NetTCP_ConnIsUsed() : -----
*                                   NET_ERR_INIT_INCOMPLETE             Network initialization NOT complete.
*                                   NET_TCP_ERR_INVALID_CONN            Invalid TCP connection number.
*
*                                                                       ---- RETURNED BY NetTCP_TxConnSync() : -----
*                                   NET_TCP_ERR_NONE                    TCP connection request successfully
*                                                                           transmitted.
*                                   NET_TCP_ERR_CONN_FAIL               TCP connection operation(s) failed.
*                                   NET_TCP_ERR_CONN_FAULT              TCP connection fault; connection(s) aborted.
*                                   NET_TCP_ERR_NONE_AVAIL              Resources NOT available.
*                                   NET_CONN_ERR_INVALID_FAMILY         Invalid     connection family.
*                                   NET_CONN_ERR_INVALID_ADDR           Invalid TCP connection address.
*                                   NET_CONN_ERR_INVALID_ADDR_LEN       Invalid TCP connection address length.
*                                   NET_TCP_ERR_TX                      TCP transmit error.
*                                   NET_ERR_TX                              Transmit error.
*
* Return(s)   : none.
*
* Caller(s)   : NetSock_ConnHandlerStream().
*
*               This function is an INTERNAL network protocol suite function & SHOULD NOT be called by 
*               application function(s).
*
* Note(s)     : (2) NetTCP_TxConnReq() blocked until network initialization completes.
*
*                   See 'NetTCP_ConnIsUsed()  Note #1'.
*
*               (3) On ANY errors, return error to TCP connection caller & allow caller to retry or close
*                   connection(s) but do NOT close TCP connection.
*
*               (4) #### IP options currently NOT implemented.
*********************************************************************************************************
*/
/*$PAGE*/
void  NetTCP_TxConnReq (NET_TCP_CONN_ID   conn_id_tcp,
                        NET_IP_TOS        TOS,
                        NET_IP_TTL        TTL,
                        CPU_INT16U        flags_ip,
                        void             *popts_ip,
                        NET_ERR          *perr)
{
#if ((NET_ERR_CFG_ARG_CHK_DBG_EN == DEF_ENABLED)                    && \
     (NET_CTR_CFG_ERR_EN         == DEF_ENABLED)                    && \
     (CPU_CFG_CRITICAL_METHOD    == CPU_CRITICAL_METHOD_STATUS_LOCAL))
    CPU_SR         cpu_sr;
#endif
    NET_TCP_CONN  *pconn;


#if (NET_ERR_CFG_ARG_CHK_DBG_EN == DEF_ENABLED)                 /* -------------- VALIDATE TCP CONN USED -------------- */
   (void)NetTCP_ConnIsUsed(conn_id_tcp, perr);
    if (*perr != NET_TCP_ERR_NONE) {
         return;
    }
#endif

    pconn = &NetTCP_ConnTbl[conn_id_tcp];

#if (NET_ERR_CFG_ARG_CHK_DBG_EN == DEF_ENABLED)                 /* ------------- VALIDATE TCP CONN STATE -------------- */
    switch (pconn->ConnState) {
        case NET_TCP_CONN_STATE_FREE:
             NET_CTR_ERR_INC(NetTCP_ErrNotUsedCtr);
            *perr = NET_TCP_ERR_CONN_NOT_USED;
             return;                                            /* Prevent 'break NOT reachable' compiler warning.      */


        case NET_TCP_CONN_STATE_CLOSED:
        case NET_TCP_CONN_STATE_LISTEN:
             break;


        case NET_TCP_CONN_STATE_SYNC_RXD:
        case NET_TCP_CONN_STATE_SYNC_RXD_PASSIVE:
        case NET_TCP_CONN_STATE_SYNC_RXD_ACTIVE:
        case NET_TCP_CONN_STATE_SYNC_TXD:
        case NET_TCP_CONN_STATE_CONN:
        case NET_TCP_CONN_STATE_FIN_WAIT_1:
        case NET_TCP_CONN_STATE_FIN_WAIT_2:
        case NET_TCP_CONN_STATE_CLOSING:
        case NET_TCP_CONN_STATE_TIME_WAIT:
        case NET_TCP_CONN_STATE_CLOSE_WAIT:
        case NET_TCP_CONN_STATE_LAST_ACK:
        case NET_TCP_CONN_STATE_CLOSING_DATA_AVAIL:
             NET_CTR_ERR_INC(NetTCP_ErrConnInvalidOpCtr);
            *perr = NET_TCP_ERR_INVALID_CONN_OP;
             return;                                            /* Prevent 'break NOT reachable' compiler warning.      */


        case NET_TCP_CONN_STATE_NONE:
        default:
             NetTCP_ConnClose((NET_TCP_CONN     *)pconn,
                              (NET_BUF_HDR      *)0,
                              (CPU_BOOLEAN       )DEF_YES,
                              (NET_TCP_CLOSE_CODE)NET_TCP_CONN_CLOSE_CONN_ALL);
             NET_CTR_ERR_INC(NetTCP_ErrConnInvalidStateCtr);
            *perr = NET_TCP_ERR_INVALID_CONN_STATE;
             return;                                            /* Prevent 'break NOT reachable' compiler warning.      */
    }
#endif


                                                                /* -------------- CFG TCP CONN IP PARAMS -------------- */
    pconn->TxIP_TOS   = TOS;
    pconn->TxIP_TTL   = TTL;
    pconn->TxIP_Flags = flags_ip;
   (void)&popts_ip;                                             /* Prevent compiler warning (see Note #4).              */


                                                                /* ----------------- TX TCP CONN REQ ------------------ */
    NetTCP_TxConnSync((NET_TCP_CONN *)pconn,
                      (NET_BUF_HDR  *)0,
                      (NET_ERR      *)perr);
    if (*perr != NET_TCP_ERR_NONE) {                            /* See Note #3.                                         */
         return;
    }


                                                                /* -------------- UPDATE TCP CONN STATE --------------- */
    pconn->ConnState = NET_TCP_CONN_STATE_SYNC_TXD;

   *perr             = NET_TCP_ERR_NONE;
}


/*$PAGE*/
/*
*********************************************************************************************************
*                                       NetTCP_TxConnAppData()
*
* Description : (1) Prepare & transmit data from Application layer(s) via TCP connection :
*
*                   (a) Validate application data
*
*                   (b) Transmit application data via TCP Transmit :
*                       (1) Validate TCP connection
*                       (2) Wait on  TCP connection transmit queue
*                       (3) Prepare  TCP data segment(s) :
*                           (A) TCP segment addresses
*                           (B) Prepare application data :
*                               (1) Get buffer(s) for application data
*                               (2) Copy application data into TCP packet buffer(s)
*                               (3) Update TCP segment data controls
*                               (4) Update application data controls
*                       (4) Update TCP connection transmit window
*
*                   (c) Update TCP connection :
*                       (1) Append TCP transmit segment(s) to TCP connection transmit queue
*                       (2) Update TCP connection sequence number(s)
*
*                   (d) Transmit TCP data segment(s) via TCP Transmit
*
*
* Argument(s) : conn_id_tcp     Handle identifier of connection to transmit application data.
*
*               p_data          Pointer to application data.
*               ------          Argument validated in NetSock_TxDataHandlerStream().
*
*               data_len        Length  of application data (in octets) [see Note #5].
*               --------        Argument validated in NetSock_TxDataHandlerStream().
*
*               flags           Flags to select transmit options; bit-field flags logically OR'd :
*               -----
*                                   NET_TCP_FLAG_NONE               No       TCP transmit flags selected.
*                                   NET_TCP_FLAG_TX_BLOCK           Transmit TCP application data with blocking,
*                                                                       if flag set; without blocking, if clear.
*
*                               Argument validated in NetSock_TxDataHandlerStream().
*
*               perr        Pointer to variable that will receive the return error code from this function :
*
*                               NET_TCP_ERR_NONE                    Application data successfully prepared &
*                                                                       transmitted via TCP layer.
*                               NET_TCP_ERR_NULL_PTR                Argument 'p_data'   passed a NULL pointer.
*                               NET_TCP_ERR_INVALID_DATA_SIZE       Argument 'data_len' passed an invalid size.
*                               NET_TCP_ERR_INVALID_CONN_STATE      Invalid TCP connection state.
*                               NET_TCP_ERR_INVALID_CONN_OP         Invalid TCP connection operation.
*                               NET_TCP_ERR_CONN_NOT_USED           TCP connection NOT currently used.
*                               NET_TCP_ERR_CONN_FAULT              TCP connection fault; connection(s) aborted.
*                               NET_TCP_ERR_CONN_DATA_INVALID       TCP connection application transmit queue contains
*                                                                       invalid or improperly sequenced data.
*                               NET_TCP_ERR_TX_Q_FULL               TCP connection transmit queue full.
*                               NET_TCP_ERR_TX_Q_SUSPEND            TCP connection transmit queue temporarily suspended.
*                               NET_TCP_ERR_NONE_AVAIL              Resources NOT available.
*
*                                                                   -------- RETURNED BY NetTCP_ConnIsUsed() : ---------
*                               NET_ERR_INIT_INCOMPLETE             Network initialization NOT complete.
*                               NET_TCP_ERR_INVALID_CONN            Invalid TCP connection number.
*
*                                                                   -------- RETURNED BY NetOS_TCP_TxQ_Wait() : --------
*                               NET_TCP_ERR_TX_Q_SIGNAL_ABORT       TCP connection transmit queue signal aborted;
*                                                                       TCP connection closed/aborted.
*                               NET_TCP_ERR_TX_Q_SIGNAL_FAULT       TCP connection transmit queue signal fault.
*
*                                                                   --------- RETURNED BY NetTCP_TxConnTxQ() : ---------
*                               NET_TCP_ERR_CONN_CLOSE              TCP connection closed.
*                               NET_TCP_ERR_CONN_ACK_NONE           TCP connection acknowledgement NOT requested.
*                               NET_TCP_ERR_CONN_ACK_DLYD           TCP connection acknowledgement transmit delayed.
*                               NET_TCP_ERR_CONN_ACK_PREVLY_TXD     TCP connection acknowledgement previously
*                                                                       transmitted for segment.
*                               NET_TCP_ERR_CONN_ACK_INVALID        TCP connection acknowledgement NOT valid for
*                                                                       current TCP connection state.
*                               NET_TCP_ERR_INVALID_LEN_SEG         Invalid TCP sequence-segment length.
*
*                               NET_CONN_ERR_INVALID_FAMILY         Invalid     connection family.
*                               NET_CONN_ERR_INVALID_ADDR           Invalid TCP connection address.
*                               NET_CONN_ERR_INVALID_ADDR_LEN       Invalid TCP connection address length.
*
*                               NET_TCP_ERR_TX                      TCP transmit error.
*                               NET_ERR_TX                              Transmit error.
*
*                                                                   ------------ RETURNED BY NetOS_Lock() : ------------
*                               NET_OS_ERR_LOCK                     Network access NOT acquired.
*
* Return(s)   : Number of data octets transmitted, if NO errors.
*
*               0,                                 otherwise.
*
* Caller(s)   : NetSock_TxDataHandlerStream().
*
*               This function is an INTERNAL network protocol suite function & SHOULD NOT be called by 
*               application function(s).
*$PAGE*
* Note(s)     : (2) NetTCP_TxConnAppData() blocked until network initialization completes.
*
*                   See 'NetTCP_ConnIsUsed()  Note #1'.
*
*               (3) RFC #793, Section 3.9 'Event Processing : SEND Call' specifies how to handle transmit
*                   data requests from the application layer :
*
*                   (a) For the "CLOSED STATE ... return 'error: connection does not exist'".
*
*                   (b) For the "LISTEN STATE" ...
*
*                       (1) "If the foreign socket is specified, then" ...
*
*                           (A) "Change the connection from passive to active," ...
*                           (B) "select an ISS"                                 ...
*                           (C) "Send a SYN segment,"                           ...
*                           (D) "Set" ...
*                               (1) "SND.UNA to ISS," ...
*                               (2) "SND.NXT to ISS+1."
*                           (E) "Enter SYN-SENT state."
*                           (F) "Data associated with SEND may be" ...
*                               (1) "sent with SYN segment"        ...
*                               (2) (a) "or queued for transmission after entering ESTABLISHED state."
*                                   (b) "If there is no room to queue the request, respond with 'error:
*                                        insufficient resources'."
*
*                       (2) "If Foreign [sic] socket was not specified, then return 'error: foreign socket
*                            unspecified'."
*
*                           (A) #### NOT yet implemented; see also 
*                                   'net_sock.c  NetSock_TxDataHandlerStream()  Note #2aA'.
*
*                   (c) For the "SYN-SENT STATE, SYN-RECEIVED STATE" ...
*
*                       (1) "Queue the data for transmission after entering ESTABLISHED state."
*                       (2) "If no space to queue, respond with 'error: insufficient resources'."
*
*                   (d) For the "ESTABLISHED STATE, CLOSE-WAIT STATE" ...
*
*                       (1) (A) "Segmentize the buffer"                          ...
*                           (B) "and send it with a piggybacked ackknowledgment" ...
*                               (1) "(acknowledgment value = RCV.NXT)"
*                       (2) "If there is no insufficient space to remember this buffer, simply return
*                           'error: insufficient resources'."
*
*                   (e) For the "FIN-WAIT-1 STATE, FIN-WAIT-2 STATE, CLOSING STATE, LAST-ACK STATE,
*                       TIME-WAIT STATE" ...
*
*                       (1) "return 'error: connection closing'" ...
*                       (2) "and do not service request."
*$PAGE*
*               (4) TCP segments with transmit data are sequenced into the TCP connection's transmit
*                   queue to await transmission at the appropriate time(s) [see 'NetTCP_TxConnTxQ()
*                   Note #1b'].
*
*                   (a) Transmit TCP segments are inserted into a doubly-linked Transmit Queue, ordered
*                       consecutively by sequence number(s) [see also Note #4b].
*
*                       (1) 'TxQ_Head' points to the head of the Transmit Queue;
*                           'TxQ_Tail' points to the tail of the Transmit Queue.
*
*                       (2) Segment buffers' 'PrevPrimListPtr' & 'NextPrimListPtr'  doubly-link each
*                           segment to form the Transmit Queue.
*
*                   (b) Transmit data is packetized into TCP segments in sequence-order.  Therefore, new
*                       transmit segments are sequenced after previously packetized segments starting at
*                       the tail of the Transmit Queue.
*
*                   (c) Segments at the head of the Transmit Queue are available & ready to be transmitted
*                       via the Internet Transmit Layer.
*
*
*                                      |                                               |
*                                      |<------- TCP Connection Transmit Queue ------->|
*                                      |                (see Note #4)                  |
*
*                                  Segments Ready                           Segments Sequenced
*                                   to Transmit                             into Transmit Queue
*                                  start at head                             starting at tail
*                                  (see Note #4c)                             (see Note #4b)
*
*                                         |        NextPrimListPtr                  |
*                                         |        (see Note #4a2)                  |
*                                         v                   |                     v
*                                                             |
*                       Head of        -------       -------  v    -------       -------   (see Note #4a1)
*                       Transmit  ---->|     |------>|     |------>|     |------>|     |
*                        Queue         |     |       |     |       |     |       |     |       Tail of
*                                      |     |<------|     |<------|     |<------|     |<----  Transmit
*                   (see Note #4a1)    |     |       |     |  ^    |     |       |     |        Queue
*                                      |     |       |     |  |    |     |       |     |
*                                      -------       -------  |    -------       -------
*                                                             |
*                                                  PrevPrimListPtr
*                                                  (see Note #4a2)
*
*$PAGE*
*               (5) 'data_len' of 0 octets NOT allowed.
*
*               (6) Certain network connections MUST periodically suspend network transmit(s) to handle
*                   network receive packet(s).  To protect TCP connections from transmit corruption while
*                   suspended, ALL TCP data transmits & TCP transmit queue handling MUST be blocked for
*                   suspended connections until the connection is no longer suspended.
*
*                   See also 'NetTCP_TxConnTxQ()  Note #10b2A2'.
*
*               (7) (a) RFC #793, Section 3.8 'Interfaces : User/TCP Interface : TCP User Commands : Send'
*                       states that :
*
*                       (1) "If the PUSH flag is set, the data must be transmitted promptly to the receiver,
*                            and the PUSH bit will be set in the last TCP segment created from the buffer."
*
*                       (2) "If the PUSH flag is not set, the data may be combined with data from subsequent
*                            SENDs for transmission efficiency."
*
*                   (b) RFC #1122, Section 4.2.2.2 states that :
*
*                       (1) "When an application issues a series of SEND calls without setting the PUSH
*                            flag, the TCP MAY aggregate the data internally without sending it."
*
*                       (2) "The PSH bit is not a record marker and is independent of segment boundaries.
*                            The transmitter SHOULD collapse successive PSH bits when it packetizes data,
*                            to send the largest possible segment.
*
*                       (3) (A) "A TCP MAY implement PUSH flags on SEND calls."
*
*                           (B) (1) "If PUSH flags are not implemented, then the sending TCP: ...
*
*                                   (a) must not buffer data indefinitely, and ...
*                                   (b) MUST set the PSH bit in the last buffered segment (i.e., when
*                                       there is no more queued data to be sent)."
*
*                                       (1) However, NO RFC specifies whether the PUSH bit should be
*                                           set ONLY in the last buffered segment.  Therefore, is is
*                                           assumed that the PUSH bit MAY be set in the last buffered
*                                           segment of each call to SEND.
*
*                               (2) "When the PUSH flag is not implemented on SEND calls, i.e., when
*                                    the application/TCP interface uses a pure streaming model,
*                                    responsibility for aggregating any tiny data fragments to form
*                                    reasonable sized segments is partially borne by the application
*                                    layer."
*
*                       (4) (A) "An application program is logically required to set the PUSH flag in a
*                                SEND call whenever it needs to force delivery of the data to avoid a
*                                communication deadlock.  However, a TCP SHOULD send a maximum-sized
*                                segment whenever possible, to improve performance."
*
*                           (B) "Generally, an interactive application protocol must set the PUSH flag
*                                at least in the last SEND call in each command or response sequence."
*
*               (8) Since pointer arithmetic is based on the specific pointer data type & inherent pointer
*                   data type size, pointer arithmetic operands :
*
*                   (a) MUST be in terms of the specific pointer data type & data type size; ...
*                   (b) SHOULD NOT & in some cases MUST NOT be cast to other data types or data type sizes.
*
*               (9) Network buffers allocated for TCP connection transmit SHOULD be fully used even if
*                   the TCP connection's configured transmit window is zero.
*
*                   See also 'NetTCP_TxConnWinSizeHandlerCfgd()  Note #2'.
*
*              (10) (a) Since segments enqueued to a TCP connection's transmit queue have already been
*                       reported as transmitted to the application & since no mechanism exists for a TCP
*                       connection to re-request previously transmitted data, any TCP connection whose
*                       transmit queue becomes corrupted MUST be closed to force the application layer to
*                       abort &/or recover from the corrupted data.
*
*                   (b) For any internal errors where the TCP connection's transmit queue is NOT corrupted,
*                       the TCP connection is NOT closed.  Thus, the application layer may try to re-transmit
*                       the application data.
*
*                   (c) On ANY transmit error, any remaining application data transmit is immediately aborted.
*
*                   See also 'NetTCP_TxConnTxQ()    Note #12'.
*                          & 'NetTCP_TxConnReTxQ()  Note #11'.
*********************************************************************************************************
*/
/*$PAGE*/
CPU_INT16U  NetTCP_TxConnAppData (NET_TCP_CONN_ID   conn_id_tcp,
                                  void             *p_data,
                                  CPU_INT16U        data_len,
                                  CPU_INT16U        flags,
                                  NET_ERR          *perr)
{
#if ((NET_CTR_CFG_ERR_EN      == DEF_ENABLED)                    && \
     (CPU_CFG_CRITICAL_METHOD == CPU_CRITICAL_METHOD_STATUS_LOCAL))
    CPU_SR             cpu_sr;
#endif
    NET_TCP_CONN      *pconn;
    NET_IP_ADDR        src_addr;
    NET_IP_ADDR        dest_addr;
    NET_TCP_PORT_NBR   src_port;
    NET_TCP_PORT_NBR   dest_port;
    NET_BUF           *pbuf;
    NET_BUF           *pbuf_head;
    NET_BUF           *pbuf_tail;
    NET_BUF           *pbuf_q_tail;
    NET_BUF_HDR       *pbuf_hdr;
    NET_BUF_HDR       *pbuf_hdr_head;
    NET_BUF_HDR       *pbuf_hdr_tail;
    NET_BUF_HDR       *pbuf_hdr_q_tail;
    NET_BUF_SIZE       buf_size_max;
    NET_BUF_SIZE       buf_size_max_data;
    NET_BUF_SIZE       buf_size_max_tail;
    NET_BUF_SIZE       buf_size_max_tail_data;
    NET_BUF_SIZE       data_ix_pkt;
    NET_BUF_SIZE       data_ix_pkt_tail;
    NET_BUF_SIZE       data_len_pkt_tail;
    NET_BUF_SIZE       data_len_pkt_rem;
    NET_BUF_SIZE       data_len_pkt;
    NET_BUF_SIZE       data_len_mss;
    CPU_INT16U         data_len_rem;
    CPU_INT16U         data_len_tot;
    CPU_INT16U         flags_tcp;
    CPU_INT08U        *p_data_pkt;
    CPU_BOOLEAN        tx_q_append;
    CPU_BOOLEAN        tx_data;
    CPU_BOOLEAN        tx_err;
    CPU_BOOLEAN        block;
    NET_TCP_SEQ_NBR    seq_nbr;
    NET_ERR            err;



#if (NET_ERR_CFG_ARG_CHK_DBG_EN == DEF_ENABLED)
                                                                /* ---------------- VALIDATE APP DATA ----------------- */
    if (p_data == (void *)0) {
       *perr =  NET_TCP_ERR_NULL_PTR;
        return (0);
    }
    if (data_len < 1) {                                         /* Validate data len (see Note #5).                     */
        NET_CTR_ERR_INC(NetTCP_ErrTxInvalidSizeCtr);
       *perr =  NET_TCP_ERR_INVALID_DATA_SIZE;
        return (0);
    }

                                                                /* -------------- VALIDATE TCP CONN USED -------------- */
   (void)NetTCP_ConnIsUsed(conn_id_tcp, perr);
    if (*perr != NET_TCP_ERR_NONE) {
         return (0);
    }
#endif


/*$PAGE*/
                                                                /* ---------------- VALIDATE TCP CONN ----------------- */
    pconn = &NetTCP_ConnTbl[conn_id_tcp];

    switch (pconn->ConnState) {                                 /* Validate conn state.                                 */
        case NET_TCP_CONN_STATE_FREE:
             NET_CTR_ERR_INC(NetTCP_ErrNotUsedCtr);
            *perr =  NET_TCP_ERR_CONN_NOT_USED;
             return (0);                                        /* Prevent 'break NOT reachable' compiler warning.      */


        case NET_TCP_CONN_STATE_CLOSED:                         /* See Note #3a.                                        */
             NET_CTR_ERR_INC(NetTCP_ErrConnInvalidOpCtr);
            *perr =  NET_TCP_ERR_INVALID_CONN_OP;
             return (0);                                        /* Prevent 'break NOT reachable' compiler warning.      */


        case NET_TCP_CONN_STATE_LISTEN:                         /* See Note #3b.                                        */
                                                                /* #### NOT yet implemented (see Note #3bA).            */
            *perr =  NET_TCP_ERR_INVALID_CONN_OP;
             return (0);                                        /* Prevent 'break NOT reachable' compiler warning.      */


        case NET_TCP_CONN_STATE_SYNC_RXD:                       /* See Note #3c.                                        */
        case NET_TCP_CONN_STATE_SYNC_RXD_PASSIVE:
        case NET_TCP_CONN_STATE_SYNC_RXD_ACTIVE:
        case NET_TCP_CONN_STATE_SYNC_TXD:
             tx_data = DEF_NO;
             break;


        case NET_TCP_CONN_STATE_CONN:                           /* See Note #3d.                                        */
        case NET_TCP_CONN_STATE_CLOSE_WAIT:
             tx_data = DEF_YES;
             break;


        case NET_TCP_CONN_STATE_FIN_WAIT_1:                     /* See Note #3e.                                        */
        case NET_TCP_CONN_STATE_FIN_WAIT_2:
        case NET_TCP_CONN_STATE_CLOSING:
        case NET_TCP_CONN_STATE_TIME_WAIT:
        case NET_TCP_CONN_STATE_LAST_ACK:
        case NET_TCP_CONN_STATE_CLOSING_DATA_AVAIL:
             NET_CTR_ERR_INC(NetTCP_ErrConnInvalidOpCtr);
            *perr =  NET_TCP_ERR_INVALID_CONN_OP;
             return (0);                                        /* Prevent 'break NOT reachable' compiler warning.      */


        case NET_TCP_CONN_STATE_NONE:
        default:
             NetTCP_ConnClose((NET_TCP_CONN     *)pconn,
                              (NET_BUF_HDR      *)0,
                              (CPU_BOOLEAN       )DEF_YES,
                              (NET_TCP_CLOSE_CODE)NET_TCP_CONN_CLOSE_ALL);
             NET_CTR_ERR_INC(NetTCP_ErrConnInvalidStateCtr);
            *perr =  NET_TCP_ERR_INVALID_CONN_STATE;
             return (0);                                        /* Prevent 'break NOT reachable' compiler warning.      */
    }


    switch (pconn->TxQ_State) {                                 /* Validate tx Q state.                                 */
        case NET_TCP_TX_Q_STATE_CONN:
        case NET_TCP_TX_Q_STATE_CONN_CLOSING:
             break;


        case NET_TCP_TX_Q_STATE_CONN_SUSPEND:                   /* See Note #6.                                         */
            *perr =  NET_TCP_ERR_TX_Q_SUSPEND;
             return (0);                                        /* Prevent 'break NOT reachable' compiler warning.      */


        case NET_TCP_TX_Q_STATE_NONE:
        case NET_TCP_TX_Q_STATE_CLOSED:
        case NET_TCP_TX_Q_STATE_CONN_CLOSED:
        default:
            *perr =  NET_TCP_ERR_INVALID_CONN_STATE;
             return (0);                                        /* Prevent 'break NOT reachable' compiler warning.      */
    }


/*$PAGE*/
                                                                /* -------------- WAIT ON TCP CONN TX Q --------------- */
    if (tx_data == DEF_YES) {                                   /* If tx rdy,                    ...                    */
        if (data_len < 1) {                                     /* ... but  NO tx data avail,    ...                    */
                                                                /* ... tx q'd data OR immed ack; ...                    */
            NetTCP_TxConnTxQ((NET_TCP_CONN     *)pconn,
                             (NET_BUF_HDR      *)0,
                             (NET_TCP_ACK_CODE  )NET_TCP_CONN_TX_ACK_IMMED,
                             (CPU_BOOLEAN       )DEF_NO,
                             (NET_TCP_CLOSE_CODE)NET_TCP_CONN_CLOSE_ALL,
                             (NET_ERR          *)perr);
            return (0);
        }
                                                                /* ... Else if tx data avail,    ...                    */
        if (pconn->TxWinSizeCfgdRem < 1) {                      /* ... but tx Q full             ...                    */
            block = DEF_BIT_IS_SET(flags, NET_TCP_FLAG_TX_BLOCK);
            if (block != DEF_YES) {                             /* ... & non-blocking tx,        ...                    */
               *perr =  NET_TCP_ERR_TX_Q_FULL;                  /* ... rtn tx Q full err.                               */
                return (0);
            }

            NetOS_Unlock();
            NetOS_TCP_TxQ_Wait(conn_id_tcp, perr);
            NetOS_Lock(&err);
            if (  err != NET_OS_ERR_NONE) {
                *perr  = err;                                   /* Rtn err from NetOS_Lock().                           */
                 return (0);
            }
            if (*perr != NET_TCP_ERR_NONE) {
                 return (0);                                    /* Rtn err from NetOS_TCP_TxQ_Wait().                   */
            }

            if (pconn->TxWinSizeCfgdRem < 1) {                  /* If tx Q still full, ...                              */
               *perr =  NET_TCP_ERR_TX_Q_FULL;                  /* ... rtn tx Q full err.                               */
                return (0);
            }
        } else {
            NetOS_TCP_TxQ_Clr(conn_id_tcp, &err);               /* Clr any possible async tx Q signal.                  */
        }
    }


                                                                /* ------- PREPARE APP TX DATA INTO TCP SEG(S) -------- */
                                                                /* Prepare seg addrs.                                   */
    NetTCP_TxConnPrepareSegAddrs((NET_TCP_CONN *) pconn,
                                 (CPU_INT08U   *)&src_port,
                                 (CPU_INT08U   *)&src_addr,
                                 (CPU_INT16U    ) sizeof(src_port),
                                 (CPU_INT16U    ) sizeof(src_addr),
                                 (CPU_INT08U   *)&dest_port,
                                 (CPU_INT08U   *)&dest_addr,
                                 (CPU_INT16U    ) sizeof(dest_port),
                                 (CPU_INT16U    ) sizeof(dest_addr),
                                 (NET_ERR      *)&err);
    if ( err != NET_TCP_ERR_NONE) {
       *perr  = NET_TCP_ERR_CONN_FAULT;
        return (0);
    }


/*$PAGE*/
    pbuf_head    = (NET_BUF    *)0;
    pbuf_tail    = (NET_BUF    *)0;
    p_data_pkt   = (CPU_INT08U *)p_data;
    tx_q_append  = (CPU_BOOLEAN )DEF_YES;

    data_len_mss = (NET_BUF_SIZE)pconn->MaxSegSizeConn;
    data_len_rem = (CPU_INT16U  )data_len;
    data_len_tot = (CPU_INT16U  )0;
                                                                /* Prepare TCP tx seg hdr ctrls.                        */
    seq_nbr      =  pconn->TxSeqNbrNextQ;
    flags_tcp    =  NET_TCP_FLAG_NONE  |
                    NET_TCP_FLAG_TX_ACK;

    if (pconn->TxQ_Tail != (NET_BUF *)0) {                      /* If tx Q NOT empty;                            ...    */
        pbuf                   =  pconn->TxQ_Tail;
        pbuf_hdr               = &pbuf->Hdr;

        data_ix_pkt_tail       = (NET_BUF_SIZE)pbuf_hdr->DataIx;
        data_len_pkt_tail      = (NET_BUF_SIZE)pbuf_hdr->TCP_SegLenData;
                                                                /* ... calc tail seg's max data size,            ...    */
        buf_size_max_tail      =  NetBuf_GetMaxSize(pbuf, data_ix_pkt_tail);
        buf_size_max_tail_data =  DEF_MIN(buf_size_max_tail, data_len_mss);

#if (NET_ERR_CFG_ARG_CHK_DBG_EN == DEF_ENABLED)
        if (data_len_pkt_tail > buf_size_max_tail_data) {       /* If seg len > max data size, tx Q data seg invalid;   */
                                                                /* ... close TCP conn (see Note #10a).                  */
            NetTCP_ConnClose((NET_TCP_CONN     *)pconn,
                             (NET_BUF_HDR      *)0,
                             (CPU_BOOLEAN       )DEF_YES,
                             (NET_TCP_CLOSE_CODE)NET_TCP_CONN_CLOSE_ALL);
           *perr =  NET_TCP_ERR_CONN_DATA_INVALID;
            return (0);
        }
#endif
        if (data_len_pkt_tail < buf_size_max_tail_data) {       /* ... & if avail data space on tx Q's tail seg, ...    */
                                                                /* ... append data on tx Q tail seg (see Note #7b1).    */
            data_ix_pkt      = data_ix_pkt_tail       + data_len_pkt_tail;
            data_len_pkt_rem = buf_size_max_tail_data - data_len_pkt_tail;
            if (data_len_rem > (NET_BUF_SIZE)data_len_pkt_rem) {/* If data len rem > pkt data len rem, ...              */
                data_len_pkt = (NET_BUF_SIZE)data_len_pkt_rem;  /* ...  limit pkt data len to pkt data len rem.         */
            } else {
                data_len_pkt = (NET_BUF_SIZE)data_len_rem;      /* Else limit pkt data len to data len rem.             */
            }

            NetBuf_DataWr((NET_BUF    *) pbuf,                  /* Wr app data into TCP tx buf.                         */
                          (NET_BUF_SIZE) data_ix_pkt,
                          (NET_BUF_SIZE) data_len_pkt,
                          (CPU_INT08U *) p_data_pkt,
                          (NET_ERR    *)&err);
            if ( err != NET_BUF_ERR_NONE) {                     /* If wr err, tx Q data corrupted; ...                  */
                                                                /* ... close TCP conn (see Note #10a).                  */
                NetTCP_ConnClose((NET_TCP_CONN     *)pconn,
                                 (NET_BUF_HDR      *)0,
                                 (CPU_BOOLEAN       )DEF_YES,
                                 (NET_TCP_CLOSE_CODE)NET_TCP_CONN_CLOSE_ALL);
               *perr  = NET_TCP_ERR_CONN_FAULT;
                return (0);
            }

                                                                /* Update TCP seg tx buf ctrls.                         */
            pbuf_hdr->DataLen        += (NET_BUF_SIZE)data_len_pkt;
            pbuf_hdr->TotLen         += (NET_BUF_SIZE)data_len_pkt;

            pbuf_hdr->TCP_SegLenInit += (CPU_INT16U  )data_len_pkt;
            pbuf_hdr->TCP_SegLen     += (CPU_INT16U  )data_len_pkt;
            pbuf_hdr->TCP_SegLenData += (CPU_INT16U  )data_len_pkt;


            pbuf_head     = (NET_BUF   *)pbuf;                  /* Set tx Q tail as first seg onto tx app data chain.   */
            pbuf_tail     = (NET_BUF   *)pbuf;
            tx_q_append   = (CPU_BOOLEAN)DEF_NO;

                                                                /* Update data ptr & lens.                              */
            p_data_pkt   +=             data_len_pkt;           /* MUST NOT cast ptr operand (see Note #8b).            */
            data_len_tot += (CPU_INT16U)data_len_pkt;
            data_len_rem -= (CPU_INT16U)data_len_pkt;

            seq_nbr      += (NET_TCP_SEQ_NBR)data_len_pkt;
                                                                /* Dec TCP conn's tx win size (see Note #9).            */
            NetTCP_TxConnWinSizeHandlerCfgd((NET_TCP_CONN   *) pconn,
                                            (NET_TCP_WIN_SIZE) data_len_pkt,
                                            (NET_TCP_WIN_CODE) NET_TCP_CONN_TX_WIN_DEC,
                                            (NET_ERR        *)&err);
            if ( err != NET_TCP_ERR_NONE) {
               *perr  = NET_TCP_ERR_CONN_FAULT;
                return (0);
            }
        }
    }


/*$PAGE*/
                                                                /* Calc max data size.                                  */
    data_ix_pkt       = NET_BUF_DATA_TX_IX;
    buf_size_max      = NetBuf_GetMaxSize((NET_BUF    *)0,
                                          (NET_BUF_SIZE)data_ix_pkt);
    buf_size_max_data = DEF_MIN(buf_size_max, data_len_mss);

    tx_err = DEF_NO;
    while ((data_len_rem            > 0) &&                     /* Prepare TCP seg(s) for ALL app data ...              */
           (pconn->TxWinSizeCfgdRem > 0) &&                     /* ... as net rsrc(s)/err(s) permit.                    */
           (tx_err == DEF_NO)) {

        if (data_len_rem > (NET_BUF_SIZE)buf_size_max_data) {   /* If data len rem > max data size, ...                 */
            data_len_pkt = (NET_BUF_SIZE)buf_size_max_data;     /* ...  limit pkt data len to max data size.            */
        } else {
            data_len_pkt = (NET_BUF_SIZE)data_len_rem;          /* Else limit pkt data len to data len rem.             */
        }

        pbuf = NetBuf_Get((NET_BUF_SIZE) data_len_pkt,          /* Get app data tx buf.                                 */
                          (NET_BUF_SIZE) data_ix_pkt,
                          (CPU_INT16U  ) NET_BUF_FLAG_NONE,
                          (NET_ERR    *)&err);
        if (err != NET_BUF_ERR_NONE) {
            tx_err = DEF_YES;
        }

        if (tx_err == DEF_NO) {
            NetBuf_DataWr((NET_BUF    *) pbuf,                  /* Wr app data into TCP tx buf.                         */
                          (NET_BUF_SIZE) data_ix_pkt,
                          (NET_BUF_SIZE) data_len_pkt,
                          (CPU_INT08U *) p_data_pkt,
                          (NET_ERR    *)&err);
            if (err != NET_BUF_ERR_NONE) {
                NetTCP_TxPktDiscard(pbuf, &err);
                tx_err = DEF_YES;
            }
        }

        if (tx_err == DEF_NO) {
                                                                /* Init TCP seg(s) tx buf ctrls.                        */
            pbuf_hdr                   = &pbuf->Hdr;
            pbuf_hdr->DataIx           = (CPU_INT16U  )data_ix_pkt;
            pbuf_hdr->DataLen          = (NET_BUF_SIZE)data_len_pkt;
            pbuf_hdr->TotLen           = (NET_BUF_SIZE)pbuf_hdr->DataLen;
            pbuf_hdr->ProtocolHdrType  =  NET_PROTOCOL_TYPE_APP;

            pbuf_hdr->TCP_UDP_PortSrc  = (NET_PORT_NBR)src_port;
            pbuf_hdr->IP_AddrSrc       = (CPU_INT32U  )src_addr;
            pbuf_hdr->TCP_UDP_PortDest = (NET_PORT_NBR)dest_port;
            pbuf_hdr->IP_AddrDest      = (CPU_INT32U  )dest_addr;

            pbuf_hdr->TCP_SegLenInit   = (CPU_INT16U  )data_len_pkt;
            pbuf_hdr->TCP_SegLen       = (CPU_INT16U  )pbuf_hdr->TCP_SegLenInit;
            pbuf_hdr->TCP_SegLenData   = (CPU_INT16U  )pbuf_hdr->TCP_SegLenInit;
            pbuf_hdr->TCP_SegSync      = (CPU_BOOLEAN )DEF_NO;
            pbuf_hdr->TCP_SegClose     = (CPU_BOOLEAN )DEF_NO;
            pbuf_hdr->TCP_SegAck       = (CPU_BOOLEAN )DEF_YES;
            pbuf_hdr->TCP_SegReset     = (CPU_BOOLEAN )DEF_NO;

            pbuf_hdr->TCP_SeqNbrInit   = (CPU_INT32U  )seq_nbr;
            pbuf_hdr->TCP_SeqNbr       = (CPU_INT32U  )pbuf_hdr->TCP_SeqNbrInit;

            pbuf_hdr->TCP_Flags        = (CPU_INT16U  )flags_tcp;


            if (pbuf_tail != (NET_BUF *)0) {                    /* If tx app data chain NOT empty, ...                  */
                                                                /* ... append seg(s) @ chain tail.                      */
                pbuf_hdr_tail                  = (NET_BUF_HDR *)&pbuf_tail->Hdr;
                pbuf_hdr_tail->NextPrimListPtr = (void        *) pbuf;
                pbuf_hdr->PrevPrimListPtr      = (void        *) pbuf_tail;
                pbuf_tail                      = (NET_BUF     *) pbuf;

            } else {                                            /* Else add seg as first seg onto tx app data chain.    */
                pbuf_head                      = (NET_BUF     *) pbuf;
                pbuf_tail                      = (NET_BUF     *) pbuf;
            }

                                                                /* Update data ptr & lens.                              */
            p_data_pkt   +=             data_len_pkt;           /* MUST NOT cast ptr operand (see Note #8b).            */
            data_len_tot += (CPU_INT16U)data_len_pkt;
            data_len_rem -= (CPU_INT16U)data_len_pkt;

            seq_nbr      += (NET_TCP_SEQ_NBR)data_len_pkt;
                                                                /* Dec TCP conn's tx win size (see Note #9).            */
            NetTCP_TxConnWinSizeHandlerCfgd((NET_TCP_CONN   *) pconn,
                                            (NET_TCP_WIN_SIZE) data_len_pkt,
                                            (NET_TCP_WIN_CODE) NET_TCP_CONN_TX_WIN_DEC,
                                            (NET_ERR        *)&err);
            if ( err != NET_TCP_ERR_NONE) {
               *perr  = NET_TCP_ERR_CONN_FAULT;
                return (0);
            }
        }
    }


/*$PAGE*/
    if (pbuf_head == (NET_BUF *)0) {                            /* If NO data seg'd, rtn no rsrc(s) err ...             */
       *perr =  NET_TCP_ERR_NONE_AVAIL;                         /* ... (see Notes #3b1F2b, #3c2, & #3d2).               */
        return (0);
    }

    DEF_BIT_SET(pbuf_hdr->TCP_Flags, NET_TCP_FLAG_TX_PUSH);     /* Set PUSH flag in last q'd tx seg (see Note #7b3B1b). */




                                                                /* ----------------- UPDATE TCP CONN ------------------ */
    if (pconn->TxQ_Tail != (NET_BUF *)0) {                      /* If tx Q NOT empty                            ...     */
        if (tx_q_append == DEF_YES) {                           /* ... & tx app data chain NOT already on tx Q, ...     */
                                                                /* ... append seg(s) @ Q tail (see Note #4b).           */
            pbuf_q_tail                      = (NET_BUF     *) pconn->TxQ_Tail;
            pbuf_hdr_q_tail                  = (NET_BUF_HDR *)&pbuf_q_tail->Hdr;
            pbuf_hdr_q_tail->NextPrimListPtr = (void        *) pbuf_head;

            pbuf_hdr_head                    = (NET_BUF_HDR *)&pbuf_head->Hdr;
            pbuf_hdr_head->PrevPrimListPtr   = (void        *) pbuf_q_tail;
        }

        pconn->TxQ_Tail = (NET_BUF *)pbuf_tail;

    } else {                                                    /* Else add seg(s) to empty tx Q.                       */
        pconn->TxQ_Head = (NET_BUF *)pbuf_head;
        pconn->TxQ_Tail = (NET_BUF *)pbuf_tail;
    }

                                                                /* Update TCP conn tx seq nbr(s).                       */
    pconn->TxSeqNbrNextQ = seq_nbr;



                                                                /* ---------------- TX TCP DATA SEG(S) ---------------- */
    if (tx_data == DEF_YES) {
        NetTCP_TxConnTxQ((NET_TCP_CONN     *)pconn,
                         (NET_BUF_HDR      *)0,
                         (NET_TCP_ACK_CODE  )NET_TCP_CONN_TX_ACK_NONE,
                         (CPU_BOOLEAN       )DEF_NO,
                         (NET_TCP_CLOSE_CODE)NET_TCP_CONN_CLOSE_ALL,
                         (NET_ERR          *)perr);
        switch (*perr) {
            case NET_TCP_ERR_NONE:
            case NET_TCP_ERR_CONN_ACK_NONE:
            case NET_TCP_ERR_CONN_ACK_DLYD:
            case NET_TCP_ERR_CONN_ACK_PREVLY_TXD:
            case NET_ERR_TX:                                    /* Ignore transitory tx err(s).                         */
                 break;


            case NET_ERR_INIT_INCOMPLETE:
            case NET_TCP_ERR_CONN_NOT_USED:
            case NET_TCP_ERR_CONN_CLOSE:
            case NET_TCP_ERR_CONN_FAULT:
            case NET_TCP_ERR_CONN_FAIL:
            case NET_TCP_ERR_CONN_ACK_INVALID:
            case NET_TCP_ERR_INVALID_CONN_STATE:
            case NET_TCP_ERR_INVALID_CONN_OP:
            case NET_TCP_ERR_INVALID_LEN_SEG:
            case NET_TCP_ERR_NONE_AVAIL:
            case NET_TCP_ERR_TX:
            case NET_CONN_ERR_INVALID_FAMILY:
            case NET_CONN_ERR_INVALID_ADDR:
            case NET_CONN_ERR_INVALID_ADDR_LEN:
            default:
                 return (0);                                    /* Prevent 'break NOT reachable' compiler warning.      */
        }
    }



   *perr =  NET_TCP_ERR_NONE;

    return (data_len_tot);
}


/*$PAGE*/
/*
*********************************************************************************************************
*                                          NetTCP_ConnGet()
*
* Description : (1) Allocate & initialize a TCP connection :
*
*                   (a) Get      a TCP connection
*                   (b) Validate   TCP connection
*                   (c) Initialize TCP connection
*                   (d) Update     TCP connection pool statistics
*                   (e) Return TCP connection handle identifier
*                         OR
*                       Null identifier & error code, on failure
*
*               (2) The TCP connection pool is implemented as a stack :
*
*                   (a) 'NetTCP_ConnPoolPtr' points to the head of the TCP connection pool.
*
*                   (b) TCP connections' 'NextPtr's link each TCP connection to form the TCP connection pool stack.
*
*                   (c) TCP connections are inserted & removed at the head of        the TCP connection pool stack.
*
*
*                                    TCP connections are
*                                    inserted & removed
*                                        at the head
*                                      (see Note #2c)
*
*                                             |                 NextPtr
*                                             |             (see Note #2b)
*                                             v                    |
*                                                                  |
*                                          -------       -------   v   -------       -------
*                     TCP Connection  ---->|     |------>|     |------>|     |------>|     |
*                      Pool Pointer        |     |       |     |       |     |       |     |
*                                          |     |       |     |       |     |       |     |
*                     (see Note #2a)       -------       -------       -------       -------
*
*                                          |                                               |
*                                          |<------- Pool of Free TCP Connections -------->|
*                                          |                (see Note #2)                  |
*
*
* Argument(s) : perr        Pointer to variable that will receive the return error code from this function :
*
*                               NET_TCP_ERR_NONE                    TCP connection successfully allocated &
*                                                                       initialized.
*                               NET_TCP_ERR_NONE_AVAIL              NO available TCP connections to allocate.
*                               NET_TCP_ERR_INVALID_CONN_TYPE       TCP connection is NOT a valid type.
*
* Return(s)   : TCP connection handle identifier, if NO errors.
*
*               NET_TCP_CONN_ID_NONE,             otherwise.
*
* Caller(s)   : various.
*
*               This function is an INTERNAL network protocol suite function & MUST NOT be called by 
*               application function(s).
*
* Note(s)     : (3) (a) TCP connection pool is accessed by 'NetTCP_ConnPoolPtr' during execution of
*
*                       (1) NetTCP_Init()
*                       (2) NetTCP_ConnGet()
*                       (3) NetTCP_ConnFree()
*
*                   (b) Since the primary tasks of the network protocol suite are prevented from running
*                       concurrently (see 'net.h  Note #2'), it is NOT necessary to protect the shared
*                       resources of the connection pool since no asynchronous access from other network
*                       tasks is possible.
*********************************************************************************************************
*/
/*$PAGE*/
NET_TCP_CONN_ID  NetTCP_ConnGet (NET_ERR  *perr)
{
#if ((NET_CTR_CFG_ERR_EN      == DEF_ENABLED)                    && \
     (CPU_CFG_CRITICAL_METHOD == CPU_CRITICAL_METHOD_STATUS_LOCAL))
    CPU_SR            cpu_sr;
#endif
    NET_TCP_CONN     *pconn;
    NET_TCP_CONN_ID   conn_id_tcp;
    NET_ERR           stat_err;

                                                                /* ------------------- GET TCP CONN ------------------- */
    if (NetTCP_ConnPoolPtr != (NET_TCP_CONN *)0) {              /* If TCP conn pool NOT empty, get TCP conn from pool.  */
        pconn               = (NET_TCP_CONN *)NetTCP_ConnPoolPtr;
        NetTCP_ConnPoolPtr  = (NET_TCP_CONN *)pconn->NextPtr;

    } else {                                                    /* If none avail, rtn err.                              */
        NET_CTR_ERR_INC(NetTCP_ErrNoneAvailCtr);
       *perr =  NET_TCP_ERR_NONE_AVAIL;
        return (NET_TCP_CONN_ID_NONE);
    }

#if (NET_ERR_CFG_ARG_CHK_DBG_EN == DEF_ENABLED)                 /* ---------------- VALIDATE TCP CONN ----------------- */
    if (pconn->Type != NET_TCP_TYPE_CONN) {
        NetTCP_ConnDiscard(pconn);
        NET_CTR_ERR_INC(NetTCP_ErrConnInvalidTypeCtr);
       *perr =  NET_TCP_ERR_INVALID_CONN_TYPE;
        return (NET_TCP_CONN_ID_NONE);
    }
#endif

                                                                /* ------------------ INIT TCP CONN ------------------- */
    NetTCP_ConnClr(pconn);
    DEF_BIT_SET(pconn->Flags, NET_TCP_FLAG_USED);               /* Set TCP conn as used.                                */
    pconn->ConnState = NET_TCP_CONN_STATE_CLOSED;

                                                                /* ------------ UPDATE TCP CONN POOL STATS ------------ */
    NetStat_PoolEntryUsedInc(&NetTCP_ConnPoolStat, &stat_err);

                                                                /* ----------------- RTN TCP CONN ID ------------------ */
    conn_id_tcp = pconn->ID;
   *perr        = NET_TCP_ERR_NONE;

    return (conn_id_tcp);
}


/*$PAGE*/
/*
*********************************************************************************************************
*                                          NetTCP_ConnFree()
*
* Description : Free a TCP connection.
*
* Argument(s) : conn_id_tcp     Handle identifier of TCP connection to free.
*
* Return(s)   : none.
*
* Caller(s)   : NetSock_Listen(),
*               NetSock_GetConnTransport().
*
*               This function is an INTERNAL network protocol suite function & MUST NOT be called by 
*               application function(s).
*
* Note(s)     : (1) #### To prevent freeing a TCP connection already freed via previous TCP connection
*                   free, NetTCP_ConnFree() checks if the TCP connection is used BEFORE freeing the
*                   TCP connection.
*
*                   This prevention is only best-effort since any invalid duplicate TCP connection frees
*                   MAY be asynchronous to potentially valid TCP connection gets.  Thus the invalid TCP
*                   connection free(s) MAY corrupt the TCP connection's valid operation(s).
*
*                   However, since the primary tasks of the network protocol suite are prevented from
*                   running concurrently (see 'net.h  Note #2'), it is NOT necessary to protect TCP
*                   connection resources from possible corruption since no asynchronous access from
*                   other network tasks is possible.
*********************************************************************************************************
*/

void  NetTCP_ConnFree (NET_TCP_CONN_ID  conn_id_tcp)
{
#if (NET_ERR_CFG_ARG_CHK_DBG_EN == DEF_ENABLED)
    NET_ERR        err;
#endif
    NET_TCP_CONN  *pconn;

                                                                /* ---------------- VALIDATE TCP CONN ----------------- */
    if (conn_id_tcp == NET_TCP_CONN_ID_NONE) {
        return;
    }

#if (NET_ERR_CFG_ARG_CHK_DBG_EN == DEF_ENABLED)                 /* -------------- VALIDATE TCP CONN USED -------------- */
   (void)NetTCP_ConnIsUsed(conn_id_tcp, &err);
    if (err != NET_TCP_ERR_NONE) {                              /* If TCP conn NOT used, ...                            */
        return;                                                 /* ... rtn but do NOT free (see Note #1).               */
    }
#endif

                                                                /* ------------------ FREE TCP CONN ------------------- */
    pconn = &NetTCP_ConnTbl[conn_id_tcp];
    NetTCP_ConnFreeHandler(pconn, NET_TCP_CONN_FREE_ALL);
}


/*$PAGE*/
/*
*********************************************************************************************************
*                                     NetTCP_ConnCloseFromConn()
*
* Description : Close a TCP connection via a network connection.
*
*               (1) When a network connection closes a TCP connection, the TCP connection :
*
*                   (a) (1) Closes NO other network connection(s),
*                       (2) MUST NOT recursively re-close other network connection(s);
*
*                   (b) SHOULD clear network connection(s)' handle identifiers.
*
*                   See also 'net_sock.c  NetSock_CloseFromConn()       Note #1',
*                          & 'net_conn.c  NetConn_CloseFromTransport()  Note #1b'.
*
*
* Argument(s) : conn_id_tcp     Handle identifier of TCP connection to close.
*
* Return(s)   : none.
*
* Caller(s)   : NetConn_CloseTransport().
*
*               This function is an INTERNAL network protocol suite function & MUST NOT be called by 
*               application function(s).
*
* Note(s)     : (2) #### To prevent closing a TCP connection already closed via previous TCP connection
*                   close, NetTCP_ConnCloseFromConn() checks if the TCP connection is used BEFORE closing
*                   the TCP connection.
*
*                   This prevention is only best-effort since any invalid duplicate TCP connection closes
*                   MAY be asynchronous to potentially valid TCP connection gets.  Thus the invalid TCP
*                   connection closes(s) MAY corrupt the TCP connection's valid operation(s).
*
*                   However, since the primary tasks of the network protocol suite are prevented from
*                   running concurrently (see 'net.h  Note #2'), it is NOT necessary to protect TCP
*                   connection resources from possible corruption since no asynchronous access from
*                   other network tasks is possible.
*********************************************************************************************************
*/

void  NetTCP_ConnCloseFromConn (NET_TCP_CONN_ID  conn_id_tcp)
{
#if (NET_ERR_CFG_ARG_CHK_DBG_EN == DEF_ENABLED)
    NET_ERR        err;
#endif
    NET_TCP_CONN  *pconn;

                                                                /* ---------------- VALIDATE TCP CONN ----------------- */
    if (conn_id_tcp == NET_TCP_CONN_ID_NONE) {
        return;
    }

#if (NET_ERR_CFG_ARG_CHK_DBG_EN == DEF_ENABLED)                 /* -------------- VALIDATE TCP CONN USED -------------- */
   (void)NetTCP_ConnIsUsed(conn_id_tcp, &err);
    if (err != NET_TCP_ERR_NONE) {                              /* If TCP conn NOT used, ...                            */
        return;                                                 /* ... rtn but do NOT close (see Note #2).              */
    }
#endif

                                                                /* ------------------ CLOSE TCP CONN ------------------ */
    pconn = &NetTCP_ConnTbl[conn_id_tcp];
    NetTCP_ConnClose((NET_TCP_CONN     *)pconn,
                     (NET_BUF_HDR      *)0,
                     (CPU_BOOLEAN       )DEF_NO,                /* See Note #1.                                         */
                     (NET_TCP_CLOSE_CODE)NET_TCP_CONN_CLOSE_ALL);
}


/*$PAGE*/
/*
*********************************************************************************************************
*                                       NetTCP_ConnSetID_Conn()
*
* Description : Set a TCP connection's network connection handle identifier.
*
* Argument(s) : conn_id_tcp     Handle identifier of TCP connection to set.
*
*               conn_id         Handle identifier of network connection.
*
*               perr        Pointer to variable that will receive the return error code from this function :
*
*                               NET_TCP_ERR_NONE                TCP connection's network connection handle
*                                                                   identifier successfully set.
*                               NET_TCP_ERR_INVALID_CONN_ID     Invalid network connection handle identifier.
*
*                                                               ----- RETURNED BY NetTCP_ConnIsUsed() : -----
*                               NET_ERR_INIT_INCOMPLETE         Network initialization NOT complete.
*                               NET_TCP_ERR_INVALID_CONN        Invalid TCP connection number.
*                               NET_TCP_ERR_CONN_NOT_USED       TCP connection NOT currently used.
*
*                                                               ------ RETURNED BY NetConn_IsUsed() : -------
*                               NET_CONN_ERR_INVALID_CONN       Invalid network connection number.
*                               NET_CONN_ERR_NOT_USED           Network connection NOT currently used.
*
* Return(s)   : none.
*
* Caller(s)   : NetSock_GetConnTransport().
*
*               This function is an INTERNAL network protocol suite function & MUST NOT be called by 
*               application function(s).
*
* Note(s)     : none.
*********************************************************************************************************
*/

void  NetTCP_ConnSetID_Conn (NET_TCP_CONN_ID   conn_id_tcp,
                             NET_CONN_ID       conn_id,
                             NET_ERR          *perr)
{
    NET_TCP_CONN  *pconn;


#if (NET_ERR_CFG_ARG_CHK_DBG_EN == DEF_ENABLED)
                                                                /* -------------- VALIDATE TCP CONN USED -------------- */
   (void)NetTCP_ConnIsUsed(conn_id_tcp, perr);
    if (*perr != NET_TCP_ERR_NONE) {
         return;
    }

                                                                /* --------------- VALIDATE NET CONN ID --------------- */
    if (conn_id != NET_CONN_ID_NONE) {
       (void)NetConn_IsUsed(conn_id, perr);
        if (*perr != NET_CONN_ERR_NONE) {
             return;
        }
    }
#endif


    pconn          = &NetTCP_ConnTbl[conn_id_tcp];
    pconn->ID_Conn =  conn_id;                                  /* Set TCP conn's conn id.                              */


   *perr = NET_TCP_ERR_NONE;
}


/*$PAGE*/
/*
*********************************************************************************************************
*                                     NetTCP_ConnSetStateListen()
*
* Description : Set TCP connection to LISTEN state.
*
* Argument(s) : conn_id_tcp     Handle identifier of TCP connection to set LISTEN state.
*
*               perr        Pointer to variable that will receive the return error code from this function :
*
*                               NET_TCP_ERR_NONE                    TCP connection state successfully set to LISTEN.
*                               NET_TCP_ERR_CONN_NOT_USED           TCP connection NOT currently used.
*                               NET_TCP_ERR_INVALID_CONN_ID         Invalid network connection handle identifier.
*                               NET_TCP_ERR_INVALID_CONN_STATE      Invalid TCP connection state.
*                               NET_TCP_ERR_INVALID_CONN_OP         Invalid TCP connection operation.
*
*                                                                   ------ RETURNED BY NetTCP_ConnIsUsed() : -------
*                               NET_ERR_INIT_INCOMPLETE             Network initialization NOT complete.
*                               NET_TCP_ERR_INVALID_CONN            Invalid TCP connection number.
*
* Return(s)   : none.
*
* Caller(s)   : NetSock_Listen().
*
*               This function is an INTERNAL network protocol suite function & SHOULD NOT be called by 
*               application function(s).
*
* Note(s)     : none.
*********************************************************************************************************
*/

void  NetTCP_ConnSetStateListen (NET_TCP_CONN_ID   conn_id_tcp,
                                 NET_ERR          *perr)
{
#if ((NET_CTR_CFG_ERR_EN      == DEF_ENABLED)                    && \
     (CPU_CFG_CRITICAL_METHOD == CPU_CRITICAL_METHOD_STATUS_LOCAL))
    CPU_SR         cpu_sr;
#endif
#if (NET_ERR_CFG_ARG_CHK_DBG_EN == DEF_ENABLED)
    CPU_BOOLEAN    used;
    NET_CONN_ID    conn_id;
    NET_CONN_ID    conn_id_transport;
    NET_ERR        err;
#endif
    NET_TCP_CONN  *pconn;


#if (NET_ERR_CFG_ARG_CHK_DBG_EN == DEF_ENABLED)                 /* -------------- VALIDATE TCP CONN USED -------------- */
   (void)NetTCP_ConnIsUsed(conn_id_tcp, perr);
    if (*perr != NET_TCP_ERR_NONE) {
         return;
    }
#endif

    pconn = &NetTCP_ConnTbl[conn_id_tcp];

#if (NET_ERR_CFG_ARG_CHK_DBG_EN == DEF_ENABLED)                 /* ---------------- VALIDATE CONN IDs ----------------- */
    conn_id = pconn->ID_Conn;
    used    = NetConn_IsUsed(conn_id, &err);
    if (used != DEF_YES) {
       *perr  = NET_TCP_ERR_INVALID_CONN_ID;
        return;
    }

    conn_id_transport =  NetConn_ID_TransportGet(conn_id, &err);
    if (conn_id_tcp  != (NET_TCP_CONN_ID)conn_id_transport) {
       *perr = NET_TCP_ERR_INVALID_CONN_ID;
        return;
    }
#endif


/*$PAGE*/
    switch (pconn->ConnState) {
        case NET_TCP_CONN_STATE_FREE:
             NET_CTR_ERR_INC(NetTCP_ErrNotUsedCtr);
            *perr = NET_TCP_ERR_CONN_NOT_USED;
             return;                                            /* Prevent 'break NOT reachable' compiler warning.      */


        case NET_TCP_CONN_STATE_CLOSED:
             pconn->ConnState = NET_TCP_CONN_STATE_LISTEN;
             break;


        case NET_TCP_CONN_STATE_LISTEN:
        case NET_TCP_CONN_STATE_SYNC_RXD:
        case NET_TCP_CONN_STATE_SYNC_RXD_PASSIVE:
        case NET_TCP_CONN_STATE_SYNC_RXD_ACTIVE:
        case NET_TCP_CONN_STATE_SYNC_TXD:
        case NET_TCP_CONN_STATE_CONN:
        case NET_TCP_CONN_STATE_FIN_WAIT_1:
        case NET_TCP_CONN_STATE_FIN_WAIT_2:
        case NET_TCP_CONN_STATE_CLOSING:
        case NET_TCP_CONN_STATE_TIME_WAIT:
        case NET_TCP_CONN_STATE_CLOSE_WAIT:
        case NET_TCP_CONN_STATE_LAST_ACK:
        case NET_TCP_CONN_STATE_CLOSING_DATA_AVAIL:
             NET_CTR_ERR_INC(NetTCP_ErrConnInvalidOpCtr);
            *perr = NET_TCP_ERR_INVALID_CONN_OP;
             return;                                            /* Prevent 'break NOT reachable' compiler warning.      */


        case NET_TCP_CONN_STATE_NONE:
        default:
             NetTCP_ConnClose((NET_TCP_CONN     *)pconn,
                              (NET_BUF_HDR      *)0,
                              (CPU_BOOLEAN       )DEF_YES,
                              (NET_TCP_CLOSE_CODE)NET_TCP_CONN_CLOSE_ALL);
             NET_CTR_ERR_INC(NetTCP_ErrConnInvalidStateCtr);
            *perr = NET_TCP_ERR_INVALID_CONN_STATE;
             return;                                            /* Prevent 'break NOT reachable' compiler warning.      */
    }


   *perr = NET_TCP_ERR_NONE;
}


/*$PAGE*/
/*
*********************************************************************************************************
*                                        NetTCP_ConnReqClose()
*
* Description : (1) Request TCP connection close :
*
*                   (a) Handle TCP connection close                             See Note #2a
*                   (b) Update TCP connection timer                             See Note #2b
*
*
* Argument(s) : conn_id_tcp         Handle identifier of TCP connection to request close.
*
*               conn_close_code     Indicate whether to close transport connection :
*
*                                       NET_CONN_CLOSE_FULL         Close TCP connection but do NOT allow
*                                                                       closing receive data to be available.
*                                       NET_CONN_CLOSE_HALF         Close TCP connection but        allow
*                                                                       closing receive data to be available.
*
*               perr        Pointer to variable that will receive the return error code from this function :
*
*                               NET_TCP_ERR_NONE                    TCP connection close successfully requested.
*                               NET_TCP_ERR_CONN_NOT_USED           TCP connection NOT currently used.
*                               NET_TCP_ERR_CONN_FAIL               TCP connection operation(s) failed.
*                               NET_TCP_ERR_INVALID_CONN_ID         Invalid network connection handle identifier.
*                               NET_TCP_ERR_INVALID_CONN_STATE      Invalid TCP connection state.
*                               NET_TCP_ERR_INVALID_CONN_OP         Invalid TCP connection operation.
*
*                                                                   ----- RETURNED BY NetTCP_ConnIsUsed() : -----
*                               NET_ERR_INIT_INCOMPLETE             Network initialization NOT complete.
*                               NET_TCP_ERR_INVALID_CONN            Invalid TCP connection number.
*
*                                                                   ---- RETURNED BY NetTCP_TxConnClose() : -----
*                               NET_ERR_INIT_INCOMPLETE             Network initialization NOT complete.
*                               NET_TCP_ERR_NONE_AVAIL              Resources NOT available.
*                               NET_TCP_ERR_CONN_ACK_INVALID        TCP connection acknowledgement NOT valid for
*                                                                       current TCP connection state.
*                               NET_TCP_ERR_INVALID_LEN_SEG         Invalid TCP sequence-segment length.
*                               NET_CONN_ERR_INVALID_FAMILY         Invalid     connection family.
*                               NET_CONN_ERR_INVALID_ADDR           Invalid TCP connection address.
*                               NET_CONN_ERR_INVALID_ADDR_LEN       Invalid TCP connection address length.
*                               NET_TCP_ERR_TX                      TCP transmit error.
*
* Return(s)   : none.
*
* Caller(s)   : NetSock_CloseHandlerStream().
*
*               This function is an INTERNAL network protocol suite function & SHOULD NOT be called by 
*               application function(s).
*$PAGE*
* Note(s)     : (2) (a) RFC #793, Section 3.9 'Event Processing : CLOSE Call' specifies how to handle
*                       close requests from the application layer :
*
*                       (1) For the "CLOSED STATE ... return 'error: connection does not exist'".
*
*                       (2) For the "LISTEN STATE ... any outstanding RECEIVEs are returned with 'error:
*                           closing' responses.  Delete TCB [and] enter CLOSED state".
*
*                       (3) For the "SYN-SENT STATE ... Delete the TCB and return 'error: closing'
*                           responses to any queued SENDs, or RECEIVEs".
*
*                       (4) For the "SYN-RECEIVED STATE" ...
*
*                           (A) "if no SENDs have been issued and there is no pending data to send," ...
*                               (1) "then form a FIN segment and send it,"                           ...
*                               (2) "and enter FIN-WAIT-1 state;"                                    ...
*
*                           (B) "otherwise queue for processing after entering ESTABLISHED state."
*
*                       (5) For the "ESTABLISHED STATE" ...
*
*                           (A) "Queue this until all preceding SENDs have been segmentized," ...
*                           (B) "then form a FIN segment and send it"                         ...
*                           (C) "In any case, enter FIN-WAIT-1 state."
*
*                       (6) For the "FIN-WAIT-1 STATE, FIN-WAIT-2 STATE" ...
*
*                           (A) "Strictly speaking, this is an error and should receive a 'error: connection
*                                closing' response."
*
*                           (B) "An 'ok' response would be acceptable, too, as long as a second FIN is not
*                                emitted (the first FIN may be retransmitted though)."
*
*                       (7) For the "CLOSE-WAIT STATE" ...
*
*                           (A) "Queue this request until all preceding SENDs have been segmentized;" ...
*                           (B) "then send a FIN segment,"                                            ...
*                           (C) (1) "enter CLOSING state."
*                               (2) RFC #1122, Section 4.2.2.20.(a) amends the state transition to "enter
*                                   LAST-ACK state, not CLOSING".
*
*                       (8) For the "CLOSING STATE, LAST-ACK STATE, TIME-WAIT STATE ... respond with 'error:
*                           connection closing'".
*
*                   (b) RFC #793, Section 3.9 'Event Processing : CLOSE Call' does NOT specify which timeout
*                       values to set for each state transition to closing state(s).
*
*                       #### Therefore, the following timeout values will be used for the following close
*                       state transitions :
*
*                       (1) SYN-RECEIVED STATE  ->  FIN-WAIT-1 STATE                TCP User/Connection timeout
*                           See also 'NetTCP_RxPktConnHandlerSyncRxd()  Note #3'.
*
*                       (2) ESTABLISHED  STATE  ->  FIN-WAIT-1 STATE                TCP User/Connection timeout
*                           See also 'NetTCP_RxPktConnHandlerConn()     Note #3'.
*
*                       (3) CLOSE-WAIT   STATE  ->  LAST-ACK   STATE                TCP Time-Wait / Two TCP Maximum
*                                                                                       Segment Lifetimes timeout
*                           See also 'NetTCP_RxPktConnHandlerLastAck()  Note #3'.
*
*                   (c) RFC #1122, Section 4.2.2.13 states that "a TCP connection may terminate in two ways" :
*
*                       (1) "The normal TCP close sequence using a FIN handshake."
*                       (2) "An 'abort' in which one or more RST segments are sent and the connection state
*                            is immediately discarded."
*
*               (3) (a) RFC #793, Section 3.9 'Event Processing : SEGMENT ARRIVES : Check ACK Field :
*                       FIN-WAIT-2 STATE' states that "if the retransmission queue is empty, the user's
*                       CLOSE can be acknowledged".
*
*                   (b) However, TCP connection should signal the application layer that "the user's close
*                       [is] acknowledged" whenever its re-transmit queue becomes &/or is empty :
*
*                       (1) Transition from LISTEN   to CLOSED
*                       (2) Transition from SYN-SENT to CLOSED
*
*                   See also 'NetTCP_RxPktConnHandlerSignalClose()  Note #1'.
*
*               (4) On ANY errors, network resources MUST be appropriately freed :
*
*                   (a) Close the TCP connection.
*                   (b) #### Do NOT close the network or application connection(s); application layer
*                       responsible for closing remaining connection(s)?
*********************************************************************************************************
*/
/*$PAGE*/
void  NetTCP_ConnReqClose (NET_TCP_CONN_ID   conn_id_tcp,
                           CPU_INT08U        conn_close_code,
                           NET_ERR          *perr)
{
#if ((NET_CTR_CFG_ERR_EN      == DEF_ENABLED)                    && \
     (CPU_CFG_CRITICAL_METHOD == CPU_CRITICAL_METHOD_STATUS_LOCAL))
    CPU_SR                cpu_sr;
#endif
#if (NET_ERR_CFG_ARG_CHK_DBG_EN == DEF_ENABLED)
    CPU_BOOLEAN           used;
    NET_CONN_ID           conn_id;
    NET_CONN_ID           conn_id_transport;
#endif
    NET_TCP_CONN         *pconn;
    NET_TCP_TIMEOUT_SEC   timeout_sec;
    NET_TMR_TICK          timeout_tick;
    NET_ERR               err;


#if (NET_ERR_CFG_ARG_CHK_DBG_EN == DEF_ENABLED)                 /* -------------- VALIDATE TCP CONN USED -------------- */
   (void)NetTCP_ConnIsUsed(conn_id_tcp, perr);
    if (*perr != NET_TCP_ERR_NONE) {
         return;
    }
#endif

    pconn = &NetTCP_ConnTbl[conn_id_tcp];

#if (NET_ERR_CFG_ARG_CHK_DBG_EN == DEF_ENABLED)                 /* ---------------- VALIDATE CONN IDs ----------------- */
    conn_id = pconn->ID_Conn;
    used    = NetConn_IsUsed(conn_id, &err);
    if (used != DEF_YES) {
       *perr = NET_TCP_ERR_INVALID_CONN_ID;
        return;
    }

    conn_id_transport =  NetConn_ID_TransportGet(conn_id, &err);
    if (conn_id_tcp  != (NET_TCP_CONN_ID)conn_id_transport) {
       *perr = NET_TCP_ERR_INVALID_CONN_ID;
        return;
    }
#endif


/*$PAGE*/
                                                                /* ---------------- HANDLE CONN CLOSE ----------------- */
    switch (pconn->ConnState) {
        case NET_TCP_CONN_STATE_FREE:
             NET_CTR_ERR_INC(NetTCP_ErrNotUsedCtr);
            *perr = NET_TCP_ERR_CONN_NOT_USED;
             return;                                            /* Prevent 'break NOT reachable' compiler warning.      */


        case NET_TCP_CONN_STATE_CLOSED:                         /* See Note #2a1.                                       */
             NET_CTR_ERR_INC(NetTCP_ErrConnInvalidOpCtr);
            *perr = NET_TCP_ERR_INVALID_CONN_OP;
             return;                                            /* Prevent 'break NOT reachable' compiler warning.      */


        case NET_TCP_CONN_STATE_LISTEN:                         /* See Note #2a2.                                       */
        case NET_TCP_CONN_STATE_SYNC_TXD:                       /* See Note #2a3.                                       */
                                                                /* Signal app conn close (see Note #3b) ...             */
             NetTCP_RxPktConnHandlerSignalClose(pconn, DEF_NO, &err);
                                                                /* ... & close TCP conn.                                */
             NetTCP_ConnCloseHandler(pconn, pconn->ConnCloseAppFlag, NET_TCP_CONN_CLOSE_ALL);
            *perr = NET_TCP_ERR_NONE;
             return;                                            /* Prevent 'break NOT reachable' compiler warning.      */


        case NET_TCP_CONN_STATE_SYNC_RXD:                       /* See Note #2a4.                                       */
        case NET_TCP_CONN_STATE_SYNC_RXD_PASSIVE:
        case NET_TCP_CONN_STATE_SYNC_RXD_ACTIVE:
        case NET_TCP_CONN_STATE_CONN:                           /* See Note #2a5.                                       */
             NetTCP_TxConnClose(pconn, perr);                   /* Tx TCP conn close          (see Note #2a5B), ...     */
             if (*perr != NET_TCP_ERR_NONE) {
                  return;
             }
                                                                /* ... enter fin-wait-1 state (see Note #2a5C), ...     */
             pconn->ConnState     = NET_TCP_CONN_STATE_FIN_WAIT_1;
             pconn->TxQ_State     = NET_TCP_TX_Q_STATE_CONN_CLOSING;
             pconn->ConnCloseCode = conn_close_code;
             timeout_sec          = pconn->TimeoutConn_sec;     /* ... & reset conn tmr       (see Notes #2b1 & #2b2).  */
             break;


        case NET_TCP_CONN_STATE_CLOSE_WAIT:                     /* See Note #2a7.                                       */
             NetTCP_TxConnClose(pconn, perr);                   /* Tx TCP conn close          (see Note #2a7B),  ...    */
             if (*perr != NET_TCP_ERR_NONE) {
                  return;
             }
                                                                /* ... enter last-ack state   (see Note #2a7C2), ...    */
             pconn->ConnState     = NET_TCP_CONN_STATE_LAST_ACK;
             pconn->TxQ_State     = NET_TCP_TX_Q_STATE_CONN_CLOSING;
             pconn->ConnCloseCode = conn_close_code;
                                                                /* ... & start time-wait tmr  (see Note #2b3).          */
             timeout_sec          = pconn->TimeoutMaxSeg_sec * NET_TCP_CONN_TIMEOUT_MAX_SEG_SCALAR;
             break;


        case NET_TCP_CONN_STATE_FIN_WAIT_1:                     /* See Note #2a6.                                       */
        case NET_TCP_CONN_STATE_FIN_WAIT_2:
        case NET_TCP_CONN_STATE_TIME_WAIT:                      /* See Note #2a8.                                       */
        case NET_TCP_CONN_STATE_CLOSING:
        case NET_TCP_CONN_STATE_LAST_ACK:
        case NET_TCP_CONN_STATE_CLOSING_DATA_AVAIL:
             NET_CTR_ERR_INC(NetTCP_ErrConnInvalidOpCtr);
            *perr = NET_TCP_ERR_INVALID_CONN_OP;
             return;                                            /* Prevent 'break NOT reachable' compiler warning.      */


        case NET_TCP_CONN_STATE_NONE:
        default:
             NetTCP_ConnClose((NET_TCP_CONN     *)pconn,
                              (NET_BUF_HDR      *)0,
                              (CPU_BOOLEAN       )DEF_YES,
                              (NET_TCP_CLOSE_CODE)NET_TCP_CONN_CLOSE_ALL);
             NET_CTR_ERR_INC(NetTCP_ErrConnInvalidStateCtr);
            *perr = NET_TCP_ERR_INVALID_CONN_STATE;
             return;                                            /* Prevent 'break NOT reachable' compiler warning.      */
    }


/*$PAGE*/
                                                                /* -------------------- UPDATE TMR -------------------- */
    timeout_tick = (NET_TMR_TICK)timeout_sec * NET_TMR_TIME_TICK_PER_SEC;
    if (pconn->TimeoutTmr != (NET_TMR *)0) {
        NetTmr_Set((NET_TMR    *) pconn->TimeoutTmr,
                   (CPU_FNCT_PTR) NetTCP_ConnCloseTimeout,
                   (NET_TMR_TICK) timeout_tick,
                   (NET_ERR    *)&err);
    } else {
        pconn->TimeoutTmr = NetTmr_Get((void       *) pconn,
                                       (CPU_FNCT_PTR) NetTCP_ConnCloseTimeout,
                                       (NET_TMR_TICK) timeout_tick,
                                       (CPU_INT16U  ) NET_TMR_FLAG_NONE,
                                       (NET_ERR    *)&err);
    }

    if (err != NET_TMR_ERR_NONE) {
        NetTCP_ConnClose((NET_TCP_CONN     *)pconn,
                         (NET_BUF_HDR      *)0,
                         (CPU_BOOLEAN       )pconn->ConnCloseAppFlag,
                         (NET_TCP_CLOSE_CODE)NET_TCP_CONN_CLOSE_ALL);
       *perr = NET_TCP_ERR_CONN_FAIL;
        return;
    }


   *perr = NET_TCP_ERR_NONE;
}


/*$PAGE*/
/*
*********************************************************************************************************
*                                   NetTCP_ConnCfgMaxSegSizeLocal()
*
* Description : Configure TCP connection's local maximum segment size.
*
* Argument(s) : conn_id_tcp     Handle identifier of TCP connection to configure local maximum segment size.
*
*               max_seg_size    Desired maximum segment size.
*
* Return(s)   : DEF_OK,   Local maximum segment size successfully configured.
*
*               DEF_FAIL, otherwise.
*
* Caller(s)   : Application.
*
*               This function is a network protocol suite application interface (API) function & MAY be 
*               called by application function(s).
*
* Note(s)     : (1) RFC #793, Section 3.1 'Header Format : Options : Maximum Segment Size' states that
*                   a TCP connection advertises its "maximum receive segment size ... only ... in the
*                   initial connection request (i.e., in segments with the SYN control bit set)".
*
*                   Thus any configuration of the local receive maximum segment size MUST be performed
*                   by the application layer PRIOR to any TCP connection request/synchronization.
*********************************************************************************************************
*/

CPU_BOOLEAN  NetTCP_ConnCfgMaxSegSizeLocal (NET_TCP_CONN_ID   conn_id_tcp,
                                            NET_TCP_SEG_SIZE  max_seg_size)
{
#if (CPU_CFG_CRITICAL_METHOD == CPU_CRITICAL_METHOD_STATUS_LOCAL)
    CPU_SR         cpu_sr;
#endif
    NET_TCP_CONN  *pconn;


#if ((NET_ERR_CFG_ARG_CHK_EXT_EN == DEF_ENABLED) || \
     (NET_ERR_CFG_ARG_CHK_DBG_EN == DEF_ENABLED))
                                                                /* ---------------- VALIDATE TCP CONN ----------------- */
    if (conn_id_tcp < NET_TCP_CONN_ID_MIN) {
        return (DEF_FAIL);
    }
    if (conn_id_tcp > NET_TCP_CONN_ID_MAX) {
        return (DEF_FAIL);
    }
#endif


                                                                /* -------------- VALIDATE MAX SEG SIZE --------------- */
#if (NET_TCP_MAX_SEG_SIZE_MIN > 0)
    if (max_seg_size < NET_TCP_MAX_SEG_SIZE_MIN) {
        max_seg_size = NET_TCP_MAX_SEG_SIZE_MIN;
    }
#endif
#if ((NET_TCP_MAX_SEG_SIZE_MAX < DEF_INT_08U_MAX_VAL)                                                      || \
    ((NET_TCP_MAX_SEG_SIZE_MAX < DEF_INT_16U_MAX_VAL) && (NET_TCP_MAX_SEG_SIZE_MAX > DEF_INT_08U_MAX_VAL)) || \
    ((NET_TCP_MAX_SEG_SIZE_MAX < DEF_INT_32U_MAX_VAL) && (NET_TCP_MAX_SEG_SIZE_MAX > DEF_INT_16U_MAX_VAL)))
    if (max_seg_size > NET_TCP_MAX_SEG_SIZE_MAX) {
        max_seg_size = NET_TCP_MAX_SEG_SIZE_MAX;
    }
#endif


                                                                /* ------------ CFG TCP CONN MAX SEG SIZE ------------- */
    pconn = &NetTCP_ConnTbl[conn_id_tcp];

    CPU_CRITICAL_ENTER();
    pconn->MaxSegSizeLocal = max_seg_size;
    CPU_CRITICAL_EXIT();


    return (DEF_OK);
}


/*$PAGE*/
/*
*********************************************************************************************************
*                                      NetTCP_ConnCfgRxWinSize()
*
* Description : Configure TCP connection's receive window size.
*
* Argument(s) : conn_id_tcp     Handle identifier of TCP connection to configure receive window size.
*
*               win_size        Desired receive window size.
*
* Return(s)   : DEF_OK,   Receive window size successfully configured.
*
*               DEF_FAIL, otherwise.
*
* Caller(s)   : Application.
*
*               This function is a network protocol suite application interface (API) function & MAY be 
*               called by application function(s).
*
* Note(s)     : (1) A TCP connection's receive window controls should NOT be updated until after the
*                   following TCP connection control(s) have been configured :
*
*                       (a) TCP connection's connection maximum segment size ('MaxSegSizeConn')
*                              [see 'NetTCP_RxConnWinSizeCfgUpdateTh()  Note #2b']
*********************************************************************************************************
*/

CPU_BOOLEAN  NetTCP_ConnCfgRxWinSize (NET_TCP_CONN_ID   conn_id_tcp,
                                      NET_TCP_WIN_SIZE  win_size)
{
#if (CPU_CFG_CRITICAL_METHOD == CPU_CRITICAL_METHOD_STATUS_LOCAL)
    CPU_SR         cpu_sr;
#endif
    NET_TCP_CONN  *pconn;


#if ((NET_ERR_CFG_ARG_CHK_EXT_EN == DEF_ENABLED) || \
     (NET_ERR_CFG_ARG_CHK_DBG_EN == DEF_ENABLED))
                                                                /* ---------------- VALIDATE TCP CONN ----------------- */
    if (conn_id_tcp < NET_TCP_CONN_ID_MIN) {
        return (DEF_FAIL);
    }
    if (conn_id_tcp > NET_TCP_CONN_ID_MAX) {
        return (DEF_FAIL);
    }
#endif


                                                                /* --------------- VALIDATE RX WIN SIZE --------------- */
#if (NET_TCP_WIN_SIZE_MIN > 0)
    if (win_size < NET_TCP_WIN_SIZE_MIN) {
        win_size = NET_TCP_WIN_SIZE_MIN;
    }
#endif
#if ((NET_TCP_WIN_SIZE_MAX < DEF_INT_08U_MAX_VAL)                                                  || \
    ((NET_TCP_WIN_SIZE_MAX < DEF_INT_16U_MAX_VAL) && (NET_TCP_WIN_SIZE_MAX > DEF_INT_08U_MAX_VAL)) || \
    ((NET_TCP_WIN_SIZE_MAX < DEF_INT_32U_MAX_VAL) && (NET_TCP_WIN_SIZE_MAX > DEF_INT_16U_MAX_VAL)))
    if (win_size > NET_TCP_WIN_SIZE_MAX) {
        win_size = NET_TCP_WIN_SIZE_MAX;
    }
#endif


                                                                        /* --------- CFG TCP CONN RX WIN SIZE --------- */
    pconn = &NetTCP_ConnTbl[conn_id_tcp];

    CPU_CRITICAL_ENTER();
    if (pconn->MaxSegSizeConn == NET_TCP_MAX_SEG_SIZE_NONE) {           /* If TCP conn MSS NOT cfg'd (see Note #1a), .. */
        CPU_CRITICAL_EXIT();
        return (DEF_FAIL);                                              /* .. do NOT cfg TCP conn rx win.               */
    }

    pconn->RxWinSizeCfgd = win_size;                                    /* Cfg new rx win size.                         */
    if (pconn->RxWinSizeCfgdActual          <= pconn->RxWinSizeCfgd) {  /* If actual <= cfg'd rx win size, ...          */
        pconn->RxWinSizeCfgdActual           = pconn->RxWinSizeCfgd;    /* ... update  actual rx win size.              */
        pconn->RxWinSizeCfgdActualUpdateRem  = 0;

    } else {                                                            /* Else cfg rem'ing win size update val.        */
        pconn->RxWinSizeCfgdActualUpdateRem  = pconn->RxWinSizeCfgdActual - pconn->RxWinSizeCfgd;
    }

    NetTCP_RxConnWinSizeCfg(pconn);                                     /* Cfg rx win ctrls.                            */
    CPU_CRITICAL_EXIT();


    return (DEF_OK);
}


/*$PAGE*/
/*
*********************************************************************************************************
*                                      NetTCP_ConnCfgReTxMaxTh()
*
* Description : Configure TCP connection's maximum number of same segment retransmissions.
*
* Argument(s) : conn_id_tcp     Handle identifier of TCP connection to configure maximum number of
*                                   same segment retransmissions.
*
*               nbr_re_tx       Desired maximum number of same segment retransmissions.
*
* Return(s)   : DEF_OK,   Maximum number of same segment retransmissions successfully configured.
*
*               DEF_FAIL, otherwise.
*
* Caller(s)   : Application.
*
*               This function is a network protocol suite application interface (API) function & MAY be 
*               called by application function(s).
*
* Note(s)     : none.
*********************************************************************************************************
*/

CPU_BOOLEAN  NetTCP_ConnCfgReTxMaxTh (NET_TCP_CONN_ID  conn_id_tcp,
                                      CPU_INT16U       nbr_max_re_tx)
{
#if (CPU_CFG_CRITICAL_METHOD == CPU_CRITICAL_METHOD_STATUS_LOCAL)
    CPU_SR         cpu_sr;
#endif
    NET_TCP_CONN  *pconn;


#if ((NET_ERR_CFG_ARG_CHK_EXT_EN == DEF_ENABLED) || \
     (NET_ERR_CFG_ARG_CHK_DBG_EN == DEF_ENABLED))
                                                                /* ---------------- VALIDATE TCP CONN ----------------- */
    if (conn_id_tcp < NET_TCP_CONN_ID_MIN) {
        return (DEF_FAIL);
    }
    if (conn_id_tcp > NET_TCP_CONN_ID_MAX) {
        return (DEF_FAIL);
    }
#endif


                                                                /* ---------------- VALIDATE RE-TX TH ----------------- */
#if (NET_TCP_RE_TX_TH_MIN > DEF_INT_16U_MIN_VAL)
    if (nbr_max_re_tx < NET_TCP_RE_TX_TH_MIN) {
        nbr_max_re_tx = NET_TCP_RE_TX_TH_MIN;
    }
#endif
#if (NET_TCP_RE_TX_TH_MAX < DEF_INT_16U_MAX_VAL)
    if (nbr_max_re_tx > NET_TCP_RE_TX_TH_MAX) {
        nbr_max_re_tx = NET_TCP_RE_TX_TH_MAX;
    }
#endif


                                                                /* -------------- CFG TCP CONN RE-TX TH --------------- */
    pconn = &NetTCP_ConnTbl[conn_id_tcp];

    CPU_CRITICAL_ENTER();
    pconn->TxSegReTxTh = nbr_max_re_tx;
    CPU_CRITICAL_EXIT();


    return (DEF_OK);
}


/*$PAGE*/
/*
*********************************************************************************************************
*                                   NetTCP_ConnCfgReTxMaxTimeout()
*
* Description : Configure TCP connection's maximum retransmission timeout.
*
* Argument(s) : conn_id_tcp     Handle identifier of TCP connection to configure retransmission
*                                   maximum timeout value.
*
*               timeout_sec     Desired value for TCP connection retransmission maximum timeout
*                                   (in seconds).
*
* Return(s)   : DEF_OK,   TCP connection retransmission maximum timeout successfully configured.
*
*               DEF_FAIL, otherwise.
*
* Caller(s)   : Application.
*
*               This function is a network protocol suite application interface (API) function & MAY be 
*               called by application function(s).
*
* Note(s)     : (1) (a) RFC #2988, Section 2.4 states that "a maximum value MAY be placed on RTO 
*                       provided it is at least 60 seconds".
*
*                   (b) RFC #1122, Section 4.2.3.1 states that "the recommended ... RTO ... upper 
*                       bound should be 2*MSL".
*
*                   (c) Stevens, TCP/IP Illustrated, Volume 1, 8th Printing, Section 21.2, Page 299
*                       states that "the timeout value ... [has] an upper limit of 64 seconds".
********************************************************************************************************
*/

CPU_BOOLEAN  NetTCP_ConnCfgReTxMaxTimeout (NET_TCP_CONN_ID      conn_id_tcp,
                                           NET_TCP_TIMEOUT_SEC  timeout_sec)
{
#if (CPU_CFG_CRITICAL_METHOD == CPU_CRITICAL_METHOD_STATUS_LOCAL)
    CPU_SR         cpu_sr;
#endif
    NET_TCP_CONN  *pconn;


#if ((NET_ERR_CFG_ARG_CHK_EXT_EN == DEF_ENABLED) || \
     (NET_ERR_CFG_ARG_CHK_DBG_EN == DEF_ENABLED))
                                                                /* ---------------- VALIDATE TCP CONN ----------------- */
    if (conn_id_tcp < NET_TCP_CONN_ID_MIN) {
        return (DEF_FAIL);
    }
    if (conn_id_tcp > NET_TCP_CONN_ID_MAX) {
        return (DEF_FAIL);
    }
#endif

                                                                /* ---------------- VALIDATE RTO MAX ------------------ */
                                                                /* See Note #1.                                         */
#if (NET_TCP_TX_RTO_MAX_TIMEOUT_MIN_SEC > 0)
    if (timeout_sec < NET_TCP_TX_RTO_MAX_TIMEOUT_MIN_SEC) {
        timeout_sec = NET_TCP_TX_RTO_MAX_TIMEOUT_MIN_SEC;
    }
#endif
#if ((NET_TCP_TX_RTO_MAX_TIMEOUT_MAX_SEC < DEF_INT_08U_MAX_VAL)                                                                || \
    ((NET_TCP_TX_RTO_MAX_TIMEOUT_MAX_SEC < DEF_INT_16U_MAX_VAL) && (NET_TCP_TX_RTO_MAX_TIMEOUT_MAX_SEC > DEF_INT_08U_MAX_VAL)) || \
    ((NET_TCP_TX_RTO_MAX_TIMEOUT_MAX_SEC < DEF_INT_32U_MAX_VAL) && (NET_TCP_TX_RTO_MAX_TIMEOUT_MAX_SEC > DEF_INT_16U_MAX_VAL)))
    if (timeout_sec > NET_TCP_TX_RTO_MAX_TIMEOUT_MAX_SEC) {
        timeout_sec = NET_TCP_TX_RTO_MAX_TIMEOUT_MAX_SEC;
    }
#endif


                                                                /* --------------- CFG TCP CONN RTO MAX --------------- */
    pconn = &NetTCP_ConnTbl[conn_id_tcp];

    CPU_CRITICAL_ENTER();
    pconn->TxRTT_RTO_Max_sec = timeout_sec;

    NetTCP_TxConnRTO_CfgMaxTimeout(pconn);                      /* Cfg RTO ctrls.                                       */
    CPU_CRITICAL_EXIT();


    return (DEF_OK);
}


/*$PAGE*/
/*
*********************************************************************************************************
*                                 NetTCP_ConnCfgTxAckImmedRxdPushEn()
*
* Description : Configure TCP connection's transmit immediate acknowledgement for received & pushed TCP
*                   segments enable.
*
* Argument(s) : conn_id_tcp         Handle identifier of TCP connection to configure transmit immediate
*                                       acknowledgement for received & pushed TCP segments enable.
*
*               tx_immed_ack_en     Desired value for TCP connection transmit immediate acknowledgement
*                                       for received & pushed TCP segments enable :
*
*                                       DEF_ENABLED             TCP connection acknowledgements
*                                                                   immediately transmitted for any
*                                                                   pushed TCP segments received.
*
*                                       DEF_DISABLED            TCP connection acknowledgements NOT
*                                                                   immediately transmitted for any
*                                                                   pushed TCP segments received.
*
*
* Return(s)   : DEF_OK,   TCP connection transmit immediate acknowledgement for received & pushed TCP
*                             segments enable successfully configured.
*
*               DEF_FAIL, otherwise.
*
* Caller(s)   : Application.
*
*               This function is a network protocol suite application interface (API) function & MAY be 
*               called by application function(s).
*
* Note(s)     : (1) See 'NetTCP_TxConnAck()  Note #4a4A1'.
*********************************************************************************************************
*/

CPU_BOOLEAN  NetTCP_ConnCfgTxAckImmedRxdPushEn (NET_TCP_CONN_ID  conn_id_tcp,
                                                CPU_BOOLEAN      tx_immed_ack_en)
{
#if (CPU_CFG_CRITICAL_METHOD == CPU_CRITICAL_METHOD_STATUS_LOCAL)
    CPU_SR         cpu_sr;
#endif
    NET_TCP_CONN  *pconn;


#if ((NET_ERR_CFG_ARG_CHK_EXT_EN == DEF_ENABLED) || \
     (NET_ERR_CFG_ARG_CHK_DBG_EN == DEF_ENABLED))
                                                                /* ---------------- VALIDATE TCP CONN ----------------- */
    if (conn_id_tcp < NET_TCP_CONN_ID_MIN) {
        return (DEF_FAIL);
    }
    if (conn_id_tcp > NET_TCP_CONN_ID_MAX) {
        return (DEF_FAIL);
    }
#endif


                                                                /* ------------- VALIDATE TX IMMED ACK EN ------------- */
    switch (tx_immed_ack_en) {
        case DEF_ENABLED:
        case DEF_DISABLED:
             break;


        default:
             tx_immed_ack_en = DEF_ENABLED;                     /* See Note #1.                                         */
             break;
    }


                                                                /* ----------- CFG TCP CONN TX IMMED ACK EN ----------- */
    pconn = &NetTCP_ConnTbl[conn_id_tcp];

    CPU_CRITICAL_ENTER();
    pconn->TxAckImmedRxdPushEn = tx_immed_ack_en;
    CPU_CRITICAL_EXIT();


    return (DEF_OK);
}


/*$PAGE*/
/*
*********************************************************************************************************
*                                         NetTCP_ConnIsUsed()
*
* Description : Validate TCP connection in use.
*
* Argument(s) : conn_id_tcp     Handle identifier of TCP connection to validate.
*
*               perr        Pointer to variable that will receive the return error code from this function :
*
*                               NET_TCP_ERR_NONE                TCP connection successfully validated as
*                                                                   in use.
*                               NET_ERR_INIT_INCOMPLETE         Network initialization NOT complete.
*                               NET_TCP_ERR_INVALID_CONN        Invalid TCP connection number.
*                               NET_TCP_ERR_CONN_NOT_USED       TCP connection NOT currently used.
*
* Return(s)   : DEF_YES, TCP connection   valid &      in use.
*
*               DEF_NO,  TCP connection invalid or NOT in use.
*
* Caller(s)   : various.
*
*               This function is an INTERNAL network protocol suite function & SHOULD NOT be called by 
*               application function(s).
*
* Note(s)     : (1) NetTCP_ConnIsUsed() blocked until network initialization completes.
*
*               (2) NetTCP_ConnIsUsed() MUST be called with the global network lock already acquired.
*********************************************************************************************************
*/

CPU_BOOLEAN  NetTCP_ConnIsUsed (NET_TCP_CONN_ID   conn_id_tcp,
                                NET_ERR          *perr)
{
#if ((NET_CTR_CFG_ERR_EN      == DEF_ENABLED)                    && \
     (CPU_CFG_CRITICAL_METHOD == CPU_CRITICAL_METHOD_STATUS_LOCAL))
    CPU_SR         cpu_sr;
#endif
    NET_TCP_CONN  *pconn;
    CPU_BOOLEAN    used;


#if (NET_ERR_CFG_ARG_CHK_EXT_EN == DEF_ENABLED)
    if (Net_InitDone != DEF_YES) {                              /* If init NOT complete, exit (see Note #1).            */
       *perr =  NET_ERR_INIT_INCOMPLETE;
        return (DEF_NO);
    }
#endif

                                                                /* --------------- VALIDATE TCP CONN ID --------------- */
    if (conn_id_tcp < NET_TCP_CONN_ID_MIN) {
        NET_CTR_ERR_INC(NetTCP_ErrConnInvalidCtr);
       *perr =  NET_TCP_ERR_INVALID_CONN;
        return (DEF_NO);
    }
    if (conn_id_tcp > NET_TCP_CONN_ID_MAX) {
        NET_CTR_ERR_INC(NetTCP_ErrConnInvalidCtr);
       *perr =  NET_TCP_ERR_INVALID_CONN;
        return (DEF_NO);
    }

                                                                /* -------------- VALIDATE TCP CONN USED -------------- */
    pconn = &NetTCP_ConnTbl[conn_id_tcp];
    used  =  DEF_BIT_IS_SET(pconn->Flags, NET_TCP_FLAG_USED);
    if (used != DEF_YES) {
        NET_CTR_ERR_INC(NetTCP_ErrNotUsedCtr);
       *perr =  NET_TCP_ERR_CONN_NOT_USED;
        return (DEF_NO);
    }


   *perr =  NET_TCP_ERR_NONE;

    return (DEF_YES);
}


/*$PAGE*/
/*
*********************************************************************************************************
*                                      NetTCP_ConnPoolStatGet()
*
* Description : Get TCP connection's statistics pool.
*
* Argument(s) : none.
*
* Return(s)   : TCP connection statistics pool, if NO errors.
*
*               NULL           statistics pool, otherwise.
*
* Caller(s)   : Application.
*
*               This function is a network protocol suite application interface (API) function & MAY be 
*               called by application function(s).
*
* Note(s)     : (1) NetTCP_ConnPoolStatGet() blocked until network initialization completes; return NULL
*                   statistics pool.
*********************************************************************************************************
*/

NET_STAT_POOL  NetTCP_ConnPoolStatGet (void)
{
#if (CPU_CFG_CRITICAL_METHOD == CPU_CRITICAL_METHOD_STATUS_LOCAL)
    CPU_SR         cpu_sr;
#endif
#if (NET_ERR_CFG_ARG_CHK_EXT_EN == DEF_ENABLED)
    NET_ERR        err;
#endif
    NET_STAT_POOL  stat_pool;


#if (NET_ERR_CFG_ARG_CHK_EXT_EN == DEF_ENABLED)
    if (Net_InitDone != DEF_YES) {                              /* If init NOT complete, ...                            */
        NetStat_PoolClr(&stat_pool, &err);
        return (stat_pool);                                     /* ... rtn NULL stat pool (see Note #1).                */
    }
#endif


    CPU_CRITICAL_ENTER();
    stat_pool = NetTCP_ConnPoolStat;
    CPU_CRITICAL_EXIT();

    return (stat_pool);
}


/*$PAGE*/
/*
*********************************************************************************************************
*                                  NetTCP_ConnPoolStatResetMaxUsed()
*
* Description : Reset TCP connection's statistics pool's maximum number of entries used.
*
* Argument(s) : none.
*
* Return(s)   : none.
*
* Caller(s)   : Application.
*
*               This function is a network protocol suite application interface (API) function & MAY be 
*               called by application function(s).
*
* Note(s)     : none.
*********************************************************************************************************
*/

void  NetTCP_ConnPoolStatResetMaxUsed (void)
{
    NET_ERR  err;


    NetStat_PoolResetUsedMax(&NetTCP_ConnPoolStat, &err);
}


/*$PAGE*/
/*
*********************************************************************************************************
*********************************************************************************************************
*                                           LOCAL FUNCTIONS
*********************************************************************************************************
*********************************************************************************************************
*/

/*
*********************************************************************************************************
*                                      NetTCP_RxPktValidateBuf()
*
* Description : Validate received buffer header as TCP protocol.
*
* Argument(s) : pbuf_hdr    Pointer to network buffer header that received TCP packet.
*               --------    Argument validated in NetTCP_Rx().
*
*               perr        Pointer to variable that will receive the return error code from this function :
*
*                               NET_TCP_ERR_NONE                Received buffer's TCP header validated.
*                               NET_ERR_INVALID_PROTOCOL        Buffer's protocol type is NOT TCP.
*                               NET_BUF_ERR_INVALID_IX          Invalid buffer index.
*
* Return(s)   : none.
*
* Caller(s)   : NetTCP_Rx().
*
* Note(s)     : none.
*********************************************************************************************************
*/

#if (NET_ERR_CFG_ARG_CHK_DBG_EN == DEF_ENABLED)
static  void  NetTCP_RxPktValidateBuf (NET_BUF_HDR  *pbuf_hdr,
                                       NET_ERR      *perr)
{
#if ((NET_CTR_CFG_ERR_EN      == DEF_ENABLED)                    && \
     (CPU_CFG_CRITICAL_METHOD == CPU_CRITICAL_METHOD_STATUS_LOCAL))
    CPU_SR  cpu_sr;
#endif

                                                                /* --------------- VALIDATE TCP BUF HDR --------------- */
    if (pbuf_hdr->ProtocolHdrType != NET_PROTOCOL_TYPE_TCP) {
        NET_CTR_ERR_INC(Net_ErrInvalidProtocolCtr);
       *perr = NET_ERR_INVALID_PROTOCOL;
        return;
    }

    if (pbuf_hdr->TCP_UDP_HdrDataIx == NET_BUF_IX_NONE) {
        NET_CTR_ERR_INC(NetTCP_ErrRxInvalidBufIxCtr);
       *perr = NET_BUF_ERR_INVALID_IX;
        return;
    }

   *perr = NET_TCP_ERR_NONE;
}
#endif


/*$PAGE*/
/*
*********************************************************************************************************
*                                       NetTCP_RxPktValidate()
*
* Description : (1) Validate received TCP packet :
*
*                   (a) Get TCP packet RTT timestamp received.              See 'NetTCP_TxConnRTT_RTO_Calc()
*                                                                                   Note #2a2A2'
*
*                   (b) (1) Validate the received packet's following TCP header fields :
*
*                           (A) Source      Port
*                           (B) Destination Port
*                           (C) Header  Length
*                           (D) Segment Length                              See Note #3
*                           (E) Flags
*                           (F) Check-Sum                                   See Note #4
*                           (G) Options
*
*                       (2) Validation ignores the following TCP header fields :
*
*                           (A) Sequence        Number
*                           (B) Acknowledgement Number
*                           (C) Window Advertisement
*                           (D) Urgent Pointer                              See 'net_tcp.c  Note #1b'
*
*                   (c) Convert the following TCP header fields from network-order to host-order :
*
*                       (1) Source      Port                                See Note #1cB1
*                       (2) Destination Port                                See Note #1cB2
*                       (3) Sequence        Number                          See Note #1cB3
*                       (4) Acknowledgement Number                          See Note #1cB4
*                       (5) Header Length/Flags                             See Note #1cB5
*                       (6) Window Advertisement                            See Note #1cB6
*                       (7) Check-Sum                                       See Note #4f
*                       (8) Urgent Pointer                                  See 'net_tcp.c  Note #1b'
*
*                           (A) These fields are NOT converted directly in the received packet buffer's
*                               data area but are converted in local or network buffer variables ONLY.
*
*                           (B) The following TCP header fields are converted & stored in network buffer
*                               variables :
*
*                               (1) Source      Port
*                               (2) Destination Port
*                               (3) Sequence        Number
*                               (4) Acknowledgement Number
*                               (5) Header Length/Flags
*                               (6) Window Advertisement
*
*                   (d) Update network buffer's protocol controls.
*
*
* Argument(s) : pbuf        Pointer to network buffer that received TCP packet.
*               ----        Argument checked   in NetTCP_Rx().
*
*               pbuf_hdr    Pointer to network buffer header.
*               --------    Argument validated in NetTCP_Rx().
*
*               ptcp_hdr    Pointer to received packet's TCP header.
*               --------    Argument validated in NetTCP_Rx()/NetTCP_RxPktValidateBuf().
*
*               perr        Pointer to variable that will receive the return error code from this function :
*
*                               NET_TCP_ERR_NONE                Received packet validated.
*                               NET_TCP_ERR_INVALID_PORT_NBR    Invalid TCP port number.
*                               NET_TCP_ERR_INVALID_LEN_HDR     Invalid TCP header  length.
*                               NET_TCP_ERR_INVALID_LEN_SEG     Invalid TCP segment length.
*                               NET_TCP_ERR_INVALID_LEN_DATA    Invalid TCP data    length.
*                               NET_TCP_ERR_INVALID_FLAG        Invalid TCP flags.
*                               NET_TCP_ERR_INVALID_CHK_SUM     Invalid TCP check-sum.
*
*                                                               - RETURNED BY NetTCP_RxPktValidateOpt() : -
*                               NET_TCP_ERR_INVALID_OPT_LEN     Invalid TCP option length.
*                               NET_TCP_ERR_INVALID_OPT_END     Invalid TCP option list ending.
*                               NET_TCP_ERR_INVALID_OPT_NBR     Invalid TCP option number of same option.
*
* Return(s)   : none.
*
* Caller(s)   : NetTCP_Rx().
*$PAGE*
* Note(s)     : (2) See 'net_tcp.h  TCP HEADER' for TCP header format.
*
*               (3) Since TCP segment headers do NOT contain a segment length field, the TCP Segment Length
*                   is assumed to be the remaining IP Datagram Length.
*
*               (4) (a) TCP header Check-Sum field MUST be validated BEFORE (or AFTER) any multi-octet words
*                       are converted from network-order to host-order since "the sum of 16-bit integers can
*                       be computed in either byte order" [RFC #1071, Section 2.(B)].
*
*                       In other words, the TCP Segment Check-Sum CANNOT be validated AFTER SOME but NOT ALL
*                       multi-octet words have been converted from network-order to host-order.
*
*                   (b) However, ALL received packets' multi-octet words are converted in local or network
*                       buffer variables ONLY (see Note #1cA).  Therefore, TCP Segment Check-Sum may be
*                       validated at any point.
*
*                   (c) The TCP Segment Check-Sum MUST be validated AFTER the TCP segment length has been
*                       validated so that the total TCP Segment Length (in octets) will already be calculated
*                       for the TCP Check-Sum calculation.
*
*                       For efficiency, the TCP Segment Check-Sum is validated AFTER all other TCP header
*                       fields have been validated.  Thus, the iteration-intensive TCP Segment Check-Sum is
*                       calculated only after all other TCP header fields have been quickly validated.
*
*                   (d) (1) In addition to the TCP segment header & data, the TCP Check-Sum calculation
*                           includes "a 96-bit pseudo header conceptually prefixed to the TCP header ...
*                           [which] contains the Source Address, the Destination Address, the Protocol,
*                           and TCP length" (see RFC #793, Section 3.1 'Header Format : Checksum').
*
*                       (2) Since network check-sum functions REQUIRE that 16-bit one's-complement check-
*                           sum calculations be performed on headers & data arranged in network-order (see
*                           'net_util.c  NetUtil_16BitOnesCplChkSumDataVerify()  Note #4'), TCP pseudo-header
*                           values MUST be set or converted to network-order.
*
*                   (e) RFC #793, Section 3.1 'Header Format : Checksum' specifies that "if a segment contains
*                       an odd number of header and text octets ... the last octet is padded ... with zeros to
*                       form a 16-bit word for checksum purposes".
*
*                       See also 'net_util.c  NetUtil_16BitSumDataCalc()  Note #8'.
*
*                   (f) After the TCP Segment Check-Sum is validated, it is NOT necessary to convert the Check-
*                       Sum from network-order to host-order since    it is NOT required for further processing.
*
*               (5) (a) Since the minimum network buffer size MUST be configured such that the entire TCP
*                       header MUST be received in a single packet (see 'net_buf.h  NETWORK BUFFER INDEX & 
*                       SIZE DEFINES  Note #1c'), after the TCP header size is decremented from the first 
*                       packet buffer's remaining number of data octets, any remaining octets MUST be user 
*                       &/or application data octets.
*
*                       (1) Note that the 'Data' index is updated regardless of a null-size data length.
*
*                   (b) If additional packet buffers exist, the remaining IP datagram 'Data' MUST be user
*                       &/or application data.  Therefore, the 'Data' length does NOT need to be adjusted
*                       but the 'Data' index MUST be updated.
*
*                   (c) #### Total TCP Segment Length & Data Length is duplicated in ALL fragmented packet
*                       buffers (may NOT be necessary; remove if unnecessary).
*
*               (6) RFC #1122, Sections 3.2.1 & 3.2.2 require that IP & ICMP packets with certain invalid
*                   header fields be "silently discarded".  However, NO RFC specifies how TCP should handle
*                   received segments with invalid header fields.
*
*                   Therefore, it is assumed that ALL TCP segments with ANY invalid header fields SHOULD
*                   be silently discarded.
*********************************************************************************************************
*/

static  void  NetTCP_RxPktValidate (NET_BUF      *pbuf,
                                    NET_BUF_HDR  *pbuf_hdr,
                                    NET_TCP_HDR  *ptcp_hdr,
                                    NET_ERR      *perr)
{
#if ((NET_CTR_CFG_ERR_EN      == DEF_ENABLED)                    && \
     (CPU_CFG_CRITICAL_METHOD == CPU_CRITICAL_METHOD_STATUS_LOCAL))
    CPU_SR               cpu_sr;
#endif
    CPU_INT08U           tcp_hdr_len_tot;
    CPU_INT16U           tcp_hdr_len;
    CPU_INT16U           tcp_tot_len;
    CPU_INT16U           tcp_data_len;
    CPU_INT16U           tcp_flags;
    CPU_INT16U           tcp_flags_reserved;
    CPU_BOOLEAN          tcp_chk_sum_valid;
    NET_TCP_PSEUDO_HDR   tcp_pseudo_hdr;
    NET_BUF             *pbuf_next;
    NET_BUF_HDR         *pbuf_next_hdr;


/*$PAGE*/
                                                                /* ---------------- GET TCP RTT RX TS ----------------- */
    pbuf_hdr->TCP_RTT_TS_Rxd_ms = (CPU_INT32U)NetTCP_TxConnRTT_GetTS_ms();



                                                                /* ---------------- VALIDATE TCP PORTS ---------------- */
    NET_UTIL_VAL_COPY_GET_NET_16(&pbuf_hdr->TCP_UDP_PortSrc,  &ptcp_hdr->PortSrc);
    if (pbuf_hdr->TCP_UDP_PortSrc  == NET_TCP_PORT_NBR_RESERVED) {
        NET_CTR_ERR_INC(NetTCP_ErrRxHdrPortSrcCtr);
       *perr = NET_TCP_ERR_INVALID_PORT_NBR;
        return;
    }

    NET_UTIL_VAL_COPY_GET_NET_16(&pbuf_hdr->TCP_UDP_PortDest, &ptcp_hdr->PortDest);
    if (pbuf_hdr->TCP_UDP_PortDest == NET_TCP_PORT_NBR_RESERVED) {
        NET_CTR_ERR_INC(NetTCP_ErrRxHdrPortDestCtr);
       *perr = NET_TCP_ERR_INVALID_PORT_NBR;
        return;
    }


                                                                /* --------------- VALIDATE TCP HDR LEN --------------- */
                                                                /* See 'net_tcp.h  TCP HEADER  Note #2'.                */
    NET_UTIL_VAL_COPY_GET_NET_16(&pbuf_hdr->TCP_HdrLen_Flags, &ptcp_hdr->HdrLen_Flags);
    tcp_hdr_len   = pbuf_hdr->TCP_HdrLen_Flags & NET_TCP_HDR_LEN_MASK;
    tcp_hdr_len >>= NET_TCP_HDR_LEN_SHIFT;
    if (tcp_hdr_len < NET_TCP_HDR_LEN_MIN) {                    /* If hdr len < min hdr len, rtn err.                   */
        NET_CTR_ERR_INC(NetTCP_ErrRxHdrLenCtr);
       *perr = NET_TCP_ERR_INVALID_LEN_HDR;
        return;
    }
#if (NET_ERR_CFG_ARG_CHK_DBG_EN == DEF_ENABLED)
    if (tcp_hdr_len > NET_TCP_HDR_LEN_MAX) {                    /* If hdr len > max hdr len, rtn err.                   */
        NET_CTR_ERR_INC(NetTCP_ErrRxHdrLenCtr);
       *perr = NET_TCP_ERR_INVALID_LEN_HDR;
        return;
    }
#endif

    tcp_hdr_len_tot = tcp_hdr_len * NET_TCP_HDR_LEN_WORD_SIZE;



                                                                /* ------------- VALIDATE TCP SEG TOT LEN ------------- */
    tcp_tot_len              = pbuf_hdr->IP_DatagramLen;        /* See Note #3.                                         */
    pbuf_hdr->TCP_UDP_TotLen = tcp_tot_len;
    if (pbuf_hdr->TCP_UDP_TotLen < NET_TCP_TOT_LEN_MIN) {       /* If seg tot len < min tot len, rtn err.               */
        NET_CTR_ERR_INC(NetTCP_ErrRxHdrSegLenCtr);
       *perr = NET_TCP_ERR_INVALID_LEN_SEG;
        return;
    }
    if (pbuf_hdr->TCP_UDP_TotLen > NET_TCP_TOT_LEN_MAX) {       /* If seg tot len > max tot len, rtn err.               */
        NET_CTR_ERR_INC(NetTCP_ErrRxHdrSegLenCtr);
       *perr = NET_TCP_ERR_INVALID_LEN_SEG;
        return;
    }


                                                                /* ---------------- VALIDATE TCP FLAGS ---------------- */
                                                                /* See 'net_tcp.h  TCP HEADER  Note #2'.                */
#if 1                                                           /* ???? Allow invalid reserved flags for rx'd segs?     */
    tcp_flags          = pbuf_hdr->TCP_HdrLen_Flags  & NET_TCP_HDR_FLAG_MASK;
    tcp_flags_reserved = DEF_BIT_IS_SET_ANY(tcp_flags, NET_TCP_HDR_FLAG_RESERVED);
    if (tcp_flags_reserved != DEF_NO) {                         /* If reserved flag bits set, rtn err.                  */
        NET_CTR_ERR_INC(NetTCP_ErrRxHdrFlagsCtr);
       *perr = NET_TCP_ERR_INVALID_FLAG;
        return;
    }
#endif

    pbuf_hdr->TCP_SegSync  = DEF_BIT_IS_SET(pbuf_hdr->TCP_HdrLen_Flags, NET_TCP_HDR_FLAG_SYNC );
    pbuf_hdr->TCP_SegClose = DEF_BIT_IS_SET(pbuf_hdr->TCP_HdrLen_Flags, NET_TCP_HDR_FLAG_CLOSE);
    pbuf_hdr->TCP_SegAck   = DEF_BIT_IS_SET(pbuf_hdr->TCP_HdrLen_Flags, NET_TCP_HDR_FLAG_ACK  );
    pbuf_hdr->TCP_SegReset = DEF_BIT_IS_SET(pbuf_hdr->TCP_HdrLen_Flags, NET_TCP_HDR_FLAG_RESET);



/*$PAGE*/
                                                                /* ---------------- VALIDATE TCP OPTS ----------------- */
    if (tcp_hdr_len_tot > NET_TCP_HDR_SIZE_MIN) {               /* If hdr len > min, validate/process TCP opts.         */
        NetTCP_RxPktValidateOpt(pbuf_hdr, ptcp_hdr, tcp_hdr_len_tot, perr);
        if (*perr != NET_TCP_ERR_NONE) {
            return;
        }
    }

                                                                /* --------------- VALIDATE TCP CHK SUM --------------- */
                                                                /* See Note #4.                                         */
                                                                /* Prepare TCP chk sum pseudo-hdr (see Note #4d).       */
    tcp_pseudo_hdr.AddrSrc  = (NET_IP_ADDR)NET_UTIL_HOST_TO_NET_32(pbuf_hdr->IP_AddrSrc);
    tcp_pseudo_hdr.AddrDest = (NET_IP_ADDR)NET_UTIL_HOST_TO_NET_32(pbuf_hdr->IP_AddrDest);
    tcp_pseudo_hdr.Zero     = (CPU_INT08U )0x00;
    tcp_pseudo_hdr.Protocol = (CPU_INT08U )NET_IP_HDR_PROTOCOL_TCP;
    tcp_pseudo_hdr.TotLen   = (CPU_INT16U )NET_UTIL_HOST_TO_NET_16(pbuf_hdr->TCP_UDP_TotLen);

    tcp_chk_sum_valid       =  NetUtil_16BitOnesCplChkSumDataVerify((void     *) pbuf,
                                                                    (void     *)&tcp_pseudo_hdr,
                                                                    (CPU_INT16U) NET_TCP_PSEUDO_HDR_SIZE,
                                                                    (NET_ERR  *) perr);
    if (tcp_chk_sum_valid != DEF_OK) {
        NET_CTR_ERR_INC(NetTCP_ErrRxHdrChkSumCtr);
       *perr = NET_TCP_ERR_INVALID_CHK_SUM;
        return;
    }
#if 0                                                           /* See Note #4f.                                        */
   (void)NET_UTIL_VAL_GET_NET_16(&ptcp_hdr->ChkSum);
#endif


                                                                /* ---------------- CONVERT TCP FIELDS ---------------- */
                                                                /* See Note #1c.                                        */
    NET_UTIL_VAL_COPY_GET_NET_32(&pbuf_hdr->TCP_SeqNbr,  &ptcp_hdr->SeqNbr);
    NET_UTIL_VAL_COPY_GET_NET_32(&pbuf_hdr->TCP_AckNbr,  &ptcp_hdr->AckNbr);
    NET_UTIL_VAL_COPY_GET_NET_16(&pbuf_hdr->TCP_WinSize, &ptcp_hdr->WinSize);


                                                                /* ----------------- UPDATE BUF CTRLS ----------------- */
                                                                /* Calc TCP data len/ix (see Note #5a).                 */
    pbuf_hdr->TCP_UDP_HdrLen = tcp_hdr_len_tot;
#if (NET_ERR_CFG_ARG_CHK_DBG_EN == DEF_ENABLED)
    if (pbuf_hdr->TCP_UDP_HdrLen > tcp_tot_len) {
        NET_CTR_ERR_INC(NetTCP_ErrRxHdrDataLenCtr);
       *perr = NET_TCP_ERR_INVALID_LEN_DATA;
        return;
    }
    if (pbuf_hdr->TCP_UDP_HdrLen > pbuf_hdr->DataLen) {
        NET_CTR_ERR_INC(NetTCP_ErrRxHdrDataLenCtr);
       *perr = NET_TCP_ERR_INVALID_LEN_DATA;
        return;
    }
#endif
    tcp_data_len               =  tcp_tot_len - pbuf_hdr->TCP_UDP_HdrLen;
    pbuf_hdr->TCP_UDP_DataLen  =  tcp_data_len;
    pbuf_hdr->TCP_SegLenInit   =  pbuf_hdr->TCP_UDP_DataLen;
    pbuf_hdr->TCP_SegLen       =  pbuf_hdr->TCP_SegLenInit;
    pbuf_hdr->TCP_SegLenData   =  pbuf_hdr->TCP_SegLenInit;
    pbuf_hdr->TCP_SeqNbrInit   =  pbuf_hdr->TCP_SeqNbr;

    pbuf_hdr->DataLen         -= (NET_BUF_SIZE) pbuf_hdr->TCP_UDP_HdrLen;
    pbuf_hdr->DataIx           = (CPU_INT16U  )(pbuf_hdr->TCP_UDP_HdrDataIx + pbuf_hdr->TCP_UDP_HdrLen);
    pbuf_hdr->ProtocolHdrType  =  NET_PROTOCOL_TYPE_APP;

    pbuf_next = (NET_BUF *)pbuf_hdr->NextBufPtr;
    while (pbuf_next != (NET_BUF *)0) {                         /* Calc ALL pkt bufs' data len/ix    (see Note #5b).    */
        pbuf_next_hdr                  = &pbuf_next->Hdr;
        pbuf_next_hdr->DataIx          =  pbuf_next_hdr->TCP_UDP_HdrDataIx;
        pbuf_next_hdr->TCP_UDP_HdrLen  =  0;                    /* NULL TCP hdr  len in each pkt buf.                   */
        pbuf_next_hdr->TCP_UDP_TotLen  =  tcp_tot_len;          /* Dup  TCP tot  len & ...                              */
        pbuf_next_hdr->TCP_UDP_DataLen =  tcp_data_len;         /* ...      data len in each pkt buf (see Note #5c).    */
        pbuf_next_hdr->TCP_SegLenInit  =  pbuf_next_hdr->TCP_UDP_DataLen;
        pbuf_next_hdr->TCP_SegLen      =  pbuf_next_hdr->TCP_SegLenInit;
        pbuf_next_hdr->TCP_SegLenData  =  pbuf_next_hdr->TCP_SegLenInit;
        pbuf_hdr->ProtocolHdrType      =  NET_PROTOCOL_TYPE_APP;
        pbuf_next                      = (NET_BUF *)pbuf_next_hdr->NextBufPtr;
    }


   *perr = NET_TCP_ERR_NONE;
}


/*$PAGE*/
/*
*********************************************************************************************************
*                                      NetTCP_RxPktValidateOpt()
*
* Description : Validate & process received packet's TCP options.
*
* Argument(s) : pbuf_hdr            Pointer to network buffer header that received TCP packet.
*               --------            Argument validated in NetTCP_Rx().
*
*               ptcp_hdr            Pointer to received packet's TCP header.
*               --------            Argument validated in NetTCP_Rx()/NetTCP_RxPktValidateBuf().
*
*               tcp_hdr_len_size    Length  of received packet's TCP header.
*               ----------------    Argument validated in NetTCP_RxPktValidate().
*
*               perr        Pointer to variable that will receive the return error code from this function :
*
*                               NET_TCP_ERR_NONE                TCP options validated & processed.
*                               NET_TCP_ERR_INVALID_OPT_LEN     Invalid TCP option length.
*                               NET_TCP_ERR_INVALID_OPT_END     Invalid TCP option list ending.
*                               NET_TCP_ERR_INVALID_OPT_NBR     Invalid TCP option number of same option.
*
* Return(s)   : none.
*
* Caller(s)   : NetTCP_RxPktValidate().
*
* Note(s)     : (1) (a) See 'net_tcp.h  TCP HEADER OPTIONS DEFINES' for   supported TCP options' summary.
*
*                   (b) See 'net_tcp.c  Note #1c'                   for unsupported TCP options.
*
*                       See also Note #2b3.
*
*               (2) (a) RFC # 793, Section 3.1 'Options' states that each option is "a multiple of 8 bits
*                       in length" and "may begin on any octet boundary".
*
*                       (1) Since TCP options are NOT required or guaranteed to align multi-octet words on
*                           appropriate word boundaries, ALL TCP options are decoded & processed a single
*                           octet at a time.
*
*                   (b) RFC #1122, Section 4.2.2.5 states that ... :
*
*                       (1) "A TCP MUST be able to receive a TCP option in any segment."
*
*                       (2) "A TCP MUST ignore without error any TCP option it does not implement, assuming
*                            that the option has a field length" ...
*
*                       (3) "All TCP options defined in the future will have length fields."
*
*                       See also 'net_tcp.h  TCP HEADER OPTIONS DEFINES  Note #2b'.
*********************************************************************************************************
*/

static  void  NetTCP_RxPktValidateOpt (NET_BUF_HDR  *pbuf_hdr,
                                       NET_TCP_HDR  *ptcp_hdr,
                                       CPU_INT08U    tcp_hdr_len_size,
                                       NET_ERR      *perr)
{
#if ((NET_CTR_CFG_ERR_EN      == DEF_ENABLED)                    && \
     (CPU_CFG_CRITICAL_METHOD == CPU_CRITICAL_METHOD_STATUS_LOCAL))
    CPU_SR        cpu_sr;
#endif
    CPU_INT08U   *popts;
    CPU_INT08U   *popt;
    CPU_INT08U    opt_list_len_size;
    CPU_INT08U    opt_list_len_rem;
    CPU_INT08U    opt_len;
    CPU_INT08U    opt_nbr_max_seg_size;
    CPU_BOOLEAN   opt_err;
    CPU_BOOLEAN   opt_list_end;


    opt_list_len_size = tcp_hdr_len_size - NET_TCP_HDR_SIZE_MIN;    /* Calc opt list len size.                          */

#if (NET_ERR_CFG_ARG_CHK_DBG_EN == DEF_ENABLED)                     /* -------- VALIDATE TCP HDR OPT LIST SIZE -------- */
    if (opt_list_len_size > NET_TCP_HDR_OPT_SIZE_MAX) {             /* If tot opt len > max opt size, ...               */
        NET_CTR_ERR_INC(NetTCP_ErrRxHdrOptsCtr);
       *perr = NET_TCP_ERR_INVALID_OPT_LEN;                         /* ... rtn err.                                     */
        return;
    }

    if ((opt_list_len_size % NET_TCP_HDR_OPT_SIZE_WORD) != 0) {     /* If tot opt len NOT multiple of opt size, ...     */
        NET_CTR_ERR_INC(NetTCP_ErrRxHdrOptsCtr);
       *perr = NET_TCP_ERR_INVALID_OPT_LEN;                         /* ... rtn err.                                     */
        return;
    }
#endif


/*$PAGE*/
    opt_err              =  DEF_NO;
    opt_list_end         =  DEF_NO;
    opt_nbr_max_seg_size =  0;

    popts                = (CPU_INT08U *)&ptcp_hdr->Opts[0];
    opt_list_len_rem     =  opt_list_len_size;

                                                                /* ------------- DECODE/VALIDATE TCP OPTS ------------- */
    while (opt_list_len_rem > 0) {                              /* Process each opt in list (see Notes #1 & #2).        */
        switch (*popts) {
            case NET_TCP_HDR_OPT_END_LIST:                      /* ------------------- END OPT LIST ------------------- */
                 opt_list_end = DEF_YES;                        /* Mark end of opt list.                                */
                 opt_len      = NET_TCP_HDR_OPT_LEN_END_LIST;
                 break;


            case NET_TCP_HDR_OPT_NOP:                           /* --------------------- NOP OPT ---------------------- */
#if 1                                                           /* ???? NOP's invalid after END?                        */
                 if (opt_list_end != DEF_NO) {                  /* If opt found AFTER end of opt list, rtn err.         */
                     NET_CTR_ERR_INC(NetTCP_ErrRxHdrOptsCtr);
                    *perr = NET_TCP_ERR_INVALID_OPT_END;
                     return;
                 }
#endif
                 opt_len = NET_TCP_HDR_OPT_LEN_NOP;
                 break;


            case NET_TCP_HDR_OPT_MAX_SEG_SIZE:                  /* ----------------- MAX SEG SIZE OPT ----------------- */
                 if (opt_list_end != DEF_NO) {                  /* If opt found AFTER end of opt list, rtn err.         */
                     NET_CTR_ERR_INC(NetTCP_ErrRxHdrOptsCtr);
                    *perr = NET_TCP_ERR_INVALID_OPT_END;
                     return;
                 }
                 if (opt_nbr_max_seg_size > 0) {                /* If > 1 max seg size opt,            rtn err.         */
                     NET_CTR_ERR_INC(NetTCP_ErrRxHdrOptsCtr);
                    *perr = NET_TCP_ERR_INVALID_OPT_NBR;
                     return;
                 }
                 opt_nbr_max_seg_size++;

                 opt_err = NetTCP_RxPktValidateOptMaxSegSize(pbuf_hdr, popts, &opt_len, perr);
                 break;

#if 0                                                           /* --------------- UNSUPPORTED TCP OPTS --------------- */
                                                                /* See Notes #1b & #2b2.                                */
            case NET_TCP_HDR_OPT_WIN_SCALE:
            case NET_TCP_HDR_OPT_SACK_PERMIT:
            case NET_TCP_HDR_OPT_SACK:
            case NET_TCP_HDR_OPT_ECHO_REQ:
            case NET_TCP_HDR_OPT_ECHO_REPLY:
            case NET_TCP_HDR_OPT_TS:
                                                                /* 'break' intentionally omitted; do NOT move from the  */
                                                                /* ... following case : 'default'.                      */
#endif

            default:                                            /* ----------------- UNKNOWN TCP OPTS ----------------- */
                 popt = popts;

                 popt++;
                 opt_len = *popt;                               /* Validate opt len (see Note #2b3).                    */
                 if (opt_len < NET_TCP_HDR_OPT_LEN_MIN_LEN) {   /* If opt len < min opt len, rtn err.                   */
                     NET_CTR_ERR_INC(NetTCP_ErrRxHdrOptsCtr);
                    *perr = NET_TCP_ERR_INVALID_OPT_LEN;
                     return;
                 }
                 break;
        }

        if (opt_err != DEF_NO) {                                /* If ANY opt errs,               rtn err.              */
            return;
        }

        if (opt_len > opt_list_len_rem) {                       /* If opt len > rem opt list len, rtn err.              */
            NET_CTR_ERR_INC(NetTCP_ErrRxHdrOptsCtr);
           *perr = NET_TCP_ERR_INVALID_OPT_LEN;
            return;
        }

        opt_list_len_rem -= opt_len;
        popts            += opt_len;
    }

   *perr = NET_TCP_ERR_NONE;
}


/*$PAGE*/
/*
*********************************************************************************************************
*                                 NetTCP_RxPktValidateOptMaxSegSize()
*
* Description : Validate & process received TCP Maximum Segment Size option.
*
* Argument(s) : pbuf_hdr    Pointer to network buffer header that received TCP packet.
*               --------    Argument validated in NetTCP_Rx().
*
*               popt        Pointer to Maximum Segment Size option.
*               ----        Argument validated in NetTCP_RxPktValidateOpt().
*
*               popt_len    Pointer to variable that will receive the TCP option length (in octets).
*               --------    Argument validated in NetTCP_RxPktValidateOpt().
*
*               perr        Pointer to variable that will receive the return error code from this function :
*
*                               NET_TCP_ERR_NONE                TCP option validated & processed.
*                               NET_TCP_ERR_INVALID_OPT_LEN     Invalid TCP option length.
*
* Return(s)   : DEF_NO,  NO Maximum Segment Size option error.
*
*               DEF_YES, otherwise.
*
* Caller(s)   : NetTCP_RxPktValidateOpt().
*
* Note(s)     : (1) See 'net_tcp.h  TCP HEADER OPTIONS DEFINES  Note #2b1' for TCP Maximum Segment Size
*                   option summary.
*
*               (2) (a) RFC # 793, Section 3.1 'Options' states that each option is "a multiple of 8 bits
*                       in length" and "may begin on any octet boundary".
*
*                   (b) Since TCP options are NOT required or guaranteed to align multi-octet words on
*                       appropriate word boundaries, ALL TCP options are decoded & processed a single
*                       octet at a time.
*********************************************************************************************************
*/

static  CPU_BOOLEAN  NetTCP_RxPktValidateOptMaxSegSize (NET_BUF_HDR  *pbuf_hdr,
                                                        CPU_INT08U   *popt,
                                                        CPU_INT08U   *popt_len,
                                                        NET_ERR      *perr)
{
#if ((NET_CTR_CFG_ERR_EN      == DEF_ENABLED)                    && \
     (CPU_CFG_CRITICAL_METHOD == CPU_CRITICAL_METHOD_STATUS_LOCAL))
    CPU_SR            cpu_sr;
#endif
    NET_TCP_SEG_SIZE  max_seg_size;


   *popt_len = NET_TCP_HDR_OPT_LEN_MAX_SEG_SIZE;

    popt++;
    if (*popt != *popt_len) {                                   /* If opt len != max seg size opt len, rtn err.         */
         NET_CTR_ERR_INC(NetTCP_ErrRxHdrOptsCtr);
        *perr  = NET_TCP_ERR_INVALID_OPT_LEN;
         return (DEF_YES);
    }

                                                                /* Calc max seg size (see Note #2b).                    */
    popt++;
    max_seg_size   = *popt;
    max_seg_size <<=  DEF_OCTET_NBR_BITS;
    popt++;
    max_seg_size  += *popt;

    if (max_seg_size > NET_TCP_MAX_SEG_SIZE_MAX) {              /* If max seg size > max, rtn err.                      */
        NET_CTR_ERR_INC(NetTCP_ErrRxHdrOptsCtr);
       *perr =  NET_TCP_ERR_INVALID_OPT_LEN;
        return (DEF_YES);
    }

    pbuf_hdr->TCP_MaxSegSize = (CPU_INT16U)max_seg_size;

   *perr                     =  NET_TCP_ERR_NONE;

    return (DEF_NO);
}


/*$PAGE*/
/*
*********************************************************************************************************
*                                       NetTCP_RxPktDemuxSeg()
*
* Description : (1) Demultiplex received packet to appropriate TCP connection :
*
*                   (a) Search connection lists for connection whose local &/or remote addresses are
*                       identical to the received packet's destination & source addresses.
*
*                   (b) Update network buffer's connection controls.
*
*
* Argument(s) : pbuf        Pointer to network buffer that received TCP packet.
*               ----        Argument checked   in NetTCP_Rx().
*
*               pbuf_hdr    Pointer to network buffer header.
*               --------    Argument validated in NetTCP_Rx().
*
*               perr        Pointer to variable that will receive the return error code from this function :
*
*                               NET_TCP_ERR_NONE                Received packet successfully demultiplexed
*                                                                   to appropriate TCP connection.
*                               NET_CONN_ERR_INVALID_FAMILY     Invalid network connection family.
*                               NET_CONN_ERR_INVALID_CONN       Invalid network connection number(s).
*                               NET_ERR_RX_DEST                 Invalid destination; no connection available
*                                                                   for received packet.
*
* Return(s)   : none.
*
* Caller(s)   : NetTCP_Rx().
*
* Note(s)     : (2) The 'SRCH CONN LIST(S) FOR PKT/CONN ADDR(S)' pre-processor 'else'-conditional code will
*                   never be compiled/linked since 'net_conn.h' ensures that the family type configuration
*                   constant (NET_CONN_CFG_FAMILY) is configured with an appropriate family type value
*                   (see 'net_conn.h  CONFIGURATION ERRORS').  The 'else'-conditional code is included for
*                   completeness & as an extra precaution in case 'net_conn.h' is incorrectly modified.
*
*               (3) (a) RFC #793, Section 3.9 'Event Processing : SEGMENT ARRIVES : CLOSED [State]' states
*                       that "an incoming segment ... causes a RST to be sent in response".
*
*                   (b) RFC #792, Section 'Destination Unreachable Message : Description' states that
*                       "if, in the destination host, the IP module cannot deliver the datagram because
*                       the indicated ... process port is not active, the destination host may send a
*                       destination unreachable message to the source host".
*********************************************************************************************************
*/
/*$PAGE*/
static  void  NetTCP_RxPktDemuxSeg (NET_BUF      *pbuf,
                                    NET_BUF_HDR  *pbuf_hdr,
                                    NET_ERR      *perr)
{
#if ((NET_CTR_CFG_ERR_EN      == DEF_ENABLED)                    && \
     (CPU_CFG_CRITICAL_METHOD == CPU_CRITICAL_METHOD_STATUS_LOCAL))
    CPU_SR            cpu_sr;
#endif
#if (NET_CONN_CFG_FAMILY == NET_CONN_FAMILY_IP_V4_SOCK)
    NET_IP_ADDR       addr_ip;
#endif
    CPU_INT08U        addr_local[NET_CONN_CFG_ADDR_LEN];
    CPU_INT08U        addr_remote[NET_CONN_CFG_ADDR_LEN];
    NET_TCP_PORT_NBR  port_nbr;
    NET_CONN_LIST_IX  protocol_ix;
    NET_CONN_FAMILY   family;
    NET_CONN_ID       conn_id;
    NET_CONN_ID       conn_id_transport;
    NET_CONN_ID       conn_id_app;
    NET_ERR           err;


                                                                    /* ---- SRCH CONN LIST(S) FOR PKT/CONN ADDR(S) ---- */
#if (NET_CONN_CFG_FAMILY == NET_CONN_FAMILY_IP_V4_SOCK)
    family      = NET_CONN_FAMILY_IP_V4_SOCK;
    protocol_ix = NET_CONN_LIST_IX_IP_V4_SOCK_TCP;

                                                                    /* Cfg srch local  addr as pkt dest addr.           */
    port_nbr = (NET_TCP_PORT_NBR)NET_UTIL_HOST_TO_NET_16(pbuf_hdr->TCP_UDP_PortDest);
    addr_ip  = (NET_IP_ADDR     )NET_UTIL_HOST_TO_NET_32(pbuf_hdr->IP_AddrDest);

    Mem_Copy((void     *)&addr_local[NET_CONN_ADDR_IP_IX_PORT],
             (void     *)&port_nbr,
             (CPU_SIZE_T) NET_CONN_ADDR_IP_LEN_PORT);
    Mem_Copy((void     *)&addr_local[NET_CONN_ADDR_IP_IX_ADDR],
             (void     *)&addr_ip,
             (CPU_SIZE_T) NET_CONN_ADDR_IP_LEN_ADDR);

                                                                    /* Cfg srch remote addr as pkt src  addr.           */
    port_nbr = (NET_TCP_PORT_NBR)NET_UTIL_HOST_TO_NET_16(pbuf_hdr->TCP_UDP_PortSrc);
    addr_ip  = (NET_IP_ADDR     )NET_UTIL_HOST_TO_NET_32(pbuf_hdr->IP_AddrSrc);

    Mem_Copy((void     *)&addr_remote[NET_CONN_ADDR_IP_IX_PORT],
             (void     *)&port_nbr,
             (CPU_SIZE_T) NET_CONN_ADDR_IP_LEN_PORT);
    Mem_Copy((void     *)&addr_remote[NET_CONN_ADDR_IP_IX_ADDR],
             (void     *)&addr_ip,
             (CPU_SIZE_T) NET_CONN_ADDR_IP_LEN_ADDR);

#else                                                               /* See Note #2.                                     */
   *perr = NET_CONN_ERR_INVALID_FAMILY;
    return;
#endif


/*$PAGE*/
    conn_id = NetConn_Srch((NET_CONN_FAMILY   ) family,             /* Srch for TCP conn whose local/remote addrs ...   */
                           (NET_CONN_LIST_IX  ) protocol_ix,        /* ... are identical to pkt dest/src addrs.         */
                           (NET_CONN_LIST_TYPE) NET_CONN_LIST_TYPE_ALL,
                           (CPU_BOOLEAN       ) DEF_YES,
                           (CPU_INT08U       *)&addr_local[0],
                           (CPU_INT08U       *)&addr_remote[0],
                           (NET_CONN_ADDR_LEN ) NET_CONN_CFG_ADDR_LEN,
                           (NET_CONN_ID      *)&conn_id_transport,
                           (NET_CONN_ID      *)&conn_id_app);

    if (conn_id == NET_CONN_ID_NONE) {                              /* If complete TCP conn NOT found,            ..    */
        conn_id  = NetConn_Srch((NET_CONN_FAMILY   ) family,        /* .. srch for TCP half-conn whose local addr ..    */
                                (NET_CONN_LIST_IX  ) protocol_ix,   /* .. is identical to pkt dest addr.                */
                                (NET_CONN_LIST_TYPE) NET_CONN_LIST_TYPE_ALL,
                                (CPU_BOOLEAN       ) DEF_NO,
                                (CPU_INT08U       *)&addr_local[0],
                                (CPU_INT08U       *) 0,
                                (NET_CONN_ADDR_LEN ) NET_CONN_CFG_ADDR_LEN,
                                (NET_CONN_ID      *)&conn_id_transport,
                                (NET_CONN_ID      *)&conn_id_app);

        if (conn_id == NET_CONN_ID_NONE) {                          /* If NO TCP conn found,                    ...     */
            NetTCP_TxConnReset((NET_TCP_CONN     *) 0,              /* ... tx TCP  conn reset   (see Note #3a), ...     */
                               (NET_BUF_HDR      *) pbuf_hdr,
                               (NET_TCP_RESET_CODE) NET_TCP_CONN_TX_RESET,
                               (NET_TCP_CLOSE_CODE) NET_TCP_CONN_CLOSE_ALL,
                               (NET_ERR          *)&err);
            NetICMP_TxMsgErr(pbuf,                                  /* ... tx ICMP port unreach (see Note #3b), ...     */
                             NET_ICMP_MSG_TYPE_DEST_UNREACH,
                             NET_ICMP_MSG_CODE_DEST_PORT,
                             NET_ICMP_MSG_PTR_NONE,
                            &err);
            NET_CTR_ERR_INC(NetTCP_ErrRxDestCtr);
           *perr = NET_ERR_RX_DEST;                                 /* ... & rtn dest err.                              */
            return;

        } else {
            pbuf_hdr->ConnType = NET_CONN_TYPE_CONN_HALF;
        }

    } else {
        pbuf_hdr->ConnType = NET_CONN_TYPE_CONN_FULL;
    }


                                                                    /* ------------ UPDATE BUF CONN CTRLS ------------- */
#if (NET_ERR_CFG_ARG_CHK_DBG_EN == DEF_ENABLED)
    if (conn_id           == NET_CONN_ID_NONE) {
       *perr = NET_CONN_ERR_INVALID_CONN;
        return;
    }
    if (conn_id_transport == NET_CONN_ID_NONE) {
       *perr = NET_CONN_ERR_INVALID_CONN;
        return;
    }
#endif

    pbuf_hdr->Conn_ID           = (CPU_INT16S)conn_id;
    pbuf_hdr->Conn_ID_Transport = (CPU_INT16S)conn_id_transport;
    pbuf_hdr->Conn_ID_App       = (CPU_INT16S)conn_id_app;


   *perr = NET_TCP_ERR_NONE;
}


/*$PAGE*/
/*
*********************************************************************************************************
*                                      NetTCP_RxPktConnHandler()
*
* Description : (1) Handle received TCP packets for its TCP connection :
*
*                   (a) Demultiplex  TCP packet to appropriate TCP connection state handler
*                   (b) Free/Discard TCP packet
*                   (c) Update receive statistics                                   See Note #2
*
*
* Argument(s) : pbuf        Pointer to network buffer that received TCP packet.
*               ----        Argument checked   in NetTCP_Rx().
*
*               pbuf_hdr    Pointer to network buffer header.
*               --------    Argument validated in NetTCP_Rx().
*
*               perr        Pointer to variable that will receive the return error code from this function :
*
*                               NET_TCP_ERR_CONN_DATA_NONE          Received packet successfully handled; but NO
*                                                                       data queued to receive queue(s).
*                               NET_TCP_ERR_CONN_DATA_VALID         Received packet successfully handled & valid
*                                                                       data queued for later processing.
*                               NET_TCP_ERR_CONN_RESET_VALID        Received reset segment successfully handled;
*                                                                       i.e. the TCP connection was reset.
*                               NET_TCP_ERR_CONN_CLOSED             TCP connection successfully closed.
*
*                               NET_TCP_ERR_INVALID_CONN_STATE      Invalid TCP connection state.
*
*                                                                   ---- RETURNED BY NetTCP_ConnIsUsed() : -----
*                               NET_ERR_INIT_INCOMPLETE             Network initialization NOT complete.
*                               NET_TCP_ERR_INVALID_CONN            Invalid TCP connection number.
*                               NET_TCP_ERR_CONN_NOT_USED           TCP connection NOT currently used.
*
*                                                                   --- RETURNED BY NetTCP_RxPktDiscard() : ----
*                               NET_ERR_RX                          Receive error; packet discarded.
*
* Return(s)   : none.
*
* Caller(s)   : NetTCP_Rx().
*
* Note(s)     : (2) (a) SOME   TCP receive statistics updated in NetTCP_RxPktDiscard(); do NOT re-update.
*
*                   (b) Update TCP receive statistics even if any transitory transmit error(s) occur in
*                       TCP connection state handler functions.
*
*               (3) RFC #1122, Section 4.2.2.13 states that "a host MAY implement a 'half-duplex' TCP
*                   close sequence ... i.e., closed in only one direction, and a host is permitted to
*                   continue sending data in the open direction on a half-closed connection".
*
*                   (a) "A host ... that has called CLOSE cannot continue to read data from the
*                        connection.  If such a host issues a CLOSE call while received data is
*                        still pending ... its TCP SHOULD send a RST to show that data was lost."
*
*                       However, since it does NOT seem reasonable to allow a half-closed connection
*                       "to continue sending data in the open direction" (i.e. from the host that did
*                       NOT issue a CLOSE call) but prevent the receiving host (i.e. the host that DID
*                       issue the CLOSE call) from receiving the transmitted data; it is assumed that
*                       the host that issued the CLOSE call MUST be allowed to receive data transmitted
*                       from the other host that has NOT yet issued its CLOSE.
*
*                   (b) However, "if such a host issues a CLOSE call ... [and] new data is received
*                       after CLOSE is called, its TCP SHOULD send a RST to show that data was lost".
*
*                       In other words, since a TCP connection in the connection-closing-data-available
*                       state is closed to further TCP data or controls, a TCP reset is transmitted as
*                       for the CLOSED state.
*
*                   (c) "Some systems have not implemented half-closed connections."
*********************************************************************************************************
*/
/*$PAGE*/
static  void  NetTCP_RxPktConnHandler (NET_BUF      *pbuf,
                                       NET_BUF_HDR  *pbuf_hdr,
                                       NET_ERR      *perr)
{
#if (((NET_CTR_CFG_STAT_EN     == DEF_ENABLED)                    || \
      (NET_CTR_CFG_ERR_EN      == DEF_ENABLED))                   && \
      (CPU_CFG_CRITICAL_METHOD == CPU_CRITICAL_METHOD_STATUS_LOCAL))
    CPU_SR            cpu_sr;
#endif
    NET_TCP_CONN_ID   conn_id_tcp;
    NET_TCP_CONN     *pconn;
    NET_ERR           err;


    conn_id_tcp = (NET_TCP_CONN_ID)pbuf_hdr->Conn_ID_Transport;

#if (NET_ERR_CFG_ARG_CHK_DBG_EN == DEF_ENABLED)                 /* -------------- VALIDATE TCP CONN USED -------------- */
   (void)NetTCP_ConnIsUsed(conn_id_tcp, perr);
    if (*perr != NET_TCP_ERR_NONE) {
         return;
    }
#endif


/*$PAGE*/
    pconn = &NetTCP_ConnTbl[conn_id_tcp];

    switch (pconn->ConnState) {
        case NET_TCP_CONN_STATE_FREE:
             NET_CTR_ERR_INC(NetTCP_ErrNotUsedCtr);
            *perr = NET_TCP_ERR_CONN_NOT_USED;
             return;                                            /* Prevent 'break NOT reachable' compiler warning.      */


        case NET_TCP_CONN_STATE_LISTEN:
             NetTCP_RxPktConnHandlerListen(pconn, pbuf, pbuf_hdr, perr);

             switch (*perr) {
                 case NET_TCP_ERR_CONN_DATA_NONE:
                      NetTCP_RxPktFree(pbuf);
                                                                /* 'break' intentionally omitted; do NOT move from the  */
                                                                /* ... following case : 'NET_TCP_ERR_CONN_DATA_VALID'.  */

                 case NET_TCP_ERR_CONN_DATA_VALID:
                      NET_CTR_STAT_INC(NetTCP_StatRxSegProcessedCtr);
                      break;


                 case NET_TCP_ERR_CONN_NOT_USED:
                 case NET_TCP_ERR_CONN_FAIL:
                 case NET_TCP_ERR_CONN_SEQ_INVALID:
                 case NET_TCP_ERR_CONN_ACK_INVALID:
                 case NET_TCP_ERR_CONN_RESET_INVALID:
                 case NET_TCP_ERR_CONN_SEQ_FIN_INVALID:
                 case NET_TCP_ERR_CONN_LISTEN_Q_MAX:
                 case NET_TCP_ERR_INVALID_CONN_ID:
                 case NET_TCP_ERR_INVALID_CONN_STATE:
                 case NET_TCP_ERR_INVALID_CONN_OP:
                 case NET_TCP_ERR_INVALID_LEN_SEG:
                 case NET_TCP_ERR_NONE_AVAIL:
                 case NET_TCP_ERR_TX:
                 case NET_ERR_TX:
                 case NET_CONN_ERR_NOT_USED:
                 case NET_CONN_ERR_INVALID_CONN:
                 case NET_CONN_ERR_INVALID_FAMILY:
                 case NET_CONN_ERR_INVALID_ADDR:
                 case NET_CONN_ERR_INVALID_ADDR_LEN:
                 default:
                      NetTCP_RxPktDiscard(pbuf, perr);
                      return;                                   /* Prevent 'break NOT reachable' compiler warning.      */
             }
             break;


        case NET_TCP_CONN_STATE_SYNC_RXD:
        case NET_TCP_CONN_STATE_SYNC_RXD_PASSIVE:
        case NET_TCP_CONN_STATE_SYNC_RXD_ACTIVE:
             NetTCP_RxPktConnHandlerSyncRxd(pconn, pbuf, pbuf_hdr, perr);

             switch (*perr) {
                 case NET_TCP_ERR_CONN_RESET_VALID:
                 case NET_TCP_ERR_CONN_DATA_NONE:
                      NetTCP_RxPktFree(pbuf);
                                                                /* 'break' intentionally omitted; do NOT move from the  */
                                                                /* ... following case : 'NET_TCP_ERR_CONN_DATA_VALID'.  */

                 case NET_TCP_ERR_CONN_DATA_VALID:
                      NET_CTR_STAT_INC(NetTCP_StatRxSegProcessedCtr);
                      break;


                 case NET_ERR_INIT_INCOMPLETE:
                 case NET_TCP_ERR_CONN_NOT_USED:
                 case NET_TCP_ERR_CONN_CLOSE:
                 case NET_TCP_ERR_CONN_FAULT:
                 case NET_TCP_ERR_CONN_FAIL:
                 case NET_TCP_ERR_CONN_SEQ_SYNC_INVALID:
                 case NET_TCP_ERR_CONN_SEQ_INVALID:
                 case NET_TCP_ERR_CONN_ACK_NONE:
                 case NET_TCP_ERR_CONN_ACK_INVALID:
                 case NET_TCP_ERR_CONN_RESET_INVALID:
                 case NET_TCP_ERR_CONN_DATA_INVALID:
                 case NET_TCP_ERR_CONN_DATA_DUP:
                 case NET_TCP_ERR_INVALID_CONN_STATE:
                 case NET_TCP_ERR_INVALID_CONN_OP:
                 case NET_TCP_ERR_INVALID_LEN_SEG:
                 case NET_TCP_ERR_TX:
                 case NET_TCP_ERR_TX_Q_SIGNAL_FAULT:
                 case NET_TCP_ERR_RE_TX_SEG_TH:
                 case NET_TCP_ERR_NONE_AVAIL:
                 case NET_CONN_ERR_INVALID_FAMILY:
                 case NET_CONN_ERR_INVALID_ADDR:
                 case NET_CONN_ERR_INVALID_ADDR_LEN:
                 default:
                      NetTCP_RxPktDiscard(pbuf, perr);
                      return;                                   /* Prevent 'break NOT reachable' compiler warning.      */
             }
             break;

/*$PAGE*/
        case NET_TCP_CONN_STATE_SYNC_TXD:
             NetTCP_RxPktConnHandlerSyncTxd(pconn, pbuf, pbuf_hdr, perr);

             switch (*perr) {
                 case NET_TCP_ERR_CONN_RESET_VALID:
                 case NET_TCP_ERR_CONN_DATA_NONE:
                      NetTCP_RxPktFree(pbuf);
                                                                /* 'break' intentionally omitted; do NOT move from the  */
                                                                /* ... following case : 'NET_TCP_ERR_CONN_DATA_VALID'.  */

                 case NET_TCP_ERR_CONN_DATA_VALID:
                      NET_CTR_STAT_INC(NetTCP_StatRxSegProcessedCtr);
                      break;


                 case NET_ERR_INIT_INCOMPLETE:
                 case NET_TCP_ERR_CONN_NOT_USED:
                 case NET_TCP_ERR_CONN_CLOSE:
                 case NET_TCP_ERR_CONN_FAULT:
                 case NET_TCP_ERR_CONN_FAIL:
                 case NET_TCP_ERR_CONN_SEQ_INVALID:
                 case NET_TCP_ERR_CONN_ACK_INVALID:
                 case NET_TCP_ERR_CONN_RESET_INVALID:
                 case NET_TCP_ERR_CONN_SEQ_FIN_INVALID:
                 case NET_TCP_ERR_CONN_DATA_INVALID:
                 case NET_TCP_ERR_CONN_DATA_DUP:
                 case NET_TCP_ERR_INVALID_CONN_STATE:
                 case NET_TCP_ERR_INVALID_CONN_OP:
                 case NET_TCP_ERR_INVALID_LEN_SEG:
                 case NET_TCP_ERR_TX:
                 case NET_TCP_ERR_TX_Q_SIGNAL_FAULT:
                 case NET_TCP_ERR_RE_TX_SEG_TH:
                 case NET_TCP_ERR_NONE_AVAIL:
                 case NET_CONN_ERR_INVALID_FAMILY:
                 case NET_CONN_ERR_INVALID_ADDR:
                 case NET_CONN_ERR_INVALID_ADDR_LEN:
                 default:
                      NetTCP_RxPktDiscard(pbuf, perr);
                      return;                                   /* Prevent 'break NOT reachable' compiler warning.      */
             }
             break;


        case NET_TCP_CONN_STATE_CONN:
             NetTCP_RxPktConnHandlerConn(pconn, pbuf, pbuf_hdr, perr);

             switch (*perr) {
                 case NET_TCP_ERR_CONN_RESET_VALID:
                 case NET_TCP_ERR_CONN_DATA_NONE:
                      NetTCP_RxPktFree(pbuf);
                                                                /* 'break' intentionally omitted; do NOT move from the  */
                                                                /* ... following case : 'NET_TCP_ERR_CONN_DATA_VALID'.  */

                 case NET_TCP_ERR_CONN_DATA_VALID:
                      NET_CTR_STAT_INC(NetTCP_StatRxSegProcessedCtr);
                      break;


                 case NET_ERR_INIT_INCOMPLETE:
                 case NET_TCP_ERR_CONN_NOT_USED:
                 case NET_TCP_ERR_CONN_CLOSE:
                 case NET_TCP_ERR_CONN_FAULT:
                 case NET_TCP_ERR_CONN_FAIL:
                 case NET_TCP_ERR_CONN_SEQ_SYNC_INVALID:
                 case NET_TCP_ERR_CONN_SEQ_INVALID:
                 case NET_TCP_ERR_CONN_ACK_NONE:
                 case NET_TCP_ERR_CONN_ACK_INVALID:
                 case NET_TCP_ERR_CONN_RESET_INVALID:
                 case NET_TCP_ERR_CONN_DATA_INVALID:
                 case NET_TCP_ERR_CONN_DATA_DUP:
                 case NET_TCP_ERR_INVALID_CONN_STATE:
                 case NET_TCP_ERR_INVALID_CONN_OP:
                 case NET_TCP_ERR_INVALID_LEN_SEG:
                 case NET_TCP_ERR_RX_Q_FULL:
                 case NET_TCP_ERR_RX_Q_SIGNAL_FAULT:
                 case NET_TCP_ERR_TX:
                 case NET_TCP_ERR_TX_Q_SIGNAL_FAULT:
                 case NET_TCP_ERR_RE_TX_SEG_TH:
                 case NET_TCP_ERR_NONE_AVAIL:
                 case NET_CONN_ERR_INVALID_FAMILY:
                 case NET_CONN_ERR_INVALID_ADDR:
                 case NET_CONN_ERR_INVALID_ADDR_LEN:
                 default:
                      NetTCP_RxPktDiscard(pbuf, perr);
                      return;                                   /* Prevent 'break NOT reachable' compiler warning.      */
             }
             break;

/*$PAGE*/
        case NET_TCP_CONN_STATE_FIN_WAIT_1:
             NetTCP_RxPktConnHandlerFinWait1(pconn, pbuf, pbuf_hdr, perr);

             switch (*perr) {
                 case NET_TCP_ERR_CONN_RESET_VALID:
                 case NET_TCP_ERR_CONN_DATA_NONE:
                      NetTCP_RxPktFree(pbuf);
                                                                /* 'break' intentionally omitted; do NOT move from the  */
                                                                /* ... following case : 'NET_TCP_ERR_CONN_DATA_VALID'.  */

                 case NET_TCP_ERR_CONN_DATA_VALID:
                      NET_CTR_STAT_INC(NetTCP_StatRxSegProcessedCtr);
                      break;


                 case NET_ERR_INIT_INCOMPLETE:
                 case NET_TCP_ERR_CONN_NOT_USED:
                 case NET_TCP_ERR_CONN_CLOSE:
                 case NET_TCP_ERR_CONN_FAULT:
                 case NET_TCP_ERR_CONN_FAIL:
                 case NET_TCP_ERR_CONN_SEQ_SYNC_INVALID:
                 case NET_TCP_ERR_CONN_SEQ_INVALID:
                 case NET_TCP_ERR_CONN_ACK_NONE:
                 case NET_TCP_ERR_CONN_ACK_INVALID:
                 case NET_TCP_ERR_CONN_RESET_INVALID:
                 case NET_TCP_ERR_CONN_DATA_INVALID:
                 case NET_TCP_ERR_CONN_DATA_DUP:
                 case NET_TCP_ERR_INVALID_CONN_ID:
                 case NET_TCP_ERR_INVALID_CONN_STATE:
                 case NET_TCP_ERR_INVALID_CONN_OP:
                 case NET_TCP_ERR_INVALID_LEN_SEG:
                 case NET_TCP_ERR_RX_Q_FULL:
                 case NET_TCP_ERR_RX_Q_SIGNAL_FAULT:
                 case NET_TCP_ERR_TX:
                 case NET_TCP_ERR_TX_Q_SIGNAL_FAULT:
                 case NET_TCP_ERR_RE_TX_SEG_TH:
                 case NET_TCP_ERR_NONE_AVAIL:
                 case NET_CONN_ERR_INVALID_FAMILY:
                 case NET_CONN_ERR_INVALID_ADDR:
                 case NET_CONN_ERR_INVALID_ADDR_LEN:
                 case NET_CONN_ERR_INVALID_CONN:
                 case NET_CONN_ERR_NOT_USED:
                 default:
                      NetTCP_RxPktDiscard(pbuf, perr);
                      return;                                   /* Prevent 'break NOT reachable' compiler warning.      */
             }
             break;


        case NET_TCP_CONN_STATE_FIN_WAIT_2:
             NetTCP_RxPktConnHandlerFinWait2(pconn, pbuf, pbuf_hdr, perr);

             switch (*perr) {
                 case NET_TCP_ERR_CONN_RESET_VALID:
                 case NET_TCP_ERR_CONN_DATA_NONE:
                      NetTCP_RxPktFree(pbuf);
                                                                /* 'break' intentionally omitted; do NOT move from the  */
                                                                /* ... following case : 'NET_TCP_ERR_CONN_DATA_VALID'.  */

                 case NET_TCP_ERR_CONN_DATA_VALID:
                      NET_CTR_STAT_INC(NetTCP_StatRxSegProcessedCtr);
                      break;


                 case NET_ERR_INIT_INCOMPLETE:
                 case NET_TCP_ERR_CONN_NOT_USED:
                 case NET_TCP_ERR_CONN_FAULT:
                 case NET_TCP_ERR_CONN_FAIL:
                 case NET_TCP_ERR_CONN_SEQ_SYNC_INVALID:
                 case NET_TCP_ERR_CONN_SEQ_INVALID:
                 case NET_TCP_ERR_CONN_ACK_NONE:
                 case NET_TCP_ERR_CONN_ACK_INVALID:
                 case NET_TCP_ERR_CONN_RESET_INVALID:
                 case NET_TCP_ERR_CONN_DATA_INVALID:
                 case NET_TCP_ERR_CONN_DATA_DUP:
                 case NET_TCP_ERR_INVALID_CONN_STATE:
                 case NET_TCP_ERR_INVALID_CONN_OP:
                 case NET_TCP_ERR_INVALID_LEN_SEG:
                 case NET_TCP_ERR_RX_Q_FULL:
                 case NET_TCP_ERR_RX_Q_SIGNAL_FAULT:
                 case NET_TCP_ERR_NONE_AVAIL:
                 default:
                      NetTCP_RxPktDiscard(pbuf, perr);
                      return;                                   /* Prevent 'break NOT reachable' compiler warning.      */
             }
             break;

/*$PAGE*/
        case NET_TCP_CONN_STATE_CLOSING:
             NetTCP_RxPktConnHandlerClosing(pconn, pbuf, pbuf_hdr, perr);

             switch (*perr) {
                 case NET_TCP_ERR_CONN_RESET_VALID:
                 case NET_TCP_ERR_CONN_DATA_NONE:
                      NetTCP_RxPktFree(pbuf);
                                                                /* 'break' intentionally omitted; do NOT move from the  */
                                                                /* ... following case : 'NET_TCP_ERR_CONN_DATA_VALID'.  */

                 case NET_TCP_ERR_CONN_DATA_VALID:
                      NET_CTR_STAT_INC(NetTCP_StatRxSegProcessedCtr);
                      break;


                 case NET_ERR_INIT_INCOMPLETE:
                 case NET_TCP_ERR_CONN_NOT_USED:
                 case NET_TCP_ERR_CONN_FAULT:
                 case NET_TCP_ERR_CONN_FAIL:
                 case NET_TCP_ERR_CONN_SEQ_SYNC_INVALID:
                 case NET_TCP_ERR_CONN_SEQ_INVALID:
                 case NET_TCP_ERR_CONN_ACK_NONE:
                 case NET_TCP_ERR_CONN_ACK_INVALID:
                 case NET_TCP_ERR_CONN_RESET_INVALID:
                 case NET_TCP_ERR_CONN_DATA_INVALID:
                 case NET_TCP_ERR_CONN_DATA_DUP:
                 case NET_TCP_ERR_INVALID_CONN_ID:
                 case NET_TCP_ERR_INVALID_CONN_STATE:
                 case NET_TCP_ERR_INVALID_CONN_OP:
                 case NET_TCP_ERR_INVALID_LEN_SEG:
                 case NET_TCP_ERR_RX_Q_FULL:
                 case NET_TCP_ERR_RX_Q_SIGNAL_FAULT:
                 case NET_TCP_ERR_TX:
                 case NET_TCP_ERR_TX_Q_SIGNAL_FAULT:
                 case NET_TCP_ERR_RE_TX_SEG_TH:
                 case NET_TCP_ERR_NONE_AVAIL:
                 case NET_CONN_ERR_INVALID_FAMILY:
                 case NET_CONN_ERR_INVALID_ADDR:
                 case NET_CONN_ERR_INVALID_ADDR_LEN:
                 case NET_CONN_ERR_INVALID_CONN:
                 case NET_CONN_ERR_NOT_USED:
                 default:
                      NetTCP_RxPktDiscard(pbuf, perr);
                      return;                                   /* Prevent 'break NOT reachable' compiler warning.      */
             }
             break;


        case NET_TCP_CONN_STATE_TIME_WAIT:
             NetTCP_RxPktConnHandlerTimeWait(pconn, pbuf, pbuf_hdr, perr);

             switch (*perr) {
                 case NET_TCP_ERR_CONN_RESET_VALID:
                 case NET_TCP_ERR_CONN_DATA_NONE:
                      NetTCP_RxPktFree(pbuf);
                                                                /* 'break' intentionally omitted; do NOT move from the  */
                                                                /* ... following case : 'NET_TCP_ERR_CONN_DATA_VALID'.  */

                 case NET_TCP_ERR_CONN_DATA_VALID:
                      NET_CTR_STAT_INC(NetTCP_StatRxSegProcessedCtr);
                      break;


                 case NET_ERR_INIT_INCOMPLETE:
                 case NET_TCP_ERR_CONN_NOT_USED:
                 case NET_TCP_ERR_CONN_FAULT:
                 case NET_TCP_ERR_CONN_FAIL:
                 case NET_TCP_ERR_CONN_SEQ_SYNC_INVALID:
                 case NET_TCP_ERR_CONN_SEQ_INVALID:
                 case NET_TCP_ERR_CONN_ACK_NONE:
                 case NET_TCP_ERR_CONN_ACK_INVALID:
                 case NET_TCP_ERR_CONN_RESET_INVALID:
                 case NET_TCP_ERR_CONN_DATA_INVALID:
                 case NET_TCP_ERR_CONN_DATA_DUP:
                 case NET_TCP_ERR_INVALID_CONN_STATE:
                 case NET_TCP_ERR_INVALID_CONN_OP:
                 case NET_TCP_ERR_INVALID_LEN_SEG:
                 case NET_TCP_ERR_RX_Q_FULL:
                 case NET_TCP_ERR_RX_Q_SIGNAL_FAULT:
                 case NET_TCP_ERR_NONE_AVAIL:
                 default:
                      NetTCP_RxPktDiscard(pbuf, perr);
                      return;                                   /* Prevent 'break NOT reachable' compiler warning.      */
             }
             break;

/*$PAGE*/
        case NET_TCP_CONN_STATE_CLOSE_WAIT:
             NetTCP_RxPktConnHandlerCloseWait(pconn, pbuf, pbuf_hdr, perr);

             switch (*perr) {
                 case NET_TCP_ERR_CONN_RESET_VALID:
                 case NET_TCP_ERR_CONN_DATA_NONE:
                      NetTCP_RxPktFree(pbuf);
                                                                /* 'break' intentionally omitted; do NOT move from the  */
                                                                /* ... following case : 'NET_TCP_ERR_CONN_DATA_VALID'.  */

                 case NET_TCP_ERR_CONN_DATA_VALID:
                      NET_CTR_STAT_INC(NetTCP_StatRxSegProcessedCtr);
                      break;


                 case NET_ERR_INIT_INCOMPLETE:
                 case NET_TCP_ERR_CONN_NOT_USED:
                 case NET_TCP_ERR_CONN_FAULT:
                 case NET_TCP_ERR_CONN_FAIL:
                 case NET_TCP_ERR_CONN_SEQ_SYNC_INVALID:
                 case NET_TCP_ERR_CONN_SEQ_INVALID:
                 case NET_TCP_ERR_CONN_ACK_NONE:
                 case NET_TCP_ERR_CONN_ACK_INVALID:
                 case NET_TCP_ERR_CONN_RESET_INVALID:
                 case NET_TCP_ERR_CONN_DATA_INVALID:
                 case NET_TCP_ERR_CONN_DATA_DUP:
                 case NET_TCP_ERR_INVALID_CONN_STATE:
                 case NET_TCP_ERR_INVALID_CONN_OP:
                 case NET_TCP_ERR_INVALID_LEN_SEG:
                 case NET_TCP_ERR_RX_Q_FULL:
                 case NET_TCP_ERR_RX_Q_SIGNAL_FAULT:
                 case NET_TCP_ERR_TX:
                 case NET_TCP_ERR_TX_Q_SIGNAL_FAULT:
                 case NET_TCP_ERR_RE_TX_SEG_TH:
                 case NET_TCP_ERR_NONE_AVAIL:
                 case NET_CONN_ERR_INVALID_FAMILY:
                 case NET_CONN_ERR_INVALID_ADDR:
                 case NET_CONN_ERR_INVALID_ADDR_LEN:
                 default:
                      NetTCP_RxPktDiscard(pbuf, perr);
                      return;                                   /* Prevent 'break NOT reachable' compiler warning.      */
             }
             break;


        case NET_TCP_CONN_STATE_LAST_ACK:
             NetTCP_RxPktConnHandlerLastAck(pconn, pbuf, pbuf_hdr, perr);

             switch (*perr) {
                 case NET_TCP_ERR_CONN_RESET_VALID:
                 case NET_TCP_ERR_CONN_DATA_NONE:
                 case NET_TCP_ERR_CONN_CLOSED:
                      NetTCP_RxPktFree(pbuf);
                                                                /* 'break' intentionally omitted; do NOT move from the  */
                                                                /* ... following case : 'NET_TCP_ERR_CONN_DATA_VALID'.  */

                 case NET_TCP_ERR_CONN_DATA_VALID:
                      NET_CTR_STAT_INC(NetTCP_StatRxSegProcessedCtr);
                      break;


                 case NET_ERR_INIT_INCOMPLETE:
                 case NET_TCP_ERR_CONN_NOT_USED:
                 case NET_TCP_ERR_CONN_FAULT:
                 case NET_TCP_ERR_CONN_FAIL:
                 case NET_TCP_ERR_CONN_SEQ_SYNC_INVALID:
                 case NET_TCP_ERR_CONN_SEQ_INVALID:
                 case NET_TCP_ERR_CONN_ACK_NONE:
                 case NET_TCP_ERR_CONN_ACK_INVALID:
                 case NET_TCP_ERR_CONN_RESET_INVALID:
                 case NET_TCP_ERR_CONN_DATA_INVALID:
                 case NET_TCP_ERR_CONN_DATA_DUP:
                 case NET_TCP_ERR_INVALID_CONN_STATE:
                 case NET_TCP_ERR_INVALID_CONN_OP:
                 case NET_TCP_ERR_INVALID_LEN_SEG:
                 case NET_TCP_ERR_RX_Q_FULL:
                 case NET_TCP_ERR_RX_Q_SIGNAL_FAULT:
                 case NET_TCP_ERR_TX:
                 case NET_TCP_ERR_TX_Q_SIGNAL_FAULT:
                 case NET_TCP_ERR_RE_TX_SEG_TH:
                 case NET_TCP_ERR_NONE_AVAIL:
                 case NET_CONN_ERR_INVALID_FAMILY:
                 case NET_CONN_ERR_INVALID_ADDR:
                 case NET_CONN_ERR_INVALID_ADDR_LEN:
                 default:
                      NetTCP_RxPktDiscard(pbuf, perr);
                      return;                                   /* Prevent 'break NOT reachable' compiler warning.      */
             }
             break;

/*$PAGE*/
        case NET_TCP_CONN_STATE_CLOSING_DATA_AVAIL:
             NetTCP_TxConnReset((NET_TCP_CONN     *) 0,         /* Tx TCP conn reset (see Note #3b).                    */
                                (NET_BUF_HDR      *) pbuf_hdr,
                                (NET_TCP_RESET_CODE) NET_TCP_CONN_TX_RESET,
                                (NET_TCP_CLOSE_CODE) NET_TCP_CONN_CLOSE_ALL,
                                (NET_ERR          *)&err);

             NetTCP_RxPktDiscard(pbuf, perr);
             return;                                            /* Prevent 'break NOT reachable' compiler warning.      */


        case NET_TCP_CONN_STATE_NONE:
        case NET_TCP_CONN_STATE_CLOSED:
        default:
             NetTCP_ConnClose(pconn, pbuf_hdr, DEF_YES, NET_TCP_CONN_CLOSE_ALL);
             NET_CTR_ERR_INC(NetTCP_ErrConnInvalidStateCtr);
            *perr = NET_TCP_ERR_INVALID_CONN_STATE;
             return;                                            /* Prevent 'break NOT reachable' compiler warning.      */
    }
}


/*$PAGE*/
/*
*********************************************************************************************************
*                                   NetTCP_RxPktConnHandlerListen()
*
* Description : (1) Handle TCP connection in LISTEN state :
*
*                   (a) Validate received TCP packet for current TCP connection state :
*
*                       (1) Reset           (RST)                                           See Note #2a
*                       (2) Acknowledgement (ACK)                                           See Note #2b
*                       (3) Synchronization (SYN)                                           See Note #2c
*
*                   (b) Check if TCP connection listen queue is available                   See Note #3
*
*                   (c) Prepare/configure TCP connection :
*
*                       (1) Clone new TCP connection from current TCP listen connection,    See Note #5a
*                               if half-connection :
*
*                           (A) Get  connections
*                           (B) Set  connection  identification handles
*                           (C) Set  connection  addresses
*                           (D) Add  connection  into connection list
*                           (E) Copy connection  from half-connection
*
*                       (2) Re-configure current TCP listen connection,                     See Note #5b
*                               if full-connection
*
*                   (d) Update TCP connection :
*                       (1) Handle received TCP segment                                     See Note #2c2
*                       (2) Configure TCP connection remote host maximum segment size       See Note #7
*
*                   (e) Transmit TCP connection synchronization for valid received          See Note #2c3
*                           TCP connection reqeusts
*
*                   (f) Update TCP connection state                                         See Note #2c
*
*
* Argument(s) : pconn       Pointer to a TCP connection.
*               -----       Argument validated in NetTCP_RxPktConnHandler().
*
*               pbuf        Pointer to network buffer that received TCP packet.
*               ----        Argument checked   in NetTCP_Rx().
*
*               pbuf_hdr    Pointer to network buffer header that received TCP packet.
*               --------    Argument validated in NetTCP_Rx().
*
*               perr        Pointer to variable that will receive the return error code from this function :
*
*                               NET_TCP_ERR_CONN_SEQ_INVALID        Received segment's sequence        number is
*                                                                       NOT valid for current TCP connection.
*                               NET_TCP_ERR_CONN_ACK_INVALID        Received segment's acknowledgement number is
*                                                                       NOT valid for current TCP connection.
*                               NET_TCP_ERR_CONN_SEQ_FIN_INVALID    Received segment's finish/close flag is
*                                                                       NOT valid for current TCP connection.
*                               NET_TCP_ERR_CONN_RESET_INVALID      Received segment's reset        flag is
*                                                                       NOT valid for current TCP connection.
*
*                               NET_TCP_ERR_CONN_LISTEN_Q_MAX       TCP connection listen queue is NOT available
*                                                                       queue a new connection.
*
*                               NET_TCP_ERR_CONN_FAIL               TCP connection operation(s) failed.
*                               NET_TCP_ERR_NONE_AVAIL              Resources NOT available.
*
*                               NET_CONN_ERR_INVALID_FAMILY         Invalid network connection family.
*
*                                                                   ------ RETURNED BY NetTCP_RxPktConnIsValidReset() : ------
*                                                                   ------- RETURNED BY NetTCP_RxPktConnIsValidAck() : -------
*                                                                   ------- RETURNED BY NetTCP_RxPktConnIsValidSeq() : -------
*                               NET_TCP_ERR_CONN_NOT_USED           TCP connection NOT currently used.
*                               NET_TCP_ERR_INVALID_CONN_STATE      Invalid TCP connection state.
*                               NET_TCP_ERR_INVALID_LEN_SEG         Invalid TCP sequence-segment length.
*
*                                                                   - RETURNED BY NetTCP_RxPktConnHandlerListenQ_IsAvail() : -
*                               NET_ERR_INIT_INCOMPLETE             Network initialization NOT complete.
*                               NET_TCP_ERR_INVALID_CONN_ID         Invalid application connection.
*                               NET_TCP_ERR_INVALID_CONN_OP         Invalid TCP connection operation.
*                               NET_CONN_ERR_INVALID_CONN           Invalid network connection number.
*                               NET_CONN_ERR_NOT_USED               Network connection NOT currently used.
*
*                                                                   ----------- RETURNED BY NetTCP_TxConnSync() : ------------
*                               NET_TCP_ERR_CONN_FAULT              TCP connection fault; connection(s) aborted.
*                               NET_CONN_ERR_INVALID_ADDR           Invalid TCP connection address.
*                               NET_CONN_ERR_INVALID_ADDR_LEN       Invalid TCP connection address length.
*                               NET_TCP_ERR_TX                      TCP transmit error.
*                               NET_ERR_TX                              Transmit error.
*
*                                                                   ------- RETURNED BY NetTCP_RxPktConnHandlerSeg() : -------
*                               NET_TCP_ERR_CONN_DATA_NONE          Received packet successfully handled; but NO
*                                                                       data queued to receive queue(s).
*                               NET_TCP_ERR_CONN_DATA_VALID         Received packet successfully handled & valid
*                                                                       data queued for later processing (see Note #2c2).
*
* Return(s)   : none.
*
* Caller(s)   : NetTCP_RxPktConnHandler().
*$PAGE*
* Note(s)     : (2) RFC #793, Section 3.9 'Event Processing : SEGMENT ARRIVES : LISTEN [State]' states that :
*
*                   (a) "An incoming RST should be ignored."
*
*                   (b) "Any acknowledgment is bad if it arrives on a connection still in the LISTEN state.
*                        An acceptable reset segment should be formed for any arriving ACK-bearing segment."
*
*                   (c) "If the SYN bit is set ... the connection state should be changed to SYN-RECEIVED" ...
*
*                       (1) "Set RCV.NXT to SEG.SEQ+1, IRS is set to SEG.SEQ ..."
*                           (A) See Note #2c3
*
*                       (2) "And any other control or text should be queued for processing later."
*
*                           (A) If any control or text is queued for later processing, the next sequence octet to
*                               receive (RCV.NXT) MUST include the length of this received segment (SEG.LEN) :
*
*                               (1) RCV.NXT = SEG.SEQ + SEG.LEN + 1
*
*                       (3) "ISS should be selected and a SYN segment sent."
*
*                   (d) "Any other control or text-bearing segment (not containing SYN) must have an ACK and
*                        thus would be discarded by the ACK processing ... So you are unlikely to get here,
*                        but if you do, drop the segment, and return."
*
*                   (e) RFC #793, Section 3.9 'Event Processing : SEGMENT ARRIVES : Check FIN Bit' states to
*                       "not process the FIN if the state is CLOSED, LISTEN or SYN-SENT since the SEG.SEQ cannot
*                       be validated; drop the segment".
*
*               (3) (a) Stevens, TCP/IP Illustrated, Volume 1, 8th Printing, Section 18.11, Pages 257-258 states 
*                       that :
*
*                       (1) "Each listening end point has a fixed length queue of connections that have been
*                            accepted by TCP (i.e., the three-way handshake is complete), but not yet accepted
*                            by the application."
*
*                       (3) "When a connection request arrives (i.e., the SYN segment), ... the current number
*                            of connections already queued for this listening end point [is checked] to see
*                            whether to accept the connection or not."
*
*                       (4) "If there is room on this listening end point's queue for this new connection, ...
*                            the TCP module ACKs the SYN and completes the connection."
*
*                       (5) "If there is not room on the queue for the new connection" ... :
*
*                           (A) "TCP just ignores the received SYN."
*                           (B) "Nothing is sent back (i.e., no RST segment)."
*
*                   (b) (A) Wright/Stevens, TCP/IP Illustrated, Volume 2, 3rd Printing, Section 15.9, Page 455 
*                           reiterates that :
*
*                           (2) A "listen ... socket ... limit[s] ... the number of connections that can be
*                               queued on the socket," ...
*
*                           (5) "after which the socket layer refuses to queue additional connection requests.
*                                When this occurs, TCP ignores incoming connection requests."
*
*                       (B) Wright/Stevens, TCP/IP Illustrated, Volume 2, 3rd Printing, Section 28.2, Page 930
*                           also states that :
*
*                           (5) (A) "By silently dropping the segment" ...
*                               (B) "and not replying with an RST,"    ...
*                               (C) "The client's connection request should time out, causing the client to
*                                    retransmit the SYN."
*
*                       (C) Stevens, TCP/IP Illustrated, Volume 1, 8th Printing, Section 18.11, Pages 259-260
*                           summarizes that :
*
*                           (5) (A) "TCP ignores the incoming SYN when the queue is full," ...
*                               (B) "and doesn't respond with an RST,"                     ...
*
*                               (C) (1) "because ... this condition could change in a short while ... [and] by
*                                        ignoring the SYN, the server forces the client TCP to re-transmit the
*                                        SYN later, hoping that the queue will then have room for the new
*                                        connection".
*
*                                   (2) Whereas page 259-260 counters that "if the server's TCP responded with
*                                       a reset, the client's active open would abort".
*
*                   See also 'NetTCP_RxPktConnHandlerListenQ_IsAvail()  Note #1'.
*$PAGE*
*               (4) The 'NET_CONN_CFG_FAMILY' pre-processor 'else'-conditional code will never be compiled/linked
*                   since 'net_conn.h' ensures that the family type configuration constant (NET_CONN_CFG_FAMILY)
*                   is configured with an appropriate family type value (see 'net_conn.h  CONFIGURATION ERRORS').
*                   The 'else'-conditional code is included for completeness & as an extra precaution in case
*                   'net_conn.h' is incorrectly modified.
*
*               (5) (a) (1) If any received TCP connection request to a LISTEN-state connection is a half-connection
*                           -- i.e. a connection with ONLY the local address specified/configured -- then a new
*                           connection is cloned from the LISTEN-state connection to handle each unique connection
*                           request.
*
*                       (2) The following connection parameters are cloned/copied from the LISTEN-state connection :
*
*                           (A) Application connection handle identifier
*                               (1) When the cloned connection is fully connected/established, it is queued to the
*                                   LISTEN-state connection's application connection as a cloned network connection
*                                   until the connection is accepted & a new application connection is created.
*
*                                   See also 'net_sock.c  NetSock_Accept()  Notes #1d & #1e'.
*
*                           (B) (1) TCP connection receive  parameters
*                               (2) TCP connection transmit parameters
*                               (3) TCP connection timeout  values
*
*                               See also 'NetTCP_ConnCopy()  Note #1'.
*
*                   (b) If any received TCP connection request to a LISTEN-state connection is a full-connection --
*                       i.e. a connection with BOTH the local & remote addresses specified/configured -- then the
*                       LISTEN-state connection is re-configured to handle the received connection request.
*
*               (6) On ANY TCP LISTEN-connection preparation errors, network resources MUST be appropriately freed :
*
*                   (a) If NO TCP     connections available, NO           resources  need be freed.
*                   (b) If NO network connections available, ONLY the TCP connection need be closed.
*                   (c) If    network connection preparation fails, the TCP & network connection MUST both
*                          be closed.  However, the TCP connection need NOT close application connection(s).
*
*                       See also 'NetTCP_ConnCloseHandler()  Note #2b1C1'.
*
*                   (d) If any remaining TCP connection preparation fails, the TCP & network connection MUST
*                       both be closed.  The application connection(s) SHOULD NOT be closed since it is cloned
*                       from the LISTEN-state connection (see Note #4), but network connections MAY need to be
*                       de-referenced from the application connection(s).
*
*                       See also 'NetTCP_ConnCloseHandler()  Note #2b';
*                              & 'net_conn.c  NetConn_CloseApp()          Note #1'
*                              & 'net_sock.c  NetSock_FreeConnFromSock()  Note #2'.
*
*               (7) RFC #1122, Section 4.2.2.6 states that ... :
*
*                   (a) A "TCP SHOULD send an MSS (Maximum Segment Size) option in every SYN segment".
*
*                   (b) "If an MSS option is not received at connection setup, TCP MUST assume a default
*                        send MSS of 536."
*
*               (8) TCP connection timeout for LISTEN state is implemented by TCP connection retransmission
*                   function(s) (see 'NetTCP_TxConnReTxQ()  Note #3c').
*********************************************************************************************************
*/
/*$PAGE*/
static  void  NetTCP_RxPktConnHandlerListen (NET_TCP_CONN  *pconn,
                                             NET_BUF       *pbuf,
                                             NET_BUF_HDR   *pbuf_hdr,
                                             NET_ERR       *perr)
{
#if (NET_CONN_CFG_FAMILY == NET_CONN_FAMILY_IP_V4_SOCK)
    NET_IP_ADDR          addr_ip;
#endif
    CPU_INT08U           addr_local[NET_CONN_CFG_ADDR_LEN];
    CPU_INT08U           addr_remote[NET_CONN_CFG_ADDR_LEN];
    CPU_BOOLEAN          q_avail;
    NET_TCP_SEQ_CODE     seq_code;
    NET_TCP_ACK_CODE     ack_code;
    NET_TCP_RESET_CODE   reset_code;
    NET_TCP_PORT_NBR     port_nbr;
    NET_CONN_FAMILY      conn_family;
    NET_CONN_LIST_IX     conn_protocol_ix;
    NET_CONN_ID          conn_id;
    NET_CONN_ID          conn_id_clone;
    NET_CONN_ID          conn_id_clone_app;
    NET_TCP_CONN_ID      conn_id_clone_tcp;
    NET_TCP_CONN        *pconn_clone;
    NET_TCP_CONN        *pconn_tx_sync;
    NET_ERR              err;
    NET_ERR              err_rtn;


                                                                        /* ---------- VALIDATE RX'D TCP PKT ----------- */
                                                                        /* Chk for rx'd fin/close.                      */
    if (pbuf_hdr->TCP_SegClose != DEF_NO) {                             /* If invalid   fin/close rx'd, ...             */
       *perr = NET_TCP_ERR_CONN_SEQ_FIN_INVALID;
        return;                                                         /* ... ignore TCP pkt    (see Note #2e).        */
    }

                                                                        /* Chk for rx'd reset.                          */
    reset_code = NetTCP_RxPktConnIsValidReset(pconn, pbuf_hdr, perr);
    if (*perr != NET_TCP_ERR_NONE) {
         return;
    }
    if (reset_code != NET_TCP_CONN_RX_RESET_NONE) {                     /* If reset    rx'd, ...                        */
       *perr = NET_TCP_ERR_CONN_RESET_INVALID;
        return;                                                         /* ... ignore TCP pkt    (see Note #2a).        */
    }

                                                                        /* Chk for rx'd ack.                            */
    ack_code = NetTCP_RxPktConnIsValidAck(pconn, pbuf_hdr, perr);
    if (*perr != NET_TCP_ERR_NONE) {
         return;
    }
    if (ack_code != NET_TCP_CONN_RX_ACK_NONE) {                         /* If ack      rx'd, ...                        */
                                                                        /* ... tx TCP conn reset (see Note #2b).        */
        NetTCP_TxConnReset(pconn, pbuf_hdr, NET_TCP_CONN_TX_RESET, NET_TCP_CONN_CLOSE_ALL, &err);
       *perr = NET_TCP_ERR_CONN_ACK_INVALID;
        return;
    }

                                                                        /* Chk     rx'd seq nbr.                        */
    seq_code = NetTCP_RxPktConnIsValidSeq(pconn, pbuf_hdr, perr);
    if (*perr != NET_TCP_ERR_NONE) {
         return;
    }
    if (seq_code != NET_TCP_CONN_RX_SEQ_SYNC) {                         /* If sync NOT rx'd, ...                        */
       *perr = NET_TCP_ERR_CONN_SEQ_INVALID;
        return;                                                         /* ... ignore TCP pkt    (see Note #2d).        */
    }
                                                                        /* Else sync avail, update seg lens.            */
    pbuf_hdr->TCP_SegLenInit += NET_TCP_SEG_LEN_SYNC;
    pbuf_hdr->TCP_SegLen     += NET_TCP_SEG_LEN_SYNC;



/*$PAGE*/
                                                                        /* ---------- CHK TCP CONN LISTEN Q ----------- */
    q_avail = NetTCP_RxPktConnHandlerListenQ_IsAvail(pconn, perr);      /* Chk TCP listen Q     avail.                  */
    if (*perr != NET_TCP_ERR_NONE) {
         return;
    }

    if (q_avail != DEF_YES) {                                           /* If  TCP listen Q NOT avail (see Note #3a5),  */
       *perr = NET_TCP_ERR_CONN_LISTEN_Q_MAX;
        return;                                                         /* ... ignore TCP pkt         (see Note #3a5A). */
    }



                                                                        /* ------------- PREPARE TCP CONN ------------- */
    if (pbuf_hdr->ConnType != NET_CONN_TYPE_CONN_FULL) {                /* If pkt demux'd to half-conn, clone new conn  */
                                                                        /* .. from LISTEN    half-conn (see Note #5a).  */
                                                                        /* ---------------- GET CONNS ----------------- */
        conn_id_clone_tcp = NetTCP_ConnGet(&err);
        if ( err != NET_TCP_ERR_NONE) {                                 /* See Note #6a.                                */
           *perr  = NET_TCP_ERR_NONE_AVAIL;
            return;
        }
        pconn_clone = &NetTCP_ConnTbl[conn_id_clone_tcp];


#if (NET_CONN_CFG_FAMILY == NET_CONN_FAMILY_IP_V4_SOCK)
        conn_family      =  NET_CONN_FAMILY_IP_V4_SOCK;
        conn_protocol_ix =  NET_CONN_LIST_IX_IP_V4_SOCK_TCP;

#else                                                                   /* See Notes #4 & #6d.                          */
        NetTCP_ConnClose(pconn_clone, pbuf_hdr, DEF_YES, NET_TCP_CONN_CLOSE_ALL);
       *perr = NET_CONN_ERR_INVALID_FAMILY;
        return;
#endif

        conn_id_clone = NetConn_Get(conn_family, conn_protocol_ix, &err);
        if ( err != NET_CONN_ERR_NONE) {                                /* See Note #6b.                                */
            NetTCP_ConnClose(pconn_clone, pbuf_hdr, DEF_NO, NET_TCP_CONN_CLOSE_ALL);
           *perr  = NET_TCP_ERR_NONE_AVAIL;
            return;
        }


                                                                        /* --------------- SET CONN IDs --------------- */
        pconn_clone->ID_Conn = conn_id_clone;
        NetConn_ID_TransportSet((NET_CONN_ID) conn_id_clone,
                                (NET_CONN_ID) conn_id_clone_tcp,
                                (NET_ERR   *)&err);
        if ( err != NET_CONN_ERR_NONE) {                                /* See Note #6c.                                */
            NetTCP_ConnClose(pconn_clone, pbuf_hdr, DEF_NO, NET_TCP_CONN_CLOSE_ALL);
           *perr  = NET_TCP_ERR_CONN_FAIL;
            return;
        }


        conn_id           = pconn->ID_Conn;
        conn_id_clone_app = NetConn_ID_AppGet((NET_CONN_ID) conn_id,    /* Get half-conn's app conn id & ...            */
                                              (NET_ERR   *)&err);
        if ( err != NET_CONN_ERR_NONE) {                                /* See Note #6c.                                */
            NetTCP_ConnClose(pconn_clone, pbuf_hdr, DEF_NO, NET_TCP_CONN_CLOSE_ALL);
           *perr  = NET_TCP_ERR_CONN_FAIL;
            return;
        }

        NetConn_ID_AppCloneSet((NET_CONN_ID) conn_id_clone,             /* ... set as cloned conn's      ...            */
                               (NET_CONN_ID) conn_id_clone_app,         /* ... app conn clone id (see Note #5a2A1).     */
                               (NET_ERR   *)&err);
        if ( err != NET_CONN_ERR_NONE) {                                /* See Note #6c.                                */
            NetTCP_ConnClose(pconn_clone, pbuf_hdr, DEF_NO, NET_TCP_CONN_CLOSE_ALL);
           *perr  = NET_TCP_ERR_CONN_FAIL;
            return;
        }


/*$PAGE*/
                                                                        /* -------------- CFG CONN ADDRS -------------- */
#if (NET_CONN_CFG_FAMILY == NET_CONN_FAMILY_IP_V4_SOCK)
                                                                        /* Cfg local  addr as pkt dest addr.            */
        port_nbr = (NET_TCP_PORT_NBR)NET_UTIL_HOST_TO_NET_16(pbuf_hdr->TCP_UDP_PortDest);
        addr_ip  = (NET_IP_ADDR     )NET_UTIL_HOST_TO_NET_32(pbuf_hdr->IP_AddrDest);

        Mem_Copy((void     *)&addr_local[NET_CONN_ADDR_IP_IX_PORT],
                 (void     *)&port_nbr,
                 (CPU_SIZE_T) NET_CONN_ADDR_IP_LEN_PORT);
        Mem_Copy((void     *)&addr_local[NET_CONN_ADDR_IP_IX_ADDR],
                 (void     *)&addr_ip,
                 (CPU_SIZE_T) NET_CONN_ADDR_IP_LEN_ADDR);

                                                                        /* Cfg remote addr as pkt src  addr.            */
        port_nbr = (NET_TCP_PORT_NBR)NET_UTIL_HOST_TO_NET_16(pbuf_hdr->TCP_UDP_PortSrc);
        addr_ip  = (NET_IP_ADDR     )NET_UTIL_HOST_TO_NET_32(pbuf_hdr->IP_AddrSrc);

        Mem_Copy((void     *)&addr_remote[NET_CONN_ADDR_IP_IX_PORT],
                 (void     *)&port_nbr,
                 (CPU_SIZE_T) NET_CONN_ADDR_IP_LEN_PORT);
        Mem_Copy((void     *)&addr_remote[NET_CONN_ADDR_IP_IX_ADDR],
                 (void     *)&addr_ip,
                 (CPU_SIZE_T) NET_CONN_ADDR_IP_LEN_ADDR);

#else                                                                   /* See Notes #4 & #6d.                          */
        NetTCP_ConnClose(pconn_clone, pbuf_hdr, DEF_YES, NET_TCP_CONN_CLOSE_ALL);
       *perr = NET_CONN_ERR_INVALID_FAMILY;
        return;
#endif

        NetConn_AddrLocalSet((NET_CONN_ID      ) conn_id_clone,
                             (CPU_INT08U      *)&addr_local[0],
                             (NET_CONN_ADDR_LEN) NET_CONN_CFG_ADDR_LEN,
                             (CPU_BOOLEAN      ) DEF_NO,
                             (NET_ERR         *)&err);
        if ( err != NET_CONN_ERR_NONE) {                                /* See Note #6c.                                */
            NetTCP_ConnClose(pconn_clone, pbuf_hdr, DEF_NO, NET_TCP_CONN_CLOSE_ALL);
           *perr  = NET_TCP_ERR_CONN_FAIL;
            return;
        }

        NetConn_AddrRemoteSet((NET_CONN_ID      ) conn_id_clone,
                              (CPU_INT08U      *)&addr_remote[0],
                              (NET_CONN_ADDR_LEN) NET_CONN_CFG_ADDR_LEN,
                              (CPU_BOOLEAN      ) DEF_NO,
                              (NET_ERR         *)&err);
        if ( err != NET_CONN_ERR_NONE) {                                /* See Note #6c.                                */
            NetTCP_ConnClose(pconn_clone, pbuf_hdr, DEF_NO, NET_TCP_CONN_CLOSE_ALL);
           *perr  = NET_TCP_ERR_CONN_FAIL;
            return;
        }


                                                                        /* Add conn into server conn list.              */
        NetConn_ListAdd(conn_id_clone, NET_CONN_LIST_TYPE_SERVER, &err);
        if ( err != NET_CONN_ERR_NONE) {                                /* See Note #6c.                                */
            NetTCP_ConnClose(pconn_clone, pbuf_hdr, DEF_NO, NET_TCP_CONN_CLOSE_ALL);
           *perr  = NET_TCP_ERR_CONN_FAIL;
            return;
        }


                                                                        /* Copy half-conn state to full conn.           */
        NetTCP_ConnCopy(pconn_clone, pconn);

        pconn_tx_sync = pconn_clone;


    } else {                                                            /* Else conn to listen TCP conn (see Note #5b). */
        pconn_tx_sync = pconn;
    }



/*$PAGE*/
                                                                        /* ------------- HANDLE RX'D SEG -------------- */
    NetTCP_RxPktConnHandlerSeg(pconn_tx_sync, ack_code, pbuf, pbuf_hdr, &err_rtn);
    switch (err_rtn) {
        case NET_TCP_ERR_CONN_DATA_NONE:
        case NET_TCP_ERR_CONN_DATA_VALID:
             break;


        case NET_TCP_ERR_CONN_NOT_USED:
        case NET_TCP_ERR_INVALID_CONN_STATE:
        case NET_TCP_ERR_INVALID_CONN_OP:
        default:                                                        /* See Note #6d.                                */
             NetTCP_ConnClose(pconn_tx_sync, pbuf_hdr, pconn_tx_sync->ConnCloseAppFlag, NET_TCP_CONN_CLOSE_ALL);
            *perr = err_rtn;
             return;                                                    /* Prevent 'break NOT reachable' warning.       */
    }


                                                                        /* ------------- UPDATE TCP CONN -------------- */
                                                                        /* Cfg remote max seg size as advertised ...    */
                                                                        /* ... by remote host (see Note #7).            */
    pconn_tx_sync->MaxSegSizeRemote = (pbuf_hdr->TCP_MaxSegSize != NET_TCP_MAX_SEG_SIZE_NONE)
                                    ?  pbuf_hdr->TCP_MaxSegSize
                                    :  NET_TCP_MAX_SEG_SIZE_DFLT_TX;



                                                                        /* ------------- TX TCP CONN SYNC ------------- */
    NetTCP_TxConnSync(pconn_tx_sync, pbuf_hdr, perr);
    if (*perr != NET_TCP_ERR_NONE) {                                    /* See Note #6d.                                */
         NetTCP_ConnClose(pconn_tx_sync, pbuf_hdr, pconn_tx_sync->ConnCloseAppFlag, NET_TCP_CONN_CLOSE_ALL);
         return;
    }



                                                                        /* ---------- UPDATE TCP CONN STATE ----------- */
    pconn_tx_sync->ConnState = NET_TCP_CONN_STATE_SYNC_RXD_PASSIVE;



   *perr = err_rtn;
}


/*$PAGE*/
/*
*********************************************************************************************************
*                                  NetTCP_RxPktConnHandlerSyncRxd()
*
* Description : (1) Handle TCP connection in SYN-RECEIVED state :
*
*                   (a) Validate received TCP packet for current TCP connection state :
*
*                       (1) Sequence Number (SEQ)                                       See Note  #2a
*                       (2) Reset           (RST)                                       See Note  #2b
*                       (3) Synchronization (SYN)                                       See Note  #2c
*                       (4) Acknowledgement (ACK)                                       See Note  #2d
*                       (5) Finish/Close    (FIN)                                       See Note  #2e
*
*                   (b) Update TCP connection :
*                       (1) Handle received TCP segment                                 See Note  #2d2A1
*                       (2) Update    TCP connection state                              See Notes #2d2A1a & #2e4
*                       (3) Update    TCP connection timer
*
*                   (c) Acknowledge   TCP connection
*                       (1) Signal    TCP/application connection complete
*                       (2) Handle    TCP connection  received data                     See Note  #2d2A1
*                       (3) Transmit  TCP connection  data                              See Notes #2d2A2  & #2e3
*
*
* Argument(s) : pconn       Pointer to a TCP connection.
*               -----       Argument validated in NetTCP_RxPktConnHandler().
*
*               pbuf        Pointer to network buffer that received TCP packet.
*               ----        Argument checked   in NetTCP_Rx().
*
*               pbuf_hdr    Pointer to network buffer header that received TCP packet.
*               --------    Argument validated in NetTCP_Rx().
*
*               perr        Pointer to variable that will receive the return error code from this function :
*
*                               NET_TCP_ERR_CONN_SEQ_SYNC_INVALID   Received segment's synchronization        is
*                                                                       NOT valid for current TCP connection.
*                               NET_TCP_ERR_CONN_SEQ_INVALID        Received segment's sequence        number is
*                                                                       NOT valid for current TCP connection.
*                               NET_TCP_ERR_CONN_ACK_NONE           Received segment's acknowledgement        is
*                                                                       NOT available.
*                               NET_TCP_ERR_CONN_ACK_INVALID        Received segment's acknowledgement number is
*                                                                       NOT valid for current TCP connection.
*                               NET_TCP_ERR_CONN_RESET_VALID        Received segment's reset flag is     valid
*                                                                       for current TCP connection; i.e. reset
*                                                                       the TCP connection.
*                               NET_TCP_ERR_CONN_RESET_INVALID      Received segment's reset flag is NOT valid
*                                                                       for current TCP connection.
*
*                               NET_TCP_ERR_CONN_FAIL               TCP connection operation(s) failed.
*                               NET_TCP_ERR_NONE_AVAIL              Resources NOT available.
*
*                                                                   ----- RETURNED BY NetTCP_RxPktConnIsValidSeq() : -----
*                                                                   ----- RETURNED BY NetTCP_RxPktConnIsValidAck() : -----
*                                                                   ---- RETURNED BY NetTCP_RxPktConnIsValidReset() : ----
*                               NET_TCP_ERR_CONN_NOT_USED           TCP connection NOT currently used.
*                               NET_TCP_ERR_INVALID_CONN_STATE      Invalid TCP connection state.
*                               NET_TCP_ERR_INVALID_LEN_SEG         Invalid TCP sequence-segment length.
*
*                                                                   ----- RETURNED BY NetTCP_RxPktConnHandlerSeg() : -----
*                               NET_TCP_ERR_CONN_DATA_NONE          Received packet successfully handled; but NO
*                                                                       data to   queue  to receive queue(s).
*                               NET_TCP_ERR_CONN_DATA_VALID         Received packet successfully handled & valid
*                                                                       data processed (see Note #2d2A1).
*                               NET_TCP_ERR_CONN_DATA_INVALID       Received packet contains invalid   segment
*                                                                       data; NOT queued to receive queue(s).
*                               NET_TCP_ERR_CONN_DATA_DUP           Received packet contains duplicate segment
*                                                                       data; NOT queued to receive queue(s).
*
*                               NET_ERR_INIT_INCOMPLETE             Network initialization NOT complete.
*
*                               NET_TCP_ERR_INVALID_CONN_OP         Invalid TCP connection operation.
*
*                               NET_TCP_ERR_TX                      TCP transmit error.
*                               NET_TCP_ERR_TX_Q_SIGNAL_FAULT       TCP connection transmit queue signal fault.
*                               NET_TCP_ERR_RE_TX_SEG_TH            TCP connection closed due to excessive retransmission.
*
*                                                                   ---------- RETURNED BY NetTCP_TxConnTxQ() : ----------
*                               NET_TCP_ERR_CONN_CLOSE              TCP connection closed.
*                               NET_TCP_ERR_CONN_FAULT              TCP connection fault; connection(s) aborted.
*                               NET_CONN_ERR_INVALID_FAMILY         Invalid     connection family.
*                               NET_CONN_ERR_INVALID_ADDR           Invalid TCP connection address.
*                               NET_CONN_ERR_INVALID_ADDR_LEN       Invalid TCP connection address length.
*
* Return(s)   : none.
*
* Caller(s)   : NetTCP_RxPktConnHandler().
*$PAGE*
* Note(s)     : (2) TCP connections in the SYN-RECEIVED state are handled as follows :
*
*                   (a) RFC #793, Section 3.9 'Event Processing : SEGMENT ARRIVES : Check Sequence Number'
*                       states that in the "SYN-RECEIVED, ESTABLISHED STATE, FIN-WAIT-1 STATE, FIN-WAIT-2
*                       STATE, CLOSE-WAIT STATE, CLOSING STATE, LAST-ACK STATE, TIME-WAIT STATE" that ...
*
*                       (1) "Segments are processed in sequence ... processing is done in SEG.SEQ order."
*
*                       (2) "Initial tests on arrival are used to discard old duplicates."
*
*                       (3) "If a segment's contents straddle the boundary between old and new, only the
*                            new parts should be processed."
*
*                       (4) (A) "If an incoming segment is not acceptable," ...
*
*                           (B) "an acknowledgment should be sent in reply" ...
*
*                           (C) "(unless the RST bit is set, if so drop the segment)".
*
*                               See also Notes #2b2Aa & #2b2C.
*
*                       See also 'NetTCP_RxPktConnIsValidSeq()  Note #1d'.
*
*                   (b) (1) (A) RFC #793, Section 3.9 'Event Processing : SEGMENT ARRIVES : Check RST Bit :
*                               SYN-RECEIVED STATE' states that "if the RST bit is set" and ...
*
*                               (1) "If this connection was initiated with a passive OPEN (i.e., came from
*                                    the LISTEN state), then return this connection to the LISTEN state."
*
*                               (2) "If this connection was initiated with an active OPEN (i.e., came from
*                                    the SYN-SENT state) then the connection was refused, signal the user
*                                   'connection refused' ... enter the CLOSED state."
*
*                           (B) RFC #793, Section 3.4 'Establishing a Connection : Reset Processing' 
*                               reiterates that "if the receiver ... of a RST ... was in SYN-RECEIVED state 
*                               and had previously been in the LISTEN state, then the receiver returns to 
*                               the LISTEN state, otherwise the receiver aborts the connection and goes to 
*                               the CLOSED state".
*
*                           (C) However, since TCP connections opened from the LISTEN state are cloned from
*                               the original LISTEN-state TCP connection, it is NOT necessary to return ANY
*                               reset TCP connection from the SYN-RECEIVED state back to the LISTEN state.
*
*                           See also 'NetTCP_RxPktConnIsValidReset()  Note #2a4B'.
*
*                       (2) (A) RFC Draft-IETF-TCPm-TCPSecure #00, Section 2.2 amends the "handling of
*                               a segment with the RST when in a synchronized state" to "provide some 
*                               protection against ... blind reset attack[s] using the RST bit" :
*
*                               (a) "If the RST bit is set and the sequence number is outside the expected
*                                    window, silently drop the segment."
*
*                               (b) "If the RST bit is exactly the next expected sequence number [sic], reset
*                                    the connection"; it is assumed that this should read "if the RST bit is
*                                    set and the sequence number is exactly the next expected sequence number,
*                                    reset the connection."
*
*                               (c) "If the RST bit is set and the sequence number does not exactly match
*                                    the next expected sequence value, yet is within the acceptable window
*                                    (RCV.NXT <= SEG.SEQ < RCV.NXT+RCV.WND) send an acknowledgment."
*
*                           (B) ???? Although RFC Draft-IETF-TCPm-TCPSecure #00 explicitly states that this 
*                               amendment applies only to the "handling of a ... RST ... when in a synchronized 
*                               state", it is assumed that this should also apply to the SYN-RECEIVED state.
*
*                               See also 'NetTCP_RxPktConnIsValidReset()  Note #2a5B'.
*
*                           (C) ???? In addition, RFC Draft-IETF-TCPm-TCPSecure #00 does NOT provide a precedence 
*                               priority for handling TCP segments received with BOTH the RST & SYN bits set.
*
*                               ???? Therefore, since it does NOT seem reasonable to reset a TCP connection
*                               due to a TCP segment that also attempted to synchronize the  TCP connection,
*                               it is assumed that the amended handling of the SYN bit should take precedence
*                               over the amended handling of the RST bit.
*
*                               See also Note #2c2.
*$PAGE*
*                   (c) (1) RFC #793, Section 3.9 'Event Processing : SEGMENT ARRIVES : Check SYN Bit'
*                           states that in the "SYN-RECEIVED [STATE], ESTABLISHED STATE, FIN-WAIT STATE-1,
*                           FIN-WAIT STATE-2, CLOSE-WAIT STATE, CLOSING STATE, LAST-ACK STATE, TIME-WAIT
*                           STATE" that ...
*
*                           (A) "If the SYN is in the window it is an error, send a reset, any outstanding
*                                RECEIVEs and SEND[s] should receive 'reset' responses, all segment queues
*                                should be flushed, the user should also receive an unsolicited general
*                               'connection reset' signal[, and] enter the CLOSED state."
*
*                           (B) But "if the SYN is not in the window this step would not have been reached
*                               and an ack would have been sent".
*
*                       (2) (A) HOWEVER, RFC Draft-IETF-TCPm-TCPSecure #00, Section 3.2 amends the  "handling 
*                               of a segment with the SYN bit set in the synchronized state ... [by] handling 
*                               ... the SYN bit" as follows :
*
*                               (a) "If the SYN bit is set and the sequence number is outside the
*                                    expected window, send an ACK back to the peer."
*
*                               (b) "If the SYN bit is set and the sequence number is an exact
*                                    match to the next expected sequence (RCV.NXT == SEG.SEQ)
*                                    then send an ACK segment ... but ... subtract one from
*                                    value being acknowledged."
*
*                               (c) "If the SYN bit is set and the sequence number is acceptable,
*                                    i.e.: (RCV.NXT <= SEG.SEQ <= RCV.NXT+RCV.WND) then send an
*                                    ACK segment."
*
*                           (B) ???? Although RFC Draft-IETF-TCPm-TCPSecure #00 explicitly states that this 
*                               amendment applies only to the "handling of a ... SYN ... in a synchronized 
*                               state", it is assumed that this should also apply to the SYN-RECEIVED state.
*
*                   (d) RFC #793, Section 3.9 'Event Processing : SEGMENT ARRIVES : Check ACK Field' states
*                       that ... :
*
*                       (1) "If the ACK bit is off drop the segment."
*
*                       (2) "If the ACK bit is on [and in the] SYN-RECEIVED STATE" ...
*
*                           (A) (1) "If SND.UNA < SEG.ACK <= SND.NXT then" ...
*
*                                   (a) "enter the ESTABLISHED state" ...
*                                   (b) "and continue processing."
*
*                               (2) RFC #793, Section 3.9 'Event Processing : SEGMENT ARRIVES : SYN-SENT
*                                   [State]' states to "send ... [any] data or controls which were queued
*                                   for transmission" when the SYN-SENT state transitions to the ESTABLISHED
*                                   state.
*
*                                   Although this section is the only section to state that any data or
*                                   controls should be sent when transitioning from the SYN-SENT state
*                                   to the ESTABLISHED state, it is assumed that any data or controls
*                                   should also be sent for the transition from the SYN-RECEIVED state
*                                   to the ESTABLISHED state.
*
*                           (B) "If the segment acknowledgment is not acceptable, form a reset segment ...
*                                and send it."
*
*                   (e) RFC #793, Section 3.9 'Event Processing : SEGMENT ARRIVES : Check FIN Bit' states
*                       that "if the FIN bit is set" ...
*
*                       (1) "signal the user 'connection closing' and return any pending RECEIVEs with
*                            same message," ...
*
*                       (2) "advance RCV.NXT over the FIN," ...
*
*                       (3) "send an acknowledgment for the FIN" ...
*
*                       (4) And the "SYN-RECEIVED STATE enter[s] the CLOSE-WAIT state".
*$PAGE*
*               (3) (a) RFC #793, Section 3.9 'Event Processing : USER TIMEOUT : USER TIMEOUT' states that
*                       "for any state if the user timeout expires, flush all queues, signal the user
*                       'error : connection aborted due to user timeout' ... [and] enter the CLOSED state".
*
*                   (b) However, NO RFC specifies or suggests any mechanism to implement/handle user timeouts.
*
*                       ???? Therefore, it is assumed that ANY TCP connection that receives a valid TCP data
*                       or control segment should reset its user connection timer.
*
*                   (c) (1) Once a TCP connection enters the connected state, most of its TCP connection
*                           timers should be reset.
*
*                       (2) However, the following timers MAY already have been allocated & initialized,
*                           & MUST NOT be reset :
*
*                           (A)    Transmit Idle timer              'TxQ_IdleTmr'
*                           (B) Re-transmit      timer              'ReTxQ_Tmr'
*********************************************************************************************************
*/

static  void  NetTCP_RxPktConnHandlerSyncRxd (NET_TCP_CONN  *pconn,
                                              NET_BUF       *pbuf,
                                              NET_BUF_HDR   *pbuf_hdr,
                                              NET_ERR       *perr)
{
    NET_TCP_SEQ_CODE     seq_code;
    NET_TCP_ACK_CODE     ack_code;
    NET_TCP_RESET_CODE   reset_code;
    NET_TCP_FREE_CODE    free_code;
    NET_TCP_CONN_STATE   state;
    NET_TCP_TIMEOUT_SEC  timeout_sec;
    NET_TMR_TICK         timeout_tick;
    NET_ERR              err;
    NET_ERR              err_rtn;


/*$PAGE*/
                                                                /* -------------- VALIDATE RX'D TCP PKT --------------- */
                                                                /* Chk for rx'd fin/close.                              */
    if (pbuf_hdr->TCP_SegClose == DEF_YES) {                    /* If fin/close avail, update seg lens.                 */
        pbuf_hdr->TCP_SegLenInit += NET_TCP_SEG_LEN_CLOSE;
        pbuf_hdr->TCP_SegLen     += NET_TCP_SEG_LEN_CLOSE;
    }

                                                                /* Chk rx'd seq nbr.                                    */
    seq_code = NetTCP_RxPktConnIsValidSeq(pconn, pbuf_hdr, perr);
    if (*perr != NET_TCP_ERR_NONE) {
         return;
    }
    switch (seq_code) {
        case NET_TCP_CONN_RX_SEQ_VALID:
             break;


        case NET_TCP_CONN_RX_SEQ_SYNC:                          /* If invalid sync rx'd, ...                            */
        case NET_TCP_CONN_RX_SEQ_SYNC_INVALID:
                                                                /* ... tx TCP conn ack  (see Notes #2c2 & #2b2C).       */
             NetTCP_TxConnAck(pconn, pbuf_hdr, NET_TCP_CONN_TX_ACK_FAULT, NET_TCP_CONN_CLOSE_ALL, &err);
            *perr = NET_TCP_ERR_CONN_SEQ_SYNC_INVALID;
             return;                                            /* Prevent 'break NOT reachable' compiler warning.      */


        case NET_TCP_CONN_RX_SEQ_NONE:
        case NET_TCP_CONN_RX_SEQ_INVALID:                       /* If invalid seq  rx'd (see Note #2a4A), ...           */
        default:
             if (pbuf_hdr->TCP_SegReset != DEF_YES) {           /* ... & reset NOT rx'd (see Note #2a4C), ...           */
                                                                /* ... tx TCP conn ack  (see Note #2a4B).               */
                 NetTCP_TxConnAck(pconn, pbuf_hdr, NET_TCP_CONN_TX_ACK_FAULT, NET_TCP_CONN_CLOSE_ALL, &err);
             }
            *perr = NET_TCP_ERR_CONN_SEQ_INVALID;
             return;                                            /* Prevent 'break NOT reachable' compiler warning.      */
    }

                                                                /* Chk for rx'd reset.                                  */
    reset_code = NetTCP_RxPktConnIsValidReset(pconn, pbuf_hdr, perr);
    if (*perr != NET_TCP_ERR_NONE) {
         return;
    }
    switch (reset_code) {
        case NET_TCP_CONN_RX_RESET_NONE:
             break;


        case NET_TCP_CONN_RX_RESET_VALID:                       /* If   valid reset rx'd, ...                           */
                                                                /* ...  close TCP conn (see Note #2b2Ab).               */
             NetTCP_ConnClose(pconn, pbuf_hdr, pconn->ConnCloseAppFlag, NET_TCP_CONN_CLOSE_ALL);
            *perr = NET_TCP_ERR_CONN_RESET_VALID;
             return;                                            /* Prevent 'break NOT reachable' compiler warning.      */


        case NET_TCP_CONN_RX_RESET_INVALID:                     /* If invalid reset rx'd, ...                           */
        default:
                                                                /* ... tx TCP conn ack (see Note #2b2Ac).               */
             NetTCP_TxConnAck(pconn, pbuf_hdr, NET_TCP_CONN_TX_ACK_FAULT, NET_TCP_CONN_CLOSE_ALL, &err);
            *perr = NET_TCP_ERR_CONN_RESET_INVALID;
             return;                                            /* Prevent 'break NOT reachable' compiler warning.      */
    }

                                                                /* Chk for rx'd ack.                                    */
    ack_code = NetTCP_RxPktConnIsValidAck(pconn, pbuf_hdr, perr);
    if (*perr != NET_TCP_ERR_NONE) {
         return;
    }
    switch (ack_code) {
        case NET_TCP_CONN_RX_ACK_VALID:
             break;


        case NET_TCP_CONN_RX_ACK_NONE:                          /* If NO      ack rx'd, ...                             */
            *perr = NET_TCP_ERR_CONN_ACK_NONE;                  /* ... ignore TCP pkt    (see Note #2d1).               */
             return;                                            /* Prevent 'break NOT reachable' compiler warning.      */


        case NET_TCP_CONN_RX_ACK_INVALID:                       /* If invalid ack rx'd, ...                             */
        case NET_TCP_CONN_RX_ACK_DUP:
        case NET_TCP_CONN_RX_ACK_PREV:
        default:
                                                                /* ... tx TCP conn reset (see Note #2d2B).              */
             NetTCP_TxConnReset(pconn, pbuf_hdr, NET_TCP_CONN_TX_RESET, NET_TCP_CONN_CLOSE_ALL, &err);
            *perr = NET_TCP_ERR_CONN_ACK_INVALID;
             return;                                            /* Prevent 'break NOT reachable' compiler warning.      */
    }



/*$PAGE*/
                                                                /* ----------------- HANDLE RX'D SEG ------------------ */
    NetTCP_RxPktConnHandlerSeg(pconn, ack_code, pbuf, pbuf_hdr, &err_rtn);
    switch (err_rtn) {
        case NET_TCP_ERR_CONN_DATA_NONE:
        case NET_TCP_ERR_CONN_DATA_VALID:
             break;


        case NET_TCP_ERR_CONN_DATA_DUP:                         /* ???? Allow dup data to update TCP conn?              */
            *perr = err_rtn;
             return;                                            /* Prevent 'break NOT reachable' compiler warning.      */


        case NET_ERR_INIT_INCOMPLETE:
        case NET_TCP_ERR_CONN_NOT_USED:
        case NET_TCP_ERR_CONN_FAIL:
        case NET_TCP_ERR_CONN_ACK_INVALID:
        case NET_TCP_ERR_CONN_DATA_INVALID:
        case NET_TCP_ERR_INVALID_CONN_STATE:
        case NET_TCP_ERR_INVALID_CONN_OP:
        case NET_TCP_ERR_TX:
        case NET_TCP_ERR_TX_Q_SIGNAL_FAULT:
        case NET_TCP_ERR_RE_TX_SEG_TH:
        default:
             NetTCP_ConnClose(pconn, pbuf_hdr, pconn->ConnCloseAppFlag, NET_TCP_CONN_CLOSE_ALL);
            *perr = err_rtn;
             return;                                            /* Prevent 'break NOT reachable' compiler warning.      */
    }



                                                                /* ----------------- UPDATE TCP CONN ------------------ */
    state = pconn->ConnState;
    if (pbuf_hdr->TCP_SegClose != DEF_YES) {                    /* If fin/close NOT rx'd, ...                           */
        pconn->ConnState = NET_TCP_CONN_STATE_CONN;             /* ...  chng to conn'd     state (see Note #2d2A1a).    */
    } else {                                                    /* Else chng to close-wait state (see Note #2e4).       */
        pconn->ConnState = NET_TCP_CONN_STATE_CLOSE_WAIT;
    }

    pconn->TxQ_State = NET_TCP_TX_Q_STATE_CONN;


                                                                /* ------------------- UPDATE TMRs -------------------- */
    free_code = NET_TCP_CONN_FREE_TMR_ALL;                      /* See Note #3c1.                                       */
    DEF_BIT_CLR(free_code, NET_TCP_CONN_FREE_TMR_TX_IDLE);      /* See Note #3c2A.                                      */
    DEF_BIT_CLR(free_code, NET_TCP_CONN_FREE_TMR_RE_TX);        /* See Note #3c2B.                                      */

    NetTCP_ConnFreeTmr(pconn, free_code);                       /* Free TCP conn tmr(s) [see Note #3c].                 */


                                                                /* Get TCP conn tmr.                                    */
    timeout_sec       =  pconn->TimeoutConn_sec;                /* Start conn tmr (see Note #3b).                       */
    timeout_tick      = (NET_TMR_TICK)timeout_sec * NET_TMR_TIME_TICK_PER_SEC;
    pconn->TimeoutTmr =  NetTmr_Get((void       *) pconn,
                                    (CPU_FNCT_PTR) NetTCP_ConnCloseTimeout,
                                    (NET_TMR_TICK) timeout_tick,
                                    (CPU_INT16U  ) NET_TMR_FLAG_NONE,
                                    (NET_ERR    *)&err);
    if ( err != NET_TMR_ERR_NONE) {
        NetTCP_ConnClose(pconn, pbuf_hdr, pconn->ConnCloseAppFlag, NET_TCP_CONN_CLOSE_ALL);
       *perr  = NET_TCP_ERR_NONE_AVAIL;
        return;
    }



/*$PAGE*/
                                                                /* ------------------- ACK TCP CONN ------------------- */
    NetTCP_RxPktConnHandlerSignalConn(pconn, state, &err);      /* Signal app conn (see Note #1c1).                     */
    if ( err != NET_TCP_ERR_NONE) {
        NetTCP_ConnClose(pconn, pbuf_hdr, pconn->ConnCloseAppFlag, NET_TCP_CONN_CLOSE_ALL);
       *perr  = NET_TCP_ERR_CONN_FAIL;
        return;
    }

    NetTCP_RxPktConnHandlerRxQ_AppData(pconn, &err);            /* Handle TCP conn rx'd data (see Note #2d2A1).         */
    if ( err != NET_TCP_ERR_NONE) {                             /* #### On err, close TCP conn?                         */
       *perr  = NET_TCP_ERR_CONN_FAIL;
        return;
    }

    if (pconn->ConnState == NET_TCP_CONN_STATE_CONN) {          /* If conn'd, tx any tx data (see Note #1c3).           */
        NetTCP_TxConnTxQ(pconn, pbuf_hdr, NET_TCP_CONN_TX_ACK_NONE, DEF_NO, NET_TCP_CONN_CLOSE_ALL, perr);
        switch (*perr) {
            case NET_TCP_ERR_NONE:
            case NET_TCP_ERR_CONN_ACK_NONE:
            case NET_TCP_ERR_CONN_ACK_INVALID:
            case NET_TCP_ERR_CONN_ACK_DLYD:
            case NET_TCP_ERR_CONN_ACK_PREVLY_TXD:
            case NET_ERR_TX:                                    /* Ignore transitory tx err(s).                         */
                 break;


            case NET_ERR_INIT_INCOMPLETE:
            case NET_TCP_ERR_CONN_NOT_USED:
            case NET_TCP_ERR_CONN_CLOSE:
            case NET_TCP_ERR_CONN_FAULT:
            case NET_TCP_ERR_CONN_FAIL:
            case NET_TCP_ERR_INVALID_CONN_STATE:
            case NET_TCP_ERR_INVALID_CONN_OP:
            case NET_TCP_ERR_INVALID_LEN_SEG:
            case NET_TCP_ERR_NONE_AVAIL:
            case NET_TCP_ERR_TX:
            case NET_CONN_ERR_INVALID_FAMILY:
            case NET_CONN_ERR_INVALID_ADDR:
            case NET_CONN_ERR_INVALID_ADDR_LEN:
            default:
                 return;                                        /* Prevent 'break NOT reachable' compiler warning.      */
        }

    } else {                                                    /* Else tx TCP conn ack (see Note #2e3).                */
        NetTCP_TxConnAck(pconn, pbuf_hdr, NET_TCP_CONN_TX_ACK_IMMED, NET_TCP_CONN_CLOSE_ALL, perr);
        switch (*perr) {
            case NET_TCP_ERR_NONE:
            case NET_TCP_ERR_CONN_ACK_NONE:
            case NET_TCP_ERR_CONN_ACK_INVALID:
            case NET_TCP_ERR_CONN_ACK_DLYD:
            case NET_TCP_ERR_CONN_ACK_PREVLY_TXD:
                 break;


            case NET_TCP_ERR_CONN_NOT_USED:
            case NET_TCP_ERR_CONN_FAULT:
            case NET_TCP_ERR_INVALID_CONN_STATE:
            case NET_TCP_ERR_INVALID_CONN_OP:
            case NET_TCP_ERR_INVALID_LEN_SEG:
            case NET_TCP_ERR_NONE_AVAIL:
            default:
                 return;                                        /* Prevent 'break NOT reachable' compiler warning.      */
        }
    }



   *perr = err_rtn;
}


/*$PAGE*/
/*
*********************************************************************************************************
*                                  NetTCP_RxPktConnHandlerSyncTxd()
*
* Description : (1) Handle TCP connection in SYN-SENT state :
*
*                   (a) Validate received TCP packet for current TCP connection state :
*
*                       (1) Acknowledgement (ACK)                                           See Note  #2a
*                       (2) Reset           (RST)                                           See Note  #2b
*                       (3) Synchronization (SYN)                                           See Note  #2c
*
*                   (b) Update TCP connection :
*                       (1) Configure TCP connection remote host maximum segment size       See Note  #3
*                       (2) Handle received TCP segment                                     See Note  #2c
*                       (3) Update    TCP connection state                                  See Notes #2c3A1 & #2c3B1
*                       (4) Update    TCP connection timer
*
*                   (c) Acknowledge  TCP connection
*                       (1) Signal   TCP/application connection complete
*                       (2) Handle   TCP connection  received data                          See Note  #2c3A3
*                       (3) Transmit TCP connection  acknowledgement & data                 See Note  #2c3A2
*
*
* Argument(s) : pconn       Pointer to a TCP connection.
*               -----       Argument validated in NetTCP_RxPktConnHandler().
*
*               pbuf        Pointer to network buffer that received TCP packet.
*               ----        Argument checked   in NetTCP_Rx().
*
*               pbuf_hdr    Pointer to network buffer header that received TCP packet.
*               --------    Argument validated in NetTCP_Rx().
*
*               perr        Pointer to variable that will receive the return error code from this function :
*
*                               NET_TCP_ERR_CONN_SEQ_INVALID        Received segment's sequence        number is
*                                                                       NOT valid for current TCP connection.
*                               NET_TCP_ERR_CONN_ACK_INVALID        Received segment's acknowledgement number is
*                                                                       NOT valid for current TCP connection.
*                               NET_TCP_ERR_CONN_SEQ_FIN_INVALID    Received segment's finish/close flag is
*                                                                       NOT valid for current TCP connection.
*                               NET_TCP_ERR_CONN_RESET_VALID        Received segment's reset flag is     valid
*                                                                       for current TCP connection; i.e. reset
*                                                                       the TCP connection.
*                               NET_TCP_ERR_CONN_RESET_INVALID      Received segment's reset flag is NOT valid
*                                                                       for current TCP connection.
*
*                               NET_TCP_ERR_CONN_FAIL               TCP connection operation(s) failed.
*                               NET_TCP_ERR_NONE_AVAIL              Resources NOT available.
*
*                                                                   ----- RETURNED BY NetTCP_RxPktConnIsValidSeq() : -----
*                                                                   ----- RETURNED BY NetTCP_RxPktConnIsValidAck() : -----
*                                                                   ---- RETURNED BY NetTCP_RxPktConnIsValidReset() : ----
*                               NET_TCP_ERR_CONN_NOT_USED           TCP connection NOT currently used.
*                               NET_TCP_ERR_INVALID_CONN_STATE      Invalid TCP connection state.
*                               NET_TCP_ERR_INVALID_LEN_SEG         Invalid TCP sequence-segment length.
*
*                                                                   ----- RETURNED BY NetTCP_RxPktConnHandlerSeg() : -----
*                               NET_TCP_ERR_CONN_DATA_NONE          Received packet successfully handled; but NO
*                                                                       data to   queue  to receive queue(s).
*                               NET_TCP_ERR_CONN_DATA_VALID         Received packet successfully handled &
*                                                                       valid data queued for processing
*                                                                       (see Notes #2c3A3 & #2c3B3).
*                               NET_TCP_ERR_CONN_DATA_INVALID       Received packet contains invalid   segment
*                                                                       data; NOT queued to receive queue(s).
*                               NET_TCP_ERR_CONN_DATA_DUP           Received packet contains duplicate segment
*                                                                       data; NOT queued to receive queue(s).
*
*                               NET_ERR_INIT_INCOMPLETE             Network initialization NOT complete.
*
*                               NET_TCP_ERR_INVALID_CONN_OP         Invalid TCP connection operation.
*
*                               NET_TCP_ERR_TX                      TCP transmit error.
*                               NET_TCP_ERR_TX_Q_SIGNAL_FAULT       TCP connection transmit queue signal fault.
*                               NET_TCP_ERR_RE_TX_SEG_TH            TCP connection closed due to excessive retransmission.
*
*                                                                   ---------- RETURNED BY NetTCP_TxConnTxQ() : ----------
*                               NET_TCP_ERR_CONN_CLOSE              TCP connection closed.
*                               NET_TCP_ERR_CONN_FAULT              TCP connection fault; connection(s) aborted.
*                               NET_CONN_ERR_INVALID_FAMILY         Invalid     connection family.
*                               NET_CONN_ERR_INVALID_ADDR           Invalid TCP connection address.
*                               NET_CONN_ERR_INVALID_ADDR_LEN       Invalid TCP connection address length.
*
* Return(s)   : none.
*
* Caller(s)   : NetTCP_RxPktConnHandler().
*$PAGE*
* Note(s)     : (2) RFC #793, Section 3.9 'Event Processing : SEGMENT ARRIVES : SYN-SENT [State]' states to :
*
*                   (a) "First check the ACK bit[;] if the ACK bit is set" :
*
*                       (1) "If SEG.ACK =< ISS, or SEG.ACK > SND.NXT, send a reset (unless the RST bit is
*                            set) ... and discard the segment."
*
*                       (2) "If SND.UNA < SEG.ACK =< SND.NXT then the ACK is acceptable."
*
*                       See also 'NetTCP_RxPktConnIsValidAck()  Note #1c1A'.
*
*                   (b) "Second check the RST bit[;] if the RST bit is set [and] if the ACK was acceptable
*                        then signal the user 'error: connection reset', drop the segment, [and] enter
*                        CLOSED state."
*
*                        See also 'NetTCP_RxPktConnIsValidReset()  Notes #2a3 & #2a5C'.
*
*                   (c) "Fourth check the SYN bit[;] if the SYN bit is on and ... acceptable then" ...
*
*                       (1) "RCV.NXT is set to SEG.SEQ+1, IRS is set to SEG.SEQ."
*                           (A) See also Note #2c3B3a
*
*                       (2) (A) "SND.UNA should be advanced to equal SEG.ACK (if there is an ACK)" ...
*
*                           (B) "and any segments on the retransmission queue which are thereby acknowledged
*                                should be removed."
*
*                       (3) (A) "If SND.UNA > ISS (our SYN has been ACKed)," ...
*
*                               (1) "change the connection state to ESTABLISHED" ...
*
*                               (2) (a) "form an ACK segment ... and send it."
*
*                                   (b) "Data or controls which were queued for transmission may be included."
*
*                               (3) "If there are other controls or text in the segment then continue processing."
*
*                               (4) RFC #1122, Section 4.2.2.20.(c) adds that "when the connection enters
*                                   ESTABLISHED state, the following variables must be set" :
*
*                                   (a) SND.WND <- SEG.WND
*                                   (b) SND.WL1 <- SEG.SEQ
*                                   (c) SND.WL2 <- SEG.ACK
*
*                           (B) "Otherwise" ...
*
*                               (1) "enter SYN-RECEIVED," ...
*
*                               (2) "form an SYN,ACK segment ... and send it."
*
*                               (3) "If there are other controls or text in the segment, queue them for later
*                                    processing after the ESTABLISHED state has been reached."
*
*                                   (a) If any control or text is queued for later processing, the next sequence
*                                       octet to receive (RCV.NXT) MUST include the length of this received
*                                       segment (SEG.LEN) :
*
*                                       (1) RCV.NXT = SEG.SEQ + SEG.LEN + 1
*
*                   (d) "Fifth, if neither of the SYN or RST bits is set then drop the segment."
*
*                   (e) RFC #793, Section 3.9 'Event Processing : SEGMENT ARRIVES : Check FIN Bit' states
*                       to "not process the FIN if the state is CLOSED, LISTEN or SYN-SENT since the SEG.SEQ
*                       cannot be validated; drop the segment".
*$PAGE*
*               (3) RFC #1122, Section 4.2.2.6 states that ... :
*
*                   (a) A "TCP SHOULD send an MSS (Maximum Segment Size) option in every SYN segment".
*
*                   (b) "If an MSS option is not received at connection setup, TCP MUST assume a default
*                        send MSS of 536."
*
*               (4) (a) TCP connection timeout for SYN-SENT state is implemented by TCP connection retransmission
*                       function(s) (see 'NetTCP_TxConnReTxQ()  Note #3c').
*
*                   (b) (1) RFC #793, Section 3.9 'Event Processing : USER TIMEOUT : USER TIMEOUT' states that
*                           "for any state if the user timeout expires, flush all queues, signal the user
*                           'error : connection aborted due to user timeout' ... [and] enter the CLOSED state".
*
*                       (2) However, NO RFC specifies or suggests any mechanism to implement/handle user timeouts.
*
*                           ???? Therefore, it is assumed that ANY TCP connection that receives a valid TCP data
*                           or control segment should reset its user connection timer.
*
*                   (c) (1) Once a TCP connection enters the connected state, most of its TCP connection
*                           timers should be reset.
*
*                       (2) However, the following timers MAY already have been allocated & initialized,
*                           & MUST NOT be reset :
*
*                           (A)    Transmit Idle timer              'TxQ_IdleTmr'
*                           (B) Re-transmit      timer              'ReTxQ_Tmr'
*********************************************************************************************************
*/
/*$PAGE*/
static  void  NetTCP_RxPktConnHandlerSyncTxd (NET_TCP_CONN  *pconn,
                                              NET_BUF       *pbuf,
                                              NET_BUF_HDR   *pbuf_hdr,
                                              NET_ERR       *perr)
{
    NET_TCP_SEQ_CODE     seq_code;
    NET_TCP_ACK_CODE     ack_code;
    NET_TCP_RESET_CODE   reset_code;
    NET_TCP_FREE_CODE    free_code;
    NET_TCP_CONN_STATE   state;
    NET_TCP_TIMEOUT_SEC  timeout_sec;
    NET_TMR_TICK         timeout_tick;
    NET_ERR              err;
    NET_ERR              err_rtn;


                                                                /* -------------- VALIDATE RX'D TCP PKT --------------- */
                                                                /* Chk for rx'd fin/close.                              */
    if (pbuf_hdr->TCP_SegClose != DEF_NO) {                     /* If invalid   fin/close rx'd, ...                     */
       *perr = NET_TCP_ERR_CONN_SEQ_FIN_INVALID;
        return;                                                 /* ... ignore TCP pkt (see Note #2e).                   */
    }

                                                                /* Chk for rx'd ack.                                    */
    ack_code = NetTCP_RxPktConnIsValidAck(pconn, pbuf_hdr, perr);
    if (*perr != NET_TCP_ERR_NONE) {
         return;
    }
    if (ack_code == NET_TCP_CONN_RX_ACK_INVALID) {              /* If invalid ack rx'd, ...                             */
                                                                /* ... tx TCP conn reset (see Note #2a1).              */
        NetTCP_TxConnReset(pconn, pbuf_hdr, NET_TCP_CONN_TX_RESET, NET_TCP_CONN_CLOSE_ALL, &err);
       *perr = NET_TCP_ERR_CONN_ACK_INVALID;
        return;
    }

                                                                /* Chk for rx'd reset.                                  */
    reset_code = NetTCP_RxPktConnIsValidReset(pconn, pbuf_hdr, perr);
    if (*perr != NET_TCP_ERR_NONE) {
         return;
    }
    switch (reset_code) {
        case NET_TCP_CONN_RX_RESET_NONE:
             break;


        case NET_TCP_CONN_RX_RESET_VALID:                       /* If valid reset rx'd, close TCP conn (see Note #2b).  */
             NetTCP_ConnClose(pconn, pbuf_hdr, pconn->ConnCloseAppFlag, NET_TCP_CONN_CLOSE_ALL);
            *perr = NET_TCP_ERR_CONN_RESET_VALID;
             return;                                            /* Prevent 'break NOT reachable' compiler warning.      */


        case NET_TCP_CONN_RX_RESET_INVALID:
        default:
            *perr = NET_TCP_ERR_CONN_RESET_INVALID;
             return;                                            /* Prevent 'break NOT reachable' compiler warning.      */
    }

                                                                /* Chk rx'd seq nbr.                                    */
    seq_code = NetTCP_RxPktConnIsValidSeq(pconn, pbuf_hdr, perr);
    if (*perr != NET_TCP_ERR_NONE) {
         return;
    }
    if (seq_code != NET_TCP_CONN_RX_SEQ_SYNC) {                 /* If sync NOT rx'd, ...                                */
       *perr = NET_TCP_ERR_CONN_SEQ_INVALID;
        return;                                                 /* ... ignore TCP pkt (see Note #2d).                   */
    }
                                                                /* Else sync avail, update seg lens.                    */
    pbuf_hdr->TCP_SegLenInit += NET_TCP_SEG_LEN_SYNC;
    pbuf_hdr->TCP_SegLen     += NET_TCP_SEG_LEN_SYNC;



/*$PAGE*/
                                                                /* ----------------- UPDATE TCP CONN ------------------ */
                                                                /* Cfg remote max seg size ...                          */
                                                                /* ... as advertised by remote host (see Note #3).      */
    pconn->MaxSegSizeRemote = (pbuf_hdr->TCP_MaxSegSize != NET_TCP_MAX_SEG_SIZE_NONE)
                            ?  pbuf_hdr->TCP_MaxSegSize
                            :  NET_TCP_MAX_SEG_SIZE_DFLT_TX;


                                                                /* ----------------- HANDLE RX'D SEG ------------------ */
    NetTCP_RxPktConnHandlerSeg(pconn, ack_code, pbuf, pbuf_hdr, &err_rtn);
    switch (err_rtn) {
        case NET_TCP_ERR_CONN_DATA_NONE:
        case NET_TCP_ERR_CONN_DATA_VALID:
             break;


        case NET_TCP_ERR_CONN_DATA_DUP:                         /* ???? Allow dup data to update TCP conn?              */
            *perr = err_rtn;
             return;                                            /* Prevent 'break NOT reachable' compiler warning.      */


        case NET_ERR_INIT_INCOMPLETE:
        case NET_TCP_ERR_CONN_NOT_USED:
        case NET_TCP_ERR_CONN_FAIL:
        case NET_TCP_ERR_CONN_ACK_INVALID:
        case NET_TCP_ERR_CONN_DATA_INVALID:
        case NET_TCP_ERR_INVALID_CONN_STATE:
        case NET_TCP_ERR_INVALID_CONN_OP:
        case NET_TCP_ERR_TX:
        case NET_TCP_ERR_TX_Q_SIGNAL_FAULT:
        case NET_TCP_ERR_RE_TX_SEG_TH:
        default:
             NetTCP_ConnClose(pconn, pbuf_hdr, pconn->ConnCloseAppFlag, NET_TCP_CONN_CLOSE_ALL);
            *perr = err_rtn;
             return;                                            /* Prevent 'break NOT reachable' compiler warning.      */
    }



                                                                /* ----------------- UPDATE TCP CONN ------------------ */
    if (ack_code == NET_TCP_CONN_RX_ACK_VALID) {                /* If valid ack rx'd        (see Note #2a1), ...        */
        state            = pconn->ConnState;
        pconn->ConnState = NET_TCP_CONN_STATE_CONN;             /* ... chng to conn'd state (see Note #2c3A1).          */
        pconn->TxQ_State = NET_TCP_TX_Q_STATE_CONN;

    } else {                                                    /* Else chng to sync rx'd state (see Note #2c3B1).      */
        pconn->ConnState = NET_TCP_CONN_STATE_SYNC_RXD_ACTIVE;
    }


                                                                /* ------------------- UPDATE TMRs -------------------- */
    free_code = NET_TCP_CONN_FREE_TMR_ALL;                      /* See Note #4c1.                                       */
    DEF_BIT_CLR(free_code, NET_TCP_CONN_FREE_TMR_TX_IDLE);      /* See Note #4c2A.                                      */
    DEF_BIT_CLR(free_code, NET_TCP_CONN_FREE_TMR_RE_TX);        /* See Note #4c2B.                                      */

    NetTCP_ConnFreeTmr(pconn, free_code);                       /* Free TCP conn tmr(s) [see Note #4c].                 */


    if (pconn->ConnState ==  NET_TCP_CONN_STATE_CONN) {         /* If conn'd, get TCP conn tmr.                         */
        timeout_sec       =  pconn->TimeoutConn_sec;            /* Start conn tmr (see Note #4b2).                      */
        timeout_tick      = (NET_TMR_TICK)timeout_sec * NET_TMR_TIME_TICK_PER_SEC;
        pconn->TimeoutTmr =  NetTmr_Get((void       *) pconn,
                                        (CPU_FNCT_PTR) NetTCP_ConnCloseTimeout,
                                        (NET_TMR_TICK) timeout_tick,
                                        (CPU_INT16U  ) NET_TMR_FLAG_NONE,
                                        (NET_ERR    *)&err);
        if ( err != NET_TMR_ERR_NONE) {
            NetTCP_ConnClose(pconn, pbuf_hdr, pconn->ConnCloseAppFlag, NET_TCP_CONN_CLOSE_ALL);
           *perr  = NET_TCP_ERR_NONE_AVAIL;
            return;
        }
    }



/*$PAGE*/
                                                                /* ------------------- ACK TCP CONN ------------------- */
    if (pconn->ConnState == NET_TCP_CONN_STATE_CONN) {          /* If conn'd, ...                                       */
        NetTCP_RxPktConnHandlerSignalConn(pconn, state, &err);  /* ... signal app conn           (see Note #1c1);   ... */
        if ( err != NET_TCP_ERR_NONE) {
            NetTCP_ConnClose(pconn, pbuf_hdr, pconn->ConnCloseAppFlag, NET_TCP_CONN_CLOSE_ALL);
           *perr  = NET_TCP_ERR_CONN_FAIL;
            return;
        }

        NetTCP_RxPktConnHandlerRxQ_AppData(pconn, &err);        /* ... handle TCP conn rx'd data (see Note #2d2A1); ... */
        if ( err != NET_TCP_ERR_NONE) {                         /* #### On err, close TCP conn?                         */
           *perr  = NET_TCP_ERR_CONN_FAIL;
            return;
        }
                                                                /* ... & tx ack & any tx data    (see Note #1c3).       */
        NetTCP_TxConnTxQ(pconn, pbuf_hdr, NET_TCP_CONN_TX_ACK_IMMED, DEF_NO, NET_TCP_CONN_CLOSE_ALL, perr);
        switch (*perr) {
            case NET_TCP_ERR_NONE:
            case NET_TCP_ERR_CONN_ACK_NONE:
            case NET_TCP_ERR_CONN_ACK_INVALID:
            case NET_TCP_ERR_CONN_ACK_DLYD:
            case NET_TCP_ERR_CONN_ACK_PREVLY_TXD:
            case NET_ERR_TX:                                    /* Ignore transitory tx err(s).                         */
                 break;


            case NET_ERR_INIT_INCOMPLETE:
            case NET_TCP_ERR_CONN_NOT_USED:
            case NET_TCP_ERR_CONN_CLOSE:
            case NET_TCP_ERR_CONN_FAULT:
            case NET_TCP_ERR_CONN_FAIL:
            case NET_TCP_ERR_INVALID_CONN_STATE:
            case NET_TCP_ERR_INVALID_CONN_OP:
            case NET_TCP_ERR_INVALID_LEN_SEG:
            case NET_TCP_ERR_NONE_AVAIL:
            case NET_TCP_ERR_TX:
            case NET_CONN_ERR_INVALID_FAMILY:
            case NET_CONN_ERR_INVALID_ADDR:
            case NET_CONN_ERR_INVALID_ADDR_LEN:
            default:
                 return;                                        /* Prevent 'break NOT reachable' compiler warning.      */
        }

    } else {                                                    /* Else tx TCP conn sync/ack (see Note #2c3B2).         */
        NetTCP_TxConnSync(pconn, pbuf_hdr, &err);
        if ( err != NET_TCP_ERR_NONE) {
            NetTCP_ConnClose(pconn, pbuf_hdr, pconn->ConnCloseAppFlag, NET_TCP_CONN_CLOSE_ALL);
           *perr  = NET_TCP_ERR_CONN_CLOSE;
            return;
        }
    }



   *perr = err_rtn;
}


/*$PAGE*/
/*
*********************************************************************************************************
*                                    NetTCP_RxPktConnHandlerConn()
*
* Description : (1) Handle TCP connection in ESTABLISHED state :
*
*                   (a) Validate received TCP packet for current TCP connection state :
*
*                       (1) Sequence Number (SEQ)                                   See Note  #2a
*                       (2) Reset           (RST)                                   See Note  #2b
*                       (3) Synchronization (SYN)                                   See Note  #2c
*                       (4) Acknowledgement (ACK)                                   See Note  #2d
*                       (5) Finish/Close    (FIN)                                   See Note  #2f
*
*                   (b) Update TCP connection :
*                       (1) Handle received TCP segment                             See Notes #2d & #2e
*                       (2) Update TCP connection state                             See Note  #2f5
*                       (3) Update TCP connection timer                             See Note  #3
*
*                   (c) Transmit TCP connection acknowledgement & data              See Notes #2e2A & #2f3
*
*
* Argument(s) : pconn       Pointer to a TCP connection.
*               -----       Argument validated in NetTCP_RxPktConnHandler().
*
*               pbuf        Pointer to network buffer that received TCP packet.
*               ----        Argument checked   in NetTCP_Rx().
*
*               pbuf_hdr    Pointer to network buffer header that received TCP packet.
*               --------    Argument validated in NetTCP_Rx().
*
*               perr        Pointer to variable that will receive the return error code from this function :
*
*                               NET_TCP_ERR_CONN_SEQ_SYNC_INVALID   Received segment's synchronization        is
*                                                                       NOT valid for current TCP connection.
*                               NET_TCP_ERR_CONN_SEQ_INVALID        Received segment's sequence        number is
*                                                                       NOT valid for current TCP connection.
*                               NET_TCP_ERR_CONN_ACK_NONE           Received segment's acknowledgement        is
*                                                                       NOT available.
*                               NET_TCP_ERR_CONN_ACK_INVALID        Received segment's acknowledgement number is
*                                                                       NOT valid for current TCP connection.
*                               NET_TCP_ERR_CONN_RESET_VALID        Received segment's reset flag is     valid
*                                                                       for current TCP connection; i.e. reset
*                                                                       the TCP connection.
*                               NET_TCP_ERR_CONN_RESET_INVALID      Received segment's reset flag is NOT valid
*                                                                       for current TCP connection.
*
*                               NET_TCP_ERR_CONN_FAIL               TCP connection operation(s) failed.
*
*                                                                   ----- RETURNED BY NetTCP_RxPktConnIsValidSeq() : -----
*                                                                   ----- RETURNED BY NetTCP_RxPktConnIsValidAck() : -----
*                                                                   ---- RETURNED BY NetTCP_RxPktConnIsValidReset() : ----
*                               NET_TCP_ERR_CONN_NOT_USED           TCP connection NOT currently used.
*                               NET_TCP_ERR_INVALID_CONN_STATE      Invalid TCP connection state.
*                               NET_TCP_ERR_INVALID_LEN_SEG         Invalid TCP sequence-segment length.
*
*                                                                   ----- RETURNED BY NetTCP_RxPktConnHandlerSeg() : -----
*                               NET_TCP_ERR_CONN_DATA_NONE          Received packet successfully handled; but NO
*                                                                       data to   queue  to receive queue(s).
*                               NET_TCP_ERR_CONN_DATA_VALID         Received packet successfully handled & valid
*                                                                       data queued for processing.
*                               NET_TCP_ERR_CONN_DATA_INVALID       Received packet contains invalid   segment
*                                                                       data; NOT queued to receive queue(s).
*                               NET_TCP_ERR_CONN_DATA_DUP           Received packet contains duplicate segment
*                                                                       data; NOT queued to receive queue(s).
*
*                               NET_ERR_INIT_INCOMPLETE             Network initialization NOT complete.
*
*                               NET_TCP_ERR_INVALID_CONN_OP         Invalid TCP connection operation.
*
*                               NET_TCP_ERR_RX_Q_FULL               TCP connection receive  queue full.
*                               NET_TCP_ERR_RX_Q_SIGNAL_FAULT       TCP connection receive  queue signal fault.
*                               NET_TCP_ERR_TX_Q_SIGNAL_FAULT       TCP connection transmit queue signal fault.
*                               NET_TCP_ERR_RE_TX_SEG_TH            TCP connection closed due to excessive retransmission.
*                               NET_TCP_ERR_TX                      TCP transmit error.
*
*                                                                   ---------- RETURNED BY NetTCP_TxConnTxQ() : ----------
*                               NET_TCP_ERR_CONN_CLOSE              TCP connection closed.
*                               NET_TCP_ERR_CONN_FAULT              TCP connection fault; connection(s) aborted.
*                               NET_TCP_ERR_NONE_AVAIL              Resources NOT available.
*                               NET_CONN_ERR_INVALID_FAMILY         Invalid     connection family.
*                               NET_CONN_ERR_INVALID_ADDR           Invalid TCP connection address.
*                               NET_CONN_ERR_INVALID_ADDR_LEN       Invalid TCP connection address length.
*
* Return(s)   : none.
*
* Caller(s)   : NetTCP_RxPktConnHandler().
*$PAGE*
* Note(s)     : (2) TCP connections in the ESTABLISHED state are handled as follows :
*
*                   (a) RFC #793, Section 3.9 'Event Processing : SEGMENT ARRIVES : Check Sequence Number'
*                       states that in the "SYN-RECEIVED, ESTABLISHED STATE, FIN-WAIT-1 STATE, FIN-WAIT-2
*                       STATE, CLOSE-WAIT STATE, CLOSING STATE, LAST-ACK STATE, TIME-WAIT STATE" that ...
*
*                       (1) "Segments are processed in sequence ... processing is done in SEG.SEQ order."
*
*                       (2) "Initial tests on arrival are used to discard old duplicates."
*
*                       (3) "If a segment's contents straddle the boundary between old and new, only the
*                            new parts should be processed."
*
*                       (4) (A) "If an incoming segment is not acceptable," ...
*
*                           (B) "an acknowledgment should be sent in reply" ...
*
*                           (C) "(unless the RST bit is set, if so drop the segment)".
*
*                               See also Notes #2b2Aa & #2b2B.
*
*                       See also 'NetTCP_RxPktConnIsValidSeq()  Note #1d'.
*
*                   (b) (1) (A) RFC #793, Section 3.9 'Event Processing : SEGMENT ARRIVES : Check RST Bit' states
*                               that in the "ESTABLISHED, FIN-WAIT-1, FIN-WAIT-2, CLOSE-WAIT" states that "if the
*                               RST bit is set then, any outstanding RECEIVEs and SEND[s] should receive 'reset'
*                               responses.  All segment queues should be flushed.  Users should also receive an
*                               unsolicited general 'connection reset' signal[, and] enter the CLOSED state".
*
*                           (B) RFC #793, Section 3.4 'Establishing a Connection : Reset Processing' reiterates
*                               that "if the receiver ... of a RST ... was in any other state [other than LISTEN
*                               or SYN-RECEIVED], it aborts the connection and advises the user and goes to the
*                               CLOSED state".
*
*                       (2) (A) RFC Draft-IETF-TCPm-TCPSecure #00, Section 2.2 amends the "handling of a segment 
*                               with the RST bit when in a synchronized state" to "provide some protection against
*                               ... blind reset attack[s] using the RST bit" :
*
*                               (a) "If the RST bit is set and the sequence number is outside the expected
*                                    window, silently drop the segment."
*
*                               (b) "If the RST bit is exactly the next expected sequence number [sic], reset
*                                    the connection"; it is assumed that this should read "if the RST bit is
*                                    set and the sequence number is exactly the next expected sequence number,
*                                    reset the connection."
*
*                               (c) "If the RST bit is set and the sequence number does not exactly match
*                                    the next expected sequence value, yet is within the acceptable window
*                                    (RCV.NXT <= SEG.SEQ < RCV.NXT+RCV.WND) send an acknowledgment."
*
*                           (B) ???? In addition, RFC Draft-IETF-TCPm-TCPSecure #00 does NOT provide a precedence 
*                               priority for handling TCP segments received with BOTH the RST & SYN bits set.
*
*                               ???? Therefore, since it does NOT seem reasonable to reset a TCP connection
*                               due to a TCP segment that also attempted to synchronize the  TCP connection,
*                               it is assumed that the amended handling of the SYN bit should take precedence
*                               over the amended handling of the RST bit.
*
*                               See also Note #2c2.
*
*                   (c) (1) RFC #793, Section 3.9 'Event Processing : SEGMENT ARRIVES : Check SYN Bit'
*                           states that in the "SYN-RECEIVED [STATE], ESTABLISHED STATE, FIN-WAIT STATE-1,
*                           FIN-WAIT STATE-2, CLOSE-WAIT STATE, CLOSING STATE, LAST-ACK STATE, TIME-WAIT
*                           STATE" that ...
*
*                           (A) "If the SYN is in the window it is an error, send a reset, any outstanding
*                                RECEIVEs and SEND[s] should receive 'reset' responses, all segment queues
*                                should be flushed, the user should also receive an unsolicited general
*                               'connection reset' signal[, and] enter the CLOSED state."
*
*                           (B) But "if the SYN is not in the window this step would not have been reached
*                               and an ack would have been sent".
*
*                       (2) HOWEVER, RFC Draft-IETF-TCPm-TCPSecure #00, Section 3.2 amends the  "handling
*                           of a segment with the SYN bit set in the synchronized state ... [by] handling
*                           ... the SYN bit" as follows :
*
*                           (a) "If the SYN bit is set and the sequence number is outside the
*                                expected window, send an ACK back to the peer."
*
*                           (b) "If the SYN bit is set and the sequence number is an exact
*                                match to the next expected sequence (RCV.NXT == SEG.SEQ)
*                                then send an ACK segment ... but ... subtract one from
*                                value being acknowledged."
*
*                           (c) "If the SYN bit is set and the sequence number is acceptable,
*                                i.e.: (RCV.NXT <= SEG.SEQ <= RCV.NXT+RCV.WND) then send an
*                                ACK segment."
*$PAGE*
*                   (d) RFC #793, Section 3.9 'Event Processing : SEGMENT ARRIVES : Check ACK Field'
*                       states that ... :
*
*                       (1) "If the ACK bit is off drop the segment."
*
*                       (2) "If the ACK bit is on [and in the] ESTABLISHED STATE" ...
*
*                           (A) "If SND.UNA < SEG.ACK <= SND.NXT then" ...
*
*                               (1) "set SND.UNA <- SEG.ACK."
*
*                               (2) "Any segments on the retransmission queue which are thereby entirely
*                                    acknowledged are removed."
*
*                               (3) "the send window should be updated" :
*
*                                   (a) (1) (A) "If ((SND.WL1 <  SEG.SEQ) or" ...
*
*                                           (B) (1) "(SND.WL1  = SEG.SEQ and" ...
*                                               (2)  "SND.WL2 <= SEG.ACK))," ...
*
*                                       (2) (A) "set SND.WND <- SEG.WND," ...
*                                           (B) "set SND.WL1 <- SEG.SEQ," ...
*                                           (C) "set SND.WL2 <- SEG.ACK."
*
*                                   (b) "Note that SND.WND is an offset from SND.UNA, that SND.WL1 records the
*                                        sequence number of the last segment used to update SND.WND, and that
*                                        SND.WL2 records the acknowledgment number of the last segment used to
*                                        update SND.WND.  The check here preveents using old segments to update
*                                        the window."
*
*                           (B) (1) "If the ACK is a duplicate (SEG.ACK <= SND.UNA), it can be ignored."
*
*                               (2) RFC #1122, Section 4.2.2.20.(g) amends the transmit window update criteria
*                                   for the segment's acknowledgement to include SND.UNA : "The window should
*                                   updated if SND.UNA <= SEG.ACK <= SND.NXT."
*
*                                   See also 'NetTCP_RxPktConnHandlerTxWinRemote()  Note #1b2'.
*
*                           (C) "If the ACK acks something not yet sent (SEG.ACK > SND.NXT) then send an ACK
*                                [and] drop the segment."
*
*                   (e) RFC #793, Section 3.9 'Event Processing : SEGMENT ARRIVES : Process Segment Text'
*                       states that for the "ESTABLISHED STATE, FIN-WAIT-1 STATE, FIN-WAIT-2 STATE ... it
*                       is possible to deliver segment text to user RECEIVE buffers" :
*
*                       (1) "If the segment ... carries [a] PUSH flag, then the user is informed [and] the
*                            buffer is returned."
*
*                       (2) (A) (1) "When the TCP takes responsibility for delivering the data to the user it
*                                    must also acknowledge the receipt of the data."
*
*                               (2) "This acknowledgment should be piggybacked on a segment being transmitted
*                                    if possible without incurring undue delay."
*
*                           (B) "Once the TCP takes responsibility for the data" ...
*
*                               (1) "it advances RCV.NXT over the data accepted," ...
*
*                               (2) "adjusts RCV.WND as appropriate to the current buffer availability" ...
*
*                               (3) (a) "The total of RCV.NXT and RCV.WND should not be reduced."
*
*                                   (b) RFC #793,  Section 3.7 'Data Communication : Managing the Window' &
*                                       RFC #1122, Section 4.2.2.16 confirm that "a TCP receiver SHOULD NOT
*                                       shrink the window"; i.e. "advertise a much smaller window without
*                                       having accepted that much data".
*
*                   (f) RFC #793, Section 3.9 'Event Processing : SEGMENT ARRIVES : Check FIN Bit' states
*                       that "if the FIN bit is set" ...
*
*                       (1) "signal the user 'connection closing' and return any pending RECEIVEs with
*                            same message," ...
*
*                       (2) "advance RCV.NXT over the FIN," ...
*
*                       (3) "send an acknowledgment for the FIN" ...
*
*                       (4) "FIN implies PUSH for any segment text not yet delivered to the user" ...
*
*                       (5) And the "ESTABLISHED STATE enter[s] the CLOSE-WAIT state".
*$PAGE*
*               (3) (a) RFC #793, Section 3.9 'Event Processing : USER TIMEOUT : USER TIMEOUT' states that
*                       "for any state if the user timeout expires, flush all queues, signal the user
*                       'error : connection aborted due to user timeout' ... [and] enter the CLOSED state".
*
*                   (b) However, NO RFC specifies or suggests any mechanism to implement/handle user timeouts.
*
*                       ???? Therefore, it is assumed that ANY TCP connection that receives a valid TCP data
*                       or control segment should reset its user connection timer.
*********************************************************************************************************
*/

static  void  NetTCP_RxPktConnHandlerConn (NET_TCP_CONN  *pconn,
                                           NET_BUF       *pbuf,
                                           NET_BUF_HDR   *pbuf_hdr,
                                           NET_ERR       *perr)
{
    NET_TCP_SEQ_CODE     seq_code;
    NET_TCP_ACK_CODE     ack_code;
    NET_TCP_RESET_CODE   reset_code;
    NET_TCP_TIMEOUT_SEC  timeout_sec;
    NET_TMR_TICK         timeout_tick;
    NET_ERR              err;
    NET_ERR              err_rtn;


/*$PAGE*/
                                                                /* -------------- VALIDATE RX'D TCP PKT --------------- */
                                                                /* Chk for rx'd fin/close.                              */
    if (pbuf_hdr->TCP_SegClose == DEF_YES) {                    /* If fin/close avail, update seg lens.                 */
        pbuf_hdr->TCP_SegLenInit += NET_TCP_SEG_LEN_CLOSE;
        pbuf_hdr->TCP_SegLen     += NET_TCP_SEG_LEN_CLOSE;
    }

                                                                /* Chk rx'd seq nbr.                                    */
    seq_code = NetTCP_RxPktConnIsValidSeq(pconn, pbuf_hdr, perr);
    if (*perr != NET_TCP_ERR_NONE) {
         return;
    }
    switch (seq_code) {
        case NET_TCP_CONN_RX_SEQ_VALID:
             break;


        case NET_TCP_CONN_RX_SEQ_SYNC:                          /* If invalid sync rx'd, ...                            */
        case NET_TCP_CONN_RX_SEQ_SYNC_INVALID:
                                                                /* ... tx TCP conn ack  (see Notes #2c2 & #2b2B).       */
             NetTCP_TxConnAck(pconn, pbuf_hdr, NET_TCP_CONN_TX_ACK_FAULT, NET_TCP_CONN_CLOSE_ALL, &err);
            *perr = NET_TCP_ERR_CONN_SEQ_SYNC_INVALID;
             return;                                            /* Prevent 'break NOT reachable' compiler warning.      */


        case NET_TCP_CONN_RX_SEQ_NONE:
        case NET_TCP_CONN_RX_SEQ_INVALID:                       /* If invalid seq  rx'd (see Note #2a4A), ...           */
        default:
             if (pbuf_hdr->TCP_SegReset != DEF_YES) {           /* ... & reset NOT rx'd (see Note #2a4C), ...           */
                                                                /* ... tx TCP conn ack  (see Note #2a4B).               */
                 NetTCP_TxConnAck(pconn, pbuf_hdr, NET_TCP_CONN_TX_ACK_FAULT, NET_TCP_CONN_CLOSE_ALL, &err);
             }
            *perr = NET_TCP_ERR_CONN_SEQ_INVALID;
             return;                                            /* Prevent 'break NOT reachable' compiler warning.      */
    }

                                                                /* Chk for rx'd reset.                                  */
    reset_code = NetTCP_RxPktConnIsValidReset(pconn, pbuf_hdr, perr);
    if (*perr != NET_TCP_ERR_NONE) {
         return;
    }
    switch (reset_code) {
        case NET_TCP_CONN_RX_RESET_NONE:
             break;


        case NET_TCP_CONN_RX_RESET_VALID:                       /* If   valid reset rx'd, ...                           */
                                                                /* ...  close TCP conn (see Note #2b1A).                */
             NetTCP_ConnClose(pconn, pbuf_hdr, pconn->ConnCloseAppFlag, NET_TCP_CONN_CLOSE_ALL);
            *perr = NET_TCP_ERR_CONN_RESET_VALID;
             return;                                            /* Prevent 'break NOT reachable' compiler warning.      */


        case NET_TCP_CONN_RX_RESET_INVALID:                     /* If invalid reset rx'd, ...                           */
        default:
                                                                /* ... tx TCP conn ack (see Note #2b2Ac).               */
             NetTCP_TxConnAck(pconn, pbuf_hdr, NET_TCP_CONN_TX_ACK_FAULT, NET_TCP_CONN_CLOSE_ALL, &err);
            *perr = NET_TCP_ERR_CONN_RESET_INVALID;
             return;                                            /* Prevent 'break NOT reachable' compiler warning.      */
    }

                                                                /* Chk for rx'd ack.                                    */
    ack_code = NetTCP_RxPktConnIsValidAck(pconn, pbuf_hdr, perr);
    if (*perr != NET_TCP_ERR_NONE) {
         return;
    }
    switch (ack_code) {
        case NET_TCP_CONN_RX_ACK_VALID:
        case NET_TCP_CONN_RX_ACK_DUP:
        case NET_TCP_CONN_RX_ACK_PREV:
             break;


        case NET_TCP_CONN_RX_ACK_NONE:                          /* If NO      ack rx'd, ...                             */
            *perr = NET_TCP_ERR_CONN_ACK_NONE;                  /* ... ignore TCP pkt  (see Note #2d1).                 */
             return;                                            /* Prevent 'break NOT reachable' compiler warning.      */


        case NET_TCP_CONN_RX_ACK_INVALID:                       /* If invalid ack rx'd, ...                             */
        default:
                                                                /* ... tx TCP conn ack (see Note #2d2C).                */
             NetTCP_TxConnAck(pconn, pbuf_hdr, NET_TCP_CONN_TX_ACK_FAULT, NET_TCP_CONN_CLOSE_ALL, &err);
            *perr = NET_TCP_ERR_CONN_ACK_INVALID;
             return;                                            /* Prevent 'break NOT reachable' compiler warning.      */
    }



/*$PAGE*/
                                                                /* ----------------- HANDLE RX'D SEG ------------------ */
    NetTCP_RxPktConnHandlerSeg(pconn, ack_code, pbuf, pbuf_hdr, &err_rtn);
    switch (err_rtn) {
        case NET_TCP_ERR_CONN_DATA_NONE:
        case NET_TCP_ERR_CONN_DATA_VALID:
             break;


        case NET_TCP_ERR_CONN_DATA_DUP:                         /* ???? Allow dup data to update TCP conn?              */
            *perr = err_rtn;
             return;                                            /* Prevent 'break NOT reachable' compiler warning.      */


        case NET_ERR_INIT_INCOMPLETE:
        case NET_TCP_ERR_CONN_NOT_USED:
        case NET_TCP_ERR_CONN_FAIL:
        case NET_TCP_ERR_CONN_ACK_INVALID:
        case NET_TCP_ERR_CONN_DATA_INVALID:
        case NET_TCP_ERR_INVALID_CONN_STATE:
        case NET_TCP_ERR_INVALID_CONN_OP:
        case NET_TCP_ERR_INVALID_LEN_SEG:
        case NET_TCP_ERR_RX_Q_FULL:
        case NET_TCP_ERR_RX_Q_SIGNAL_FAULT:
        case NET_TCP_ERR_TX:
        case NET_TCP_ERR_TX_Q_SIGNAL_FAULT:
        case NET_TCP_ERR_RE_TX_SEG_TH:
        default:
             NetTCP_ConnClose(pconn, pbuf_hdr, pconn->ConnCloseAppFlag, NET_TCP_CONN_CLOSE_ALL);
            *perr = err_rtn;
             return;                                            /* Prevent 'break NOT reachable' compiler warning.      */
    }



                                                                /* ----------------- UPDATE TCP CONN ------------------ */
    if (pbuf_hdr->TCP_SegClose == DEF_YES) {                    /* If fin/close rx'd, ...                               */
        pconn->ConnState = NET_TCP_CONN_STATE_CLOSE_WAIT;       /* ... chng to close-wait state (see Note #2f5).        */
    }


                                                                /* -------------------- UPDATE TMR -------------------- */
    timeout_sec  =  pconn->TimeoutConn_sec;                     /* Reset conn tmr (see Note #3b).                       */
    timeout_tick = (NET_TMR_TICK)timeout_sec * NET_TMR_TIME_TICK_PER_SEC;
    if (pconn->TimeoutTmr != (NET_TMR *)0) {
        NetTmr_Set((NET_TMR    *) pconn->TimeoutTmr,
                   (CPU_FNCT_PTR) NetTCP_ConnCloseTimeout,
                   (NET_TMR_TICK) timeout_tick,
                   (NET_ERR    *)&err);
    } else {
        pconn->TimeoutTmr = NetTmr_Get((void       *) pconn,
                                       (CPU_FNCT_PTR) NetTCP_ConnCloseTimeout,
                                       (NET_TMR_TICK) timeout_tick,
                                       (CPU_INT16U  ) NET_TMR_FLAG_NONE,
                                       (NET_ERR    *)&err);
    }

    if ( err != NET_TMR_ERR_NONE) {
        NetTCP_ConnClose(pconn, pbuf_hdr, pconn->ConnCloseAppFlag, NET_TCP_CONN_CLOSE_ALL);
       *perr  = NET_TCP_ERR_CONN_FAIL;
        return;
    }



/*$PAGE*/
                                                                /* --------------- TX TCP CONN ACK/DATA --------------- */
    ack_code = ((pbuf_hdr->TCP_SegAckTxReqCode == NET_TCP_CONN_TX_ACK_IMMED) ||
                (pbuf_hdr->TCP_SegClose        == DEF_YES))     /* See Note #2f3.                                       */
             ?   NET_TCP_CONN_TX_ACK_IMMED
             :   NET_TCP_CONN_TX_ACK;
                                                                /* Tx ack & any tx data (see Note #1c).                 */
    NetTCP_TxConnTxQ(pconn, pbuf_hdr, ack_code, DEF_NO, NET_TCP_CONN_CLOSE_ALL, perr);
    switch (*perr) {
        case NET_TCP_ERR_NONE:
        case NET_TCP_ERR_CONN_ACK_NONE:
        case NET_TCP_ERR_CONN_ACK_INVALID:
        case NET_TCP_ERR_CONN_ACK_DLYD:
        case NET_TCP_ERR_CONN_ACK_PREVLY_TXD:
        case NET_ERR_TX:                                        /* Ignore transitory tx err(s).                         */
             break;


        case NET_ERR_INIT_INCOMPLETE:
        case NET_TCP_ERR_CONN_NOT_USED:
        case NET_TCP_ERR_CONN_CLOSE:
        case NET_TCP_ERR_CONN_FAULT:
        case NET_TCP_ERR_CONN_FAIL:
        case NET_TCP_ERR_INVALID_CONN_STATE:
        case NET_TCP_ERR_INVALID_CONN_OP:
        case NET_TCP_ERR_INVALID_LEN_SEG:
        case NET_TCP_ERR_NONE_AVAIL:
        case NET_TCP_ERR_TX:
        case NET_CONN_ERR_INVALID_FAMILY:
        case NET_CONN_ERR_INVALID_ADDR:
        case NET_CONN_ERR_INVALID_ADDR_LEN:
        default:
             return;                                            /* Prevent 'break NOT reachable' compiler warning.      */
    }



   *perr = err_rtn;
}


/*$PAGE*/
/*
*********************************************************************************************************
*                                  NetTCP_RxPktConnHandlerFinWait1()
*
* Description : (1) Handle TCP connection in FIN-WAIT-1 state :
*
*                   (a) Validate received TCP packet for current TCP connection state :
*
*                       (1) Sequence Number (SEQ)                                   See Note  #2a
*                       (2) Reset           (RST)                                   See Note  #2b
*                       (3) Synchronization (SYN)                                   See Note  #2c
*                       (4) Acknowledgement (ACK)                                   See Note  #2d
*                       (5) Finish/Close    (FIN)                                   See Note  #2f
*
*                   (b) Update TCP connection :
*                       (1) Handle received TCP segment                             See Notes #2d   & #2e
*                       (2) Signal TCP/application connection close                 See Note  #2d2B2
*                       (3) Update TCP connection state :                           See Notes #2f5A1, #2f5A2b1, & #2f5B
*                           (A) Configure TCP connection timeout value
*                           (B) Configure TCP connection timeout function
*                       (4) Update TCP connection timer(s)                          See Notes #2f5A1, #2f5A2b2, & #3
*
*                   (c) Transmit TCP connection acknowledgement & data              See Notes #2e2A & #2f3
*
*
* Argument(s) : pconn       Pointer to a TCP connection.
*               -----       Argument validated in NetTCP_RxPktConnHandler().
*
*               pbuf        Pointer to network buffer that received TCP packet.
*               ----        Argument checked   in NetTCP_Rx().
*
*               pbuf_hdr    Pointer to network buffer header that received TCP packet.
*               --------    Argument validated in NetTCP_Rx().
*
*               perr        Pointer to variable that will receive the return error code from this function :
*
*                               NET_TCP_ERR_CONN_SEQ_SYNC_INVALID   Received segment's synchronization        is
*                                                                       NOT valid for current TCP connection.
*                               NET_TCP_ERR_CONN_SEQ_INVALID        Received segment's sequence        number is
*                                                                       NOT valid for current TCP connection.
*                               NET_TCP_ERR_CONN_ACK_NONE           Received segment's acknowledgement        is
*                                                                       NOT available.
*                               NET_TCP_ERR_CONN_ACK_INVALID        Received segment's acknowledgement number is
*                                                                       NOT valid for current TCP connection.
*                               NET_TCP_ERR_CONN_RESET_VALID        Received segment's reset flag is     valid
*                                                                       for current TCP connection; i.e. reset
*                                                                       the TCP connection.
*                               NET_TCP_ERR_CONN_RESET_INVALID      Received segment's reset flag is NOT valid
*                                                                       for current TCP connection.
*
*                               NET_TCP_ERR_CONN_FAIL               TCP connection operation(s) failed.
*
*                                                                   ----- RETURNED BY NetTCP_RxPktConnIsValidSeq() : -----
*                                                                   ----- RETURNED BY NetTCP_RxPktConnIsValidAck() : -----
*                                                                   ---- RETURNED BY NetTCP_RxPktConnIsValidReset() : ----
*                               NET_TCP_ERR_CONN_NOT_USED           TCP connection NOT currently used.
*                               NET_TCP_ERR_INVALID_CONN_STATE      Invalid TCP connection state.
*                               NET_TCP_ERR_INVALID_LEN_SEG         Invalid TCP sequence-segment length.
*
*                                                                   ----- RETURNED BY NetTCP_RxPktConnHandlerSeg() : -----
*                               NET_TCP_ERR_CONN_DATA_NONE          Received packet successfully handled; but NO
*                                                                       data to   queue  to receive queue(s).
*                               NET_TCP_ERR_CONN_DATA_VALID         Received packet successfully handled & valid
*                                                                       data queued for processing.
*                               NET_TCP_ERR_CONN_DATA_INVALID       Received packet contains invalid   segment
*                                                                       data; NOT queued to receive queue(s).
*                               NET_TCP_ERR_CONN_DATA_DUP           Received packet contains duplicate segment
*                                                                       data; NOT queued to receive queue(s).
*
*                               NET_ERR_INIT_INCOMPLETE             Network initialization NOT complete.
*
*                               NET_TCP_ERR_INVALID_CONN_OP         Invalid TCP connection operation.
*
*                               NET_TCP_ERR_RX_Q_FULL               TCP connection receive  queue full.
*                               NET_TCP_ERR_RX_Q_SIGNAL_FAULT       TCP connection receive  queue signal fault.
*                               NET_TCP_ERR_TX_Q_SIGNAL_FAULT       TCP connection transmit queue signal fault.
*                               NET_TCP_ERR_RE_TX_SEG_TH            TCP connection closed due to excessive retransmission.
*                               NET_TCP_ERR_TX                      TCP transmit error.
*
*                                                                   - RETURNED BY NetTCP_RxPktConnHandlerSignalClose() : -
*                               NET_TCP_ERR_INVALID_CONN_ID         Invalid application connection.
*                               NET_CONN_ERR_INVALID_FAMILY         Invalid network connection family.
*                               NET_CONN_ERR_INVALID_CONN           Invalid network connection number.
*                               NET_CONN_ERR_NOT_USED               Network connection NOT currently used.
*
*                                                                   ---------- RETURNED BY NetTCP_TxConnTxQ() : ----------
*                               NET_TCP_ERR_CONN_CLOSE              TCP connection closed.
*                               NET_TCP_ERR_CONN_FAULT              TCP connection fault; connection(s) aborted.
*                               NET_TCP_ERR_NONE_AVAIL              Resources NOT available.
*                               NET_CONN_ERR_INVALID_FAMILY         Invalid     connection family.
*                               NET_CONN_ERR_INVALID_ADDR           Invalid TCP connection address.
*                               NET_CONN_ERR_INVALID_ADDR_LEN       Invalid TCP connection address length.
*$PAGE*
* Return(s)   : none.
*
* Caller(s)   : NetTCP_RxPktConnHandler().
*
* Note(s)     : (2) TCP connections in the FIN-WAIT-1 state are handled as follows :
*
*                   (a) RFC #793, Section 3.9 'Event Processing : SEGMENT ARRIVES : Check Sequence Number'
*                       states that in the "SYN-RECEIVED, ESTABLISHED STATE, FIN-WAIT-1 STATE, FIN-WAIT-2
*                       STATE, CLOSE-WAIT STATE, CLOSING STATE, LAST-ACK STATE, TIME-WAIT STATE" that ...
*
*                       (1) "Segments are processed in sequence ... processing is done in SEG.SEQ order."
*
*                       (2) "Initial tests on arrival are used to discard old duplicates."
*
*                       (3) "If a segment's contents straddle the boundary between old and new, only the
*                            new parts should be processed."
*
*                       (4) (A) "If an incoming segment is not acceptable," ...
*
*                           (B) "an acknowledgment should be sent in reply" ...
*
*                           (C) "(unless the RST bit is set, if so drop the segment)".
*
*                               See also Notes #2b2Aa & #2b2B.
*
*                       See also 'NetTCP_RxPktConnIsValidSeq()  Note #1d'.
*
*                   (b) (1) (A) RFC #793, Section 3.9 'Event Processing : SEGMENT ARRIVES : Check RST Bit' states
*                               that in the "ESTABLISHED, FIN-WAIT-1, FIN-WAIT-2, CLOSE-WAIT" states that "if the
*                               RST bit is set then, any outstanding RECEIVEs and SEND[s] should receive 'reset'
*                               responses.  All segment queues should be flushed.  Users should also receive an
*                               unsolicited general 'connection reset' signal[, and] enter the CLOSED state".
*
*                           (B) RFC #793, Section 3.4 'Establishing a Connection : Reset Processing' reiterates
*                               that "if the receiver ... of a RST ... was in any other state [other than LISTEN
*                               or SYN-RECEIVED], it aborts the connection and advises the user and goes to the
*                               CLOSED state".
*
*                       (2) (A) RFC Draft-IETF-TCPm-TCPSecure #00, Section 2.2 amends the "handling of a segment 
*                               with the RST bit when in a synchronized state" to "provide some protection against
*                               ... blind reset attack[s] using the RST bit" :
*
*                               (a) "If the RST bit is set and the sequence number is outside the expected
*                                    window, silently drop the segment."
*
*                               (b) "If the RST bit is exactly the next expected sequence number [sic], reset
*                                    the connection"; it is assumed that this should read "if the RST bit is
*                                    set and the sequence number is exactly the next expected sequence number,
*                                    reset the connection."
*
*                               (c) "If the RST bit is set and the sequence number does not exactly match
*                                    the next expected sequence value, yet is within the acceptable window
*                                    (RCV.NXT <= SEG.SEQ < RCV.NXT+RCV.WND) send an acknowledgment."
*
*                           (B) ???? In addition, RFC Draft-IETF-TCPm-TCPSecure #00 does NOT provide a precedence
*                               priority for handling TCP segments received with BOTH the RST & SYN bits set.
*
*                               ???? Therefore, since it does NOT seem reasonable to reset a TCP connection
*                               due to a TCP segment that also attempted to synchronize the  TCP connection,
*                               it is assumed that the amended handling of the SYN bit should take precedence
*                               over the amended handling of the RST bit.
*
*                               See also Note #2c2.
*
*                   (c) (1) RFC #793, Section 3.9 'Event Processing : SEGMENT ARRIVES : Check SYN Bit'
*                           states that in the "SYN-RECEIVED [STATE], ESTABLISHED STATE, FIN-WAIT STATE-1,
*                           FIN-WAIT STATE-2, CLOSE-WAIT STATE, CLOSING STATE, LAST-ACK STATE, TIME-WAIT
*                           STATE" that ...
*
*                           (A) "If the SYN is in the window it is an error, send a reset, any outstanding
*                                RECEIVEs and SEND[s] should receive 'reset' responses, all segment queues
*                                should be flushed, the user should also receive an unsolicited general
*                               'connection reset' signal[, and] enter the CLOSED state."
*
*                           (B) But "if the SYN is not in the window this step would not have been reached
*                               and an ack would have been sent".
*
*                       (2) HOWEVER, RFC Draft-IETF-TCPm-TCPSecure #00, Section 3.2 amends the  "handling 
*                           of a segment with the SYN bit set in the synchronized state ... [by] handling 
*                           ... the SYN bit" as follows :
*
*                           (a) "If the SYN bit is set and the sequence number is outside the
*                                expected window, send an ACK back to the peer."
*
*                           (b) "If the SYN bit is set and the sequence number is an exact
*                                match to the next expected sequence (RCV.NXT == SEG.SEQ)
*                                then send an ACK segment ... but ... subtract one from
*                                value being acknowledged."
*
*                           (c) "If the SYN bit is set and the sequence number is acceptable,
*                                i.e.: (RCV.NXT <= SEG.SEQ <= RCV.NXT+RCV.WND) then send an
*                                ACK segment."
*$PAGE*
*                   (d) RFC #793, Section 3.9 'Event Processing : SEGMENT ARRIVES : Check ACK Field'
*                       states that ... :
*
*                       (1) "If the ACK bit is off drop the segment."
*
*                       (2) "If the ACK bit is on" ...
*
*                           (A) And in the "ESTABLISHED STATE" ...
*
*                               (1) "If SND.UNA < SEG.ACK <= SND.NXT then" ...
*
*                                   (a) "set SND.UNA <- SEG.ACK."
*
*                                   (b) "Any segments on the retransmission queue which are thereby entirely
*                                        acknowledged are removed."
*
*                                   (c) "the send window should be updated" :
*
*                                       (1) (A) (1) "If ((SND.WL1 <  SEG.SEQ) or" ...
*
*                                               (2) (a) "(SND.WL1  = SEG.SEQ and" ...
*                                                   (b)  "SND.WL2 <= SEG.ACK))," ...
*
*                                           (B) (1) "set SND.WND <- SEG.WND," ...
*                                               (2) "set SND.WL1 <- SEG.SEQ," ...
*                                               (3) "set SND.WL2 <- SEG.ACK."
*
*                                       (2) "Note that SND.WND is an offset from SND.UNA, that SND.WL1 records the
*                                            sequence number of the last segment used to update SND.WND, and that
*                                            SND.WL2 records the acknowledgment number of the last segment used to
*                                            update SND.WND.  The check here preveents using old segments to update
*                                            the window."
*
*                               (2) (a) "If the ACK is a duplicate (SEG.ACK <= SND.UNA), it can be ignored."
*
*                                   (b) RFC #1122, Section 4.2.2.20.(g) amends the transmit window update criteria
*                                       for the segment's acknowledgement to include SND.UNA : "The window should
*                                       updated if SND.UNA <= SEG.ACK <= SND.NXT."
*
*                                       See also 'NetTCP_RxPktConnHandlerTxWinRemote()  Note #1b2'.
*
*                               (3) "If the ACK acks something not yet sent (SEG.ACK > SND.NXT) then send an ACK
*                                    [and] drop the segment."
*
*                           (B) (1) For the "FIN-WAIT-1 STATE" :
*
*                                   (a) "in addition to the processing for the ESTABLISHED state" ...
*                                   (b) "if our FIN is now acknowledged then"                     ...
*                                       (1) "enter FIN-WAIT-2 [state] and continue processing in that state."
*
*                               (2) (a) RFC #793, Section 3.9 'Event Processing : SEGMENT ARRIVES : Check ACK Field :
*                                       FIN-WAIT-2 STATE' states that "if the retransmission queue is empty, the user's
*                                       CLOSE can be acknowledged".
*
*                                   (b) However, a TCP connection transitions into the FIN-WAIT-2 state if & only if
*                                       the TCP connection's close request was previously acknowledged while in the
*                                       FIN-WAIT-1 state.  Thus, the TCP connection's re-transmit queue should
*                                       already be empty prior to entering the FIN-WAIT-2 state.
*
*                                       ???? Therefore, a TCP connection in the FIN-WAIT-1 state should :
*
*                                       (1) Signal the application layer that "the user's close [is] acknowledged"
*                                           whenever its re-transmit queue becomes empty.
*
*                                       (2) Close all unused timers (see also Note #2f5A1b).
*$PAGE*
*                   (e) RFC #793, Section 3.9 'Event Processing : SEGMENT ARRIVES : Process Segment Text'
*                       states that for the "ESTABLISHED STATE, FIN-WAIT-1 STATE, FIN-WAIT-2 STATE ... it
*                       is possible to deliver segment text to user RECEIVE buffers" :
*
*                       (1) "If the segment ... carries [a] PUSH flag, then the user is informed [and] the
*                            buffer is returned."
*
*                       (2) (A) (1) "When the TCP takes responsibility for delivering the data to the user it
*                                    must also acknowledge the receipt of the data."
*
*                               (2) "This acknowledgment should be piggybacked on a segment being transmitted
*                                    if possible without incurring undue delay."
*
*                           (B) "Once the TCP takes responsibility for the data" ...
*
*                               (1) "it advances RCV.NXT over the data accepted," ...
*
*                               (2) "adjusts RCV.WND as appropriate to the current buffer availability" ...
*
*                               (3) (a) "The total of RCV.NXT and RCV.WND should not be reduced."
*
*                                   (b) RFC #793,  Section 3.7 'Data Communication : Managing the Window' &
*                                       RFC #1122, Section 4.2.2.16 confirm that "a TCP receiver SHOULD NOT
*                                       shrink the window"; i.e. "advertise a much smaller window without
*                                       having accepted that much data".
*
*                   (f) RFC #793, Section 3.9 'Event Processing : SEGMENT ARRIVES : Check FIN Bit' states
*                       that "if the FIN bit is set" ...
*
*                       (1) "signal the user 'connection closing' and return any pending RECEIVEs with
*                            same message," ...
*
*                       (2) "advance RCV.NXT over the FIN," ...
*
*                       (3) "send an acknowledgment for the FIN" ...
*
*                       (4) "FIN implies PUSH for any segment text not yet delivered to the user" ...
*
*                       (5) For the "FIN-WAIT-1 STATE" :
*
*                           (A) "If our FIN has been ACKed (perhaps in this segment), then" ...
*
*                               (1) "enter TIME-WAIT [state]" ...
*                                   (a) "start the time-wait timer,  ...
*                                       (1) A TCP connection should be closed WITHOUT fault following a TCP
*                                           connection TIME-WAIT timeout.
*
*                                   (b) "turn off the other timers;" ...
*
*                               (2) However, it is possible that some closing received data from the remote
*                                   host is available but has NOT yet been received by the application layer.
*
*                                   (a) Therefore, if the application receive queue is closed, then enter the
*                                       TIME-WAIT state.
*
*                                   (b) (1) But if the application receive queue is NOT closed, then enter the
*                                           connection-closing-data-available state to allow the application
*                                           layer to receive the remaining receive data.
*
*                                       (2) (A) To satisfy the required time-wait timeout of two maximum segment
*                                               lifetimes (see Note #2f5A1a), the time-wait timeout is intially
*                                               used to provide the application layer sufficient time to receive
*                                               the closing received data.
*
*                                           (B) If after the time-wait timeout expires, the application receive
*                                               queue is still not empty, the user connection timeout is used
*                                               to provide the application layer additional time to receive the
*                                               closing received data.
*
*                                           See also Note #3.
*
*                           (B) "otherwise, enter the CLOSING state."
*$PAGE*
*               (3) (a) RFC #793, Section 3.9 'Event Processing : USER TIMEOUT : USER TIMEOUT' states that
*                       "for any state if the user timeout expires, flush all queues, signal the user
*                       'error : connection aborted due to user timeout' ... [and] enter the CLOSED state".
*
*                   (b) However, NO RFC specifies or suggests any mechanism to implement/handle user timeouts.
*
*                       ???? Therefore, it is assumed that ANY TCP connection that receives a valid TCP data
*                       or control segment should reset its user connection timer.
*
*               (4) Since the mechanisms of TCP connection close are independent of the application layer
*                   close; any external application layer close error(s) are ignored.
*********************************************************************************************************
*/

static  void  NetTCP_RxPktConnHandlerFinWait1 (NET_TCP_CONN  *pconn,
                                               NET_BUF       *pbuf,
                                               NET_BUF_HDR   *pbuf_hdr,
                                               NET_ERR       *perr)
{
    NET_TCP_SEQ_CODE     seq_code;
    NET_TCP_ACK_CODE     ack_code;
    NET_TCP_RESET_CODE   reset_code;
    CPU_BOOLEAN          data_avail;
    NET_TCP_TIMEOUT_SEC  timeout_sec;
    NET_TMR_TICK         timeout_tick;
    CPU_FNCT_PTR         timeout_fnct;
    NET_TCP_FREE_CODE    free_code;
    NET_ERR              err;
    NET_ERR              err_rtn;


/*$PAGE*/
                                                                /* -------------- VALIDATE RX'D TCP PKT --------------- */
                                                                /* Chk for rx'd fin/close.                              */
    if (pbuf_hdr->TCP_SegClose == DEF_YES) {                    /* If fin/close avail, update seg lens.                 */
        pbuf_hdr->TCP_SegLenInit += NET_TCP_SEG_LEN_CLOSE;
        pbuf_hdr->TCP_SegLen     += NET_TCP_SEG_LEN_CLOSE;
    }

                                                                /* Chk rx'd seq nbr.                                    */
    seq_code = NetTCP_RxPktConnIsValidSeq(pconn, pbuf_hdr, perr);
    if (*perr != NET_TCP_ERR_NONE) {
         return;
    }
    switch (seq_code) {
        case NET_TCP_CONN_RX_SEQ_VALID:
             break;


        case NET_TCP_CONN_RX_SEQ_SYNC:                          /* If invalid sync rx'd, ...                            */
        case NET_TCP_CONN_RX_SEQ_SYNC_INVALID:
                                                                /* ... tx TCP conn ack  (see Notes #2c2 & #2b2B).       */
             NetTCP_TxConnAck(pconn, pbuf_hdr, NET_TCP_CONN_TX_ACK_FAULT, NET_TCP_CONN_CLOSE_ALL, &err);
            *perr = NET_TCP_ERR_CONN_SEQ_SYNC_INVALID;
             return;                                            /* Prevent 'break NOT reachable' compiler warning.      */


        case NET_TCP_CONN_RX_SEQ_NONE:
        case NET_TCP_CONN_RX_SEQ_INVALID:                       /* If invalid seq  rx'd (see Note #2a4A), ...           */
        default:
             if (pbuf_hdr->TCP_SegReset != DEF_YES) {           /* ... & reset NOT rx'd (see Note #2a4C), ...           */
                                                                /* ... tx TCP conn ack  (see Note #2a4B).               */
                 NetTCP_TxConnAck(pconn, pbuf_hdr, NET_TCP_CONN_TX_ACK_FAULT, NET_TCP_CONN_CLOSE_ALL, &err);
             }
            *perr = NET_TCP_ERR_CONN_SEQ_INVALID;
             return;                                            /* Prevent 'break NOT reachable' compiler warning.      */
    }

                                                                /* Chk for rx'd reset.                                  */
    reset_code = NetTCP_RxPktConnIsValidReset(pconn, pbuf_hdr, perr);
    if (*perr != NET_TCP_ERR_NONE) {
         return;
    }
    switch (reset_code) {
        case NET_TCP_CONN_RX_RESET_NONE:
             break;


        case NET_TCP_CONN_RX_RESET_VALID:                       /* If   valid reset rx'd, ...                           */
                                                                /* ...  close TCP conn (see Note #2b1A).                */
             NetTCP_ConnClose(pconn, pbuf_hdr, pconn->ConnCloseAppFlag, NET_TCP_CONN_CLOSE_ALL);
            *perr = NET_TCP_ERR_CONN_RESET_VALID;
             return;                                            /* Prevent 'break NOT reachable' compiler warning.      */


        case NET_TCP_CONN_RX_RESET_INVALID:                     /* If invalid reset rx'd, ...                           */
        default:
                                                                /* ... tx TCP conn ack (see Note #2b2Ac).               */
             NetTCP_TxConnAck(pconn, pbuf_hdr, NET_TCP_CONN_TX_ACK_FAULT, NET_TCP_CONN_CLOSE_ALL, &err);
            *perr = NET_TCP_ERR_CONN_RESET_INVALID;
             return;                                            /* Prevent 'break NOT reachable' compiler warning.      */
    }

                                                                /* Chk for rx'd ack.                                    */
    ack_code = NetTCP_RxPktConnIsValidAck(pconn, pbuf_hdr, perr);
    if (*perr != NET_TCP_ERR_NONE) {
         return;
    }
    switch (ack_code) {
        case NET_TCP_CONN_RX_ACK_VALID:
        case NET_TCP_CONN_RX_ACK_DUP:
        case NET_TCP_CONN_RX_ACK_PREV:
             break;


        case NET_TCP_CONN_RX_ACK_NONE:                          /* If NO      ack rx'd, ...                             */
            *perr = NET_TCP_ERR_CONN_ACK_NONE;                  /* ... ignore TCP pkt  (see Note #2d1).                 */
             return;                                            /* Prevent 'break NOT reachable' compiler warning.      */


        case NET_TCP_CONN_RX_ACK_INVALID:                       /* If invalid ack rx'd, ...                             */
        default:
                                                                /* ... tx TCP conn ack (see Note #2d2A3).               */
             NetTCP_TxConnAck(pconn, pbuf_hdr, NET_TCP_CONN_TX_ACK_FAULT, NET_TCP_CONN_CLOSE_ALL, &err);
            *perr = NET_TCP_ERR_CONN_ACK_INVALID;
             return;                                            /* Prevent 'break NOT reachable' compiler warning.      */
    }



/*$PAGE*/
                                                                /* ----------------- HANDLE RX'D SEG ------------------ */
    NetTCP_RxPktConnHandlerSeg(pconn, ack_code, pbuf, pbuf_hdr, &err_rtn);
    switch (err_rtn) {
        case NET_TCP_ERR_CONN_DATA_NONE:
        case NET_TCP_ERR_CONN_DATA_VALID:
             break;


        case NET_TCP_ERR_CONN_DATA_DUP:                         /* ???? Allow dup data to update TCP conn?              */
            *perr = err_rtn;
             return;                                            /* Prevent 'break NOT reachable' compiler warning.      */


        case NET_ERR_INIT_INCOMPLETE:
        case NET_TCP_ERR_CONN_NOT_USED:
        case NET_TCP_ERR_CONN_FAIL:
        case NET_TCP_ERR_CONN_ACK_INVALID:
        case NET_TCP_ERR_CONN_DATA_INVALID:
        case NET_TCP_ERR_INVALID_CONN_STATE:
        case NET_TCP_ERR_INVALID_CONN_OP:
        case NET_TCP_ERR_INVALID_LEN_SEG:
        case NET_TCP_ERR_RX_Q_FULL:
        case NET_TCP_ERR_RX_Q_SIGNAL_FAULT:
        case NET_TCP_ERR_TX:
        case NET_TCP_ERR_TX_Q_SIGNAL_FAULT:
        case NET_TCP_ERR_RE_TX_SEG_TH:
        default:
             NetTCP_ConnClose(pconn, pbuf_hdr, pconn->ConnCloseAppFlag, NET_TCP_CONN_CLOSE_ALL);
            *perr = err_rtn;
             return;                                            /* Prevent 'break NOT reachable' compiler warning.      */
    }



                                                                /* ----------------- UPDATE TCP CONN ------------------ */
    timeout_fnct = (CPU_FNCT_PTR)0;

    if (pconn->TxQ_State == NET_TCP_TX_Q_STATE_CONN_CLOSED) {   /* If local conn close ack'd (see Note #2f5A);      ... */
                                                                /* Closing data avail for half-closed conns ONLY.       */
        data_avail = ((pconn->ConnCloseCode !=  NET_CONN_CLOSE_HALF           ) ||
                     ((pconn->RxQ_State     ==  NET_TCP_RX_Q_STATE_CONN_CLOSED) &&
                      (pconn->RxQ_App_Head  == (NET_BUF *)0))) ? DEF_NO : DEF_YES;

                                                                /* ... signal app conn close (see Note #2d2B2b1);   ... */
        NetTCP_RxPktConnHandlerSignalClose(pconn, data_avail, &err);
        switch (err) {
            case NET_TCP_ERR_NONE:
            case NET_TCP_ERR_CONN_FAIL:                         /* Ignore any app conn close err(s) [see Note #4].      */
                 break;


            case NET_TCP_ERR_CONN_NOT_USED:
            case NET_TCP_ERR_INVALID_CONN_ID:
            case NET_TCP_ERR_INVALID_CONN_STATE:
            case NET_TCP_ERR_INVALID_CONN_OP:
            case NET_CONN_ERR_INVALID_FAMILY:
            case NET_CONN_ERR_INVALID_CONN:
            case NET_CONN_ERR_NOT_USED:
            default:
                 NetTCP_ConnClose(pconn, pbuf_hdr, DEF_YES, NET_TCP_CONN_CLOSE_ALL);
                *perr = err;
                 return;                                        /* Prevent 'break NOT reachable' compiler warning.      */
        }
/*$PAGE*/
        if (pbuf_hdr->TCP_SegClose == DEF_YES) {                /* ... & if fin/close rx'd                          ... */

            if (data_avail != DEF_YES) {                        /* ... & NO app data avail,                         ... */
                                                                /* ... chng to time-wait state (see Note  #2f5A2a); ... */
                pconn->ConnState                 =  NET_TCP_CONN_STATE_TIME_WAIT;
                pconn->ConnCloseTimeoutFaultFlag =  DEF_NO;     /* ... clr close timeout fault (see Note  #2f5A1a1);... */
                timeout_fnct                     = (CPU_FNCT_PTR)NetTCP_ConnCloseTimeout;

            } else {                                            /* ... else chng to conn-closing-data-avail state   ... */
                                                                /* ...                         (see Note  #2f5A2b1);... */
                pconn->ConnState =  NET_TCP_CONN_STATE_CLOSING_DATA_AVAIL;
                timeout_fnct     = (CPU_FNCT_PTR)NetTCP_ConnClosingTimeoutDataAvail;
            }
                                                                /* ... & start time-wait tmr   (see Notes #2f5A1a & ... */
                                                                /* ...                                    #2f5A2b2A).   */
            timeout_sec = pconn->TimeoutMaxSeg_sec * NET_TCP_CONN_TIMEOUT_MAX_SEG_SCALAR;

        } else {
            pconn->ConnState =  NET_TCP_CONN_STATE_FIN_WAIT_2;  /* ... else chng to fin-wait-2 state (see Note #2d2B1b1)*/
            timeout_sec      =  pconn->TimeoutConn_sec;         /* ... & start conn close tmr (see Note #3b).           */
            timeout_fnct     = (CPU_FNCT_PTR)NetTCP_ConnCloseTimeout;
        }


    } else {
        if (pbuf_hdr->TCP_SegClose == DEF_YES) {                /* Else if fin/close rx'd,                    ...       */
            pconn->ConnState =  NET_TCP_CONN_STATE_CLOSING;     /* ... chng to closing state (see Note #2f5B) ...       */
            timeout_sec      =  pconn->TimeoutConn_sec;         /* ... & start conn close tmr (see Note #3b).           */
            timeout_fnct     = (CPU_FNCT_PTR)NetTCP_ConnCloseTimeout;
        }
    }


                                                                /* ------------------- UPDATE TMRs -------------------- */
    switch (pconn->ConnState) {
        case NET_TCP_CONN_STATE_TIME_WAIT:                      /* If in time-wait            (see Note #2f5A1)    ...  */
        case NET_TCP_CONN_STATE_FIN_WAIT_2:
        case NET_TCP_CONN_STATE_CLOSING_DATA_AVAIL:             /* ... or closing state(s)    [see Note #2d2B2b2], ...  */
             free_code = NET_TCP_CONN_FREE_TMR_ALL;             /* ... free all TCP conn tmrs (see Note #2f5A1b).       */
             DEF_BIT_CLR(free_code, NET_TCP_CONN_FREE_TMR_TIMEOUT);
             NetTCP_ConnFreeTmr(pconn, free_code);
             break;
    }


    if (timeout_fnct != (CPU_FNCT_PTR)0) {
        timeout_tick  = (NET_TMR_TICK)timeout_sec * NET_TMR_TIME_TICK_PER_SEC;
        if (pconn->TimeoutTmr != (NET_TMR *)0) {
            NetTmr_Set((NET_TMR    *) pconn->TimeoutTmr,
                       (CPU_FNCT_PTR) timeout_fnct,
                       (NET_TMR_TICK) timeout_tick,
                       (NET_ERR    *)&err);
        } else {
            pconn->TimeoutTmr = NetTmr_Get((void       *) pconn,
                                           (CPU_FNCT_PTR) timeout_fnct,
                                           (NET_TMR_TICK) timeout_tick,
                                           (CPU_INT16U  ) NET_TMR_FLAG_NONE,
                                           (NET_ERR    *)&err);
        }

        if ( err != NET_TMR_ERR_NONE) {
            NetTCP_ConnClose(pconn, pbuf_hdr, pconn->ConnCloseAppFlag, NET_TCP_CONN_CLOSE_ALL);
           *perr  = NET_TCP_ERR_CONN_FAIL;
            return;
        }
    }



/*$PAGE*/
                                                                /* --------------- TX TCP CONN ACK/DATA --------------- */
    ack_code = ((pbuf_hdr->TCP_SegAckTxReqCode == NET_TCP_CONN_TX_ACK_IMMED) ||
                (pbuf_hdr->TCP_SegClose        == DEF_YES))     /* See Note #2f3.                                       */
             ?   NET_TCP_CONN_TX_ACK_IMMED
             :   NET_TCP_CONN_TX_ACK;

    if ((pconn->ConnState == NET_TCP_CONN_STATE_FIN_WAIT_1) ||  /* If TCP conn tx Q NOT closed, ...                     */
        (pconn->ConnState == NET_TCP_CONN_STATE_CLOSING   )) {  /* ... tx ack & any tx data (see Note #1c).             */
        NetTCP_TxConnTxQ(pconn, pbuf_hdr, ack_code, DEF_NO, NET_TCP_CONN_CLOSE_ALL, perr);
        switch (*perr) {
            case NET_TCP_ERR_NONE:
            case NET_TCP_ERR_CONN_ACK_NONE:
            case NET_TCP_ERR_CONN_ACK_INVALID:
            case NET_TCP_ERR_CONN_ACK_DLYD:
            case NET_TCP_ERR_CONN_ACK_PREVLY_TXD:
            case NET_ERR_TX:                                    /* Ignore transitory tx err(s).                         */
                 break;


            case NET_ERR_INIT_INCOMPLETE:
            case NET_TCP_ERR_CONN_NOT_USED:
            case NET_TCP_ERR_CONN_CLOSE:
            case NET_TCP_ERR_CONN_FAULT:
            case NET_TCP_ERR_CONN_FAIL:
            case NET_TCP_ERR_INVALID_CONN_STATE:
            case NET_TCP_ERR_INVALID_CONN_OP:
            case NET_TCP_ERR_INVALID_LEN_SEG:
            case NET_TCP_ERR_NONE_AVAIL:
            case NET_TCP_ERR_TX:
            case NET_CONN_ERR_INVALID_FAMILY:
            case NET_CONN_ERR_INVALID_ADDR:
            case NET_CONN_ERR_INVALID_ADDR_LEN:
            default:
                 return;                                        /* Prevent 'break NOT reachable' compiler warning.      */
        }

    } else {                                                    /* Else tx TCP conn ack (see Note #2f3).                */
        NetTCP_TxConnAck(pconn, pbuf_hdr, ack_code, NET_TCP_CONN_CLOSE_ALL, perr);
        switch (*perr) {
            case NET_TCP_ERR_NONE:
            case NET_TCP_ERR_CONN_ACK_NONE:
            case NET_TCP_ERR_CONN_ACK_INVALID:
            case NET_TCP_ERR_CONN_ACK_DLYD:
            case NET_TCP_ERR_CONN_ACK_PREVLY_TXD:
                 break;


            case NET_TCP_ERR_CONN_NOT_USED:
            case NET_TCP_ERR_CONN_FAULT:
            case NET_TCP_ERR_INVALID_CONN_STATE:
            case NET_TCP_ERR_INVALID_CONN_OP:
            case NET_TCP_ERR_INVALID_LEN_SEG:
            case NET_TCP_ERR_NONE_AVAIL:
            default:
                 return;                                        /* Prevent 'break NOT reachable' compiler warning.      */
        }
    }



   *perr = err_rtn;
}


/*$PAGE*/
/*
*********************************************************************************************************
*                                  NetTCP_RxPktConnHandlerFinWait2()
*
* Description : (1) Handle TCP connection in FIN-WAIT-2 state :
*
*                   (a) Validate received TCP packet for current TCP connection state :
*
*                       (1) Sequence Number (SEQ)                                   See Note  #2a
*                       (2) Reset           (RST)                                   See Note  #2b
*                       (3) Synchronization (SYN)                                   See Note  #2c
*                       (4) Acknowledgement (ACK)                                   See Note  #2d
*                       (5) Finish/Close    (FIN)                                   See Note  #2f
*
*                   (b) Update TCP connection :
*                       (1) Handle received TCP segment                             See Notes #2d   & #2e
*                       (2) Update TCP connection state :                           See Notes #2f5A & #2f5B2a
*                           (A) Configure TCP connection timeout value
*                           (B) Configure TCP connection timeout function
*                       (3) Update TCP connection timer(s)                          See Notes #2f5A,  #2f5B2b, & #3
*
*                   (c) Transmit TCP connection acknowledgement                     See Notes #2e2A & #2f3
*
*
* Argument(s) : pconn       Pointer to a TCP connection.
*               -----       Argument validated in NetTCP_RxPktConnHandler().
*
*               pbuf        Pointer to network buffer that received TCP packet.
*               ----        Argument checked   in NetTCP_Rx().
*
*               pbuf_hdr    Pointer to network buffer header that received TCP packet.
*               --------    Argument validated in NetTCP_Rx().
*
*               perr        Pointer to variable that will receive the return error code from this function :
*
*                               NET_TCP_ERR_CONN_SEQ_SYNC_INVALID   Received segment's synchronization        is
*                                                                       NOT valid for current TCP connection.
*                               NET_TCP_ERR_CONN_SEQ_INVALID        Received segment's sequence        number is
*                                                                       NOT valid for current TCP connection.
*                               NET_TCP_ERR_CONN_ACK_NONE           Received segment's acknowledgement        is
*                                                                       NOT available.
*                               NET_TCP_ERR_CONN_ACK_INVALID        Received segment's acknowledgement number is
*                                                                       NOT valid for current TCP connection.
*                               NET_TCP_ERR_CONN_RESET_VALID        Received segment's reset flag is     valid
*                                                                       for current TCP connection; i.e. reset
*                                                                       the TCP connection.
*                               NET_TCP_ERR_CONN_RESET_INVALID      Received segment's reset flag is NOT valid
*                                                                       for current TCP connection.
*
*                               NET_TCP_ERR_CONN_FAIL               TCP connection operation(s) failed.
*
*                                                                   -- RETURNED BY NetTCP_RxPktConnIsValidSeq() : --
*                                                                   -- RETURNED BY NetTCP_RxPktConnIsValidAck() : --
*                                                                   - RETURNED BY NetTCP_RxPktConnIsValidReset() : -
*                               NET_TCP_ERR_CONN_NOT_USED           TCP connection NOT currently used.
*                               NET_TCP_ERR_INVALID_CONN_STATE      Invalid TCP connection state.
*                               NET_TCP_ERR_INVALID_LEN_SEG         Invalid TCP sequence-segment length.
*
*                                                                   -- RETURNED BY NetTCP_RxPktConnHandlerSeg() : --
*                               NET_TCP_ERR_CONN_DATA_NONE          Received packet successfully handled; but NO
*                                                                       data to   queue  to receive queue(s).
*                               NET_TCP_ERR_CONN_DATA_VALID         Received packet successfully handled & valid
*                                                                       data queued for processing.
*                               NET_TCP_ERR_CONN_DATA_INVALID       Received packet contains invalid   segment
*                                                                       data; NOT queued to receive queue(s).
*                               NET_TCP_ERR_CONN_DATA_DUP           Received packet contains duplicate segment
*                                                                       data; NOT queued to receive queue(s).
*
*                               NET_ERR_INIT_INCOMPLETE             Network initialization NOT complete.
*
*                               NET_TCP_ERR_INVALID_CONN_OP         Invalid TCP connection operation.
*
*                               NET_TCP_ERR_RX_Q_FULL               TCP connection receive queue full.
*                               NET_TCP_ERR_RX_Q_SIGNAL_FAULT       TCP connection receive queue signal fault.
*
*                                                                   ------- RETURNED BY NetTCP_TxConnAck() : -------
*                               NET_TCP_ERR_CONN_FAULT              TCP connection fault; connection(s) aborted.
*                               NET_TCP_ERR_NONE_AVAIL              Resources NOT available.
*
* Return(s)   : none.
*
* Caller(s)   : NetTCP_RxPktConnHandler().
*$PAGE*
* Note(s)     : (2) TCP connections in the FIN-WAIT-2 state are handled as follows :
*
*                   (a) RFC #793, Section 3.9 'Event Processing : SEGMENT ARRIVES : Check Sequence Number'
*                       states that in the "SYN-RECEIVED, ESTABLISHED STATE, FIN-WAIT-1 STATE, FIN-WAIT-2
*                       STATE, CLOSE-WAIT STATE, CLOSING STATE, LAST-ACK STATE, TIME-WAIT STATE" that ...
*
*                       (1) "Segments are processed in sequence ... processing is done in SEG.SEQ order."
*
*                       (2) "Initial tests on arrival are used to discard old duplicates."
*
*                       (3) "If a segment's contents straddle the boundary between old and new, only the
*                            new parts should be processed."
*
*                       (4) (A) "If an incoming segment is not acceptable," ...
*
*                           (B) "an acknowledgment should be sent in reply" ...
*
*                           (C) "(unless the RST bit is set, if so drop the segment)".
*
*                               See also Notes #2b2Aa & #2b2B.
*
*                       See also 'NetTCP_RxPktConnIsValidSeq()  Note #1d'.
*
*                   (b) (1) (A) RFC #793, Section 3.9 'Event Processing : SEGMENT ARRIVES : Check RST Bit' states
*                               that in the "ESTABLISHED, FIN-WAIT-1, FIN-WAIT-2, CLOSE-WAIT" states that "if the
*                               RST bit is set then, any outstanding RECEIVEs and SEND[s] should receive 'reset'
*                               responses.  All segment queues should be flushed.  Users should also receive an
*                               unsolicited general 'connection reset' signal[, and] enter the CLOSED state".
*
*                           (B) RFC #793, Section 3.4 'Establishing a Connection : Reset Processing' reiterates
*                               that "if the receiver ... of a RST ... was in any other state [other than LISTEN
*                               or SYN-RECEIVED], it aborts the connection and advises the user and goes to the
*                               CLOSED state".
*
*                       (2) (A) RFC Draft-IETF-TCPm-TCPSecure #00, Section 2.2 amends the "handling of a segment 
*                               with the RST bit when in a synchronized state" to "provide some protection against
*                               ... blind reset attack[s] using the RST bit" :
*
*                               (a) "If the RST bit is set and the sequence number is outside the expected
*                                    window, silently drop the segment."
*
*                               (b) "If the RST bit is exactly the next expected sequence number [sic], reset
*                                    the connection"; it is assumed that this should read "if the RST bit is
*                                    set and the sequence number is exactly the next expected sequence number,
*                                    reset the connection."
*
*                               (c) "If the RST bit is set and the sequence number does not exactly match
*                                    the next expected sequence value, yet is within the acceptable window
*                                    (RCV.NXT <= SEG.SEQ < RCV.NXT+RCV.WND) send an acknowledgment."
*
*                           (B) ???? In addition, RFC Draft-IETF-TCPm-TCPSecure #00 does NOT provide a precedence 
*                               priority for handling TCP segments received with BOTH the RST & SYN bits set.
*
*                               ???? Therefore, since it does NOT seem reasonable to reset a TCP connection
*                               due to a TCP segment that also attempted to synchronize the  TCP connection,
*                               it is assumed that the amended handling of the SYN bit should take precedence
*                               over the amended handling of the RST bit.
*
*                               See also Note #2c2.
*
*                   (c) (1) RFC #793, Section 3.9 'Event Processing : SEGMENT ARRIVES : Check SYN Bit'
*                           states that in the "SYN-RECEIVED [STATE], ESTABLISHED STATE, FIN-WAIT STATE-1,
*                           FIN-WAIT STATE-2, CLOSE-WAIT STATE, CLOSING STATE, LAST-ACK STATE, TIME-WAIT
*                           STATE" that ...
*
*                           (A) "If the SYN is in the window it is an error, send a reset, any outstanding
*                                RECEIVEs and SEND[s] should receive 'reset' responses, all segment queues
*                                should be flushed, the user should also receive an unsolicited general
*                               'connection reset' signal[, and] enter the CLOSED state."
*
*                           (B) But "if the SYN is not in the window this step would not have been reached
*                               and an ack would have been sent".
*
*                       (2) HOWEVER, RFC Draft-IETF-TCPm-TCPSecure #00, Section 3.2 amends the  "handling 
*                           of a segment with the SYN bit set in the synchronized state ... [by] handling 
*                           ... the SYN bit" as follows :
*
*                           (a) "If the SYN bit is set and the sequence number is outside the
*                                expected window, send an ACK back to the peer."
*
*                           (b) "If the SYN bit is set and the sequence number is an exact
*                                match to the next expected sequence (RCV.NXT == SEG.SEQ)
*                                then send an ACK segment ... but ... subtract one from
*                                value being acknowledged."
*
*                           (c) "If the SYN bit is set and the sequence number is acceptable,
*                                i.e.: (RCV.NXT <= SEG.SEQ <= RCV.NXT+RCV.WND) then send an
*                                ACK segment."
*$PAGE*
*                   (d) RFC #793, Section 3.9 'Event Processing : SEGMENT ARRIVES : Check ACK Field'
*                       states that ... :
*
*                       (1) "If the ACK bit is off drop the segment."
*
*                       (2) "If the ACK bit is on" ...
*
*                           (A) And in the "ESTABLISHED STATE" ...
*
*                               (1) "If SND.UNA < SEG.ACK <= SND.NXT then" ...
*
*                                   (a) "set SND.UNA <- SEG.ACK."
*
*                                   (b) "Any segments on the retransmission queue which are thereby entirely
*                                        acknowledged are removed."
*
*                                   (c) "the send window should be updated" :
*
*                                       (1) (A) (1) "If ((SND.WL1 <  SEG.SEQ) or" ...
*
*                                               (2) (a) "(SND.WL1  = SEG.SEQ and" ...
*                                                   (b)  "SND.WL2 <= SEG.ACK))," ...
*
*                                           (B) (1) "set SND.WND <- SEG.WND," ...
*                                               (2) "set SND.WL1 <- SEG.SEQ," ...
*                                               (3) "set SND.WL2 <- SEG.ACK."
*
*                                       (2) "Note that SND.WND is an offset from SND.UNA, that SND.WL1 records the
*                                            sequence number of the last segment used to update SND.WND, and that
*                                            SND.WL2 records the acknowledgment number of the last segment used to
*                                            update SND.WND.  The check here preveents using old segments to update
*                                            the window."
*
*                               (2) (a) "If the ACK is a duplicate (SEG.ACK <= SND.UNA), it can be ignored."
*
*                                   (b) RFC #1122, Section 4.2.2.20.(g) amends the transmit window update criteria
*                                       for the segment's acknowledgement to include SND.UNA : "The window should
*                                       updated if SND.UNA <= SEG.ACK <= SND.NXT."
*
*                                       See also 'NetTCP_RxPktConnHandlerTxWinRemote()  Note #1b2'.
*
*                               (3) "If the ACK acks something not yet sent (SEG.ACK > SND.NXT) then send an ACK
*                                    [and] drop the segment."
*
*                           (B) For the "FIN-WAIT-2 STATE" :
*
*                               (1) "in addition to the processing for the ESTABLISHED state" ...
*                               (2) "if the retransmission queue is empty,"                   ...
*
*                                   (a) (1) "the user's CLOSE can be acknowledged."
*                                       (2) However, a TCP connection transitions into the FIN-WAIT-2 state if &
*                                           only if the TCP connection's close request was previously acknowledged
*                                           while in the FIN-WAIT-1 state.  Thus, the TCP connection's re-transmit
*                                           queue should already be empty prior to entering the FIN-WAIT-2 state.
*
*                                           See also 'NetTCP_RxPktConnHandlerFinWait1()  Note #2d2B2'.
*
*                   (e) RFC #793, Section 3.9 'Event Processing : SEGMENT ARRIVES : Process Segment Text'
*                       states that for the "ESTABLISHED STATE, FIN-WAIT-1 STATE, FIN-WAIT-2 STATE ... it
*                       is possible to deliver segment text to user RECEIVE buffers" :
*
*                       (1) "If the segment ... carries [a] PUSH flag, then the user is informed [and] the
*                            buffer is returned."
*
*                       (2) (A) "When the TCP takes responsibility for delivering the data to the user it
*                                must also acknowledge the receipt of the data."
*
*                           (B) "Once the TCP takes responsibility for the data" ...
*
*                               (1) "it advances RCV.NXT over the data accepted," ...
*
*                               (2) "adjusts RCV.WND as appropriate to the current buffer availability" ...
*
*                               (3) (a) "The total of RCV.NXT and RCV.WND should not be reduced."
*
*                                   (b) RFC #793,  Section 3.7 'Data Communication : Managing the Window' &
*                                       RFC #1122, Section 4.2.2.16 confirm that "a TCP receiver SHOULD NOT
*                                       shrink the window"; i.e. "advertise a much smaller window without
*                                       having accepted that much data".
*$PAGE*
*                   (f) RFC #793, Section 3.9 'Event Processing : SEGMENT ARRIVES : Check FIN Bit' states
*                       that "if the FIN bit is set" ...
*
*                       (1) "signal the user 'connection closing' and return any pending RECEIVEs with
*                            same message," ...
*
*                       (2) "advance RCV.NXT over the FIN," ...
*
*                       (3) "send an acknowledgment for the FIN" ...
*
*                       (4) "FIN implies PUSH for any segment text not yet delivered to the user" ...
*
*                       (5) For the "FIN-WAIT-2 STATE" :
*
*                           (A) "Enter the TIME-WAIT state"      ...
*                               (1) "Start the time-wait timer," ...
*                                   (a) A TCP connection should be closed WITHOUT fault following a TCP
*                                       connection TIME-WAIT timeout.
*
*                               (2) "turn off the other timers."
*
*                           (B) However, it is possible that some closing received data from the remote
*                               host is available but has NOT yet been received by the application layer.
*
*                               (1) Therefore, if the application receive queue is closed, then enter the
*                                   TIME-WAIT state.
*
*                               (2) (a) But if the application receive queue is NOT closed, then enter the
*                                       connection-closing-data-available state to allow the application
*                                       layer to receive the remaining receive data.
*
*                                   (b) (1) To satisfy the required time-wait timeout of two maximum segment
*                                           lifetimes (see Note #2f5A1a), the time-wait timeout is intially
*                                           used to provide the application layer sufficient time to receive
*                                           the closing received data.
*
*                                       (2) If after the time-wait timeout expires, the application receive
*                                           queue is still not empty, the user connection timeout is used
*                                           to provide the application layer additional time to receive the
*                                           closing received data.
*
*                                       See also Note #3.
*
*               (3) (a) RFC #793, Section 3.9 'Event Processing : USER TIMEOUT : USER TIMEOUT' states that
*                       "for any state if the user timeout expires, flush all queues, signal the user
*                       'error : connection aborted due to user timeout' ... [and] enter the CLOSED state".
*
*                   (b) However, NO RFC specifies or suggests any mechanism to implement/handle user timeouts.
*
*                       ???? Therefore, it is assumed that ANY TCP connection that receives a valid TCP data
*                       or control segment should reset its user connection timer.
*********************************************************************************************************
*/

static  void  NetTCP_RxPktConnHandlerFinWait2 (NET_TCP_CONN  *pconn,
                                               NET_BUF       *pbuf,
                                               NET_BUF_HDR   *pbuf_hdr,
                                               NET_ERR       *perr)
{
    NET_TCP_SEQ_CODE     seq_code;
    NET_TCP_ACK_CODE     ack_code;
    NET_TCP_RESET_CODE   reset_code;
    CPU_BOOLEAN          data_avail;
    NET_TCP_TIMEOUT_SEC  timeout_sec;
    NET_TMR_TICK         timeout_tick;
    CPU_FNCT_PTR         timeout_fnct;
    NET_TCP_FREE_CODE    free_code;
    NET_ERR              err;
    NET_ERR              err_rtn;


/*$PAGE*/
                                                                /* -------------- VALIDATE RX'D TCP PKT --------------- */
                                                                /* Chk for rx'd fin/close.                              */
    if (pbuf_hdr->TCP_SegClose == DEF_YES) {                    /* If fin/close avail, update seg lens.                 */
        pbuf_hdr->TCP_SegLenInit += NET_TCP_SEG_LEN_CLOSE;
        pbuf_hdr->TCP_SegLen     += NET_TCP_SEG_LEN_CLOSE;
    }

                                                                /* Chk rx'd seq nbr.                                    */
    seq_code = NetTCP_RxPktConnIsValidSeq(pconn, pbuf_hdr, perr);
    if (*perr != NET_TCP_ERR_NONE) {
         return;
    }
    switch (seq_code) {
        case NET_TCP_CONN_RX_SEQ_VALID:
             break;


        case NET_TCP_CONN_RX_SEQ_SYNC:                          /* If invalid sync rx'd, ...                            */
        case NET_TCP_CONN_RX_SEQ_SYNC_INVALID:
                                                                /* ... tx TCP conn ack  (see Notes #2c2 & #2b2B).       */
             NetTCP_TxConnAck(pconn, pbuf_hdr, NET_TCP_CONN_TX_ACK_FAULT, NET_TCP_CONN_CLOSE_ALL, &err);
            *perr = NET_TCP_ERR_CONN_SEQ_SYNC_INVALID;
             return;                                            /* Prevent 'break NOT reachable' compiler warning.      */


        case NET_TCP_CONN_RX_SEQ_NONE:
        case NET_TCP_CONN_RX_SEQ_INVALID:                       /* If invalid seq  rx'd (see Note #2a4A), ...           */
        default:
             if (pbuf_hdr->TCP_SegReset != DEF_YES) {           /* ... & reset NOT rx'd (see Note #2a4C), ...           */
                                                                /* ... tx TCP conn ack  (see Note #2a4B).               */
                 NetTCP_TxConnAck(pconn, pbuf_hdr, NET_TCP_CONN_TX_ACK_FAULT, NET_TCP_CONN_CLOSE_ALL, &err);
             }
            *perr = NET_TCP_ERR_CONN_SEQ_INVALID;
             return;                                            /* Prevent 'break NOT reachable' compiler warning.      */
    }

                                                                /* Chk for rx'd reset.                                  */
    reset_code = NetTCP_RxPktConnIsValidReset(pconn, pbuf_hdr, perr);
    if (*perr != NET_TCP_ERR_NONE) {
         return;
    }
    switch (reset_code) {
        case NET_TCP_CONN_RX_RESET_NONE:
             break;


        case NET_TCP_CONN_RX_RESET_VALID:                       /* If   valid reset rx'd, ...                           */
                                                                /* ...  close TCP conn (see Note #2b1A).                */
             NetTCP_ConnClose(pconn, pbuf_hdr, pconn->ConnCloseAppFlag, NET_TCP_CONN_CLOSE_ALL);
            *perr = NET_TCP_ERR_CONN_RESET_VALID;
             return;                                            /* Prevent 'break NOT reachable' compiler warning.      */


        case NET_TCP_CONN_RX_RESET_INVALID:                     /* If invalid reset rx'd, ...                           */
        default:
                                                                /* ... tx TCP conn ack (see Note #2b2Ac).               */
             NetTCP_TxConnAck(pconn, pbuf_hdr, NET_TCP_CONN_TX_ACK_FAULT, NET_TCP_CONN_CLOSE_ALL, &err);
            *perr = NET_TCP_ERR_CONN_RESET_INVALID;
             return;                                            /* Prevent 'break NOT reachable' compiler warning.      */
    }

                                                                /* Chk for rx'd ack.                                    */
    ack_code = NetTCP_RxPktConnIsValidAck(pconn, pbuf_hdr, perr);
    if (*perr != NET_TCP_ERR_NONE) {
         return;
    }
    switch (ack_code) {
        case NET_TCP_CONN_RX_ACK_VALID:
        case NET_TCP_CONN_RX_ACK_DUP:
        case NET_TCP_CONN_RX_ACK_PREV:
             break;


        case NET_TCP_CONN_RX_ACK_NONE:                          /* If NO      ack rx'd, ...                             */
            *perr = NET_TCP_ERR_CONN_ACK_NONE;                  /* ... ignore TCP pkt  (see Note #2d1).                 */
             return;                                            /* Prevent 'break NOT reachable' compiler warning.      */


        case NET_TCP_CONN_RX_ACK_INVALID:                       /* If invalid ack rx'd, ...                             */
        default:
                                                                /* ... tx TCP conn ack (see Note #2d2A3).               */
             NetTCP_TxConnAck(pconn, pbuf_hdr, NET_TCP_CONN_TX_ACK_FAULT, NET_TCP_CONN_CLOSE_ALL, &err);
            *perr = NET_TCP_ERR_CONN_ACK_INVALID;
             return;                                            /* Prevent 'break NOT reachable' compiler warning.      */
    }



/*$PAGE*/
                                                                /* ----------------- HANDLE RX'D SEG ------------------ */
    NetTCP_RxPktConnHandlerSeg(pconn, ack_code, pbuf, pbuf_hdr, &err_rtn);
    switch (err_rtn) {
        case NET_TCP_ERR_CONN_DATA_NONE:
        case NET_TCP_ERR_CONN_DATA_VALID:
             break;


        case NET_TCP_ERR_CONN_DATA_DUP:                         /* ???? Allow dup data to update TCP conn?              */
            *perr = err_rtn;
             return;                                            /* Prevent 'break NOT reachable' compiler warning.      */


        case NET_ERR_INIT_INCOMPLETE:
        case NET_TCP_ERR_CONN_NOT_USED:
        case NET_TCP_ERR_CONN_ACK_INVALID:
        case NET_TCP_ERR_CONN_DATA_INVALID:
        case NET_TCP_ERR_INVALID_CONN_STATE:
        case NET_TCP_ERR_INVALID_CONN_OP:
        case NET_TCP_ERR_INVALID_LEN_SEG:
        case NET_TCP_ERR_RX_Q_FULL:
        case NET_TCP_ERR_RX_Q_SIGNAL_FAULT:
        default:
             NetTCP_ConnClose(pconn, pbuf_hdr, pconn->ConnCloseAppFlag, NET_TCP_CONN_CLOSE_ALL);
            *perr = err_rtn;
             return;                                            /* Prevent 'break NOT reachable' compiler warning.      */
    }



                                                                /* ----------------- UPDATE TCP CONN ------------------ */
    if (pbuf_hdr->TCP_SegClose == DEF_YES) {                    /* If fin/close rx'd,                               ... */
                                                                /* Closing data avail for half-closed conns ONLY.       */
        data_avail = ((pconn->ConnCloseCode !=  NET_CONN_CLOSE_HALF           ) ||
                     ((pconn->RxQ_State     ==  NET_TCP_RX_Q_STATE_CONN_CLOSED) &&
                      (pconn->RxQ_App_Head  == (NET_BUF *)0))) ? DEF_NO : DEF_YES;

        if (data_avail != DEF_YES) {                            /* ... & NO app data avail,                         ... */
                                                                /* ... chng to time-wait state (see Note  #2f5B1);  ... */
            pconn->ConnState                 =  NET_TCP_CONN_STATE_TIME_WAIT;
            pconn->ConnCloseTimeoutFaultFlag =  DEF_NO;         /* ... clr close timeout fault (see Note  #2f5A1a); ... */
            timeout_fnct                     = (CPU_FNCT_PTR)NetTCP_ConnCloseTimeout;

        } else {                                                /* ... else chng to conn-closing-data-avail state   ... */
                                                                /* ...                         (see Note  #2f5B2a); ... */
            pconn->ConnState =  NET_TCP_CONN_STATE_CLOSING_DATA_AVAIL;
            timeout_fnct     = (CPU_FNCT_PTR)NetTCP_ConnClosingTimeoutDataAvail;
        }
                                                                /* ... & start time-wait tmr   (see Notes #2f5A1 &  ... */
                                                                /* ...                                    #2f5B2b1).    */
        timeout_sec  =  pconn->TimeoutMaxSeg_sec * NET_TCP_CONN_TIMEOUT_MAX_SEG_SCALAR;

    } else {
        timeout_sec  =  pconn->TimeoutConn_sec;                 /* Else start conn close tmr (see Note #3b).            */
        timeout_fnct = (CPU_FNCT_PTR)NetTCP_ConnCloseTimeout;
    }


/*$PAGE*/
                                                                /* ------------------- UPDATE TMRs -------------------- */
                                                                /* In time-wait or closing state(s) [see Note #2f5A],   */
    free_code = NET_TCP_CONN_FREE_TMR_ALL;                      /* ... free all TCP conn tmrs       (see Note #2f5A2).  */
    DEF_BIT_CLR(free_code, NET_TCP_CONN_FREE_TMR_TIMEOUT);
    NetTCP_ConnFreeTmr(pconn, free_code);


    timeout_tick = (NET_TMR_TICK)timeout_sec * NET_TMR_TIME_TICK_PER_SEC;
    if (pconn->TimeoutTmr != (NET_TMR *)0) {
        NetTmr_Set((NET_TMR    *) pconn->TimeoutTmr,
                   (CPU_FNCT_PTR) timeout_fnct,
                   (NET_TMR_TICK) timeout_tick,
                   (NET_ERR    *)&err);
    } else {
        pconn->TimeoutTmr = NetTmr_Get((void       *) pconn,
                                       (CPU_FNCT_PTR) timeout_fnct,
                                       (NET_TMR_TICK) timeout_tick,
                                       (CPU_INT16U  ) NET_TMR_FLAG_NONE,
                                       (NET_ERR    *)&err);
    }

    if ( err != NET_TMR_ERR_NONE) {
        NetTCP_ConnClose(pconn, pbuf_hdr, pconn->ConnCloseAppFlag, NET_TCP_CONN_CLOSE_ALL);
       *perr  = NET_TCP_ERR_CONN_FAIL;
        return;
    }


                                                                /* ----------------- TC TCP CONN ACK ------------------ */
                                                                /* Tx TCP conn ack (see Notes #1c).                     */
    NetTCP_TxConnAck(pconn, pbuf_hdr, NET_TCP_CONN_TX_ACK_IMMED, NET_TCP_CONN_CLOSE_ALL, perr);
    switch (*perr) {
        case NET_TCP_ERR_NONE:
        case NET_TCP_ERR_CONN_ACK_NONE:
        case NET_TCP_ERR_CONN_ACK_INVALID:
        case NET_TCP_ERR_CONN_ACK_DLYD:
        case NET_TCP_ERR_CONN_ACK_PREVLY_TXD:
             break;


        case NET_TCP_ERR_CONN_NOT_USED:
        case NET_TCP_ERR_CONN_FAULT:
        case NET_TCP_ERR_INVALID_CONN_STATE:
        case NET_TCP_ERR_INVALID_CONN_OP:
        case NET_TCP_ERR_INVALID_LEN_SEG:
        case NET_TCP_ERR_NONE_AVAIL:
        default:
             return;                                            /* Prevent 'break NOT reachable' compiler warning.      */
    }



   *perr = err_rtn;
}


/*$PAGE*/
/*
*********************************************************************************************************
*                                  NetTCP_RxPktConnHandlerClosing()
*
* Description : (1) Handle TCP connection in CLOSING state :
*
*                   (a) Validate received TCP packet for current TCP connection state :
*
*                       (1) Sequence Number (SEQ)                                   See Note  #2a
*                       (2) Reset           (RST)                                   See Note  #2b
*                       (3) Synchronization (SYN)                                   See Note  #2c
*                       (4) Acknowledgement (ACK)                                   See Note  #2d
*                       (5) Finish/Close    (FIN)                                   See Note  #2f
*
*                   (b) Update TCP connection :
*                       (1) Handle received TCP segment                             See Notes #2d    & #2e
*                       (2) Update TCP connection state :                           See Note  #2d2B2a1A
*                           (A) Configure TCP connection timeout value
*                           (B) Configure TCP connection timeout function
*                       (3) Update TCP connection timer(s)                          See Notes #2d2B2a1A, #2d2B2a1B2b,
*                                                                                                    & #3
*
*                   (c) Transmit TCP connection acknowledgement & data              See Notes #2d2B1 & #2f3
*
*$PAGE*
* Argument(s) : pconn       Pointer to a TCP connection.
*               -----       Argument validated in NetTCP_RxPktConnHandler().
*
*               pbuf        Pointer to network buffer that received TCP packet.
*               ----        Argument checked   in NetTCP_Rx().
*
*               pbuf_hdr    Pointer to network buffer header that received TCP packet.
*               --------    Argument validated in NetTCP_Rx().
*
*               perr        Pointer to variable that will receive the return error code from this function :
*
*                               NET_TCP_ERR_CONN_SEQ_SYNC_INVALID   Received segment's synchronization        is
*                                                                       NOT valid for current TCP connection.
*                               NET_TCP_ERR_CONN_SEQ_INVALID        Received segment's sequence        number is
*                                                                       NOT valid for current TCP connection.
*                               NET_TCP_ERR_CONN_ACK_NONE           Received segment's acknowledgement        is
*                                                                       NOT available.
*                               NET_TCP_ERR_CONN_ACK_INVALID        Received segment's acknowledgement number is
*                                                                       NOT valid for current TCP connection.
*                               NET_TCP_ERR_CONN_RESET_VALID        Received segment's reset flag is     valid
*                                                                       for current TCP connection; i.e. reset
*                                                                       the TCP connection.
*                               NET_TCP_ERR_CONN_RESET_INVALID      Received segment's reset flag is NOT valid
*                                                                       for current TCP connection.
*
*                               NET_TCP_ERR_CONN_FAIL               TCP connection operation(s) failed.
*
*                                                                   ----- RETURNED BY NetTCP_RxPktConnIsValidSeq() : -----
*                                                                   ----- RETURNED BY NetTCP_RxPktConnIsValidAck() : -----
*                                                                   ---- RETURNED BY NetTCP_RxPktConnIsValidReset() : ----
*                               NET_TCP_ERR_CONN_NOT_USED           TCP connection NOT currently used.
*                               NET_TCP_ERR_INVALID_CONN_STATE      Invalid TCP connection state.
*                               NET_TCP_ERR_INVALID_LEN_SEG         Invalid TCP sequence-segment length.
*
*                                                                   ----- RETURNED BY NetTCP_RxPktConnHandlerSeg() : -----
*                               NET_TCP_ERR_CONN_DATA_NONE          Received packet successfully handled; but NO
*                                                                       data to   queue  to receive queue(s).
*                               NET_TCP_ERR_CONN_DATA_VALID         Received packet successfully handled & valid
*                                                                       data queued for processing.
*                               NET_TCP_ERR_CONN_DATA_INVALID       Received packet contains invalid   segment
*                                                                       data; NOT queued to receive queue(s).
*                               NET_TCP_ERR_CONN_DATA_DUP           Received packet contains duplicate segment
*                                                                       data; NOT queued to receive queue(s).
*
*                               NET_ERR_INIT_INCOMPLETE             Network initialization NOT complete.
*
*                               NET_TCP_ERR_INVALID_CONN_OP         Invalid TCP connection operation.
*
*                               NET_TCP_ERR_RX_Q_FULL               TCP connection receive  queue full.
*                               NET_TCP_ERR_RX_Q_SIGNAL_FAULT       TCP connection receive  queue signal fault.
*                               NET_TCP_ERR_TX_Q_SIGNAL_FAULT       TCP connection transmit queue signal fault.
*                               NET_TCP_ERR_RE_TX_SEG_TH            TCP connection closed due to excessive retransmission.
*                               NET_TCP_ERR_TX                      TCP transmit error.
*
*                                                                   - RETURNED BY NetTCP_RxPktConnHandlerSignalClose() : -
*                               NET_TCP_ERR_INVALID_CONN_ID         Invalid application connection.
*                               NET_CONN_ERR_INVALID_FAMILY         Invalid network connection family.
*                               NET_CONN_ERR_INVALID_CONN           Invalid network connection number.
*                               NET_CONN_ERR_NOT_USED               Network connection NOT currently used.
*
*                                                                   ---------- RETURNED BY NetTCP_TxConnTxQ() : ----------
*                               NET_TCP_ERR_CONN_CLOSE              TCP connection closed.
*                               NET_TCP_ERR_CONN_FAULT              TCP connection fault; connection(s) aborted.
*                               NET_TCP_ERR_NONE_AVAIL              Resources NOT available.
*                               NET_CONN_ERR_INVALID_FAMILY         Invalid     connection family.
*                               NET_CONN_ERR_INVALID_ADDR           Invalid TCP connection address.
*                               NET_CONN_ERR_INVALID_ADDR_LEN       Invalid TCP connection address length.
*$PAGE*
* Return(s)   : none.
*
* Caller(s)   : NetTCP_RxPktConnHandler().
*
* Note(s)     : (2) TCP connections in the CLOSING state are handled as follows :
*
*                   (a) RFC #793, Section 3.9 'Event Processing : SEGMENT ARRIVES : Check Sequence Number'
*                       states that in the "SYN-RECEIVED, ESTABLISHED STATE, FIN-WAIT-1 STATE, FIN-WAIT-2
*                       STATE, CLOSE-WAIT STATE, CLOSING STATE, LAST-ACK STATE, TIME-WAIT STATE" that ...
*
*                       (1) "Segments are processed in sequence ... processing is done in SEG.SEQ order."
*
*                       (2) "Initial tests on arrival are used to discard old duplicates."
*
*                       (3) "If a segment's contents straddle the boundary between old and new, only the
*                            new parts should be processed."
*
*                       (4) (A) "If an incoming segment is not acceptable," ...
*
*                           (B) "an acknowledgment should be sent in reply" ...
*
*                           (C) "(unless the RST bit is set, if so drop the segment)".
*
*                               See also Notes #2b2Aa & #2b2B.
*
*                       See also 'NetTCP_RxPktConnIsValidSeq()  Note #1d'.
*
*                   (b) (1) (A) RFC #793, Section 3.9 'Event Processing : SEGMENT ARRIVES : Check RST Bit'
*                               states that in the "CLOSING, LAST-ACK, TIME-WAIT" states that "if the RST bit
*                               is set then, enter the CLOSED state".
*
*                           (B) RFC #793, Section 3.4 'Establishing a Connection : Reset Processing' reiterates
*                               that "if the receiver ... of a RST ... was in any other state [other than LISTEN
*                               or SYN-RECEIVED], it aborts the connection and advises the user and goes to the
*                               CLOSED state".
*
*                       (2) (A) RFC Draft-IETF-TCPm-TCPSecure #00, Section 2.2 amends the "handling of a segment 
*                               with the RST bit when in a synchronized state" to "provide some protection against
*                               ... blind reset attack[s] using the RST bit" :
*
*                               (a) "If the RST bit is set and the sequence number is outside the expected
*                                    window, silently drop the segment."
*
*                               (b) "If the RST bit is exactly the next expected sequence number [sic], reset
*                                    the connection"; it is assumed that this should read "if the RST bit is
*                                    set and the sequence number is exactly the next expected sequence number,
*                                    reset the connection."
*
*                               (c) "If the RST bit is set and the sequence number does not exactly match
*                                    the next expected sequence value, yet is within the acceptable window
*                                    (RCV.NXT <= SEG.SEQ < RCV.NXT+RCV.WND) send an acknowledgment."
*
*                           (B) ???? In addition, RFC Draft-IETF-TCPm-TCPSecure #00 does NOT provide a precedence 
*                               priority for handling TCP segments received with BOTH the RST & SYN bits set.
*
*                               ???? Therefore, since it does NOT seem reasonable to reset a TCP connection
*                               due to a TCP segment that also attempted to synchronize the  TCP connection,
*                               it is assumed that the amended handling of the SYN bit should take precedence
*                               over the amended handling of the RST bit.
*
*                               See also Note #2c2.
*
*                   (c) (1) RFC #793, Section 3.9 'Event Processing : SEGMENT ARRIVES : Check SYN Bit'
*                           states that in the "SYN-RECEIVED [STATE], ESTABLISHED STATE, FIN-WAIT STATE-1,
*                           FIN-WAIT STATE-2, CLOSE-WAIT STATE, CLOSING STATE, LAST-ACK STATE, TIME-WAIT
*                           STATE" that ...
*
*                           (A) "If the SYN is in the window it is an error, send a reset, any outstanding
*                                RECEIVEs and SEND[s] should receive 'reset' responses, all segment queues
*                                should be flushed, the user should also receive an unsolicited general
*                               'connection reset' signal[, and] enter the CLOSED state."
*
*                           (B) But "if the SYN is not in the window this step would not have been reached
*                               and an ack would have been sent".
*
*                       (2) HOWEVER, RFC Draft-IETF-TCPm-TCPSecure #00, Section 3.2 amends the  "handling 
*                           of a segment with the SYN bit set in the synchronized state ... [by] handling 
*                           ... the SYN bit" as follows :
*
*                           (a) "If the SYN bit is set and the sequence number is outside the
*                                expected window, send an ACK back to the peer."
*
*                           (b) "If the SYN bit is set and the sequence number is an exact
*                                match to the next expected sequence (RCV.NXT == SEG.SEQ)
*                                then send an ACK segment ... but ... subtract one from
*                                value being acknowledged."
*
*                           (c) "If the SYN bit is set and the sequence number is acceptable,
*                                i.e.: (RCV.NXT <= SEG.SEQ <= RCV.NXT+RCV.WND) then send an
*                                ACK segment."
*$PAGE*
*                   (d) RFC #793, Section 3.9 'Event Processing : SEGMENT ARRIVES : Check ACK Field'
*                       states that ... :
*
*                       (1) "If the ACK bit is off drop the segment."
*
*                       (2) "If the ACK bit is on" ...
*
*                           (A) And in the "ESTABLISHED STATE" ...
*
*                               (1) "If SND.UNA < SEG.ACK <= SND.NXT then" ...
*
*                                   (a) "set SND.UNA <- SEG.ACK."
*
*                                   (b) "Any segments on the retransmission queue which are thereby entirely
*                                        acknowledged are removed."
*
*                                   (c) "the send window should be updated" :
*
*                                       (1) (A) (1) "If ((SND.WL1 <  SEG.SEQ) or" ...
*
*                                               (2) (a) "(SND.WL1  = SEG.SEQ and" ...
*                                                   (b)  "SND.WL2 <= SEG.ACK))," ...
*
*                                           (B) (1) "set SND.WND <- SEG.WND," ...
*                                               (2) "set SND.WL1 <- SEG.SEQ," ...
*                                               (3) "set SND.WL2 <- SEG.ACK."
*
*                                       (2) "Note that SND.WND is an offset from SND.UNA, that SND.WL1 records the
*                                            sequence number of the last segment used to update SND.WND, and that
*                                            SND.WL2 records the acknowledgment number of the last segment used to
*                                            update SND.WND.  The check here preveents using old segments to update
*                                            the window."
*
*                               (2) (a) "If the ACK is a duplicate (SEG.ACK <= SND.UNA), it can be ignored."
*
*                                   (b) RFC #1122, Section 4.2.2.20.(g) amends the transmit window update criteria
*                                       for the segment's acknowledgement to include SND.UNA : "The window should
*                                       updated if SND.UNA <= SEG.ACK <= SND.NXT."
*
*                                       See also 'NetTCP_RxPktConnHandlerTxWinRemote()  Note #1b2'.
*
*                               (3) "If the ACK acks something not yet sent (SEG.ACK > SND.NXT) then send an ACK
*                                    [and] drop the segment."
*$PAGE*
*                           (B) For the "CLOSING STATE" :
*
*                               (1) "in addition to the processing for the ESTABLISHED state" ...
*
*                               (2) (a) "if the ACK acknowledges our FIN then" ...
*
*                                       (1) (A) "enter the TIME-WAIT state," ...
*
*                                               (1) The following sections ... :
*
*                                                   (a) RFC #793, Section 3.9 'Event Processing : SEGMENT ARRIVES :
*                                                           Check FIN Bit : FIN-WAIT-1 STATE'
*                                                   (b) RFC #793, Section 3.9 'Event Processing : SEGMENT ARRIVES :
*                                                           Check FIN Bit : FIN-WAIT-2 STATE'
*
*                                               (2) ... generalize that when entering "the TIME-WAIT state" to ...
*
*                                                   (a) "Start the time-wait timer," ...
*                                                       (1) A TCP connection should be closed WITHOUT fault following 
*                                                           a TCP connection TIME-WAIT timeout.
*
*                                                   (b) "turn off the other timers."
*
*                                               (3) Although these sections are the only sections to state that these
*                                                   TCP connection timers should be updated when transitioning to the
*                                                   TIME-WAIT state, it is assumed that these timers should also be
*                                                   updated for the transition from the CLOSING state to the TIME-WAIT
*                                                   state.
*
*                                           (B) However, it is possible that some closing received data from the remote
*                                               host is available but has NOT yet been received by the application layer.
*
*                                               (1) Therefore, if the application receive queue is closed, then enter the
*                                                   TIME-WAIT state.
*
*                                               (2) (a) But if the application receive queue is NOT closed, then enter the
*                                                       connection-closing-data-available state to allow the application
*                                                       layer to receive the remaining receive data.
*
*                                                   (b) (1) To satisfy the required time-wait timeout of two maximum segment
*                                                           lifetimes (see Note #2f5A1a), the time-wait timeout is intially
*                                                           used to provide the application layer sufficient time to receive
*                                                           the closing received data.
*
*                                                       (2) If after the time-wait timeout expires, the application receive
*                                                           queue is still not empty, the user connection timeout is used
*                                                           to provide the application layer additional time to receive the
*                                                           closing received data.
*
*                                                       See also Note #3.
*
*                                       (2) (A) RFC #793, Section 3.9 'Event Processing : SEGMENT ARRIVES : Check
*                                               ACK Field : FIN-WAIT-2 STATE' states that "if the retransmission
*                                               queue is empty, the user's CLOSE can be acknowledged".
*
*                                           (B) Although this section is the only section to state that the TCP
*                                               connection should acknowledge the user's close, it is assumed that
*                                               a TCP connection should signal the application layer that "the
*                                               user's close [is] acknowledged" whenever its re-transmit queue
*                                               becomes empty.
*
*                                   (b) (1) "otherwise ignore the segment."
*
*                                       (2) However, it is possible that some but NOT all transmitted data has
*                                           been received by the remote host.  In other words, the remote host may
*                                           have received some but NOT ALL transmitted data preceding this host's
*                                           connection close request.
*
*                                           ???? Therefore, acknowledgements validated by as within the transmit
*                                           window MUST be received & processed as in connected states.
*
*                                           See also 'NetTCP_RxPktConnIsValidAck()  Note #1d'.
*
*                                       See also Note #2e2.
*$PAGE*
*                   (e) (1) RFC #793, Section 3.9 'Event Processing : SEGMENT ARRIVES : Process Segment Text'
*                           states that in the "CLOSE-WAIT STATE, CLOSING STATE, LAST-ACK STATE, TIME-WAIT
*                           STATE" that "this should not occur, since a FIN has been received from the remote
*                           side.  Ignore the segment text."
*
*                       (2) (A) However, it is possible that some but NOT all data has been received from
*                               the remote host.  In other words, the remote host's  connection close request
*                               may have received but ALL receive data preceding the connection close request
*                               may NOT have been received.
*
*                               ???? Therefore, receive data validated by sequence number as within the
*                               receive window MUST be received & processed as in connected states.
*
*                           (B) RFC #793, Section 3.9 'Event Processing : SEGMENT ARRIVES : Process Segment
*                               Text' states that "once in the ESTABLISHED state, it is possible to deliver
*                               segment text to user RECEIVE buffers".
*
*                           See also Note #2d2B2b.
*
*                   (f) RFC #793, Section 3.9 'Event Processing : SEGMENT ARRIVES : Check FIN Bit' states
*                       that "if the FIN bit is set" ...
*
*                       (1) "signal the user 'connection closing' and return any pending RECEIVEs with
*                            same message," ...
*
*                       (2) "advance RCV.NXT over the FIN," ...
*
*                       (3) "send an acknowledgment for the FIN" ...
*
*                       (4) "FIN implies PUSH for any segment text not yet delivered to the user" ...
*
*                       (5) And the "CLOSING STATE ... remain[s] in the CLOSING state".
*
*               (3) (a) RFC #793, Section 3.9 'Event Processing : USER TIMEOUT : USER TIMEOUT' states that
*                       "for any state if the user timeout expires, flush all queues, signal the user
*                       'error : connection aborted due to user timeout' ... [and] enter the CLOSED state".
*
*                   (b) However, NO RFC specifies or suggests any mechanism to implement/handle user timeouts.
*
*                       ???? Therefore, it is assumed that ANY TCP connection that receives a valid TCP data
*                       or control segment should reset its user connection timer.
*
*               (4) Since the mechanisms of TCP connection close are independent of the application layer
*                   close; any external application layer close error(s) are ignored.
*********************************************************************************************************
*/

static  void  NetTCP_RxPktConnHandlerClosing (NET_TCP_CONN  *pconn,
                                              NET_BUF       *pbuf,
                                              NET_BUF_HDR   *pbuf_hdr,
                                              NET_ERR       *perr)
{
    NET_TCP_SEQ_CODE     seq_code;
    NET_TCP_ACK_CODE     ack_code;
    NET_TCP_RESET_CODE   reset_code;
    CPU_BOOLEAN          data_avail;
    NET_TCP_TIMEOUT_SEC  timeout_sec;
    NET_TMR_TICK         timeout_tick;
    CPU_FNCT_PTR         timeout_fnct;
    NET_TCP_FREE_CODE    free_code;
    NET_ERR              err;
    NET_ERR              err_rtn;


/*$PAGE*/
                                                                /* -------------- VALIDATE RX'D TCP PKT --------------- */
                                                                /* Chk for rx'd fin/close.                              */
    if (pbuf_hdr->TCP_SegClose == DEF_YES) {                    /* If fin/close avail, update seg lens.                 */
        pbuf_hdr->TCP_SegLenInit += NET_TCP_SEG_LEN_CLOSE;
        pbuf_hdr->TCP_SegLen     += NET_TCP_SEG_LEN_CLOSE;
    }

                                                                /* Chk rx'd seq nbr.                                    */
    seq_code = NetTCP_RxPktConnIsValidSeq(pconn, pbuf_hdr, perr);
    if (*perr != NET_TCP_ERR_NONE) {
         return;
    }
    switch (seq_code) {
        case NET_TCP_CONN_RX_SEQ_VALID:
             break;


        case NET_TCP_CONN_RX_SEQ_SYNC:                          /* If invalid sync rx'd, ...                            */
        case NET_TCP_CONN_RX_SEQ_SYNC_INVALID:
                                                                /* ... tx TCP conn ack  (see Notes #2c2 & #2b2B).       */
             NetTCP_TxConnAck(pconn, pbuf_hdr, NET_TCP_CONN_TX_ACK_FAULT, NET_TCP_CONN_CLOSE_ALL, &err);
            *perr = NET_TCP_ERR_CONN_SEQ_SYNC_INVALID;
             return;                                            /* Prevent 'break NOT reachable' compiler warning.      */


        case NET_TCP_CONN_RX_SEQ_NONE:
        case NET_TCP_CONN_RX_SEQ_INVALID:                       /* If invalid seq  rx'd (see Note #2a4A), ...           */
        default:
             if (pbuf_hdr->TCP_SegReset != DEF_YES) {           /* ... & reset NOT rx'd (see Note #2a4C), ...           */
                                                                /* ... tx TCP conn ack  (see Note #2a4B).               */
                 NetTCP_TxConnAck(pconn, pbuf_hdr, NET_TCP_CONN_TX_ACK_FAULT, NET_TCP_CONN_CLOSE_ALL, &err);
             }
            *perr = NET_TCP_ERR_CONN_SEQ_INVALID;
             return;                                            /* Prevent 'break NOT reachable' compiler warning.      */
    }

                                                                /* Chk for rx'd reset.                                  */
    reset_code = NetTCP_RxPktConnIsValidReset(pconn, pbuf_hdr, perr);
    if (*perr != NET_TCP_ERR_NONE) {
         return;
    }
    switch (reset_code) {
        case NET_TCP_CONN_RX_RESET_NONE:
             break;


        case NET_TCP_CONN_RX_RESET_VALID:                       /* If   valid reset rx'd, ...                           */
                                                                /* ...  close TCP conn (see Note #2b1A).                */
             NetTCP_ConnClose(pconn, pbuf_hdr, pconn->ConnCloseAppFlag, NET_TCP_CONN_CLOSE_ALL);
            *perr = NET_TCP_ERR_CONN_RESET_VALID;
             return;                                            /* Prevent 'break NOT reachable' compiler warning.      */


        case NET_TCP_CONN_RX_RESET_INVALID:                     /* If invalid reset rx'd, ...                           */
        default:
                                                                /* ... tx TCP conn ack (see Note #2b2Ac).               */
             NetTCP_TxConnAck(pconn, pbuf_hdr, NET_TCP_CONN_TX_ACK_FAULT, NET_TCP_CONN_CLOSE_ALL, &err);
            *perr = NET_TCP_ERR_CONN_RESET_INVALID;
             return;                                            /* Prevent 'break NOT reachable' compiler warning.      */
    }

                                                                /* Chk for rx'd ack.                                    */
    ack_code = NetTCP_RxPktConnIsValidAck(pconn, pbuf_hdr, perr);
    if (*perr != NET_TCP_ERR_NONE) {
         return;
    }
    switch (ack_code) {
        case NET_TCP_CONN_RX_ACK_VALID:
        case NET_TCP_CONN_RX_ACK_DUP:
        case NET_TCP_CONN_RX_ACK_PREV:
             break;


        case NET_TCP_CONN_RX_ACK_NONE:                          /* If NO      ack rx'd, ...                             */
            *perr = NET_TCP_ERR_CONN_ACK_NONE;                  /* ... ignore TCP pkt  (see Note #2d1).                 */
             return;                                            /* Prevent 'break NOT reachable' compiler warning.      */


        case NET_TCP_CONN_RX_ACK_INVALID:                       /* If invalid ack rx'd, ...                             */
        default:
                                                                /* ... tx TCP conn ack (see Note #2d2A3).               */
             NetTCP_TxConnAck(pconn, pbuf_hdr, NET_TCP_CONN_TX_ACK_FAULT, NET_TCP_CONN_CLOSE_ALL, &err);
            *perr = NET_TCP_ERR_CONN_ACK_INVALID;
             return;                                            /* Prevent 'break NOT reachable' compiler warning.      */
    }



/*$PAGE*/
                                                                /* ----------------- HANDLE RX'D SEG ------------------ */
    NetTCP_RxPktConnHandlerSeg(pconn, ack_code, pbuf, pbuf_hdr, &err_rtn);
    switch (err_rtn) {
        case NET_TCP_ERR_CONN_DATA_NONE:
        case NET_TCP_ERR_CONN_DATA_VALID:
             break;


        case NET_TCP_ERR_CONN_DATA_DUP:                         /* ???? Allow dup data to update TCP conn?              */
            *perr = err_rtn;
             return;                                            /* Prevent 'break NOT reachable' compiler warning.      */


        case NET_ERR_INIT_INCOMPLETE:
        case NET_TCP_ERR_CONN_NOT_USED:
        case NET_TCP_ERR_CONN_FAIL:
        case NET_TCP_ERR_CONN_ACK_INVALID:
        case NET_TCP_ERR_CONN_DATA_INVALID:
        case NET_TCP_ERR_INVALID_CONN_STATE:
        case NET_TCP_ERR_INVALID_CONN_OP:
        case NET_TCP_ERR_INVALID_LEN_SEG:
        case NET_TCP_ERR_RX_Q_FULL:
        case NET_TCP_ERR_RX_Q_SIGNAL_FAULT:
        case NET_TCP_ERR_TX:
        case NET_TCP_ERR_TX_Q_SIGNAL_FAULT:
        case NET_TCP_ERR_RE_TX_SEG_TH:
        default:
             NetTCP_ConnClose(pconn, pbuf_hdr, pconn->ConnCloseAppFlag, NET_TCP_CONN_CLOSE_ALL);
            *perr = err_rtn;
             return;                                            /* Prevent 'break NOT reachable' compiler warning.      */
    }



                                                                /* ----------------- UPDATE TCP CONN ------------------ */
    if (pconn->TxQ_State == NET_TCP_TX_Q_STATE_CONN_CLOSED) {   /* If local conn close ack'd (see Note #2d2B2a);     .. */
                                                                /* Closing data avail for half-closed conns ONLY.       */
        data_avail = ((pconn->ConnCloseCode !=  NET_CONN_CLOSE_HALF           ) ||
                     ((pconn->RxQ_State     ==  NET_TCP_RX_Q_STATE_CONN_CLOSED) &&
                      (pconn->RxQ_App_Head  == (NET_BUF *)0))) ? DEF_NO : DEF_YES;

                                                                /* .. signal app conn close (see Note #2d2B2a2B),    .. */
        NetTCP_RxPktConnHandlerSignalClose(pconn, data_avail, &err);
        switch (err) {
            case NET_TCP_ERR_NONE:
            case NET_TCP_ERR_CONN_FAIL:                         /* Ignore any app conn close err(s) [see Note #4].      */
                 break;


            case NET_TCP_ERR_CONN_NOT_USED:
            case NET_TCP_ERR_INVALID_CONN_ID:
            case NET_TCP_ERR_INVALID_CONN_STATE:
            case NET_TCP_ERR_INVALID_CONN_OP:
            case NET_CONN_ERR_INVALID_FAMILY:
            case NET_CONN_ERR_INVALID_CONN:
            case NET_CONN_ERR_NOT_USED:
            default:
                 NetTCP_ConnClose(pconn, pbuf_hdr, DEF_YES, NET_TCP_CONN_CLOSE_ALL);
                *perr = err;
                 return;                                        /* Prevent 'break NOT reachable' compiler warning.      */
        }

        if (data_avail != DEF_YES) {                            /* .. & if NO app data avail,                        .. */
                                                                /* .. chng to time-wait state (see Note  #2d2B2a1B1);   */
            pconn->ConnState                 =  NET_TCP_CONN_STATE_TIME_WAIT;
            pconn->ConnCloseTimeoutFaultFlag =  DEF_NO;         /* .. clr close timeout fault (see Note  #2d2B2a1A2a1); */
            timeout_fnct                     = (CPU_FNCT_PTR)NetTCP_ConnCloseTimeout;

        } else {                                                /* .. else chng to closing-data-avail state          .. */
                                                                /* ..                         (see Note  #2d2B2a1B2a);  */
            pconn->ConnState =  NET_TCP_CONN_STATE_CLOSING_DATA_AVAIL;
            timeout_fnct     = (CPU_FNCT_PTR)NetTCP_ConnClosingTimeoutDataAvail;
        }
                                                                /* .. & start time-wait tmr   (see Notes #2d2B2a1A2a &  */
                                                                /* ..                                    #2d2B2a1B2b1). */
        timeout_sec  =  pconn->TimeoutMaxSeg_sec * NET_TCP_CONN_TIMEOUT_MAX_SEG_SCALAR;


    } else {
        timeout_sec  =  pconn->TimeoutConn_sec;                 /* Else start conn close tmr (see Note #3b).            */
        timeout_fnct = (CPU_FNCT_PTR)NetTCP_ConnCloseTimeout;
    }



/*$PAGE*/
                                                                /* ------------------- UPDATE TMRs -------------------- */
    switch (pconn->ConnState) {
        case NET_TCP_CONN_STATE_TIME_WAIT:                      /* If in time-wait            (see Note #2d2B2a1A)  ... */
        case NET_TCP_CONN_STATE_CLOSING_DATA_AVAIL:             /* ... or closing state(s)    [see Note #2d2B2a1B], ... */
             free_code = NET_TCP_CONN_FREE_TMR_ALL;             /* ... free all TCP conn tmrs (see Note #2d2B2a1A2b).   */
             DEF_BIT_CLR(free_code, NET_TCP_CONN_FREE_TMR_TIMEOUT);
             NetTCP_ConnFreeTmr(pconn, free_code);
             break;
    }


    timeout_tick = (NET_TMR_TICK)timeout_sec * NET_TMR_TIME_TICK_PER_SEC;
    if (pconn->TimeoutTmr != (NET_TMR *)0) {
        NetTmr_Set((NET_TMR    *) pconn->TimeoutTmr,
                   (CPU_FNCT_PTR) timeout_fnct,
                   (NET_TMR_TICK) timeout_tick,
                   (NET_ERR    *)&err);
    } else {
        pconn->TimeoutTmr = NetTmr_Get((void       *) pconn,
                                       (CPU_FNCT_PTR) timeout_fnct,
                                       (NET_TMR_TICK) timeout_tick,
                                       (CPU_INT16U  ) NET_TMR_FLAG_NONE,
                                       (NET_ERR    *)&err);
    }

    if ( err != NET_TMR_ERR_NONE) {
        NetTCP_ConnClose(pconn, pbuf_hdr, pconn->ConnCloseAppFlag, NET_TCP_CONN_CLOSE_ALL);
       *perr  = NET_TCP_ERR_CONN_FAIL;
        return;
    }



/*$PAGE*/
                                                                /* --------------- TX TCP CONN ACK/DATA --------------- */
    ack_code = ((pbuf_hdr->TCP_SegAckTxReqCode == NET_TCP_CONN_TX_ACK_IMMED) ||
                (pbuf_hdr->TCP_SegClose        == DEF_YES))     /* See Note #2f3.                                       */
             ?   NET_TCP_CONN_TX_ACK_IMMED
             :   NET_TCP_CONN_TX_ACK;

    if (pconn->ConnState == NET_TCP_CONN_STATE_CLOSING) {       /* If conn still closing, ...                           */
                                                                /* ... tx ack & any tx data (see Note #1c).             */
        NetTCP_TxConnTxQ(pconn, pbuf_hdr, ack_code, DEF_NO, NET_TCP_CONN_CLOSE_ALL, perr);
        switch (*perr) {
            case NET_TCP_ERR_NONE:
            case NET_TCP_ERR_CONN_ACK_NONE:
            case NET_TCP_ERR_CONN_ACK_INVALID:
            case NET_TCP_ERR_CONN_ACK_DLYD:
            case NET_TCP_ERR_CONN_ACK_PREVLY_TXD:
            case NET_ERR_TX:                                    /* Ignore transitory tx err(s).                         */
                 break;


            case NET_ERR_INIT_INCOMPLETE:
            case NET_TCP_ERR_CONN_NOT_USED:
            case NET_TCP_ERR_CONN_CLOSE:
            case NET_TCP_ERR_CONN_FAULT:
            case NET_TCP_ERR_CONN_FAIL:
            case NET_TCP_ERR_INVALID_CONN_STATE:
            case NET_TCP_ERR_INVALID_CONN_OP:
            case NET_TCP_ERR_INVALID_LEN_SEG:
            case NET_TCP_ERR_NONE_AVAIL:
            case NET_TCP_ERR_TX:
            case NET_CONN_ERR_INVALID_FAMILY:
            case NET_CONN_ERR_INVALID_ADDR:
            case NET_CONN_ERR_INVALID_ADDR_LEN:
            default:
                 return;                                        /* Prevent 'break NOT reachable' compiler warning.      */
        }

    } else {                                                    /* Else tx TCP conn ack (see Note #2f3).                */
        NetTCP_TxConnAck(pconn, pbuf_hdr, ack_code, NET_TCP_CONN_CLOSE_ALL, perr);
        switch (*perr) {
            case NET_TCP_ERR_NONE:
            case NET_TCP_ERR_CONN_ACK_NONE:
            case NET_TCP_ERR_CONN_ACK_INVALID:
            case NET_TCP_ERR_CONN_ACK_DLYD:
            case NET_TCP_ERR_CONN_ACK_PREVLY_TXD:
                 break;


            case NET_TCP_ERR_CONN_NOT_USED:
            case NET_TCP_ERR_CONN_FAULT:
            case NET_TCP_ERR_INVALID_CONN_STATE:
            case NET_TCP_ERR_INVALID_CONN_OP:
            case NET_TCP_ERR_INVALID_LEN_SEG:
            case NET_TCP_ERR_NONE_AVAIL:
            default:
                 return;                                        /* Prevent 'break NOT reachable' compiler warning.      */
        }
    }



   *perr = err_rtn;
}


/*$PAGE*/
/*
*********************************************************************************************************
*                                  NetTCP_RxPktConnHandlerTimeWait()
*
* Description : (1) Handle TCP connection in TIME-WAIT state :
*
*                   (a) Validate received TCP packet for current TCP connection state :
*
*                       (1) Sequence Number (SEQ)                                   See Note  #2a
*                       (2) Reset           (RST)                                   See Note  #2b
*                       (3) Synchronization (SYN)                                   See Note  #2c
*                       (4) Acknowledgement (ACK)                                   See Note  #2d
*                       (5) Finish/Close    (FIN)                                   See Note  #2f
*
*                   (b) Update TCP connection :
*                       (1) Handle received TCP segment                             See Notes #2d    & #2e
*                       (2) Update TCP connection timer                             See Notes #2d2C2
*
*                   (c) Transmit TCP connection acknowledgement                     See Notes #2d2C1 & #2f3
*
*
* Argument(s) : pconn       Pointer to a TCP connection.
*               -----       Argument validated in NetTCP_RxPktConnHandler().
*
*               pbuf        Pointer to network buffer that received TCP packet.
*               ----        Argument checked   in NetTCP_Rx().
*
*               pbuf_hdr    Pointer to network buffer header that received TCP packet.
*               --------    Argument validated in NetTCP_Rx().
*
*               perr        Pointer to variable that will receive the return error code from this function :
*
*                               NET_TCP_ERR_CONN_SEQ_SYNC_INVALID   Received segment's synchronization        is
*                                                                       NOT valid for current TCP connection.
*                               NET_TCP_ERR_CONN_SEQ_INVALID        Received segment's sequence        number is
*                                                                       NOT valid for current TCP connection.
*                               NET_TCP_ERR_CONN_ACK_NONE           Received segment's acknowledgement        is
*                                                                       NOT available.
*                               NET_TCP_ERR_CONN_ACK_INVALID        Received segment's acknowledgement number is
*                                                                       NOT valid for current TCP connection.
*                               NET_TCP_ERR_CONN_RESET_VALID        Received segment's reset flag is     valid
*                                                                       for current TCP connection; i.e. reset
*                                                                       the TCP connection.
*                               NET_TCP_ERR_CONN_RESET_INVALID      Received segment's reset flag is NOT valid
*                                                                       for current TCP connection.
*
*                               NET_TCP_ERR_CONN_FAIL               TCP connection operation(s) failed.
*
*                                                                   -- RETURNED BY NetTCP_RxPktConnIsValidSeq() : --
*                                                                   -- RETURNED BY NetTCP_RxPktConnIsValidAck() : --
*                                                                   - RETURNED BY NetTCP_RxPktConnIsValidReset() : -
*                               NET_TCP_ERR_CONN_NOT_USED           TCP connection NOT currently used.
*                               NET_TCP_ERR_INVALID_CONN_STATE      Invalid TCP connection state.
*                               NET_TCP_ERR_INVALID_LEN_SEG         Invalid TCP sequence-segment length.
*
*                                                                   -- RETURNED BY NetTCP_RxPktConnHandlerSeg() : --
*                               NET_TCP_ERR_CONN_DATA_NONE          Received packet successfully handled; but NO
*                                                                       data to   queue  to receive queue(s).
*                               NET_TCP_ERR_CONN_DATA_VALID         Received packet successfully handled & valid
*                                                                       data queued for processing.
*                               NET_TCP_ERR_CONN_DATA_INVALID       Received packet contains invalid   segment
*                                                                       data; NOT queued to receive queue(s).
*                               NET_TCP_ERR_CONN_DATA_DUP           Received packet contains duplicate segment
*                                                                       data; NOT queued to receive queue(s).
*
*                               NET_ERR_INIT_INCOMPLETE             Network initialization NOT complete.
*
*                               NET_TCP_ERR_INVALID_CONN_OP         Invalid TCP connection operation.
*
*                               NET_TCP_ERR_RX_Q_FULL               TCP connection receive queue full.
*                               NET_TCP_ERR_RX_Q_SIGNAL_FAULT       TCP connection receive queue signal fault.
*
*                                                                   ------- RETURNED BY NetTCP_TxConnAck() : -------
*                               NET_TCP_ERR_CONN_FAULT              TCP connection fault; connection(s) aborted.
*                               NET_TCP_ERR_NONE_AVAIL              Resources NOT available.
*
* Return(s)   : none.
*
* Caller(s)   : NetTCP_RxPktConnHandler().
*$PAGE*
* Note(s)     : (2) TCP connections in the TIME-WAIT state are handled as follows :
*
*                   (a) RFC #793, Section 3.9 'Event Processing : SEGMENT ARRIVES : Check Sequence Number'
*                       states that in the "SYN-RECEIVED, ESTABLISHED STATE, FIN-WAIT-1 STATE, FIN-WAIT-2
*                       STATE, CLOSE-WAIT STATE, CLOSING STATE, LAST-ACK STATE, TIME-WAIT STATE" that ...
*
*                       (1) "Segments are processed in sequence ... processing is done in SEG.SEQ order."
*
*                       (2) "Initial tests on arrival are used to discard old duplicates."
*
*                       (3) "If a segment's contents straddle the boundary between old and new, only the
*                            new parts should be processed."
*
*                       (4) (A) "If an incoming segment is not acceptable," ...
*
*                           (B) "an acknowledgment should be sent in reply" ...
*
*                           (C) "(unless the RST bit is set, if so drop the segment)".
*
*                               See also Notes #2b2Aa & #2b2B.
*
*                       See also 'NetTCP_RxPktConnIsValidSeq()  Note #1d'.
*
*                   (b) (1) (A) RFC #793, Section 3.9 'Event Processing : SEGMENT ARRIVES : Check RST Bit'
*                               states that in the "CLOSING, LAST-ACK, TIME-WAIT" states that "if the RST bit
*                               is set then, enter the CLOSED state".
*
*                           (B) RFC #793, Section 3.4 'Establishing a Connection : Reset Processing' reiterates
*                               that "if the receiver ... of a RST ... was in any other state [other than LISTEN
*                               or SYN-RECEIVED], it aborts the connection and advises the user and goes to the
*                               CLOSED state".
*
*                       (2) (A) RFC Draft-IETF-TCPm-TCPSecure #00, Section 2.2 amends the "handling of a segment 
*                               with the RST bit when in a synchronized state" to "provide some protection against
*                               ... blind reset attack[s] using the RST bit" :
*
*                               (a) "If the RST bit is set and the sequence number is outside the expected
*                                    window, silently drop the segment."
*
*                               (b) "If the RST bit is exactly the next expected sequence number [sic], reset
*                                    the connection"; it is assumed that this should read "if the RST bit is
*                                    set and the sequence number is exactly the next expected sequence number,
*                                    reset the connection."
*
*                               (c) "If the RST bit is set and the sequence number does not exactly match
*                                    the next expected sequence value, yet is within the acceptable window
*                                    (RCV.NXT <= SEG.SEQ < RCV.NXT+RCV.WND) send an acknowledgment."
*
*                           (B) ???? In addition, RFC Draft-IETF-TCPm-TCPSecure #00 does NOT provide a precedence 
*                               priority for handling TCP segments received with BOTH the RST & SYN bits set.
*
*                               ???? Therefore, since it does NOT seem reasonable to reset a TCP connection
*                               due to a TCP segment that also attempted to synchronize the  TCP connection,
*                               it is assumed that the amended handling of the SYN bit should take precedence
*                               over the amended handling of the RST bit.
*
*                               See also Note #2c2.
*
*                   (c) (1) RFC #793, Section 3.9 'Event Processing : SEGMENT ARRIVES : Check SYN Bit'
*                           states that in the "SYN-RECEIVED [STATE], ESTABLISHED STATE, FIN-WAIT STATE-1,
*                           FIN-WAIT STATE-2, CLOSE-WAIT STATE, CLOSING STATE, LAST-ACK STATE, TIME-WAIT
*                           STATE" that ...
*
*                           (A) "If the SYN is in the window it is an error, send a reset, any outstanding
*                                RECEIVEs and SEND[s] should receive 'reset' responses, all segment queues
*                                should be flushed, the user should also receive an unsolicited general
*                               'connection reset' signal[, and] enter the CLOSED state."
*
*                           (B) But "if the SYN is not in the window this step would not have been reached
*                               and an ack would have been sent".
*
*                       (2) HOWEVER, RFC Draft-IETF-TCPm-TCPSecure #00, Section 3.2 amends the  "handling 
*                           of a segment with the SYN bit set in the synchronized state ... [by] handling 
*                           ... the SYN bit" as follows :
*
*                           (a) "If the SYN bit is set and the sequence number is outside the
*                                expected window, send an ACK back to the peer."
*
*                           (b) "If the SYN bit is set and the sequence number is an exact
*                                match to the next expected sequence (RCV.NXT == SEG.SEQ)
*                                then send an ACK segment ... but ... subtract one from
*                                value being acknowledged."
*
*                           (c) "If the SYN bit is set and the sequence number is acceptable,
*                                i.e.: (RCV.NXT <= SEG.SEQ <= RCV.NXT+RCV.WND) then send an
*                                ACK segment."
*$PAGE*
*                   (d) RFC #793, Section 3.9 'Event Processing : SEGMENT ARRIVES : Check ACK Field'
*                       states that ... :
*
*                       (1) "If the ACK bit is off drop the segment."
*
*                       (2) "If the ACK bit is on" ...
*
*                           (A) "If the ACK is a duplicate (SEG.ACK <= SND.UNA), it can be ignored."
*
*                           (B) "If the ACK acks something not yet sent ... then send an ACK [and] drop the segment."
*
*                           (C) For the "TIME-WAIT STATE ... the only thing that can arrive in this state is a
*                               retransmission of the remote FIN" :
*
*                               (1) "Acknowledge it" ...
*                               (2) "restart the 2 MSL timeout."
*
*                   (e) (1) RFC #793, Section 3.9 'Event Processing : SEGMENT ARRIVES : Process Segment Text'
*                           states that in the "CLOSE-WAIT STATE, CLOSING STATE, LAST-ACK STATE, TIME-WAIT
*                           STATE" that "this should not occur, since a FIN has been received from the remote
*                           side.  Ignore the segment text."
*
*                       (2) (A) However, it is possible that some but NOT all data has been received from
*                               the remote host.  In other words, the remote host's  connection close request
*                               may have received but ALL receive data preceding the connection close request
*                               may NOT have been received.
*
*                               ???? Therefore, receive data validated by sequence number as within the
*                               receive window MUST be received & processed as in connected states.
*
*                           (B) RFC #793, Section 3.9 'Event Processing : SEGMENT ARRIVES : Process Segment
*                               Text' states that "once in the ESTABLISHED state, it is possible to deliver
*                               segment text to user RECEIVE buffers".
*
*                   (f) RFC #793, Section 3.9 'Event Processing : SEGMENT ARRIVES : Check FIN Bit' states
*                       that "if the FIN bit is set" ...
*
*                       (1) "signal the user 'connection closing' and return any pending RECEIVEs with
*                            same message," ...
*
*                       (2) "advance RCV.NXT over the FIN," ...
*
*                       (3) "send an acknowledgment for the FIN" ...
*
*                       (4) "FIN implies PUSH for any segment text not yet delivered to the user" ...
*
*                       (5) For the "TIME-WAIT STATE" :
*
*                           (A) "Remain in the TIME-WAIT state" ...
*                           (B) "Restart the 2 MSL time-wait timeout."
*
*               (3) RFC #793, Section 3.9 'Event Processing : USER TIMEOUT : TIME-WAIT TIMEOUT' states
*                   that "if the time-wait timeout expires on a connection ... enter the CLOSED state".
*********************************************************************************************************
*/

static  void  NetTCP_RxPktConnHandlerTimeWait (NET_TCP_CONN  *pconn,
                                               NET_BUF       *pbuf,
                                               NET_BUF_HDR   *pbuf_hdr,
                                               NET_ERR       *perr)
{
    NET_TCP_SEQ_CODE     seq_code;
    NET_TCP_ACK_CODE     ack_code;
    NET_TCP_RESET_CODE   reset_code;
    NET_TCP_TIMEOUT_SEC  timeout_sec;
    NET_TMR_TICK         timeout_tick;
    NET_ERR              err;
    NET_ERR              err_rtn;


/*$PAGE*/
                                                                /* -------------- VALIDATE RX'D TCP PKT --------------- */
   (void)&pbuf_hdr->TCP_SegClose;                               /* Ignore any rx'd fin (see Note #2f5A).                */

                                                                /* Chk rx'd seq nbr.                                    */
    seq_code = NetTCP_RxPktConnIsValidSeq(pconn, pbuf_hdr, perr);
    if (*perr != NET_TCP_ERR_NONE) {
         return;
    }
    switch (seq_code) {
        case NET_TCP_CONN_RX_SEQ_VALID:
             break;


        case NET_TCP_CONN_RX_SEQ_SYNC:                          /* If invalid sync rx'd, ...                            */
        case NET_TCP_CONN_RX_SEQ_SYNC_INVALID:
                                                                /* ... tx TCP conn ack  (see Notes #2c2 & #2b2B).       */
             NetTCP_TxConnAck(pconn, pbuf_hdr, NET_TCP_CONN_TX_ACK_FAULT, NET_TCP_CONN_CLOSE_ALL, &err);
            *perr = NET_TCP_ERR_CONN_SEQ_SYNC_INVALID;
             return;                                            /* Prevent 'break NOT reachable' compiler warning.      */


        case NET_TCP_CONN_RX_SEQ_NONE:
        case NET_TCP_CONN_RX_SEQ_INVALID:                       /* If invalid seq  rx'd (see Note #2a4A), ...           */
        default:
             if (pbuf_hdr->TCP_SegReset != DEF_YES) {           /* ... & reset NOT rx'd (see Note #2a4C), ...           */
                                                                /* ... tx TCP conn ack  (see Note #2a4B).               */
                 NetTCP_TxConnAck(pconn, pbuf_hdr, NET_TCP_CONN_TX_ACK_FAULT, NET_TCP_CONN_CLOSE_ALL, &err);
             }
            *perr = NET_TCP_ERR_CONN_SEQ_INVALID;
             return;                                            /* Prevent 'break NOT reachable' compiler warning.      */
    }

                                                                /* Chk for rx'd reset.                                  */
    reset_code = NetTCP_RxPktConnIsValidReset(pconn, pbuf_hdr, perr);
    if (*perr != NET_TCP_ERR_NONE) {
         return;
    }
    switch (reset_code) {
        case NET_TCP_CONN_RX_RESET_NONE:
             break;


        case NET_TCP_CONN_RX_RESET_VALID:                       /* If   valid reset rx'd, ...                           */
                                                                /* ...  close TCP conn (see Note #2b1A).                */
             NetTCP_ConnClose(pconn, pbuf_hdr, pconn->ConnCloseAppFlag, NET_TCP_CONN_CLOSE_ALL);
            *perr = NET_TCP_ERR_CONN_RESET_VALID;
             return;                                            /* Prevent 'break NOT reachable' compiler warning.      */


        case NET_TCP_CONN_RX_RESET_INVALID:                     /* If invalid reset rx'd, ...                           */
        default:
                                                                /* ... tx TCP conn ack (see Note #2b2Ac).               */
             NetTCP_TxConnAck(pconn, pbuf_hdr, NET_TCP_CONN_TX_ACK_FAULT, NET_TCP_CONN_CLOSE_ALL, &err);
            *perr = NET_TCP_ERR_CONN_RESET_INVALID;
             return;                                            /* Prevent 'break NOT reachable' compiler warning.      */
    }

                                                                /* Chk for rx'd ack.                                    */
    ack_code = NetTCP_RxPktConnIsValidAck(pconn, pbuf_hdr, perr);
    if (*perr != NET_TCP_ERR_NONE) {
         return;
    }
    switch (ack_code) {
        case NET_TCP_CONN_RX_ACK_VALID:
        case NET_TCP_CONN_RX_ACK_DUP:
        case NET_TCP_CONN_RX_ACK_PREV:
             break;


        case NET_TCP_CONN_RX_ACK_NONE:                          /* If NO      ack rx'd, ...                             */
            *perr = NET_TCP_ERR_CONN_ACK_NONE;                  /* ... ignore TCP pkt  (see Note #2d1).                 */
             return;                                            /* Prevent 'break NOT reachable' compiler warning.      */


        case NET_TCP_CONN_RX_ACK_INVALID:                       /* If invalid ack rx'd, ...                             */
        default:
                                                                /* ... tx TCP conn ack (see Note #2d2B).                */
             NetTCP_TxConnAck(pconn, pbuf_hdr, NET_TCP_CONN_TX_ACK_FAULT, NET_TCP_CONN_CLOSE_ALL, &err);
            *perr = NET_TCP_ERR_CONN_ACK_INVALID;
             return;                                            /* Prevent 'break NOT reachable' compiler warning.      */
    }



/*$PAGE*/
                                                                /* ----------------- HANDLE RX'D SEG ------------------ */
    NetTCP_RxPktConnHandlerSeg(pconn, ack_code, pbuf, pbuf_hdr, &err_rtn);
    switch (err_rtn) {
        case NET_TCP_ERR_CONN_DATA_NONE:
        case NET_TCP_ERR_CONN_DATA_VALID:
             break;


        case NET_TCP_ERR_CONN_DATA_DUP:                         /* ???? Allow dup data to update TCP conn?              */
            *perr = err_rtn;
             return;                                            /* Prevent 'break NOT reachable' compiler warning.      */


        case NET_ERR_INIT_INCOMPLETE:
        case NET_TCP_ERR_CONN_NOT_USED:
        case NET_TCP_ERR_CONN_ACK_INVALID:
        case NET_TCP_ERR_CONN_DATA_INVALID:
        case NET_TCP_ERR_INVALID_CONN_STATE:
        case NET_TCP_ERR_INVALID_CONN_OP:
        case NET_TCP_ERR_INVALID_LEN_SEG:
        case NET_TCP_ERR_RX_Q_FULL:
        case NET_TCP_ERR_RX_Q_SIGNAL_FAULT:
        default:
             NetTCP_ConnClose(pconn, pbuf_hdr, pconn->ConnCloseAppFlag, NET_TCP_CONN_CLOSE_ALL);
            *perr = err_rtn;
             return;                                            /* Prevent 'break NOT reachable' compiler warning.      */
    }

                                                                /* ----------------- UPDATE TCP CONN ------------------ */
                                                                /* -------------------- UPDATE TMR -------------------- */
                                                                /* Reset time-wait tmr (see Note #2d2C2).               */
    timeout_sec  =  pconn->TimeoutMaxSeg_sec * NET_TCP_CONN_TIMEOUT_MAX_SEG_SCALAR;
    timeout_tick = (NET_TMR_TICK)timeout_sec * NET_TMR_TIME_TICK_PER_SEC;
    if (pconn->TimeoutTmr != (NET_TMR *)0) {
        NetTmr_Set((NET_TMR    *) pconn->TimeoutTmr,
                   (CPU_FNCT_PTR) NetTCP_ConnCloseTimeout,
                   (NET_TMR_TICK) timeout_tick,
                   (NET_ERR    *)&err);
    } else {
        pconn->TimeoutTmr = NetTmr_Get((void       *) pconn,
                                       (CPU_FNCT_PTR) NetTCP_ConnCloseTimeout,
                                       (NET_TMR_TICK) timeout_tick,
                                       (CPU_INT16U  ) NET_TMR_FLAG_NONE,
                                       (NET_ERR    *)&err);
    }

    if ( err != NET_TMR_ERR_NONE) {
        NetTCP_ConnClose(pconn, pbuf_hdr, pconn->ConnCloseAppFlag, NET_TCP_CONN_CLOSE_ALL);
       *perr  = NET_TCP_ERR_CONN_FAIL;
        return;
    }


                                                                /* ----------------- TX TCP CONN ACK ------------------ */
                                                                /* Tx TCP conn ack (see Notes #1c).                     */
    NetTCP_TxConnAck(pconn, pbuf_hdr, NET_TCP_CONN_TX_ACK_IMMED, NET_TCP_CONN_CLOSE_ALL, perr);
    switch (*perr) {
        case NET_TCP_ERR_NONE:
        case NET_TCP_ERR_CONN_ACK_NONE:
        case NET_TCP_ERR_CONN_ACK_INVALID:
        case NET_TCP_ERR_CONN_ACK_DLYD:
        case NET_TCP_ERR_CONN_ACK_PREVLY_TXD:
             break;


        case NET_TCP_ERR_CONN_NOT_USED:
        case NET_TCP_ERR_CONN_FAULT:
        case NET_TCP_ERR_INVALID_CONN_STATE:
        case NET_TCP_ERR_INVALID_CONN_OP:
        case NET_TCP_ERR_INVALID_LEN_SEG:
        case NET_TCP_ERR_NONE_AVAIL:
        default:
             return;                                            /* Prevent 'break NOT reachable' compiler warning.      */
    }



   *perr = err_rtn;
}


/*$PAGE*/
/*
*********************************************************************************************************
*                                 NetTCP_RxPktConnHandlerCloseWait()
*
* Description : (1) Handle TCP connection in CLOSE-WAIT state :
*
*                   (a) Validate received TCP packet for current TCP connection state :
*
*                       (1) Sequence Number (SEQ)                                   See Note  #2a
*                       (2) Reset           (RST)                                   See Note  #2b
*                       (3) Synchronization (SYN)                                   See Note  #2c
*                       (4) Acknowledgement (ACK)                                   See Note  #2d
*                       (5) Finish/Close    (FIN)                                   See Note  #2f
*
*                   (b) Update TCP connection :
*                       (1) Handle received TCP segment                             See Notes #2d   & #2e
*                       (2) Update TCP connection timer                             See Note  #3
*
*                   (c) Transmit TCP connection acknowledgement & data              See Notes #2d2B & #2f3
*
*
* Argument(s) : pconn       Pointer to a TCP connection.
*               -----       Argument validated in NetTCP_RxPktConnHandler().
*
*               pbuf        Pointer to network buffer that received TCP packet.
*               ----        Argument checked   in NetTCP_Rx().
*
*               pbuf_hdr    Pointer to network buffer header that received TCP packet.
*               --------    Argument validated in NetTCP_Rx().
*
*               perr        Pointer to variable that will receive the return error code from this function :
*
*                               NET_TCP_ERR_CONN_SEQ_SYNC_INVALID   Received segment's synchronization        is
*                                                                       NOT valid for current TCP connection.
*                               NET_TCP_ERR_CONN_SEQ_INVALID        Received segment's sequence        number is
*                                                                       NOT valid for current TCP connection.
*                               NET_TCP_ERR_CONN_ACK_NONE           Received segment's acknowledgement        is
*                                                                       NOT available.
*                               NET_TCP_ERR_CONN_ACK_INVALID        Received segment's acknowledgement number is
*                                                                       NOT valid for current TCP connection.
*                               NET_TCP_ERR_CONN_RESET_VALID        Received segment's reset flag is     valid
*                                                                       for current TCP connection; i.e. reset
*                                                                       the TCP connection.
*                               NET_TCP_ERR_CONN_RESET_INVALID      Received segment's reset flag is NOT valid
*                                                                       for current TCP connection.
*
*                               NET_TCP_ERR_CONN_FAIL               TCP connection operation(s) failed.
*
*                                                                   ----- RETURNED BY NetTCP_RxPktConnIsValidSeq() : -----
*                                                                   ----- RETURNED BY NetTCP_RxPktConnIsValidAck() : -----
*                                                                   ---- RETURNED BY NetTCP_RxPktConnIsValidReset() : ----
*                               NET_TCP_ERR_CONN_NOT_USED           TCP connection NOT currently used.
*                               NET_TCP_ERR_INVALID_CONN_STATE      Invalid TCP connection state.
*                               NET_TCP_ERR_INVALID_LEN_SEG         Invalid TCP sequence-segment length.
*
*                                                                   ----- RETURNED BY NetTCP_RxPktConnHandlerSeg() : -----
*                               NET_TCP_ERR_CONN_DATA_NONE          Received packet successfully handled; but NO
*                                                                       data to   queue  to receive queue(s).
*                               NET_TCP_ERR_CONN_DATA_VALID         Received packet successfully handled & valid
*                                                                       data queued for processing.
*                               NET_TCP_ERR_CONN_DATA_INVALID       Received packet contains invalid   segment
*                                                                       data; NOT queued to receive queue(s).
*                               NET_TCP_ERR_CONN_DATA_DUP           Received packet contains duplicate segment
*                                                                       data; NOT queued to receive queue(s).
*
*                               NET_ERR_INIT_INCOMPLETE             Network initialization NOT complete.
*
*                               NET_TCP_ERR_INVALID_CONN_OP         Invalid TCP connection operation.
*
*                               NET_TCP_ERR_RX_Q_FULL               TCP connection receive  queue full.
*                               NET_TCP_ERR_RX_Q_SIGNAL_FAULT       TCP connection receive  queue signal fault.
*                               NET_TCP_ERR_TX_Q_SIGNAL_FAULT       TCP connection transmit queue signal fault.
*                               NET_TCP_ERR_RE_TX_SEG_TH            TCP connection closed due to excessive retransmission.
*                               NET_TCP_ERR_TX                      TCP transmit error.
*
*                                                                   ---------- RETURNED BY NetTCP_TxConnTxQ() : ----------
*                               NET_TCP_ERR_CONN_CLOSE              TCP connection closed.
*                               NET_TCP_ERR_CONN_FAULT              TCP connection fault; connection(s) aborted.
*                               NET_TCP_ERR_NONE_AVAIL              Resources NOT available.
*                               NET_CONN_ERR_INVALID_FAMILY         Invalid     connection family.
*                               NET_CONN_ERR_INVALID_ADDR           Invalid TCP connection address.
*                               NET_CONN_ERR_INVALID_ADDR_LEN       Invalid TCP connection address length.
*
* Return(s)   : none.
*
* Caller(s)   : NetTCP_RxPktConnHandler().
*$PAGE*
* Note(s)     : (2) TCP connections in the CLOSE-WAIT state are handled as follows :
*
*                   (a) RFC #793, Section 3.9 'Event Processing : SEGMENT ARRIVES : Check Sequence Number'
*                       states that in the "SYN-RECEIVED, ESTABLISHED STATE, FIN-WAIT-1 STATE, FIN-WAIT-2
*                       STATE, CLOSE-WAIT STATE, CLOSING STATE, LAST-ACK STATE, TIME-WAIT STATE" that ...
*
*                       (1) "Segments are processed in sequence ... processing is done in SEG.SEQ order."
*
*                       (2) "Initial tests on arrival are used to discard old duplicates."
*
*                       (3) "If a segment's contents straddle the boundary between old and new, only the
*                            new parts should be processed."
*
*                       (4) (A) "If an incoming segment is not acceptable," ...
*
*                           (B) "an acknowledgment should be sent in reply" ...
*
*                           (C) "(unless the RST bit is set, if so drop the segment)".
*
*                               See also Notes #2b2Aa & #2b2B.
*
*                       See also 'NetTCP_RxPktConnIsValidSeq()  Note #1d'.
*
*                   (b) (1) (A) RFC #793, Section 3.9 'Event Processing : SEGMENT ARRIVES : Check RST Bit' states
*                               that in the "ESTABLISHED, FIN-WAIT-1, FIN-WAIT-2, CLOSE-WAIT" states that "if the
*                               RST bit is set then, any outstanding RECEIVEs and SEND[s] should receive 'reset'
*                               responses.  All segment queues should be flushed.  Users should also receive an
*                               unsolicited general 'connection reset' signal[, and] enter the CLOSED state".
*
*                           (B) RFC #793, Section 3.4 'Establishing a Connection : Reset Processing' reiterates
*                               that "if the receiver ... of a RST ... was in any other state [other than LISTEN
*                               or SYN-RECEIVED], it aborts the connection and advises the user and goes to the
*                               CLOSED state".
*
*                       (2) (A) RFC Draft-IETF-TCPm-TCPSecure #00, Section 2.2 amends the "handling of a segment 
*                               with the RST bit when in a synchronized state" to "provide some protection against 
*                               ... blind reset attack[s] using the RST bit" :
*
*                               (a) "If the RST bit is set and the sequence number is outside the expected
*                                    window, silently drop the segment."
*
*                               (b) "If the RST bit is exactly the next expected sequence number [sic], reset
*                                    the connection"; it is assumed that this should read "if the RST bit is
*                                    set and the sequence number is exactly the next expected sequence number,
*                                    reset the connection."
*
*                               (c) "If the RST bit is set and the sequence number does not exactly match
*                                    the next expected sequence value, yet is within the acceptable window
*                                    (RCV.NXT <= SEG.SEQ < RCV.NXT+RCV.WND) send an acknowledgment."
*
*                           (B) ???? In addition, RFC Draft-IETF-TCPm-TCPSecure #00 does NOT provide a precedence 
*                               priority for handling TCP segments received with BOTH the RST & SYN bits set.
*
*                               ???? Therefore, since it does NOT seem reasonable to reset a TCP connection
*                               due to a TCP segment that also attempted to synchronize the  TCP connection,
*                               it is assumed that the amended handling of the SYN bit should take precedence
*                               over the amended handling of the RST bit.
*
*                               See also Note #2c2.
*
*                   (c) (1) RFC #793, Section 3.9 'Event Processing : SEGMENT ARRIVES : Check SYN Bit'
*                           states that in the "SYN-RECEIVED [STATE], ESTABLISHED STATE, FIN-WAIT STATE-1,
*                           FIN-WAIT STATE-2, CLOSE-WAIT STATE, CLOSING STATE, LAST-ACK STATE, TIME-WAIT
*                           STATE" that ...
*
*                           (A) "If the SYN is in the window it is an error, send a reset, any outstanding
*                                RECEIVEs and SEND[s] should receive 'reset' responses, all segment queues
*                                should be flushed, the user should also receive an unsolicited general
*                               'connection reset' signal[, and] enter the CLOSED state."
*
*                           (B) But "if the SYN is not in the window this step would not have been reached
*                               and an ack would have been sent".
*
*                       (2) HOWEVER, RFC Draft-IETF-TCPm-TCPSecure #00, Section 3.2 amends the  "handling 
*                           of a segment with the SYN bit set in the synchronized state ... [by] handling 
*                           ... the SYN bit" as follows :
*
*                           (a) "If the SYN bit is set and the sequence number is outside the
*                                expected window, send an ACK back to the peer."
*
*                           (b) "If the SYN bit is set and the sequence number is an exact
*                                match to the next expected sequence (RCV.NXT == SEG.SEQ)
*                                then send an ACK segment ... but ... subtract one from
*                                value being acknowledged."
*
*                           (c) "If the SYN bit is set and the sequence number is acceptable,
*                                i.e.: (RCV.NXT <= SEG.SEQ <= RCV.NXT+RCV.WND) then send an
*                                ACK segment."
*$PAGE*
*                   (d) RFC #793, Section 3.9 'Event Processing : SEGMENT ARRIVES : Check ACK Field'
*                       states that ... :
*
*                       (1) "If the ACK bit is off drop the segment."
*
*                       (2) "If the ACK bit is on" ...
*
*                           (A) And in the "ESTABLISHED STATE" ...
*
*                               (1) "If SND.UNA < SEG.ACK <= SND.NXT then" ...
*
*                                   (a) "set SND.UNA <- SEG.ACK."
*
*                                   (b) "Any segments on the retransmission queue which are thereby entirely
*                                        acknowledged are removed."
*
*                                   (c) "the send window should be updated" :
*
*                                       (1) (A) (1) "If ((SND.WL1 <  SEG.SEQ) or" ...
*
*                                               (2) (a) "(SND.WL1  = SEG.SEQ and" ...
*                                                   (b)  "SND.WL2 <= SEG.ACK))," ...
*
*                                           (B) (1) "set SND.WND <- SEG.WND," ...
*                                               (2) "set SND.WL1 <- SEG.SEQ," ...
*                                               (3) "set SND.WL2 <- SEG.ACK."
*
*                                       (2) "Note that SND.WND is an offset from SND.UNA, that SND.WL1 records the
*                                            sequence number of the last segment used to update SND.WND, and that
*                                            SND.WL2 records the acknowledgment number of the last segment used to
*                                            update SND.WND.  The check here preveents using old segments to update
*                                            the window."
*
*                               (2) (a) "If the ACK is a duplicate (SEG.ACK <= SND.UNA), it can be ignored."
*
*                                   (b) RFC #1122, Section 4.2.2.20.(g) amends the transmit window update criteria
*                                       for the segment's acknowledgement to include SND.UNA : "The window should
*                                       updated if SND.UNA <= SEG.ACK <= SND.NXT."
*
*                                       See also 'NetTCP_RxPktConnHandlerTxWinRemote()  Note #1b2'.
*
*                               (3) "If the ACK acks something not yet sent (SEG.ACK > SND.NXT) then send an ACK
*                                    [and] drop the segment."
*
*                           (B) For the "CLOSE-WAIT STATE ... do the same processing as for the ESTABLISHED state".
*
*                   (e) (1) RFC #793, Section 3.9 'Event Processing : SEGMENT ARRIVES : Process Segment Text'
*                           states that in the "CLOSE-WAIT STATE, CLOSING STATE, LAST-ACK STATE, TIME-WAIT
*                           STATE" that "this should not occur, since a FIN has been received from the remote
*                           side.  Ignore the segment text."
*
*                       (2) (A) However, it is possible that some but NOT all data has been received from the
*                               remote host.  In other words, the remote host's close request may have been
*                               received but ALL receive data preceding the close request may NOT have been
*                               received.
*
*                               ???? Therefore, receive data validated by sequence number as within the receive
*                               window MUST be received & processed as in connected states.
*
*                           (B) RFC #793, Section 3.9 'Event Processing : SEGMENT ARRIVES : Process Segment
*                               Text' states that "once in the ESTABLISHED state, it is possible to deliver
*                               segment text to user RECEIVE buffers".
*
*                           See also Note #2d2B.
*$PAGE*
*                   (f) RFC #793, Section 3.9 'Event Processing : SEGMENT ARRIVES : Check FIN Bit' states
*                       that "if the FIN bit is set" ...
*
*                       (1) "signal the user 'connection closing' and return any pending RECEIVEs with
*                            same message," ...
*
*                       (2) "advance RCV.NXT over the FIN," ...
*
*                       (3) "send an acknowledgment for the FIN" ...
*
*                       (4) "FIN implies PUSH for any segment text not yet delivered to the user" ...
*
*                       (5) And the "CLOSE-WAIT STATE ... remain[s] in the CLOSE-WAIT state".
*
*               (3) (a) RFC #793, Section 3.9 'Event Processing : USER TIMEOUT : USER TIMEOUT' states that
*                       "for any state if the user timeout expires, flush all queues, signal the user
*                       'error : connection aborted due to user timeout' ... [and] enter the CLOSED state".
*
*                   (b) However, NO RFC specifies or suggests any mechanism to implement/handle user timeouts.
*
*                       ???? Therefore, it is assumed that ANY TCP connection that receives a valid TCP data
*                       or control segment should reset its user connection timer.
*********************************************************************************************************
*/

static  void  NetTCP_RxPktConnHandlerCloseWait (NET_TCP_CONN  *pconn,
                                                NET_BUF       *pbuf,
                                                NET_BUF_HDR   *pbuf_hdr,
                                                NET_ERR       *perr)
{
    NET_TCP_SEQ_CODE     seq_code;
    NET_TCP_ACK_CODE     ack_code;
    NET_TCP_RESET_CODE   reset_code;
    NET_TCP_TIMEOUT_SEC  timeout_sec;
    NET_TMR_TICK         timeout_tick;
    NET_ERR              err;
    NET_ERR              err_rtn;


/*$PAGE*/
                                                                /* -------------- VALIDATE RX'D TCP PKT --------------- */
                                                                /* Chk for rx'd fin/close.                              */
    if (pbuf_hdr->TCP_SegClose == DEF_YES) {                    /* If fin/close avail, update seg lens.                 */
        pbuf_hdr->TCP_SegLenInit += NET_TCP_SEG_LEN_CLOSE;
        pbuf_hdr->TCP_SegLen     += NET_TCP_SEG_LEN_CLOSE;
    }

                                                                /* Chk rx'd seq nbr.                                    */
    seq_code = NetTCP_RxPktConnIsValidSeq(pconn, pbuf_hdr, perr);
    if (*perr != NET_TCP_ERR_NONE) {
         return;
    }
    switch (seq_code) {
        case NET_TCP_CONN_RX_SEQ_VALID:
             break;


        case NET_TCP_CONN_RX_SEQ_SYNC:                          /* If invalid sync rx'd, ...                            */
        case NET_TCP_CONN_RX_SEQ_SYNC_INVALID:
                                                                /* ... tx TCP conn ack  (see Notes #2c2 & #2b2B).       */
             NetTCP_TxConnAck(pconn, pbuf_hdr, NET_TCP_CONN_TX_ACK_FAULT, NET_TCP_CONN_CLOSE_ALL, &err);
            *perr = NET_TCP_ERR_CONN_SEQ_SYNC_INVALID;
             return;                                            /* Prevent 'break NOT reachable' compiler warning.      */


        case NET_TCP_CONN_RX_SEQ_NONE:
        case NET_TCP_CONN_RX_SEQ_INVALID:                       /* If invalid seq  rx'd (see Note #2a4A), ...           */
        default:
             if (pbuf_hdr->TCP_SegReset != DEF_YES) {           /* ... & reset NOT rx'd (see Note #2a4C), ...           */
                                                                /* ... tx TCP conn ack  (see Note #2a4B).               */
                 NetTCP_TxConnAck(pconn, pbuf_hdr, NET_TCP_CONN_TX_ACK_FAULT, NET_TCP_CONN_CLOSE_ALL, &err);
             }
            *perr = NET_TCP_ERR_CONN_SEQ_INVALID;
             return;                                            /* Prevent 'break NOT reachable' compiler warning.      */
    }

                                                                /* Chk for rx'd reset.                                  */
    reset_code = NetTCP_RxPktConnIsValidReset(pconn, pbuf_hdr, perr);
    if (*perr != NET_TCP_ERR_NONE) {
         return;
    }
    switch (reset_code) {
        case NET_TCP_CONN_RX_RESET_NONE:
             break;


        case NET_TCP_CONN_RX_RESET_VALID:                       /* If   valid reset rx'd, ...                           */
                                                                /* ...  close TCP conn (see Note #2b1A).                */
             NetTCP_ConnClose(pconn, pbuf_hdr, pconn->ConnCloseAppFlag, NET_TCP_CONN_CLOSE_ALL);
            *perr = NET_TCP_ERR_CONN_RESET_VALID;
             return;                                            /* Prevent 'break NOT reachable' compiler warning.      */


        case NET_TCP_CONN_RX_RESET_INVALID:                     /* If invalid reset rx'd, ...                           */
        default:
                                                                /* ... tx TCP conn ack (see Note #2b2Ac).               */
             NetTCP_TxConnAck(pconn, pbuf_hdr, NET_TCP_CONN_TX_ACK_FAULT, NET_TCP_CONN_CLOSE_ALL, &err);
            *perr = NET_TCP_ERR_CONN_RESET_INVALID;
             return;                                            /* Prevent 'break NOT reachable' compiler warning.      */
    }

                                                                /* Chk for rx'd ack.                                    */
    ack_code = NetTCP_RxPktConnIsValidAck(pconn, pbuf_hdr, perr);
    if (*perr != NET_TCP_ERR_NONE) {
         return;
    }
    switch (ack_code) {
        case NET_TCP_CONN_RX_ACK_VALID:
        case NET_TCP_CONN_RX_ACK_DUP:
        case NET_TCP_CONN_RX_ACK_PREV:
             break;


        case NET_TCP_CONN_RX_ACK_NONE:                          /* If NO      ack rx'd, ...                             */
            *perr = NET_TCP_ERR_CONN_ACK_NONE;                  /* ... ignore TCP pkt  (see Note #2d1).                 */
             return;                                            /* Prevent 'break NOT reachable' compiler warning.      */


        case NET_TCP_CONN_RX_ACK_INVALID:                       /* If invalid ack rx'd, ...                             */
        default:
                                                                /* ... tx TCP conn ack (see Note #2d2A3).               */
             NetTCP_TxConnAck(pconn, pbuf_hdr, NET_TCP_CONN_TX_ACK_FAULT, NET_TCP_CONN_CLOSE_ALL, &err);
            *perr = NET_TCP_ERR_CONN_ACK_INVALID;
             return;                                            /* Prevent 'break NOT reachable' compiler warning.      */
    }



/*$PAGE*/
                                                                /* ----------------- HANDLE RX'D SEG ------------------ */
    NetTCP_RxPktConnHandlerSeg(pconn, ack_code, pbuf, pbuf_hdr, &err_rtn);
    switch (err_rtn) {
        case NET_TCP_ERR_CONN_DATA_NONE:
        case NET_TCP_ERR_CONN_DATA_VALID:
             break;


        case NET_TCP_ERR_CONN_DATA_DUP:                         /* ???? Allow dup data to update TCP conn?              */
            *perr = err_rtn;
             return;                                            /* Prevent 'break NOT reachable' compiler warning.      */


        case NET_ERR_INIT_INCOMPLETE:
        case NET_TCP_ERR_CONN_NOT_USED:
        case NET_TCP_ERR_CONN_FAIL:
        case NET_TCP_ERR_CONN_ACK_INVALID:
        case NET_TCP_ERR_CONN_DATA_INVALID:
        case NET_TCP_ERR_INVALID_CONN_STATE:
        case NET_TCP_ERR_INVALID_CONN_OP:
        case NET_TCP_ERR_INVALID_LEN_SEG:
        case NET_TCP_ERR_RX_Q_FULL:
        case NET_TCP_ERR_RX_Q_SIGNAL_FAULT:
        case NET_TCP_ERR_TX:
        case NET_TCP_ERR_TX_Q_SIGNAL_FAULT:
        case NET_TCP_ERR_RE_TX_SEG_TH:
        default:
             NetTCP_ConnClose(pconn, pbuf_hdr, pconn->ConnCloseAppFlag, NET_TCP_CONN_CLOSE_ALL);
            *perr = err_rtn;
             return;                                            /* Prevent 'break NOT reachable' compiler warning.      */
    }


                                                                /* ----------------- UPDATE TCP CONN ------------------ */
                                                                /* -------------------- UPDATE TMR -------------------- */
    timeout_sec  =  pconn->TimeoutConn_sec;                     /* Reset conn close tmr (see Note #3b).                 */
    timeout_tick = (NET_TMR_TICK)timeout_sec * NET_TMR_TIME_TICK_PER_SEC;
    if (pconn->TimeoutTmr != (NET_TMR *)0) {
        NetTmr_Set((NET_TMR    *) pconn->TimeoutTmr,
                   (CPU_FNCT_PTR) NetTCP_ConnCloseTimeout,
                   (NET_TMR_TICK) timeout_tick,
                   (NET_ERR    *)&err);
    } else {
        pconn->TimeoutTmr = NetTmr_Get((void       *) pconn,
                                       (CPU_FNCT_PTR) NetTCP_ConnCloseTimeout,
                                       (NET_TMR_TICK) timeout_tick,
                                       (CPU_INT16U  ) NET_TMR_FLAG_NONE,
                                       (NET_ERR    *)&err);
    }

    if ( err != NET_TMR_ERR_NONE) {
        NetTCP_ConnClose(pconn, pbuf_hdr, pconn->ConnCloseAppFlag, NET_TCP_CONN_CLOSE_ALL);
       *perr  = NET_TCP_ERR_CONN_FAIL;
        return;
    }



/*$PAGE*/
                                                                /* --------------- TX TCP CONN ACK/DATA --------------- */
    ack_code = ((pbuf_hdr->TCP_SegAckTxReqCode == NET_TCP_CONN_TX_ACK_IMMED) ||
                (pbuf_hdr->TCP_SegClose        == DEF_YES))     /* See Note #2f3.                                       */
             ?   NET_TCP_CONN_TX_ACK_IMMED
             :   NET_TCP_CONN_TX_ACK;
                                                                /* Tx ack & any tx data (see Note #1c).                 */
    NetTCP_TxConnTxQ(pconn, pbuf_hdr, ack_code, DEF_NO, NET_TCP_CONN_CLOSE_ALL, perr);
    switch (*perr) {
        case NET_TCP_ERR_NONE:
        case NET_TCP_ERR_CONN_ACK_NONE:
        case NET_TCP_ERR_CONN_ACK_INVALID:
        case NET_TCP_ERR_CONN_ACK_DLYD:
        case NET_TCP_ERR_CONN_ACK_PREVLY_TXD:
        case NET_ERR_TX:                                        /* Ignore transitory tx err(s).                         */
             break;


        case NET_ERR_INIT_INCOMPLETE:
        case NET_TCP_ERR_CONN_NOT_USED:
        case NET_TCP_ERR_CONN_CLOSE:
        case NET_TCP_ERR_CONN_FAULT:
        case NET_TCP_ERR_CONN_FAIL:
        case NET_TCP_ERR_INVALID_CONN_STATE:
        case NET_TCP_ERR_INVALID_CONN_OP:
        case NET_TCP_ERR_INVALID_LEN_SEG:
        case NET_TCP_ERR_NONE_AVAIL:
        case NET_TCP_ERR_TX:
        case NET_CONN_ERR_INVALID_FAMILY:
        case NET_CONN_ERR_INVALID_ADDR:
        case NET_CONN_ERR_INVALID_ADDR_LEN:
        default:
             return;                                            /* Prevent 'break NOT reachable' compiler warning.      */
    }



   *perr = err_rtn;
}


/*$PAGE*/
/*
*********************************************************************************************************
*                                  NetTCP_RxPktConnHandlerLastAck()
*
* Description : (1) Handle TCP connection in LAST-ACK state :
*
*                   (a) Validate received TCP packet for current TCP connection state :
*
*                       (1) Sequence Number (SEQ)                                   See Note  #2a
*                       (2) Reset           (RST)                                   See Note  #2b
*                       (3) Synchronization (SYN)                                   See Note  #2c
*                       (4) Acknowledgement (ACK)                                   See Note  #2d
*                       (5) Finish/Close    (FIN)                                   See Note  #2f
*
*                   (b) Update TCP connection :
*                       (1) Handle received TCP segment                             See Notes #2d       & #2e
*                       (2) Update TCP connection state :                           See Notes #2d2A1a   & #2d2A1b2A
*                           (A) Configure TCP connection timeout value
*                       (3) Update TCP connection timer                             See Notes #2d2A1b2B & #3
*
*                   (c) Transmit TCP connection acknowledgement & data              See Notes #2d2B     & #2f3
*
*
* Argument(s) : pconn       Pointer to a TCP connection.
*               -----       Argument validated in NetTCP_RxPktConnHandler().
*
*               pbuf        Pointer to network buffer that received TCP packet.
*               ----        Argument checked   in NetTCP_Rx().
*
*               pbuf_hdr    Pointer to network buffer header that received TCP packet.
*               --------    Argument validated in NetTCP_Rx().
*
*               perr        Pointer to variable that will receive the return error code from this function :
*
*                               NET_TCP_ERR_CONN_SEQ_SYNC_INVALID   Received segment's synchronization        is
*                                                                       NOT valid for current TCP connection.
*                               NET_TCP_ERR_CONN_SEQ_INVALID        Received segment's sequence        number is
*                                                                       NOT valid for current TCP connection.
*                               NET_TCP_ERR_CONN_ACK_NONE           Received segment's acknowledgement        is
*                                                                       NOT available.
*                               NET_TCP_ERR_CONN_ACK_INVALID        Received segment's acknowledgement number is
*                                                                       NOT valid for current TCP connection.
*                               NET_TCP_ERR_CONN_RESET_VALID        Received segment's reset flag is     valid
*                                                                       for current TCP connection; i.e. reset
*                                                                       the TCP connection.
*                               NET_TCP_ERR_CONN_RESET_INVALID      Received segment's reset flag is NOT valid
*                                                                       for current TCP connection.
*
*                               NET_TCP_ERR_CONN_CLOSED             TCP connection successfully closed.
*                               NET_TCP_ERR_CONN_FAIL               TCP connection operation(s) failed.
*
*                                                                   ----- RETURNED BY NetTCP_RxPktConnIsValidSeq() : -----
*                                                                   ----- RETURNED BY NetTCP_RxPktConnIsValidAck() : -----
*                                                                   ---- RETURNED BY NetTCP_RxPktConnIsValidReset() : ----
*                               NET_TCP_ERR_CONN_NOT_USED           TCP connection NOT currently used.
*                               NET_TCP_ERR_INVALID_CONN_STATE      Invalid TCP connection state.
*                               NET_TCP_ERR_INVALID_LEN_SEG         Invalid TCP sequence-segment length.
*
*                                                                   ----- RETURNED BY NetTCP_RxPktConnHandlerSeg() : -----
*                               NET_TCP_ERR_CONN_DATA_NONE          Received packet successfully handled; but NO
*                                                                       data to   queue  to receive queue(s).
*                               NET_TCP_ERR_CONN_DATA_VALID         Received packet successfully handled & valid
*                                                                       data queued for processing.
*                               NET_TCP_ERR_CONN_DATA_INVALID       Received packet contains invalid   segment
*                                                                       data; NOT queued to receive queue(s).
*                               NET_TCP_ERR_CONN_DATA_DUP           Received packet contains duplicate segment
*                                                                       data; NOT queued to receive queue(s).
*
*                               NET_ERR_INIT_INCOMPLETE             Network initialization NOT complete.
*
*                               NET_TCP_ERR_INVALID_CONN_OP         Invalid TCP connection operation.
*
*                               NET_TCP_ERR_RX_Q_FULL               TCP connection receive  queue full.
*                               NET_TCP_ERR_RX_Q_SIGNAL_FAULT       TCP connection receive  queue signal fault.
*                               NET_TCP_ERR_TX_Q_SIGNAL_FAULT       TCP connection transmit queue signal fault.
*                               NET_TCP_ERR_RE_TX_SEG_TH            TCP connection closed due to excessive retransmission.
*
*                                                                   ---------- RETURNED BY NetTCP_TxConnTxQ() : ----------
*                               NET_TCP_ERR_CONN_CLOSE              TCP connection closed.
*                               NET_TCP_ERR_CONN_FAULT              TCP connection fault; connection(s) aborted.
*                               NET_TCP_ERR_NONE_AVAIL              Resources NOT available.
*                               NET_CONN_ERR_INVALID_FAMILY         Invalid     connection family.
*                               NET_CONN_ERR_INVALID_ADDR           Invalid TCP connection address.
*                               NET_CONN_ERR_INVALID_ADDR_LEN       Invalid TCP connection address length.
*
* Return(s)   : none.
*
* Caller(s)   : NetTCP_RxPktConnHandler().
*$PAGE*
* Note(s)     : (2) TCP connections in the LAST-ACK state are handled as follows :
*
*                   (a) RFC #793, Section 3.9 'Event Processing : SEGMENT ARRIVES : Check Sequence Number'
*                       states that in the "SYN-RECEIVED, ESTABLISHED STATE, FIN-WAIT-1 STATE, FIN-WAIT-2
*                       STATE, CLOSE-WAIT STATE, CLOSING STATE, LAST-ACK STATE, TIME-WAIT STATE" that ...
*
*                       (1) "Segments are processed in sequence ... processing is done in SEG.SEQ order."
*
*                       (2) "Initial tests on arrival are used to discard old duplicates."
*
*                       (3) "If a segment's contents straddle the boundary between old and new, only the
*                            new parts should be processed."
*
*                       (4) (A) "If an incoming segment is not acceptable," ...
*
*                           (B) "an acknowledgment should be sent in reply" ...
*
*                           (C) "(unless the RST bit is set, if so drop the segment)".
*
*                               See also Notes #2b2Aa & #2b2B.
*
*                       See also 'NetTCP_RxPktConnIsValidSeq()  Note #1d'.
*
*                   (b) (1) (A) RFC #793, Section 3.9 'Event Processing : SEGMENT ARRIVES : Check RST Bit' states
*                               that in the "ESTABLISHED, FIN-WAIT-1, FIN-WAIT-2, CLOSE-WAIT" states that "if the
*                               RST bit is set then, any outstanding RECEIVEs and SEND[s] should receive 'reset'
*                               responses.  All segment queues should be flushed.  Users should also receive an
*                               unsolicited general 'connection reset' signal[, and] enter the CLOSED state".
*
*                           (B) RFC #793, Section 3.4 'Establishing a Connection : Reset Processing' reiterates
*                               that "if the receiver ... of a RST ... was in any other state [other than LISTEN
*                               or SYN-RECEIVED], it aborts the connection and advises the user and goes to the
*                               CLOSED state".
*
*                       (2) (A) RFC Draft-IETF-TCPm-TCPSecure #00, Section 2.2 amends the "handling of a segment 
*                               with the RST bit when in a synchronized state" to "provide some protection against 
*                               ... blind reset attack[s] using the RST bit" :
*
*                               (a) "If the RST bit is set and the sequence number is outside the expected
*                                    window, silently drop the segment."
*
*                               (b) "If the RST bit is exactly the next expected sequence number [sic], reset
*                                    the connection"; it is assumed that this should read "if the RST bit is
*                                    set and the sequence number is exactly the next expected sequence number,
*                                    reset the connection."
*
*                               (c) "If the RST bit is set and the sequence number does not exactly match
*                                    the next expected sequence value, yet is within the acceptable window
*                                    (RCV.NXT <= SEG.SEQ < RCV.NXT+RCV.WND) send an acknowledgment."
*
*                           (B) ???? In addition, RFC Draft-IETF-TCPm-TCPSecure #00 does NOT provide a precedence 
*                               priority for handling TCP segments received with BOTH the RST & SYN bits set.
*
*                               ???? Therefore, since it does NOT seem reasonable to reset a TCP connection
*                               due to a TCP segment that also attempted to synchronize the  TCP connection,
*                               it is assumed that the amended handling of the SYN bit should take precedence
*                               over the amended handling of the RST bit.
*
*                               See also Note #2c2.
*
*                   (c) (1) RFC #793, Section 3.9 'Event Processing : SEGMENT ARRIVES : Check SYN Bit'
*                           states that in the "SYN-RECEIVED [STATE], ESTABLISHED STATE, FIN-WAIT STATE-1,
*                           FIN-WAIT STATE-2, CLOSE-WAIT STATE, CLOSING STATE, LAST-ACK STATE, TIME-WAIT
*                           STATE" that ...
*
*                           (A) "If the SYN is in the window it is an error, send a reset, any outstanding
*                                RECEIVEs and SEND[s] should receive 'reset' responses, all segment queues
*                                should be flushed, the user should also receive an unsolicited general
*                               'connection reset' signal[, and] enter the CLOSED state."
*
*                           (B) But "if the SYN is not in the window this step would not have been reached
*                               and an ack would have been sent".
*
*                       (2) HOWEVER, RFC Draft-IETF-TCPm-TCPSecure #00, Section 3.2 amends the  "handling 
*                           of a segment with the SYN bit set in the synchronized state ... [by] handling 
*                           ... the SYN bit" as follows :
*
*                           (a) "If the SYN bit is set and the sequence number is outside the
*                                expected window, send an ACK back to the peer."
*
*                           (b) "If the SYN bit is set and the sequence number is an exact
*                                match to the next expected sequence (RCV.NXT == SEG.SEQ)
*                                then send an ACK segment ... but ... subtract one from
*                                value being acknowledged."
*
*                           (c) "If the SYN bit is set and the sequence number is acceptable,
*                                i.e.: (RCV.NXT <= SEG.SEQ <= RCV.NXT+RCV.WND) then send an
*                                ACK segment."
*$PAGE*
*                   (d) RFC #793, Section 3.9 'Event Processing : SEGMENT ARRIVES : Check ACK Field'
*                       states that ... :
*
*                       (1) "If the ACK bit is off drop the segment."
*
*                       (2) "If the ACK bit is on [and in the] LAST-ACK STATE" ...
*
*                           (A) "The only thing that can arrive in this state is an acknowledgement of our FIN."
*
*                               (1) "If our FIN is now acknowledged" ...
*
*                                   (a) "enter the CLOSED state."
*
*                                   (b) However, it is possible that some closing received data from the remote
*                                       host is available but has NOT yet been received by the application layer.
*
*                                       (1) Therefore, if the application receive queue is closed, then close the
*                                           TCP connection &/or enter the CLOSED state.
*
*                                       (2) (A) But if the application receive queue is NOT closed, then enter the
*                                               connection-closing-data-available state to allow the application
*                                               layer to receive the remaining receive data.
*
*                                           (B) To provide the application layer sufficient time to receive the
*                                               closing received data, the user connection timeout is used as a
*                                               connection closing timeout.
*
*                                       See also Note #2e2.
*
*                               (2) (a) RFC #793, Section 3.9 'Event Processing : SEGMENT ARRIVES : Check ACK Field :
*                                       FIN-WAIT-2 STATE' states that "if the retransmission queue is empty, the
*                                       user's CLOSE can be acknowledged".
*
*                                   (b) However, TCP connection should signal the application layer that "the user's
*                                       close [is] acknowledged" whenever its re-transmit queue becomes &/or is
*                                       empty :
*
*                                       (1) Transition from LAST-ACK to CLOSED
*
*                                   See also 'NetTCP_RxPktConnHandlerSignalClose()  Note #1'.
*
*                           (B) However, it is possible that some but NOT all transmitted data has been received
*                               by the remote host.  In other words, the remote host may have received some but
*                               NOT ALL receive data preceding this host's close request.
*
*                               ???? Therefore, acknowledgements validated as within the transmit window MUST be
*                               received & processed as in connected states.
*
*                               See also 'NetTCP_RxPktConnIsValidAck()  Note #1d'.
*
*                   (e) (1) RFC #793, Section 3.9 'Event Processing : SEGMENT ARRIVES : Process Segment Text'
*                           states that in the "CLOSE-WAIT STATE, CLOSING STATE, LAST-ACK STATE, TIME-WAIT
*                           STATE" that "this should not occur, since a FIN has been received from the remote
*                           side.  Ignore the segment text."
*
*                       (2) (A) However, it is possible that some but NOT all data has been received from
*                               the remote host.  In other words, the remote host's close request may have
*                               received but ALL receive data preceding the close request may NOT have been
*                               received.
*
*                               ???? Therefore, receive data validated by sequence number as within the
*                               receive window MUST be received & processed as in connected states.
*
*                           (B) RFC #793, Section 3.9 'Event Processing : SEGMENT ARRIVES : Process Segment
*                               Text' states that "once in the ESTABLISHED state, it is possible to deliver
*                               segment text to user RECEIVE buffers".
*
*                           See also Note #2d2A1b.
*
*                   (f) RFC #793, Section 3.9 'Event Processing : SEGMENT ARRIVES : Check FIN Bit' states
*                       that "if the FIN bit is set" ...
*
*                       (1) "signal the user 'connection closing' and return any pending RECEIVEs with
*                            same message," ...
*
*                       (2) "advance RCV.NXT over the FIN," ...
*
*                       (3) "send an acknowledgment for the FIN" ...
*
*                       (4) "FIN implies PUSH for any segment text not yet delivered to the user" ...
*
*                       (5) And the "LAST-ACK STATE ... remain[s] in the LAST-ACK state".
*$PAGE*
*               (3) (a) RFC #793, Section 3.9 'Event Processing : USER TIMEOUT : USER TIMEOUT' states that
*                       "for any state if the user timeout expires, flush all queues, signal the user
*                       'error : connection aborted due to user timeout' ... [and] enter the CLOSED state".
*
*                   (b) (1) However, a TCP connection enters the LAST-ACK state ONLY after the remote host
*                           has initiated an active close & enters the TIME-WAIT state, waiting for its
*                           time-wait timer to expire before closing its TCP connection.
*
*                       (2) ???? Therefore, a TCP connection in the LAST-ACK state should NOT wait for its
*                           last acknowledgement from the remote host in the TIME-WAIT state longer than
*                           the remote host's time-wait timeout of two TCP maximum segment lifetimes.
*
*                       (3) ???? Therefore, it is assumed that ANY TCP connection in the LAST-ACK state
*                           that receives a valid TCP data or control segment should reset its time-wait
*                           timer for two TCP maximum segment lifetimes.
*
*               (4) Since the mechanisms of TCP connection close are independent of the application layer
*                   close; any external application layer close error(s) are ignored.
*********************************************************************************************************
*/

static  void  NetTCP_RxPktConnHandlerLastAck (NET_TCP_CONN  *pconn,
                                              NET_BUF       *pbuf,
                                              NET_BUF_HDR   *pbuf_hdr,
                                              NET_ERR       *perr)
{
    NET_TCP_SEQ_CODE     seq_code;
    NET_TCP_ACK_CODE     ack_code;
    NET_TCP_RESET_CODE   reset_code;
    CPU_BOOLEAN          data_avail;
    CPU_BOOLEAN          close_conn;
    NET_TCP_TIMEOUT_SEC  timeout_sec;
    NET_TMR_TICK         timeout_tick;
    NET_ERR              err;
    NET_ERR              err_rtn;


/*$PAGE*/
                                                                /* -------------- VALIDATE RX'D TCP PKT --------------- */
                                                                /* Chk for rx'd fin/close.                              */
    if (pbuf_hdr->TCP_SegClose == DEF_YES) {                    /* If fin/close avail, update seg lens.                 */
        pbuf_hdr->TCP_SegLenInit += NET_TCP_SEG_LEN_CLOSE;
        pbuf_hdr->TCP_SegLen     += NET_TCP_SEG_LEN_CLOSE;
    }

                                                                /* Chk rx'd seq nbr.                                    */
    seq_code = NetTCP_RxPktConnIsValidSeq(pconn, pbuf_hdr, perr);
    if (*perr != NET_TCP_ERR_NONE) {
         return;
    }
    switch (seq_code) {
        case NET_TCP_CONN_RX_SEQ_VALID:
             break;


        case NET_TCP_CONN_RX_SEQ_SYNC:                          /* If invalid sync rx'd, ...                            */
        case NET_TCP_CONN_RX_SEQ_SYNC_INVALID:
                                                                /* ... tx TCP conn ack  (see Notes #2c2 & #2b2B).       */
             NetTCP_TxConnAck(pconn, pbuf_hdr, NET_TCP_CONN_TX_ACK_FAULT, NET_TCP_CONN_CLOSE_ALL, &err);
            *perr = NET_TCP_ERR_CONN_SEQ_SYNC_INVALID;
             return;                                            /* Prevent 'break NOT reachable' compiler warning.      */


        case NET_TCP_CONN_RX_SEQ_NONE:
        case NET_TCP_CONN_RX_SEQ_INVALID:                       /* If invalid seq  rx'd (see Note #2a4A), ...           */
        default:
             if (pbuf_hdr->TCP_SegReset != DEF_YES) {           /* ... & reset NOT rx'd (see Note #2a4C), ...           */
                                                                /* ... tx TCP conn ack  (see Note #2a4B).               */
                 NetTCP_TxConnAck(pconn, pbuf_hdr, NET_TCP_CONN_TX_ACK_FAULT, NET_TCP_CONN_CLOSE_ALL, &err);
             }
            *perr = NET_TCP_ERR_CONN_SEQ_INVALID;
             return;                                            /* Prevent 'break NOT reachable' compiler warning.      */
    }

                                                                /* Chk for rx'd reset.                                  */
    reset_code = NetTCP_RxPktConnIsValidReset(pconn, pbuf_hdr, perr);
    if (*perr != NET_TCP_ERR_NONE) {
         return;
    }
    switch (reset_code) {
        case NET_TCP_CONN_RX_RESET_NONE:
             break;


        case NET_TCP_CONN_RX_RESET_VALID:                       /* If   valid reset rx'd, ...                           */
                                                                /* ...  close TCP conn (see Note #2b1A).                */
             NetTCP_ConnClose(pconn, pbuf_hdr, pconn->ConnCloseAppFlag, NET_TCP_CONN_CLOSE_ALL);
            *perr = NET_TCP_ERR_CONN_RESET_VALID;
             return;                                            /* Prevent 'break NOT reachable' compiler warning.      */


        case NET_TCP_CONN_RX_RESET_INVALID:                     /* If invalid reset rx'd, ...                           */
        default:
                                                                /* ... tx TCP conn ack (see Note #2b2Ac).               */
             NetTCP_TxConnAck(pconn, pbuf_hdr, NET_TCP_CONN_TX_ACK_FAULT, NET_TCP_CONN_CLOSE_ALL, &err);
            *perr = NET_TCP_ERR_CONN_RESET_INVALID;
             return;                                            /* Prevent 'break NOT reachable' compiler warning.      */
    }

                                                                /* Chk for rx'd ack.                                    */
    ack_code = NetTCP_RxPktConnIsValidAck(pconn, pbuf_hdr, perr);
    if (*perr != NET_TCP_ERR_NONE) {
         return;
    }
    switch (ack_code) {
        case NET_TCP_CONN_RX_ACK_VALID:
        case NET_TCP_CONN_RX_ACK_DUP:
        case NET_TCP_CONN_RX_ACK_PREV:
             break;


        case NET_TCP_CONN_RX_ACK_NONE:                          /* If NO      ack rx'd, ...                             */
            *perr = NET_TCP_ERR_CONN_ACK_NONE;                  /* ... ignore TCP pkt  (see Note #2d1).                 */
             return;                                            /* Prevent 'break NOT reachable' compiler warning.      */


        case NET_TCP_CONN_RX_ACK_INVALID:                       /* If invalid ack rx'd, ...                             */
        default:
                                                                /* ... tx TCP conn ack (see Note #2d2B).                */
             NetTCP_TxConnAck(pconn, pbuf_hdr, NET_TCP_CONN_TX_ACK_FAULT, NET_TCP_CONN_CLOSE_ALL, &err);
            *perr = NET_TCP_ERR_CONN_ACK_INVALID;
             return;                                            /* Prevent 'break NOT reachable' compiler warning.      */
    }



/*$PAGE*/
                                                                /* ----------------- HANDLE RX'D SEG ------------------ */
    NetTCP_RxPktConnHandlerSeg(pconn, ack_code, pbuf, pbuf_hdr, &err_rtn);
    switch (err_rtn) {
        case NET_TCP_ERR_CONN_DATA_NONE:
        case NET_TCP_ERR_CONN_DATA_VALID:
             break;


        case NET_TCP_ERR_CONN_DATA_DUP:                         /* ???? Allow dup data to update TCP conn?              */
            *perr = err_rtn;
             return;                                            /* Prevent 'break NOT reachable' compiler warning.      */


        case NET_ERR_INIT_INCOMPLETE:
        case NET_TCP_ERR_CONN_NOT_USED:
        case NET_TCP_ERR_CONN_FAIL:
        case NET_TCP_ERR_CONN_ACK_INVALID:
        case NET_TCP_ERR_CONN_DATA_INVALID:
        case NET_TCP_ERR_INVALID_CONN_STATE:
        case NET_TCP_ERR_INVALID_CONN_OP:
        case NET_TCP_ERR_INVALID_LEN_SEG:
        case NET_TCP_ERR_RX_Q_FULL:
        case NET_TCP_ERR_RX_Q_SIGNAL_FAULT:
        case NET_TCP_ERR_TX_Q_SIGNAL_FAULT:
        case NET_TCP_ERR_RE_TX_SEG_TH:
        default:
             NetTCP_ConnClose(pconn, pbuf_hdr, pconn->ConnCloseAppFlag, NET_TCP_CONN_CLOSE_ALL);
            *perr = err_rtn;
             return;                                            /* Prevent 'break NOT reachable' compiler warning.      */
    }



                                                                /* ----------------- UPDATE TCP CONN ------------------ */
    close_conn = DEF_NO;
    if (pconn->RxQ_State == NET_TCP_RX_Q_STATE_CONN_CLOSED) {   /* If    remote conn closed      (see #2e2A)      ...   */
                                                                /* ... & local  conn close ack'd (see #2d2A1)     ...   */
        if (pconn->TxQ_State == NET_TCP_TX_Q_STATE_CONN_CLOSED) {
            close_conn = DEF_YES;
        }
    }

    if (close_conn == DEF_YES) {
                                                                /* Closing data avail for half-closed conns ONLY.       */
        data_avail = ((pconn->ConnCloseCode !=  NET_CONN_CLOSE_HALF           ) ||
                     ((pconn->RxQ_State     ==  NET_TCP_RX_Q_STATE_CONN_CLOSED) &&
                      (pconn->RxQ_App_Head  == (NET_BUF *)0))) ? DEF_NO : DEF_YES;
                                                                /* ... signal app conn close (see Note #2d2A2b1); ...   */
                                                                /* Ignore any app conn close err(s) [see Note #4].      */
        NetTCP_RxPktConnHandlerSignalClose(pconn, data_avail, &err);


        if (data_avail != DEF_YES) {                            /* ... & if NO app data avail,                    ...   */
                                                                /* ... close TCP conn (see #2d2A1b1);             ...   */
            NetTCP_ConnCloseHandler(pconn, pconn->ConnCloseAppFlag, NET_TCP_CONN_CLOSE_ALL);
           *perr = NET_TCP_ERR_CONN_CLOSED;
            return;
        }
                                                                /* ... else chng to closing-data-avail state      ...   */
                                                                /* ... (see Note #2d2A1b2A),                      ...   */
        pconn->ConnState = NET_TCP_CONN_STATE_CLOSING_DATA_AVAIL;
        timeout_sec      = pconn->TimeoutUser_sec;              /* ... & set user tmr (see Notes #2d2A1b2B).            */

    } else {                                                    /* Else start time-wait tmr (see Note #3b3).            */
        timeout_sec      = pconn->TimeoutMaxSeg_sec * NET_TCP_CONN_TIMEOUT_MAX_SEG_SCALAR;
    }


/*$PAGE*/
                                                                /* -------------------- UPDATE TMR -------------------- */
    timeout_tick = (NET_TMR_TICK)timeout_sec * NET_TMR_TIME_TICK_PER_SEC;
    if (pconn->TimeoutTmr != (NET_TMR *)0) {
        NetTmr_Set((NET_TMR    *) pconn->TimeoutTmr,
                   (CPU_FNCT_PTR) NetTCP_ConnCloseTimeout,
                   (NET_TMR_TICK) timeout_tick,
                   (NET_ERR    *)&err);
    } else {
        pconn->TimeoutTmr = NetTmr_Get((void       *) pconn,
                                       (CPU_FNCT_PTR) NetTCP_ConnCloseTimeout,
                                       (NET_TMR_TICK) timeout_tick,
                                       (CPU_INT16U  ) NET_TMR_FLAG_NONE,
                                       (NET_ERR    *)&err);
    }

    if ( err != NET_TMR_ERR_NONE) {
        NetTCP_ConnClose(pconn, pbuf_hdr, pconn->ConnCloseAppFlag, NET_TCP_CONN_CLOSE_ALL);
       *perr  = NET_TCP_ERR_CONN_FAIL;
        return;
    }



                                                                /* --------------- TX TCP CONN ACK/DATA --------------- */
    ack_code = ((pbuf_hdr->TCP_SegAckTxReqCode == NET_TCP_CONN_TX_ACK_IMMED) ||
                (pbuf_hdr->TCP_SegClose        == DEF_YES))     /* See Note #2f3.                                       */
             ?   NET_TCP_CONN_TX_ACK_IMMED
             :   NET_TCP_CONN_TX_ACK;
                                                                /* Tx ack & any tx data (see Note #1c).                 */
    NetTCP_TxConnTxQ(pconn, pbuf_hdr, ack_code, DEF_NO, NET_TCP_CONN_CLOSE_ALL, perr);
    switch (*perr) {
        case NET_TCP_ERR_NONE:
        case NET_TCP_ERR_CONN_ACK_NONE:
        case NET_TCP_ERR_CONN_ACK_INVALID:
        case NET_TCP_ERR_CONN_ACK_DLYD:
        case NET_TCP_ERR_CONN_ACK_PREVLY_TXD:
        case NET_ERR_TX:                                        /* Ignore transitory tx err(s).                         */
             break;


        case NET_ERR_INIT_INCOMPLETE:
        case NET_TCP_ERR_CONN_NOT_USED:
        case NET_TCP_ERR_CONN_CLOSE:
        case NET_TCP_ERR_CONN_FAULT:
        case NET_TCP_ERR_CONN_FAIL:
        case NET_TCP_ERR_INVALID_CONN_STATE:
        case NET_TCP_ERR_INVALID_CONN_OP:
        case NET_TCP_ERR_INVALID_LEN_SEG:
        case NET_TCP_ERR_NONE_AVAIL:
        case NET_TCP_ERR_TX:
        case NET_CONN_ERR_INVALID_FAMILY:
        case NET_CONN_ERR_INVALID_ADDR:
        case NET_CONN_ERR_INVALID_ADDR_LEN:
        default:
             return;                                            /* Prevent 'break NOT reachable' compiler warning.      */
    }



   *perr = err_rtn;
}


/*$PAGE*/
/*
*********************************************************************************************************
*                                    NetTCP_RxPktConnHandlerSeg()
*
* Description : (1) Handle TCP connection's received segments :
*
*                   (a) Update TCP connection    transmit remote window                     See Note  #5
*                   (b) Update TCP connection controls on transition to connected state(s)
*                   (c) Handle TCP connection re-transmit queue                             See Notes #2b & #4
*                   (d) Update TCP connection    transmit congestion controls               See Note  #6
*                   (e) Handle TCP connection    receive  queue(s)                          See Note  #3
*                   (f) Handle TCP connection    receive  data                              See Notes #2a & #3
*
*
* Argument(s) : pconn       Pointer to a TCP connection.
*               -----       Argument validated in NetTCP_RxPktConnHandler().
*
*               ack_code    Indicates the received segment's acknowledgement condition :
*               --------
*                               NET_TCP_CONN_RX_ACK_NONE            NO received acknowledgement number.
*
*                               NET_TCP_CONN_RX_ACK_INVALID            Received acknowledgement number
*                                                                      is invalid for the TCP connection.
*
*                               NET_TCP_CONN_RX_ACK_VALID              Received acknowledgement number
*                                                                      is   valid for the TCP connection.
*
*                               NET_TCP_CONN_RX_ACK_DUP                Received acknowledgement number
*                                                                      is a          duplicate for the
*                                                                      TCP connection.
*
*                               NET_TCP_CONN_RX_ACK_PREV               Received acknowledgement number
*                                                                      is a previous duplicate for the
*                                                                      TCP connection.
*
*                           Argument validated in NetTCP_RxPktConnHandler() functions.
*
*               pbuf        Pointer to network buffer that received TCP packet.
*               ----        Argument checked   in NetTCP_Rx().
*
*               pbuf_hdr    Pointer to network buffer header that received TCP packet.
*               --------    Argument validated in NetTCP_Rx().
*
*               perr        Pointer to variable that will receive the return error code from this function :
*
*                               NET_TCP_ERR_CONN_ACK_INVALID        Valid received segment acknowledgement NOT available.
*
*                                                                   -- RETURNED BY NetTCP_RxPktConnHandlerTxWinRemote() : -
*                               NET_TCP_ERR_CONN_NOT_USED           TCP connection NOT currently used.
*                               NET_TCP_ERR_INVALID_CONN_STATE      Invalid TCP connection state.
*                               NET_TCP_ERR_INVALID_CONN_OP         Invalid TCP connection operation.
*
*                                                                   ---- RETURNED BY NetTCP_RxPktConnHandlerReTxQ() : -----
*                               NET_TCP_ERR_CONN_FAIL               TCP connection operation(s) failed.
*                               NET_TCP_ERR_TX_Q_SIGNAL_FAULT       TCP connection transmit queue signal fault.
*
*                                                                   - RETURNED BY NetTCP_TxConnWinSizeHandlerCongCtrl() : -
*                               NET_ERR_INIT_INCOMPLETE             Network initialization NOT complete.
*                               NET_TCP_ERR_RE_TX_SEG_TH            TCP connection closed due to excessive retransmission.
*                               NET_TCP_ERR_TX                      TCP transmit error.
*
*                                                                   --- RETURNED BY NetTCP_RxPktConnHandlerRxQ_Sync() : ---
*                                                                   --- RETURNED BY NetTCP_RxPktConnHandlerRxQ_Conn() : ---
*                               NET_TCP_ERR_CONN_DATA_NONE          Received packet successfully handled; but NO data
*                                                                       to  queue  to receive queue(s).
*                               NET_TCP_ERR_CONN_DATA_VALID         Received packet successfully handled & valid data
*                                                                       queued for application.
*
*                                                                   --- RETURNED BY NetTCP_RxPktConnHandlerRxQ_Conn() : ---
*                               NET_TCP_ERR_CONN_DATA_INVALID       Received packet contains invalid   segment data;
*                                                                       NOT queued to receive queue(s).
*                               NET_TCP_ERR_CONN_DATA_DUP           Received packet contains duplicate segment data;
*                                                                       NOT queued to receive queue(s).
*
*                               NET_TCP_ERR_CONN_SEQ_INVALID        Received segment's sequence number is NOT
*                                                                       valid for current TCP connection.
*                               NET_TCP_ERR_INVALID_LEN_SEG         Invalid TCP sequence-segment length.
*
*                                                                   -- RETURNED BY NetTCP_RxPktConnHandlerRxQ_AppData() : -
*                               NET_TCP_ERR_RX_Q_FULL               TCP connection receive queue full.
*                               NET_TCP_ERR_RX_Q_SIGNAL_FAULT       TCP connection receive queue signal fault.
*                               NET_TCP_ERR_RX_Q_SIGNAL_CLR         TCP connection receive queue clear  failed.
*
* Return(s)   : none.
*
* Caller(s)   : Various NetTCP_RxPktConnHandler() functions.
*$PAGE*
* Note(s)     : (2) (a) RFC #793, Section 3.9 'Event Processing : SEGMENT ARRIVES : Check Sequence Number'
*                       states that "segments are processed in sequence ... processing is done in SEG.SEQ
*                       order" (see also Note #3).
*
*                   (b) The following sections generalize that for the SYN-SENT & ESTABLISHED states that
*                       "any segments on the retransmission queue which are ... acknowledged should be
*                       removed" :
*
*                       (1) RFC #793, Section 3.9 'Event Processing : SEGMENT ARRIVES : SYN-SENT [State] :
*                               Check SYN Bit'
*                       (2) RFC #793, Section 3.9 'Event Processing : SEGMENT ARRIVES : Check ACK Field :
*                               ESTABLISHED STATE'
*
*               (3) TCP segments with receive data are sequenced into the appropriate TCP connection
*                   receive queue(s) to be made available & ready to be read by the application layer.
*
*                   See also 'NetTCP_RxPktConnHandlerRxQ_Conn()     Note #3'
*                          & 'NetTCP_RxPktConnHandlerRxQ_AppData()  Note #2'.
*
*               (4) A TCP connection's re-transmit queue SHOULD be updated ONLY by valid received
*                   acknowledgement segments.
*
*                   See also 'NetTCP_RxPktConnHandlerReTxQ()  Note #3'.
*
*               (5) RFC #1122, Section 4.2.2.20 generalizes that "when ... SND.UNA < SEG.ACK <= SND.NXT,
*                   the send window should be updated".
*
*                   See also 'NetTCP_RxPktConnHandlerTxWinRemote()  Note #1'.
*
*               (6) RFC #2581, Section 3.1 states that "the slow start and congestion avoidance algorithms
*                   ... [update] cwnd [TCP transmit congestion control window] for each ACK received that
*                   acknowledges new data".
*
*                   (a) A TCP connection's transmit window congestion controls SHOULD be updated :
*
*                       (1) After    any possible updating of the TCP connection re-transmit queue.
*                       (2) Prior to any possible queuing  of data segments onto the TCP connection
*                               receive queue(s).
*********************************************************************************************************
*/

static  void  NetTCP_RxPktConnHandlerSeg (NET_TCP_CONN      *pconn,
                                          NET_TCP_ACK_CODE   ack_code,
                                          NET_BUF           *pbuf,
                                          NET_BUF_HDR       *pbuf_hdr,
                                          NET_ERR           *perr)
{
#if ((NET_CTR_CFG_ERR_EN      == DEF_ENABLED)                    && \
     (CPU_CFG_CRITICAL_METHOD == CPU_CRITICAL_METHOD_STATUS_LOCAL))
    CPU_SR   cpu_sr;
#endif
    NET_ERR  err_rtn;



    switch (pconn->ConnState) {
        case NET_TCP_CONN_STATE_FREE:
             NET_CTR_ERR_INC(NetTCP_ErrNotUsedCtr);
            *perr = NET_TCP_ERR_CONN_NOT_USED;
             return;                                            /* Prevent 'break NOT reachable' compiler warning.      */


        case NET_TCP_CONN_STATE_LISTEN:
             NetTCP_RxPktConnHandlerRxQ_Sync(pconn, pbuf, pbuf_hdr, &err_rtn);
             break;

/*$PAGE*/
        case NET_TCP_CONN_STATE_SYNC_RXD:
        case NET_TCP_CONN_STATE_SYNC_RXD_PASSIVE:
        case NET_TCP_CONN_STATE_SYNC_RXD_ACTIVE:
#if (NET_ERR_CFG_ARG_CHK_DBG_EN == DEF_ENABLED)
             if (ack_code != NET_TCP_CONN_RX_ACK_VALID) {
                *perr = NET_TCP_ERR_CONN_ACK_INVALID;
                 return;
             }
#endif

             NetTCP_RxPktConnHandlerTxWinRemote(pconn, ack_code, pbuf_hdr, perr);
             if (*perr != NET_TCP_ERR_NONE) {
                  return;
             }

             NetTCP_RxPktConnHandlerCfgConn(pconn);

             NetTCP_RxPktConnHandlerReTxQ(pconn, ack_code, pbuf_hdr, perr);
             if (*perr != NET_TCP_ERR_NONE) {
                  return;
             }

             NetTCP_TxConnWinSizeHandlerCongCtrl(pconn, pbuf_hdr, ack_code, 0, NET_TCP_CONN_TX_WIN_SEG_RXD, perr);
             switch (*perr) {
                 case NET_TCP_ERR_NONE:
                 case NET_ERR_TX:                               /* Ignore transitory tx err(s).                         */
                      break;


                 case NET_ERR_INIT_INCOMPLETE:
                 case NET_TCP_ERR_CONN_NOT_USED:
                 case NET_TCP_ERR_CONN_FAIL:
                 case NET_TCP_ERR_INVALID_CONN_STATE:
                 case NET_TCP_ERR_INVALID_CONN_OP:
                 case NET_TCP_ERR_TX:
                 case NET_TCP_ERR_RE_TX_SEG_TH:
                      return;                                   /* Prevent 'break NOT reachable' compiler warning.      */
             }

             NetTCP_RxPktConnHandlerRxQ_Conn(pconn, pbuf, pbuf_hdr, &err_rtn);
             break;


        case NET_TCP_CONN_STATE_SYNC_TXD:
             if (ack_code == NET_TCP_CONN_RX_ACK_VALID) {
                 NetTCP_RxPktConnHandlerTxWinRemote(pconn, ack_code, pbuf_hdr, perr);
                 if (*perr != NET_TCP_ERR_NONE) {
                      return;
                 }

                 NetTCP_RxPktConnHandlerCfgConn(pconn);

                 NetTCP_RxPktConnHandlerReTxQ(pconn, ack_code, pbuf_hdr, perr);
                 if (*perr != NET_TCP_ERR_NONE) {
                      return;
                 }

                 NetTCP_TxConnWinSizeHandlerCongCtrl(pconn, pbuf_hdr, ack_code, 0, NET_TCP_CONN_TX_WIN_SEG_RXD, perr);
                 switch (*perr) {
                     case NET_TCP_ERR_NONE:
                     case NET_ERR_TX:                           /* Ignore transitory tx err(s).                         */
                          break;


                     case NET_ERR_INIT_INCOMPLETE:
                     case NET_TCP_ERR_CONN_NOT_USED:
                     case NET_TCP_ERR_CONN_FAIL:
                     case NET_TCP_ERR_INVALID_CONN_STATE:
                     case NET_TCP_ERR_INVALID_CONN_OP:
                     case NET_TCP_ERR_TX:
                     case NET_TCP_ERR_RE_TX_SEG_TH:
                          return;                               /* Prevent 'break NOT reachable' compiler warning.      */
                 }

                 NetTCP_RxPktConnHandlerRxQ_Conn(pconn, pbuf, pbuf_hdr, &err_rtn);

             } else {
                 NetTCP_RxPktConnHandlerRxQ_Sync(pconn, pbuf, pbuf_hdr, &err_rtn);
             }
             break;

/*$PAGE*/
        case NET_TCP_CONN_STATE_CONN:
        case NET_TCP_CONN_STATE_FIN_WAIT_1:
        case NET_TCP_CONN_STATE_CLOSING:
        case NET_TCP_CONN_STATE_CLOSE_WAIT:
        case NET_TCP_CONN_STATE_LAST_ACK:
#if (NET_ERR_CFG_ARG_CHK_DBG_EN == DEF_ENABLED)
             switch (ack_code) {
                 case NET_TCP_CONN_RX_ACK_VALID:
                 case NET_TCP_CONN_RX_ACK_DUP:
                 case NET_TCP_CONN_RX_ACK_PREV:
                      break;


                 case NET_TCP_CONN_RX_ACK_NONE:
                 case NET_TCP_CONN_RX_ACK_INVALID:
                 default:
                     *perr = NET_TCP_ERR_CONN_ACK_INVALID;
                      return;                                   /* Prevent 'break NOT reachable' compiler warning.      */
             }
#endif

             NetTCP_RxPktConnHandlerTxWinRemote(pconn, ack_code, pbuf_hdr, perr);
             if (*perr != NET_TCP_ERR_NONE) {
                  return;
             }

             switch (ack_code) {
                 case NET_TCP_CONN_RX_ACK_VALID:                /* If valid ack, update re-tx Q (see Note #3).          */
                 case NET_TCP_CONN_RX_ACK_DUP:
                      NetTCP_RxPktConnHandlerReTxQ(pconn, ack_code, pbuf_hdr, perr);
                      if (*perr != NET_TCP_ERR_NONE) {
                           return;
                      }
                      break;
             }

             NetTCP_TxConnWinSizeHandlerCongCtrl(pconn, pbuf_hdr, ack_code, 0, NET_TCP_CONN_TX_WIN_SEG_RXD, perr);
             switch (*perr) {
                 case NET_TCP_ERR_NONE:
                 case NET_ERR_TX:                               /* Ignore transitory tx err(s).                         */
                      break;


                 case NET_ERR_INIT_INCOMPLETE:
                 case NET_TCP_ERR_CONN_NOT_USED:
                 case NET_TCP_ERR_CONN_FAIL:
                 case NET_TCP_ERR_INVALID_CONN_STATE:
                 case NET_TCP_ERR_INVALID_CONN_OP:
                 case NET_TCP_ERR_TX:
                 case NET_TCP_ERR_RE_TX_SEG_TH:
                      return;                                   /* Prevent 'break NOT reachable' compiler warning.      */
             }

             NetTCP_RxPktConnHandlerRxQ_Conn(pconn, pbuf, pbuf_hdr, &err_rtn);
             switch (err_rtn) {
                 case NET_TCP_ERR_CONN_DATA_NONE:
                 case NET_TCP_ERR_CONN_DATA_VALID:
                      break;


                 case NET_TCP_ERR_CONN_DATA_DUP:
                     *perr = err_rtn;
                      return;                                   /* Prevent 'break NOT reachable' compiler warning.      */


                 case NET_TCP_ERR_CONN_NOT_USED:
                 case NET_TCP_ERR_CONN_DATA_INVALID:
                 case NET_TCP_ERR_INVALID_CONN_STATE:
                 case NET_TCP_ERR_INVALID_LEN_SEG:
                 default:
                     *perr = err_rtn;
                      return;                                   /* Prevent 'break NOT reachable' compiler warning.      */
             }

             NetTCP_RxPktConnHandlerRxQ_AppData(pconn, perr);
             if (*perr != NET_TCP_ERR_NONE) {
                  return;
             }
             break;

/*$PAGE*/
        case NET_TCP_CONN_STATE_FIN_WAIT_2:
        case NET_TCP_CONN_STATE_TIME_WAIT:
#if (NET_ERR_CFG_ARG_CHK_DBG_EN == DEF_ENABLED)
             switch (ack_code) {
                 case NET_TCP_CONN_RX_ACK_VALID:
                 case NET_TCP_CONN_RX_ACK_DUP:
                      break;


                 case NET_TCP_CONN_RX_ACK_NONE:
                 case NET_TCP_CONN_RX_ACK_INVALID:
                 default:
                     *perr = NET_TCP_ERR_CONN_ACK_INVALID;
                      return;                                   /* Prevent 'break NOT reachable' compiler warning.      */
             }
#endif

             NetTCP_RxPktConnHandlerRxQ_Conn(pconn, pbuf, pbuf_hdr, &err_rtn);
             switch (err_rtn) {
                 case NET_TCP_ERR_CONN_DATA_NONE:
                 case NET_TCP_ERR_CONN_DATA_VALID:
                      break;


                 case NET_TCP_ERR_CONN_DATA_DUP:
                     *perr = err_rtn;
                      return;                                   /* Prevent 'break NOT reachable' compiler warning.      */


                 case NET_TCP_ERR_CONN_NOT_USED:
                 case NET_TCP_ERR_CONN_DATA_INVALID:
                 case NET_TCP_ERR_INVALID_CONN_STATE:
                 case NET_TCP_ERR_INVALID_LEN_SEG:
                 default:
                     *perr = err_rtn;
                      return;                                   /* Prevent 'break NOT reachable' compiler warning.      */
             }

             NetTCP_RxPktConnHandlerRxQ_AppData(pconn, perr);
             if (*perr != NET_TCP_ERR_NONE) {
                  return;
             }
             break;


        case NET_TCP_CONN_STATE_CLOSING_DATA_AVAIL:
             NET_CTR_ERR_INC(NetTCP_ErrConnInvalidOpCtr);
            *perr = NET_TCP_ERR_INVALID_CONN_OP;
             return;                                            /* Prevent 'break NOT reachable' compiler warning.      */


        case NET_TCP_CONN_STATE_NONE:
        case NET_TCP_CONN_STATE_CLOSED:
        default:
             NetTCP_ConnClose(pconn, pbuf_hdr, DEF_YES, NET_TCP_CONN_CLOSE_ALL);
             NET_CTR_ERR_INC(NetTCP_ErrConnInvalidStateCtr);
            *perr = NET_TCP_ERR_INVALID_CONN_STATE;
             return;                                            /* Prevent 'break NOT reachable' compiler warning.      */
    }


   *perr = err_rtn;
}


/*$PAGE*/
/*
*********************************************************************************************************
*                                  NetTCP_RxPktConnHandlerCfgConn()
*
* Description : (1) Configure TCP connection's controls on transition to connected state(s) :
*
*                   (a) Configure TCP connection maximum segment size control(s)
*                   (b) Configure TCP connection window size controls
*
*
* Argument(s) : pconn       Pointer to a TCP connection.
*               -----       Argument validated in NetTCP_RxPktConnHandler().
*
* Return(s)   : none.
*
* Caller(s)   : NetTCP_RxPktConnHandlerSeg().
*
* Note(s)     : (2) During TCP connection initialization, some TCP connection controls were previously
*                   configured in NetTCP_ConnGet() when the TCP connection was allocated from the TCP
*                   connection pool.  These TCP connection controls do NOT need to be re-configured
*                   but are shown for completeness.
*********************************************************************************************************
*/

static  void  NetTCP_RxPktConnHandlerCfgConn (NET_TCP_CONN  *pconn)
{
    NET_TCP_CFG_CODE  cfg_code;

                                                                /* Cfg conn (see Note #1).                              */
    cfg_code = NET_TCP_CONN_CFG_NONE              |
               NET_TCP_CONN_CFG_MAX_SEG_SIZE_CONN |
               NET_TCP_CONN_CFG_WIN_SIZE_ALL;
#if 0                                                           /* Cfg'd in NetTCP_ConnGet() [see Note #2].             */
    DEF_BIT_SET(cfg_code, NET_TCP_CONN_CFG_TX_RTT_RTO);
#endif
    NetTCP_ConnCfg(pconn, cfg_code);
}


/*$PAGE*/
/*
*********************************************************************************************************
*                                  NetTCP_RxPktConnHandlerRxQ_Sync()
*
* Description : (1) (a) Handle TCP connection's transport receive queue ... :
*
*                       (1) Update TCP connection initial receive sequence numbers          See Note #2b
*                       (2) Queue  received TCP segments onto transport receive queue       See Note #3
*                       (3) Update TCP connection receive window
*
*                   (b) ... for the following connection-request/synchronization states :
*
*                       (1) LISTEN
*                       (2) SYN-SENT
*
*
* Argument(s) : pconn       Pointer to a TCP connection.
*               -----       Argument validated in NetTCP_RxPktConnHandler().
*
*               pbuf        Pointer to network buffer that received TCP packet.
*               ----        Argument checked   in NetTCP_Rx().
*
*               pbuf_hdr    Pointer to network buffer header that received TCP packet.
*               --------    Argument validated in NetTCP_Rx().
*
*               perr        Pointer to variable that will receive the return error code from this function :
*
*                               NET_TCP_ERR_CONN_DATA_NONE          Received packet successfully handled; but
*                                                                       NO data to queue  to receive queue(s).
*                               NET_TCP_ERR_CONN_DATA_VALID         Received packet successfully handled &
*                                                                          data    queued to receive queue(s)
*                                                                       for later processing (see Note #2c).
*                               NET_TCP_ERR_INVALID_CONN_STATE      Invalid TCP connection receive queue
*                                                                       state.
*
* Return(s)   : none.
*
* Caller(s)   : NetTCP_RxPktConnHandlerSeg().
*
* Note(s)     : (2) (a) RFC #793, Section 3.9 'Event Processing : SEGMENT ARRIVES : Check Sequence Number'
*                       states that "segments are processed in sequence ... processing is done in SEG.SEQ
*                       order."
*
*                   (b) The following sections generalize that for the LISTEN & SYN-SENT states that "if the
*                       SYN bit is on and ... acceptable then ... RCV.NXT is set to SEG.SEQ+1, IRS is set to
*                       SEG.SEQ" :
*
*                       (1) RFC #793, Section 3.9 'Event Processing : SEGMENT ARRIVES : LISTEN   [State] :
*                               Check for SYN'
*                       (2) RFC #793, Section 3.9 'Event Processing : SEGMENT ARRIVES : SYN-SENT [State] :
*                               Check SYN Bit'
*
*                   (c) (1) The following sections generalize that for the LISTEN & SYN-SENT states that "if
*                           there are other controls or text in the segment, queue them for later processing
*                           after the ESTABLISHED state has been reached" :
*
*                           (A) RFC #793, Section 3.9 'Event Processing : SEGMENT ARRIVES : LISTEN   [State] :
*                                   Check for SYN'
*                           (B) RFC #793, Section 3.9 'Event Processing : SEGMENT ARRIVES : SYN-SENT [State] :
*                                   Check SYN Bit'
*
*                       (2) If any control or text is queued for later processing, the next sequence octet to
*                           receive (RCV.NXT) MUST include the length of this received segment (SEG.LEN) :
*
*                           (A) RCV.NXT = SEG.SEQ + SEG.LEN + 1
*               (3) TCP segments with receive data are sequenced into the appropriate TCP connection
*                   receive queue(s) to be made available & ready to be read by the application layer.
*
*                   See also 'NetTCP_RxPktConnHandlerRxQ_Conn()     Note #3'
*                          & 'NetTCP_RxPktConnHandlerRxQ_AppData()  Note #2'.
*
*               (4) Some buffer controls were previously initialized in NetBuf_Get() when the buffer was
*                   allocated.  These buffer controls do NOT need to be re-initialized but are shown for
*                   completeness.
*
*               (5) RFC #793, Section 3.7 'Data Communication : Managing the Window' states that "the window 
*                   sent in each segment indicates the range of sequence numbers the sender of the window 
*                   (the data receiver) is currently prepared to accept.  There is an assumption that this 
*                   is related to the currently available data buffer space available for this connection
*                   ... One strategy would be to ... [update the] information when the window" changes.
*
*                   See also 'NetTCP_RxAppData()                 Note #7',
*                            'NetTCP_RxPktConnHandlerRxQ_Conn()  Note #6',
*                          & 'NetTCP_RxConnWinSizeHandler()      Note #2a'.
*********************************************************************************************************
*/
/*$PAGE*/
static  void  NetTCP_RxPktConnHandlerRxQ_Sync (NET_TCP_CONN  *pconn,
                                               NET_BUF       *pbuf,
                                               NET_BUF_HDR   *pbuf_hdr,
                                               NET_ERR       *perr)
{
    NET_TCP_SEG_SIZE  seg_len;
    NET_TCP_SEG_SIZE  seg_len_data;


#if (NET_ERR_CFG_ARG_CHK_DBG_EN == DEF_ENABLED)                 /* ------------- VALIDATE RX Q CONN STATE ------------- */
    switch (pconn->RxQ_State) {
        case NET_TCP_RX_Q_STATE_CONN_CLOSED:
             break;


        case NET_TCP_RX_Q_STATE_NONE:
        case NET_TCP_RX_Q_STATE_CLOSED:
        case NET_TCP_RX_Q_STATE_CONN_SYNC:
        case NET_TCP_RX_Q_STATE_CONN:
        case NET_TCP_RX_Q_STATE_CONN_CLOSING:
        default:
            *perr = NET_TCP_ERR_INVALID_CONN_STATE;
             return;                                            /* Prevent 'break NOT reachable' compiler warning.      */
    }
#endif

                                                                /* Update TCP conn rx seq nbrs (see Notes #2b & #2c2).  */
    pconn->RxSeqNbrSync = (NET_TCP_SEQ_NBR) pbuf_hdr->TCP_SeqNbr;
    pconn->RxSeqNbrNext = (NET_TCP_SEQ_NBR)(pbuf_hdr->TCP_SeqNbr + pbuf_hdr->TCP_SegLen);
    pconn->RxQ_State    =  NET_TCP_RX_Q_STATE_CONN_SYNC;


    seg_len = (NET_TCP_SEG_SIZE)pbuf_hdr->TCP_SegLen;
    if (seg_len > NET_TCP_SEG_LEN_SYNC) {                       /* If rx'd seg len > sync seg len, ...                  */
                                                                /* ... Q seg to TCP conn rx Q  (see Notes #3 & #2c1).   */
#if (NET_ERR_CFG_ARG_CHK_DBG_EN == DEF_ENABLED)
        NetTCP_ConnFreeBufQ(&pconn->RxQ_Transport_Head, &pconn->RxQ_Transport_Tail);
#endif
        pconn->RxQ_Transport_Head = (NET_BUF *)pbuf;
        pconn->RxQ_Transport_Tail = (NET_BUF *)pbuf;
#if 0                                                           /* Init'd in NetBuf_Get() [see Note #4].                */
        pbuf_hdr->PrevPrimListPtr = (void    *)0;
        pbuf_hdr->NextPrimListPtr = (void    *)0;
#endif
                                                                /* Dec TCP conn's rx win size (see Note #5).            */
        seg_len_data = (NET_TCP_SEG_SIZE)pbuf_hdr->TCP_SegLenData;
        NetTCP_RxConnWinSizeHandler((NET_TCP_CONN   *)pconn,
                                    (NET_BUF_HDR    *)pbuf_hdr,
                                    (NET_TCP_WIN_SIZE)seg_len_data,
                                    (NET_TCP_WIN_CODE)NET_TCP_CONN_RX_WIN_DEC);

       *perr = NET_TCP_ERR_CONN_DATA_VALID;

    } else {
       *perr = NET_TCP_ERR_CONN_DATA_NONE;
    }
}


/*$PAGE*/
/*
*********************************************************************************************************
*                                  NetTCP_RxPktConnHandlerRxQ_Conn()
*
* Description : (1) (a) Handle TCP connection's transport receive queue ... :
*
*                       (1) Update TCP connection receive sequence numbers          See Notes #2c  & #2e
*                       (2) Insert received TCP segments in sequence order          See Notes #3   & #4
*                       (3) Update TCP connection receive window
*
*                   (b) ... for the following connected states :
*
*                       (1) SYN-RECEIVED                                            See Notes #1bA & #2b2
*                       (2) SYN-SENT                                                See Notes #1bA & #2b1
*                       (3) ESTABLISHED                                             See Note  #1bB
*                       (4) FIN-WAIT-1                                              See Note  #1bB
*                       (5) FIN-WAIT-2                                              See Note  #1bB
*                       (6) CLOSING                                                 See Note  #1bC
*                       (7) TIME-WAIT                                               See Note  #1bC
*                       (8) CLOSE-WAIT                                              See Note  #1bC
*                       (9) LAST-ACK                                                See Note  #1bC
*
*
*                           (A) For synchronization-to-connected state transitions, segments are queued to
*                               the TCP connection's transport receive queue, but NOT to the TCP connection's
*                               application receive queue, until the application layer is signaled that the
*                               transport layer connection is complete.
*
*                               See also 'NetTCP_RxPktConnHandlerSyncRxd()  Note #1c1'
*                                      & 'NetTCP_RxPktConnHandlerSyncTxd()  Note #1c1'.
*
*                           (B) For connected states,       segments are queued to the TCP connection's
*                               transport &/or application receive queue(s) as appropriate (see Note #3).
*
*                           (C) For closing states; closing segments are queued to the TCP connection's
*                               transport &/or application receive queue(s) as for connected states.
*
*
* Argument(s) : pconn       Pointer to a TCP connection.
*               -----       Argument validated in NetTCP_RxPktConnHandler().
*
*               pbuf        Pointer to network buffer that received TCP packet.
*               ----        Argument checked   in NetTCP_Rx().
*
*               pbuf_hdr    Pointer to network buffer header that received TCP packet.
*               --------    Argument validated in NetTCP_Rx().
*
*               perr        Pointer to variable that will receive the return error code from this function :
*
*                               NET_TCP_ERR_CONN_DATA_NONE          Received packet successfully handled; but
*                                                                       NO data to queue  to receive queue(s).
*                               NET_TCP_ERR_CONN_DATA_VALID         Received packet successfully handled &
*                                                                          data    queued to receive queue(s)
*                                                                       for later processing (see Note #3).
*                               NET_TCP_ERR_CONN_DATA_INVALID       Received packet contains invalid   segment
*                                                                       data; NOT queued to receive queue(s).
*                               NET_TCP_ERR_CONN_DATA_DUP           Received packet contains duplicate segment
*                                                                       data; NOT queued to receive queue(s)
*                                                                       (see Note #2a2).
*
*                               NET_TCP_ERR_CONN_SEQ_INVALID        Received segment's sequence number is NOT
*                                                                       valid for current TCP connection.
*
*                               NET_TCP_ERR_INVALID_CONN_STATE      Invalid TCP connection receive queue state.
*
*                                                                   - RETURNED BY NetTCP_RxPktConnIsValidSeq() : -
*                               NET_TCP_ERR_CONN_NOT_USED           TCP connection NOT currently used.
*                               NET_TCP_ERR_INVALID_LEN_SEG         Invalid TCP sequence-segment length.
*
* Return(s)   : none.
*
* Caller(s)   : NetTCP_RxPktConnHandlerSeg().
*$PAGE*
* Note(s)     : (2) (a) RFC #793, Section 3.9 'Event Processing : SEGMENT ARRIVES : Check Sequence Number'
*                       states that ... :
*
*                       (1) "Segments are processed in sequence ... processing is done in SEG.SEQ order."
*
*                           (A) Assumes received segment's sequences previously validated.
*
*                       (2) "Initial tests on arrival are used to discard old duplicates."
*
*                       (3) (A) (1) "If a segment's contents straddle the boundary between old and new,
*                                    only the new parts should be processed."
*
*                               (2) "One could tailor actual segments to ... the idealized segment that
*                                    begins at RCV.NXT and does not exceed the window ... by trimming off
*                                    any portions that lie outside the window (including SYN and FIN),
*                                    and only processing further if the segment then begins at RCV.NXT.
*                                    Segments with higher beginning sequence numbers may be held for later
*                                    processing."
*
*                           (B) (1) Sequencing     received segments with duplicate data that overlaps
*                                   multiple previously-received segments' non-contiguous sequence numbers
*                                   is data intensive/expensive.
*
*                               (2) Therefore, any received segment  with duplicate data that overlaps
*                                   multiple previously-received segments' non-contiguous sequence numbers
*                                   is trimmed of duplicate data starting from the end of the received
*                                   segment's data.
*
*                                   In other words, only the first contiguous, non-duplicate data sequence
*                                   starting from the start of the received segment's data is sequenced
*                                   into the TCP connection's receive queue(s).
*
*                           (C) RFC #1122, Section 4.2.2.20 states that "a TCP SHOULD be capable of queueing
*                               out-of-order TCP segments".
*
*                   (b) The following sections generalize that in the "SYN-SENT [or] ... SYN-RECEIVED
*                       STATE[s], ... [that] if the ACK bit is on [and] our SYN has been ACKed ...
*                       then enter the ESTABLISHED state and continue processing" :
*
*                       (1) RFC #793, Section 3.9 'Event Processing : SEGMENT ARRIVES : SYN-SENT [State] :
*                               Check SYN Bit'
*                       (2) RFC #793, Section 3.9 'Event Processing : SEGMENT ARRIVES : Check ACK Field :
*                               SYN-RECEIVED STATE'
*
*                   (c) RFC #793, Section 3.9 'Event Processing : SEGMENT ARRIVES : SYN-SENT [State] :
*                       Check SYN Bit' states that "if the SYN bit is on and ... acceptable then ...
*                       RCV.NXT is set to SEG.SEQ+1, IRS is set to SEG.SEQ".
*
*                   (d) (1) RFC #793, Section 3.9 'Event Processing : SEGMENT ARRIVES : SYN-SENT [State] :
*                           Check SYN Bit' states that "if there are other controls or text in the segment,
*                           queue them for later processing after the ESTABLISHED state has been reached"
*                           (see also Note #2b).
*
*                       (2) If any control or text is queued for later processing, the next sequence octet to
*                           receive (RCV.NXT) MUST include the length of this received segment (SEG.LEN) :
*
*                           (A) RCV.NXT = SEG.SEQ + SEG.LEN + 1
*
*                   (e) (1) RFC #793, Section 3.9 'Event Processing : SEGMENT ARRIVES : Check FIN Bit' states
*                           that "if the FIN bit is set ... advance RCV.NXT over the FIN".
*
*                       (2) However, the next octet to receive is NOT updated with the sequence number of the
*                           last octet to receive.  Instead, the generic sequence algorithm maintains & updates
*                           BOTH the next & last octets to receive for the closing TCP connection.
*$PAGE*
*               (3) TCP segments with receive data are sequenced first into the TCP connection's transport
*                   receive queue to be made available & ready to be read by the application layer from the
*                   TCP connection's application receive queue (see 'NetTCP_RxPktConnHandlerRxQ_AppData()
*                   Note #2').
*
*                   (a) Received TCP segments are inserted into a doubly-linked Transport Receive Queue,
*                       sorted by their sequence number(s).
*
*                       (1) 'RxQ_Transport_Head' points to the head of the Transport Receive Queue;
*                           'RxQ_Transport_Tail' points to the tail of the Transport Receive Queue.
*
*                       (2) Segment buffers' 'PrevPrimListPtr' & 'NextPrimListPtr'  doubly-link each
*                           segment to form the Transport Receive Queue.
*
*                       (3) Fragmented segment buffer's 'PrevBufPtr' & 'NextBufPtr' doubly-link each
*                           fragmented segment (see also 'net_ip.c  NetIP_RxPktFragReasm()  Note #2b3').
*
*                   (b) Typically & most-frequently, TCP segments will be received in sequence-order.
*                       Therefore, the sequence sort algorithm starts at the tail of the Transport
*                       Receive Queue.
*
*                   (c) As segments are inserted into the Transport Receive Queue, segments migrate to
*                       the head of the Transport Receive Queue.  Queued segments with sequence numbers
*                       that are contiguous from the next expected receive sequence number are ready to
*                       be read by the application layer, so are immediately moved from the Transport
*                       Receive Queue to the Application Receive Queue.
*
*                       See also 'NetTCP_RxPktConnHandlerRxQ_AppData()  Note #2'.
*
*
*                                      |                                               |
*                                      |<-- TCP Connection Transport Receive Queue --->|
*                                      |                (see Note #3)                  |
*
*                                  Segments Moved                           Segments Sequenced
*                                  to Application                             into Transport
*                                  Receive Queue                              Receive Queue
*                                 starting at head                           starting at tail
*                                  (see Note #3c)                             (see Note #3b)
*
*                                         |        NextPrimListPtr                  |
*                                         |        (see Note #3a2)                  |
*                                         v                   |                     v
*                                                             |
*                        Head of       -------       -------  v    -------       -------   (see Note #3a1)
*                        Receive  ---->|     |------>|     |------>|     |------>|     |
*                         Queue        |     |       |     |       |     |       |     |       Tail of
*                                      |     |<------|     |<------|     |<------|     |<----  Receive
*                    (see Note #3a1)   |     |       |     |  ^    |     |       |     |        Queue
*                                      |     |       |     |  |    |     |       |     |
*                                      -------       -------  |    -------       -------
*                                        | ^                  |      | ^
*                                        | |       PrevPrimListPtr   | |
*                                        v |       (see Note #3a2)   v |
*                                      -------                     -------
*                                      |     |                     |     |
*                                      |     |                     |     |
*                                      |     |                     |     |
*                                      |     |                     |     |
*                                      |     |                     |     |
*                                      -------                     -------
*                                        | ^                         | ^
*                        NextBufPtr ---> | | <--- PrevBufPtr         | |
*                     (see Note #3a3)    v |   (see Note #3a3)       v |
*                                      -------                     -------
*                                      |     |                     |     |
*                                      |     |                     |     |
*                                      |     |                     -------
*                                      |     |
*                                      |     |
*                                      -------
*
*$PAGE*
*               (4) RFC #793 does NOT provide nor suggest any logic to determine/handle sequence number
*                   comparisons for sequence number windows that overflow the sequence number space.
*
*                   (a) For example, the next sequence octet to receive (RCV.NXT) is typically less than
*                       or equal to  the next received sequence octet (SEG.SEQ) :
*
*                           (1) RCV.NXT <= SEG.SEQ
*
*                       SEG.SEQ itself is also typically less than RCV.NXT plus the current receive window
*                       size (RCV.WND) :
*
*                           (2) SEG.SEQ <  RCV.NXT + RCV.WND
*
*                       However, if (RCV.NXT + RCV.WND) or SEG.SEQ overflows the sequence number space,
*                       these values will be MUCH less than SEG.SEQ or RCV.NXT, respectively, until
*                       SEG.SEQ & RCV.NXT also overflow :
*
*                           (3) RCV.NXT + RCV.WND << RCV.NXT
*                                                 << SEG.SEQ
*
*                           (4) SEG.SEQ           << RCV.NXT
*
*                   (b) Therefore, in order to determine if a received segment's sequence value precedes any
*                       previously received segment(s) in the TCP connection's receive queue(s), the following
*                       unsigned arithmetic comparisons MUST be checked :
*
*                           (1) RxQCur.SeqNbr - (SEG.SEQ + 1)  <   RX.WIN
*
*                           (2)     RX.NXT    - (SEG.SEQ + 1)  <  SEG.LEN
*
*                       Note that these comparisons bound any received segment's sequence within limits set
*                       by the TCP connection's receive window size & next expected receive octet.
*
*                   (c) In order to determine if a received segment's sequence value overlaps any previously
*                       received segment(s) in the TCP connection's receive queue, the following unsigned
*                       arithmetic comparisons MUST be checked :
*
*                           (1) (   SEG.SEQ    +    SEG.LEN   )  -  (RxQNext.SeqNbr + 1)  <     SEG.LEN
*
*                           (2) (RxQCur.SeqNbr + RxQCur.SegLen)  -  (SEG.SEQ        + 1)  <  RxQCur.SegLen
*
*                   See also 'NetTCP_RxPktConnIsValidSeq()  Note #2'.
*
*               (5) (a) RFC #2581, Section 3.2 states that "a TCP receiver SHOULD send an immediate ACK" :
*
*                       (1) "When an out-of-order segment arrives.  The purpose of this ACK is to inform
*                            the sender that a segment was received out-of-order and which sequence number
*                            is expected."
*
*                       (2) "In addition, ... when the incoming segment fills in all or part of a gap in
*                            the sequence space."
*
*                       See also 'NetTCP_TxConnAck()  Note #4a5'.
*
*                   (b) Since segments are typically received in sequence order (see Notes #5a1 & #3b) &
*                       since segments received in sequential order are immediately made available & ready
*                       to be read by the application layer (see Note #3c), received segments are out-of-
*                       order AND/OR fill in sequence number gaps whenever :
*
*                       (1) A TCP connection's Transport Receive Queue is initially non-empty;
*                              OR
*                       (2) A TCP connection's Transport Receive Queue's head segment's sequence number
*                           does NOT equal the TCP connection's next expected receive   sequence number.
*
*                   (c) However, since a TCP connection's next expected receive sequence numbers are NOT
*                       updated until both of the TCP connection's transport & application receive queues
*                       have been handled (see 'NetTCP_RxPktConnHandlerRxQ_AppData()  Note #1a3'), the
*                       transmission of any immediate acknowledgement MUST follow the handling of BOTH
*                       of the TCP connection's receive queues.
*
*                       See also 'NetTCP_RxPktConnHandlerRxQ_AppData()  Notes #1a3 & #4'.
*
*               (6) RFC #793, Section 3.7 'Data Communication : Managing the Window' states that "the window 
*                   sent in each segment indicates the range of sequence numbers the sender of the window 
*                   (the data receiver) is currently prepared to accept.  There is an assumption that this 
*                   is related to the currently available data buffer space available for this connection
*                   ... One strategy would be to ... [update the] information when the window" changes.
*
*                   See also 'NetTCP_RxAppData()                 Note #7',
*                            'NetTCP_RxPktConnHandlerRxQ_Sync()  Note #5',
*                          & 'NetTCP_RxConnWinSizeHandler()      Note #2a'.
*********************************************************************************************************
*/
/*$PAGE*/
static  void  NetTCP_RxPktConnHandlerRxQ_Conn (NET_TCP_CONN  *pconn,
                                               NET_BUF       *pbuf,
                                               NET_BUF_HDR   *pbuf_hdr,
                                               NET_ERR       *perr)
{
#if (NET_ERR_CFG_ARG_CHK_DBG_EN == DEF_ENABLED)
    NET_TCP_SEQ_CODE   seq_code;
#endif
    NET_BUF           *pbuf_q;
    NET_BUF           *pbuf_q_head;
    NET_BUF           *pbuf_q_prev;
    NET_BUF           *pbuf_q_next;
    NET_BUF_HDR       *pbuf_q_hdr;
    NET_BUF_HDR       *pbuf_q_hdr_head;
    NET_BUF_HDR       *pbuf_q_hdr_next;
    NET_TCP_SEQ_NBR    seq_nbr;
    NET_TCP_SEQ_NBR    seq_nbr_next;
    NET_TCP_SEQ_NBR    seq_nbr_dup;
    NET_TCP_SEQ_NBR    seq_nbr_delta;
    NET_TCP_SEQ_NBR    seq_nbr_win;
    CPU_BOOLEAN        seq_srch_done;
    CPU_BOOLEAN        seq_unordered_prev;
    CPU_BOOLEAN        seq_unordered_cur;
    CPU_BOOLEAN        seq_unordered;


                                                                /* ----------- UPDATE TCP CONN RX SEQ NBRS ------------ */
    if (pconn->ConnState == NET_TCP_CONN_STATE_SYNC_TXD) {
#if (NET_ERR_CFG_ARG_CHK_DBG_EN == DEF_ENABLED)
        switch (pconn->RxQ_State) {
            case NET_TCP_RX_Q_STATE_CONN_CLOSED:
                 break;


            case NET_TCP_RX_Q_STATE_NONE:
            case NET_TCP_RX_Q_STATE_CLOSED:
            case NET_TCP_RX_Q_STATE_CONN_SYNC:
            case NET_TCP_RX_Q_STATE_CONN:
            case NET_TCP_RX_Q_STATE_CONN_CLOSING:
            default:
                *perr = NET_TCP_ERR_INVALID_CONN_STATE;
                 return;                                        /* Prevent 'break NOT reachable' compiler warning.      */
        }
#endif
                                                                /* Init SYN-SENT state (see Notes #2c & #2d2).          */
        pconn->RxSeqNbrSync = (NET_TCP_SEQ_NBR) pbuf_hdr->TCP_SeqNbr;
        pconn->RxSeqNbrNext = (NET_TCP_SEQ_NBR)(pbuf_hdr->TCP_SeqNbr + pbuf_hdr->TCP_SegLen);
        pconn->RxQ_State    =  NET_TCP_RX_Q_STATE_CONN_SYNC;


    } else {
        switch (pconn->RxQ_State) {
            case NET_TCP_RX_Q_STATE_CONN_SYNC:
                 break;


            case NET_TCP_RX_Q_STATE_CONN:
                                                                /* Chk TCP conn closing (see Note #2e).                 */
                 if (pbuf_hdr->TCP_SegClose == DEF_YES) {
                     pconn->RxSeqNbrLast  = (NET_TCP_SEQ_NBR)(pbuf_hdr->TCP_SeqNbr + pbuf_hdr->TCP_SegLen);
                     pconn->RxSeqNbrClose = (NET_TCP_SEQ_NBR)(pconn->RxSeqNbrLast  - NET_TCP_SEG_LEN_CLOSE);
                     pconn->RxQ_State     =  NET_TCP_RX_Q_STATE_CONN_CLOSING;
                 }
                                                                /* 'break' intentionally omitted; do NOT move from the  */
                                                                /* .. following case : 'NET_TCP_RX_Q_STATE_CONN_CLOSED'.*/

            case NET_TCP_RX_Q_STATE_CONN_CLOSED:
            case NET_TCP_RX_Q_STATE_CONN_CLOSING:
#if (NET_ERR_CFG_ARG_CHK_DBG_EN == DEF_ENABLED)
                                                                /* Chk valid rx'd seq nbr.                              */
                 seq_code = NetTCP_RxPktConnIsValidSeq(pconn, pbuf_hdr, perr);
                 if (*perr != NET_TCP_ERR_NONE) {
                      return;
                 }
                 if (seq_code != NET_TCP_CONN_RX_SEQ_VALID) {
                    *perr = NET_TCP_ERR_CONN_SEQ_INVALID;
                     return;
                 }
#endif
                 break;


            case NET_TCP_RX_Q_STATE_NONE:
            case NET_TCP_RX_Q_STATE_CLOSED:
            default:
                *perr = NET_TCP_ERR_CONN_DATA_INVALID;
                 return;                                        /* Prevent 'break NOT reachable' compiler warning.      */
        }
    }


/*$PAGE*/
    if (pbuf_hdr->TCP_SegLenData < 1) {                         /* If seg data len < 1,             AND ...             */
                                                                /* ... NOT in rx conn closing state OR  ...             */
        if ((pconn->RxQ_State       != NET_TCP_RX_Q_STATE_CONN_CLOSING) ||
            (pbuf_hdr->TCP_SegClose != DEF_YES)) {              /* ... fin/close NOT rx'd;              ...             */
            *perr = NET_TCP_ERR_CONN_DATA_NONE;                 /* ... rtn data  NOT avail.                             */
             return;
        }                                                       /* Else seq & handle closing-ctrl seg.                  */
    }


                                                                /* ------- INSERT SEG INTO SEQ'D TRANSPORT RX Q ------- */
    pbuf_q             = (NET_BUF *)pconn->RxQ_Transport_Tail;  /* Start seq insert alg from rx Q tail (see Note #3b).  */
    pbuf_q_next        = (NET_BUF *)0;
    seq_srch_done      =  DEF_NO;
                                                                /* Chk init'l rx Q seq order (see Note #5b1).           */
    seq_unordered_prev = (pconn->RxQ_Transport_Head != (NET_BUF *)0)
                       ?  DEF_YES : DEF_NO;

    while (seq_srch_done == DEF_NO) {                           /* Srch rx Q to insert rx'd seg into seq nbr position.  */
        if (pbuf_q != (NET_BUF *)0) {                           /* While NOT @ rx Q head, chk if seg ...                */

            pbuf_q_hdr    = (NET_BUF_HDR   *)&pbuf_q->Hdr;
            pbuf_q_prev   = (NET_BUF       *) pbuf_q_hdr->PrevPrimListPtr;
                                                                /* ... before or after cur  rx Q seg (see Note #2a1).   */
            seq_nbr_next  = (NET_TCP_SEQ_NBR) pbuf_q_hdr->TCP_SeqNbr;
            seq_nbr       = (NET_TCP_SEQ_NBR)(pbuf_hdr->TCP_SeqNbr   + 1);
            seq_nbr_delta = (NET_TCP_SEQ_NBR)(seq_nbr_next           - seq_nbr);
            seq_nbr_win   = (NET_TCP_SEQ_NBR) pconn->RxWinSizeCfgdActual;

            if (seq_nbr_delta < seq_nbr_win) {                  /* If seg's seq nbr < cur rx Q's seq nbr (see Note #4b1)*/
                                                                /* ... adv to prev rx Q seg; but chk ...                */
                                                                /* ... for dup seqs in next rx Q seg.                   */
                seq_nbr_next  = (NET_TCP_SEQ_NBR)(pbuf_hdr->TCP_SeqNbr   + pbuf_hdr->TCP_SegLen);
                seq_nbr       = (NET_TCP_SEQ_NBR)(pbuf_q_hdr->TCP_SeqNbr + 1);
                seq_nbr_delta = (NET_TCP_SEQ_NBR)(seq_nbr_next           - seq_nbr);
                seq_nbr_win   = (NET_TCP_SEQ_NBR) pbuf_hdr->TCP_SegLen;

                if (seq_nbr_delta < seq_nbr_win) {              /* If seg overlaps next rx Q seqs (see Note #4c1), ...  */

                    seq_nbr_dup   = seq_nbr_delta + 1;          /* ... trim dup seqs from seg     (see Note #2a3); ...  */
                    if (pbuf_hdr->TCP_SegLenData  > (CPU_INT16U)seq_nbr_dup) {
                        pbuf_hdr->TCP_SegLenData -= (CPU_INT16U)seq_nbr_dup;
                        pbuf_hdr->TCP_SegLen     -= (CPU_INT16U)seq_nbr_dup;

                    } else {                                    /* ... else discard ALL dup seqs  (see Note #2a2).      */
                       *perr = NET_TCP_ERR_CONN_DATA_DUP;
                        return;
                    }
                }
                                                                /* Adv to prev rx Q seg.                                */
                pbuf_q_next = (NET_BUF *)pbuf_q;
                pbuf_q      = (NET_BUF *)pbuf_q_prev;


            } else {                                            /* Else insert seg between cur/next rx Q segs.          */
                                                                /* Chk for dup seqs in cur rx Q seg.                    */
                seq_nbr_next  = (NET_TCP_SEQ_NBR)(pbuf_q_hdr->TCP_SeqNbr + pbuf_q_hdr->TCP_SegLen);
                seq_nbr       = (NET_TCP_SEQ_NBR)(pbuf_hdr->TCP_SeqNbr   + 1);
                seq_nbr_delta = (NET_TCP_SEQ_NBR)(seq_nbr_next           - seq_nbr);
                seq_nbr_win   = (NET_TCP_SEQ_NBR) pbuf_q_hdr->TCP_SegLen;

                if (seq_nbr_delta < seq_nbr_win) {              /* If seg overlaps prev'ly rx'd seqs (see Note #4c2),   */
                    seq_nbr_dup   = seq_nbr_delta + 1;          /* ... trim dup seqs from seg    (see Note #2a3); ...   */
                    if (pbuf_hdr->TCP_SegLenData  > (CPU_INT16U)seq_nbr_dup) {
                        pbuf_hdr->TCP_SegLenData -= (CPU_INT16U)seq_nbr_dup;
                        pbuf_hdr->TCP_SegLen     -= (CPU_INT16U)seq_nbr_dup;
                        pbuf_hdr->TCP_SeqNbr      = (CPU_INT32U)seq_nbr_next;

                    } else {                                    /* ... else discard ALL dup seqs (see Note #2a2).       */
                       *perr = NET_TCP_ERR_CONN_DATA_DUP;
                        return;
                    }
                }

                seq_srch_done = DEF_YES;
            }

/*$PAGE*/
        } else {                                                /* Else if @ head of rx Q, entire rx Q srch'd; ...      */
                                                                /* ... chk for dup seqs prior to TCP conn's    ...      */
                                                                /* ... next expected rx octet.                          */
            seq_nbr_next  = (NET_TCP_SEQ_NBR) pconn->RxSeqNbrNext;
            seq_nbr       = (NET_TCP_SEQ_NBR)(pbuf_hdr->TCP_SeqNbr + 1);
            seq_nbr_delta = (NET_TCP_SEQ_NBR)(seq_nbr_next         - seq_nbr);
            seq_nbr_win   = (NET_TCP_SEQ_NBR) pbuf_hdr->TCP_SegLen;

            if (seq_nbr_delta < seq_nbr_win) {                  /* If seg overlaps prev'ly rx'd seqs (see Note #4b2),   */
                seq_nbr_dup   = seq_nbr_delta + 1;              /* ... trim dup seqs from seg    (see Note #2a3);       */
                if (pbuf_hdr->TCP_SegLenData  > (CPU_INT16U)seq_nbr_dup) {
                    pbuf_hdr->TCP_SegLenData -= (CPU_INT16U)seq_nbr_dup;
                    pbuf_hdr->TCP_SegLen     -= (CPU_INT16U)seq_nbr_dup;
                    pbuf_hdr->TCP_SeqNbr      = (CPU_INT32U)seq_nbr_next;

                } else {                                        /* ... else discard ALL dup seqs (see Note #2a2).       */
                   *perr = NET_TCP_ERR_CONN_DATA_DUP;
                    return;
                }
            }

            seq_srch_done = DEF_YES;
        }
    }

                                                                /* Insert rx'd seg between cur/next rx Q segs.          */
    pbuf_hdr->PrevPrimListPtr = (void *)pbuf_q;
    if (pbuf_q != (NET_BUF *)0) {                               /* If avail, insert rx'd seg after  cur  rx Q seg.      */
        pbuf_q_hdr->NextPrimListPtr = (void    *)pbuf;
    } else {                                                    /* Else      insert rx'd seg @ rx Q head.               */
        pconn->RxQ_Transport_Head   = (NET_BUF *)pbuf;
    }

    pbuf_hdr->NextPrimListPtr = (void *)pbuf_q_next;
    if (pbuf_q_next != (NET_BUF *)0) {                          /* If avail, insert rx'd seg before next rx Q seg.      */
        pbuf_q_hdr_next                  = (NET_BUF_HDR *)&pbuf_q_next->Hdr;
        pbuf_q_hdr_next->PrevPrimListPtr = (void        *) pbuf;
    } else {                                                    /* Else      insert rx'd seg @ rx Q tail.               */
        pconn->RxQ_Transport_Tail        = (NET_BUF     *) pbuf;
    }


                                                                /* Chk rx'd out-of-order seg(s) [see Note #5a].         */
    if (pconn->RxQ_Transport_Head != (NET_BUF *)0) {
        pbuf_q_head        =  (NET_BUF     *) pconn->RxQ_Transport_Head;
        pbuf_q_hdr_head    =  (NET_BUF_HDR *)&pbuf_q_head->Hdr;
                                                                /* Chk cur rx Q seq order       (see Note #5b2).        */
        seq_unordered_cur  = ((NET_TCP_SEQ_NBR)pbuf_q_hdr_head->TCP_SeqNbr
                          !=  (NET_TCP_SEQ_NBR)pconn->RxSeqNbrNext)
                           ?   DEF_YES : DEF_NO;
    }

    seq_unordered = ((seq_unordered_prev == DEF_YES) ||
                     (seq_unordered_cur  == DEF_YES)) ? DEF_YES : DEF_NO;

    if (seq_unordered != DEF_NO) {                              /* If out-of-order seg(s) rx'd   (see Note #5a) ...     */
        if (pconn->RxQ_State != NET_TCP_RX_Q_STATE_CONN_SYNC) { /* ... in non-sync state,                       ...     */
                                                                /* ... req immed TCP conn ack tx (see Note #5c).        */
            pbuf_hdr->TCP_SegAckTxReqCode = NET_TCP_CONN_TX_ACK_IMMED;
        }
    }


                                                                /* ----------- UPDATE TCP CONN RX WIN SIZE ------------ */
                                                                /* Dec TCP conn's rx win size (see Note #6).            */
    NetTCP_RxConnWinSizeHandler((NET_TCP_CONN   *)pconn,
                                (NET_BUF_HDR    *)pbuf_hdr,
                                (NET_TCP_WIN_SIZE)pbuf_hdr->TCP_SegLenData,
                                (NET_TCP_WIN_CODE)NET_TCP_CONN_RX_WIN_DEC);


   *perr = NET_TCP_ERR_CONN_DATA_VALID;
}


/*$PAGE*/
/*
*********************************************************************************************************
*                                NetTCP_RxPktConnHandlerRxQ_AppData()
*
* Description : (1) (a) Handle TCP connection's application receive queue ... :
*
*                       (1) Remove segments from  TCP connection's transport   receive queue    See Note #3b1B
*                       (2) Update TCP connection transport receive queue
*                       (3) Update TCP connection receive sequence numbers
*                       (4) Move   segments onto  TCP connection's application receive queue    See Note #2
*                       (5) Update TCP connection receive window                                See Note #6
*
*                   (b) ... for the following connected states :
*
*                       (1) SYN-RECEIVED                                                        See Note #1bA
*                       (2) SYN-SENT                                                            See Note #1bA
*                       (3) ESTABLISHED                                                         See Note #1bB
*                       (4) FIN-WAIT-1                                                          See Note #1bB
*                       (5) FIN-WAIT-2                                                          See Note #1bB
*                       (6) CLOSING                                                             See Note #1bC
*                       (7) TIME-WAIT                                                           See Note #1bC
*                       (8) CLOSE-WAIT                                                          See Note #1bC
*                       (9) LAST-ACK                                                            See Note #1bC
*
*
*                           (A) For synchronization-to-connected state transitions, segments are queued to
*                               the TCP connection's transport receive queue, but NOT to the TCP connection's
*                               application receive queue, until the application layer is signaled that the
*                               transport layer connection is complete.
*
*                               See also 'NetTCP_RxPktConnHandlerSyncRxd()  Note #1c1'
*                                      & 'NetTCP_RxPktConnHandlerSyncTxd()  Note #1c1'.
*
*                           (B) For connected states, segments are queued to the TCP connection's application
*                               receive queue as appropriate (see Notes #2 & #3b).
*
*                           (C) For closing states; closing segments are queued to the TCP connection's
*                               transport &/or application receive queue(s) as for connected states.
*
*
* Argument(s) : pconn       Pointer to a TCP connection.
*               -----       Argument validated in NetTCP_RxPktConnHandler().
*
*               perr        Pointer to variable that will receive the return error code from this function :
*
*                               NET_TCP_ERR_NONE                    TCP connection's application receive queue
*                                                                       successfully handled.
*                               NET_TCP_ERR_INVALID_CONN_STATE      Invalid TCP connection receive queue state.
*
*                                                                   ---- RETURNED BY NetOS_TCP_RxQ_Signal() : ----
*                               NET_TCP_ERR_RX_Q_FULL               TCP connection receive queue full.
*                               NET_TCP_ERR_RX_Q_SIGNAL_FAULT       TCP connection receive queue signal fault.
*
*                                                                   ----- RETURNED BY NetOS_TCP_RxQ_Clr() : ------
*                               NET_TCP_ERR_RX_Q_SIGNAL_CLR         TCP connection receive queue clear failed.
*
* Return(s)   : none.
*
* Caller(s)   : NetTCP_RxPktConnHandlerSeg(),
*               NetTCP_RxPktConnHandlerSyncRxd(),
*               NetTCP_RxPktConnHandlerSyncTxd().
*$PAGE*
* Note(s)     : (2) TCP segments with receive data that are available & ready to be read by the application
*                   layer are linked in a TCP connection's application receive queue.
*
*                   (a) Received TCP segments are moved from the doubly-linked Transport Receive Queue,
*                       sorted by their sequence number(s), onto the Application Receive Queue.
*
*                       (1) 'RxQ_App_Head' points to the head of the Application Receive Queue;
*                           'RxQ_App_Tail' points to the tail of the Application Receive Queue.
*
*                       (2) Segment buffers' 'PrevPrimListPtr' & 'NextPrimListPtr'  doubly-link each
*                           segment to form the Application Receive Queue.
*
*                       (3) Fragmented segment buffer's 'PrevBufPtr' & 'NextBufPtr' doubly-link each
*                           fragmented segment (see also 'net_ip.c  NetIP_RxPktFragReasm()  Note #2b3').
*
*                   (b) TCP segments are appended in sequence order from the head of a TCP connection's
*                       Transport Receive Queue to the tail of the TCP connection's Application Receive
*                       Queue.
*
*                       See also 'NetTCP_RxPktConnHandlerRxQ_Conn()  Note #3'.
*
*                   (c) Application data is read from segments starting from the head of the Application
*                       Receive Queue.  Segments that are read by the application layer are removed from
*                       the Application Receive Queue.
*
*
*                                      |                                               |
*                                      |<- TCP Connection Application Receive Queue -->|
*                                      |                (see Note #2)                  |
*
*                                 Segments Read by                         Segments Appended to
*                                 Application Layer                      Application Receive Queue
*                                 starting at head                           starting at tail
*                                  (see Note #2c)                             (see Note #2b)
*
*                                         |        NextPrimListPtr                  |
*                                         |        (see Note #2a2)                  |
*                                         v                   |                     v
*                                                             |
*                        Head of       -------       -------  v    -------       -------   (see Note #2a1)
*                        Receive  ---->|     |------>|     |------>|     |------>|     |
*                         Queue        |     |       |     |       |     |       |     |       Tail of
*                                      |     |<------|     |<------|     |<------|     |<----  Receive
*                    (see Note #2a1)   |     |       |     |  ^    |     |       |     |        Queue
*                                      |     |       |     |  |    |     |       |     |
*                                      -------       -------  |    -------       -------
*                                        | ^                  |      | ^
*                                        | |       PrevPrimListPtr   | |
*                                        v |       (see Note #2a2)   v |
*                                      -------                     -------
*                                      |     |                     |     |
*                                      |     |                     |     |
*                                      |     |                     |     |
*                                      |     |                     |     |
*                                      |     |                     |     |
*                                      -------                     -------
*                                        | ^                         | ^
*                        NextBufPtr ---> | | <--- PrevBufPtr         | |
*                     (see Note #2a3)    v |   (see Note #2a3)       v |
*                                      -------                     -------
*                                      |     |                     |     |
*                                      |     |                     |     |
*                                      |     |                     -------
*                                      |     |
*                                      |     |
*                                      -------
*
*$PAGE*
*               (3) (a) (1) RFC #793, Section 3.8 'Interfaces : User/TCP Interface : TCP User Commands :
*                           Receive' states that :
*
*                           (A) "If enough data arrive [sic] to fill the buffer before a PUSH is seen,
*                                the PUSH flag will not be set in the response to the RECEIVE.  The
*                                buffer will be filled with as much data as it can hold."
*
*                           (B) "If the PUSH is seen before the buffer is filled the buffer will be
*                                returned partially filled and PUSH indicated."
*
*                               See Notes #3b1B & #3b1B.
*
*                       (2) RFC #1122, Section 4.2.2.2 states that :
*
*                           (A) (1) "At the receiver, the PSH bit forces buffered data to be delivered to
*                                    the application (even if less than a full buffer has been received)."
*
*                               (2) (a) "Conversely, the lack of a PSH bit can be used to avoid unnecessary
*                                        wakeup calls to the application process; this can be an important
*                                        performance optimization for large timesharing hosts."
*
*                                   (b) "When a series of segments is received without the PSH bit, a TCP
*                                        MAY queue the data internally without passing it to the receiving
*                                        application."
*
*                           (B) (1) "Passing the PSH bit to the receiving application allows an ...
*                                    optimization within the application."
*
*                               (2) "RFC-793 ... erroneously implies that a received PSH flag must be passed
*                                    to the application layer.  Passing a received PSH flag to the application
*                                    layer is now OPTIONAL."
*
*                           (C) "The PSH bit is not a record marker and is independent of segment boundaries."
*
*                   (b) (1) (A) (1) Stevens, TCP/IP Illustrated, Volume 1, 8th Printing, Section 20.5, Page 284
*                                   states that "Berkeley-derived implementations ignore a received PUSH flag
*                                   because they normally never delay the delivery of received data to the
*                                   application".
*
*                               (2) Therefore, for TCP connections in any connected state, received TCP segment
*                                   data is made available to the application receive queue as soon as it is
*                                   enqueued to the application receive queue.
*
*                           (B) Thus, for TCP connections in any connected state, TCP segments are moved from
*                               a TCP connection's transport receive queue to its application receive queue
*                               whenever the transport receive queue's enqueued TCP segments are consecutively
*                               sequenced starting from the TCP connection's next expected receive octet.
*
*                       (2) Thus, TCP application-receive PUSH feature is obsoleted & NOT implemented.
*
*                       See also 'NetTCP_TxConnAck()  Note #4a4'.
*
*               (4) A TCP connection's next expected receive sequence numbers are NOT updated until
*                   both of the TCP connection's transport & application receive queues have been
*                   handled.  Thus, the transmission of any TCP connection data or acknowledgements
*                   MUST follow the handling of BOTH of the TCP connection's receive queues.
*
*                   See also Note #1a3 & 'NetTCP_RxPktConnHandlerRxQ_Conn()  Note #5c'.
*
*               (5) Stream-type connections receive all data octets in one or more non-distinct
*                   packets.  In other words, the application data is NOT bounded by any specific
*                   packet(s); rather, it is contiguous & sequenced from one packet to the next.
*
*                   Therefore, the TCP connection receive queue is signaled ONLY when data is received
*                   for a connection where data was previously unavailable.
*$PAGE*
*               (6) (a) RFC #793, Section 3.7 'Data Communication : Managing the Window' states that
*                       "the window sent in each segment indicates the range of sequence numbers the
*                       sender of the window (the data receiver) is currently prepared to accept.
*                       There is an assumption that this is related to the currently available data
*                       buffer space available for this connection".
*
*                   (b) (1) A TCP connection's advertised receive window MUST NEVER be decreased to zero
*                           if NO receive data is available & ready to be read by the application layer.
*
*                           In other words, if NO received data starting from the next expected receive
*                           sequence number(s) is queued, then NO data is available to be read by the
*                           application layer.  Therefore, the receive window size MUST NOT be decreased
*                           to zero, otherwise the receive window would deadlock since the application
*                           layer would NOT be able to read & extract any data from the receive window
*                           & the TCP connection would NOT be able to receive any more data into the
*                           receive window.
*
*                       (2) (A) In case the advertised receive window size has decreased to zero, ...
*                           (B) & NO data is available to be read by the application layer;       ...
*                           (C) then remove & free the last received TCP segment from the tail
*                                   of the TCP connection's transport receive queue,              ...
*                           (D) & increase the advertised receive window size by this freed
*                                   segment's length.
*
*                           This is permissible because removing the last received TCP segment from
*                           the TCP connection's transport receive queue does NOT interfere with TCP
*                           communications since the next expected receive sequence number(s) remains
*                           unchanged.
*
*                       (3) (A) A TCP connection's receive window SHOULD NOT become deadlocked during 
*                               correct operation of TCP communication.  However, these TCP receive
*                               zero-sized window cases are included as an extra precaution in the 
*                               case that TCP communication is incorrectly handled &/or corrupted.
*
*                           (B) A deadlocked TCP connection with a receive window of zero-size with 
*                               absolutely NO buffers queued in the TCP connection's transport receive 
*                               queue SHOULD NEVER occur.  However, the TCP receive window size reset
*                               case is included as an extra precaution in the case that a TCP connection 
*                               receive window is incorrectly handled &/or corrupted.
*
*                       See also 'NetTCP_RxConnWinSizeHandler()  Note #2a1'.
*********************************************************************************************************
*/

static  void  NetTCP_RxPktConnHandlerRxQ_AppData (NET_TCP_CONN  *pconn,
                                                  NET_ERR       *perr)
{
    NET_BUF          *pbuf;
    NET_BUF          *pbuf_head;
    NET_BUF          *pbuf_tail;
    NET_BUF          *pbuf_q_head;
    NET_BUF          *pbuf_q_tail;
    NET_BUF_HDR      *pbuf_hdr;
    NET_BUF_HDR      *pbuf_hdr_head;
    NET_BUF_HDR      *pbuf_hdr_tail;
    NET_BUF_HDR      *pbuf_hdr_q_head;
    NET_BUF_HDR      *pbuf_hdr_q_tail;
    NET_TCP_SEQ_NBR   seq_nbr;
    NET_TCP_SEQ_NBR   seq_nbr_inc;
    CPU_BOOLEAN       done;


/*$PAGE*/
                                                                    /* ---- REMOVE RX'D SEG(S) FROM TRANSPORT RX Q ---- */
    switch (pconn->RxQ_State) {                                     /* Cfg starting seq nbr.                            */
        case NET_TCP_RX_Q_STATE_CONN_SYNC:
             if (pconn->RxQ_Transport_Head == (NET_BUF *)0) {       /* If   sync seg NOT      q'd with rx'd data, ...   */
                 seq_nbr = pconn->RxSeqNbrNext;                     /* ...  start rx seq move from next rx seq.         */
             } else {                                               /* Else sync seg possibly q'd with rx'd data.       */
                 pbuf_q_head     = (NET_BUF     *) pconn->RxQ_Transport_Head;
                 pbuf_hdr_q_head = (NET_BUF_HDR *)&pbuf_q_head->Hdr;
                                                                    /* If sync seg q'd,                             ... */
                 seq_nbr         = (pbuf_hdr_q_head->TCP_SegSync == DEF_YES)
                                 ?  pconn->RxSeqNbrSync             /* ...      start rx seq move from sync rx seq; ... */
                                 :  pconn->RxSeqNbrNext;            /* ... else start rx seq move from next rx seq.     */
             }

             pconn->RxQ_State = NET_TCP_RX_Q_STATE_CONN;
             break;


        case NET_TCP_RX_Q_STATE_CONN:
        case NET_TCP_RX_Q_STATE_CONN_CLOSING:
             seq_nbr = pconn->RxSeqNbrNext;
             break;


        case NET_TCP_RX_Q_STATE_CONN_CLOSED:
            *perr = NET_TCP_ERR_NONE;
             return;                                                /* Prevent 'break NOT reachable' compiler warning.  */


        case NET_TCP_RX_Q_STATE_NONE:
        case NET_TCP_RX_Q_STATE_CLOSED:
        default:
            *perr = NET_TCP_ERR_INVALID_CONN_STATE;
             return;                                                /* Prevent 'break NOT reachable' compiler warning.  */
    }

    pbuf      = (NET_BUF *)pconn->RxQ_Transport_Head;
    pbuf_head = (NET_BUF *)pbuf;
    pbuf_tail = (NET_BUF *)0;
    done      =  DEF_NO;

    while (done == DEF_NO) {                                        /* Srch for ALL segs with consecutive seq nbrs ...  */
                                                                    /* ... from next expected rx seq.                   */
        if (pbuf != (NET_BUF *)0) {
            pbuf_hdr = (NET_BUF_HDR *)&pbuf->Hdr;
            if (pbuf_hdr->TCP_SeqNbr == seq_nbr) {                  /* If seq consecutive from next expected rx seq, .. */
                seq_nbr_inc  = (NET_TCP_SEQ_NBR)pbuf_hdr->TCP_SegLen;
                seq_nbr     += (NET_TCP_SEQ_NBR)seq_nbr_inc;        /* ..               update next expected rx seq.    */
                pbuf_tail    = (NET_BUF *)pbuf;
                pbuf         = (NET_BUF *)pbuf_hdr->NextPrimListPtr;
            } else {
                done = DEF_YES;
            }
        } else {
            done = DEF_YES;
        }
    }


                                                                    /* -------- UPDATE TCP CONN TRANSPORT RX Q -------- */
    if (pbuf != (NET_BUF *)0) {                                     /* If transport rx Q NOT empty, update ..           */
                                                                    /* .. transport rx Q head.                          */
        pbuf_hdr->PrevPrimListPtr = (void    *)0;
        pconn->RxQ_Transport_Head = (NET_BUF *)pbuf;

    } else {                                                        /* Else clr transport rx Q.                         */
        pconn->RxQ_Transport_Head = (NET_BUF *)0;
        pconn->RxQ_Transport_Tail = (NET_BUF *)0;
    }


    pconn->RxSeqNbrNext = seq_nbr;                                  /* Update next expected rx seq.                     */
    if (pconn->RxQ_State == NET_TCP_RX_Q_STATE_CONN_CLOSING) {
        if (pconn->RxSeqNbrNext == pconn->RxSeqNbrLast) {           /* If last seq rx'd, close TCP conn rx.             */
            pconn->RxQ_State = NET_TCP_RX_Q_STATE_CONN_CLOSED;
        }
    }


/*$PAGE*/
                                                                    /* -------- MOVE RX'D SEG(S) ONTO APP RX Q -------- */
    if (pbuf_tail != (NET_BUF *)0) {                                /* If avail, move rx'd seg(s) from transport rx Q   */
                                                                    /* ... onto app rx Q (see Note #3b1B).              */
        pbuf_hdr_head                  = (NET_BUF_HDR *)&pbuf_head->Hdr;
        pbuf_hdr_tail                  = (NET_BUF_HDR *)&pbuf_tail->Hdr;
        pbuf_hdr_head->PrevPrimListPtr = (void        *) pconn->RxQ_App_Tail;
        pbuf_hdr_tail->NextPrimListPtr = (void        *) 0;

        if (pconn->RxQ_App_Tail != (NET_BUF *)0) {                  /* If app rx Q NOT empty, ...                       */
                                                                    /* ... append seg(s) @ Q tail (see Note #2b).       */
            pbuf_q_tail                      = (NET_BUF     *) pconn->RxQ_App_Tail;
            pbuf_hdr_q_tail                  = (NET_BUF_HDR *)&pbuf_q_tail->Hdr;
            pbuf_hdr_q_tail->NextPrimListPtr = (void        *) pbuf_head;
            pconn->RxQ_App_Tail              = (NET_BUF     *) pbuf_tail;

        } else {                                                    /* Else add seg(s) to empty app rx Q ...            */
            pconn->RxQ_App_Head              = (NET_BUF     *) pbuf_head;
            pconn->RxQ_App_Tail              = (NET_BUF     *) pbuf_tail;

            NetOS_TCP_RxQ_Signal(pconn->ID, perr);                  /* ...   & signal non-empty app rx Q (see Note #5). */
            if (*perr != NET_TCP_ERR_NONE) {
                 return;
            }
        }


    } else {                                                        /* --------------- CHK RX WIN SIZE ---------------- */
        if (pconn->RxWinSizeActual < 1) {                           /* If avail rx win size zero  (see Note #6b2A)  ... */
            if (pconn->RxQ_App_Head == (NET_BUF *)0) {              /* ... & NO avail app rx data (see Note #6b2B); ... */
                                                                    /* ... inc rx win size (see Note #6b).              */
                pbuf = pconn->RxQ_Transport_Tail;
                if (pbuf != (NET_BUF *)0) {                         /* If transport rx Q NOT empty;              ...    */
                                                                    /* ... remove last q'd seg (see Note #6b2C), ...    */
                    pbuf_hdr    = (NET_BUF_HDR *)&pbuf->Hdr;
                    pbuf_q_tail = (NET_BUF     *) pbuf_hdr->PrevPrimListPtr;
                    if (pbuf_q_tail != (NET_BUF *)0) {
                        pconn->RxQ_Transport_Tail        = (NET_BUF     *) pbuf_q_tail;
                        pbuf_hdr_q_tail                  = (NET_BUF_HDR *)&pbuf_q_tail->Hdr;
                        pbuf_hdr_q_tail->NextPrimListPtr = (void        *) 0;

                    } else {
                        pconn->RxQ_Transport_Head        = (NET_BUF     *) 0;
                        pconn->RxQ_Transport_Tail        = (NET_BUF     *) 0;

                        NetOS_TCP_RxQ_Clr(pconn->ID, perr);
                        if (*perr != NET_TCP_ERR_NONE) {
                             NetTCP_ConnClose((NET_TCP_CONN     *)pconn,
                                              (NET_BUF_HDR      *)0,
                                              (CPU_BOOLEAN       )pconn->ConnCloseAppFlag,
                                              (NET_TCP_CLOSE_CODE)NET_TCP_CONN_CLOSE_ALL);
                             return;
                        }
                    }
                                                                    /* ... inc win size by seg's len (see Note #6b2D),  */
                    NetTCP_RxConnWinSizeHandler((NET_TCP_CONN   *)pconn,
                                                (NET_BUF_HDR    *)0,
                                                (NET_TCP_WIN_SIZE)pbuf_hdr->TCP_SegLenData,
                                                (NET_TCP_WIN_CODE)NET_TCP_CONN_RX_WIN_SET);

                    NetTCP_RxPktFree(pbuf);                         /* ... & free seg (see Note #6b2C).                 */

                } else {                                            /* Else reset TCP conn rx win size (see Note #6b3B).*/
                    NetTCP_RxConnWinSizeHandler((NET_TCP_CONN   *)pconn,
                                                (NET_BUF_HDR    *)0,
                                                (NET_TCP_WIN_SIZE)0,
                                                (NET_TCP_WIN_CODE)NET_TCP_CONN_RX_WIN_RESET);
                }
            }
        }
    }


   *perr = NET_TCP_ERR_NONE;
}


/*$PAGE*/
/*
*********************************************************************************************************
*                                NetTCP_RxPktConnHandlerTxWinRemote()
*
* Description : Handle TCP connection's transmit remote host window update.
*
* Argument(s) : pconn       Pointer to a TCP connection.
*               -----       Argument validated in NetTCP_RxPktConnHandler().
*
*               ack_code    Indicates the received segment's acknowledgement condition :
*               --------
*                               NET_TCP_CONN_RX_ACK_VALID           Received acknowledgement number is
*                                                                       valid for the TCP connection.
*
*                               NET_TCP_CONN_RX_ACK_DUP             Received acknowledgement number is a
*                                                                                duplicate for the TCP
*                                                                       connection.
*
*                               NET_TCP_CONN_RX_ACK_PREV            Received acknowledgement number is a
*                                                                       previous duplicate for the TCP
*                                                                       connection.
*
*                           Argument validated in NetTCP_RxPktConnHandler() functions.
*
*               pbuf_hdr    Pointer to network buffer header that received TCP packet.
*               --------    Argument validated in NetTCP_Rx().
*
*               perr        Pointer to variable that will receive the return error code from this function :
*
*                               NET_TCP_ERR_NONE                    TCP connection's transmit remote host
*                                                                       window successfully handled.
*                               NET_TCP_ERR_CONN_NOT_USED           TCP connection NOT currently used.
*                               NET_TCP_ERR_INVALID_CONN_STATE      Invalid TCP connection state.
*                               NET_TCP_ERR_INVALID_CONN_OP         Invalid TCP connection operation.
*
* Return(s)   : none.
*
* Caller(s)   : NetTCP_RxPktConnHandlerSeg().
*$PAGE*
* Note(s)     : (1) (a) (1) The following sections ... :
*
*                           (A) RFC #1122, Section 4.2.2.20.(c)
*                           (B) RFC #1122, Section 4.2.2.20.(f)
*
*                       (2) ... generalize that "when the connection enters ESTABLISHED STATE, the following
*                           variables should be set" :
*
*                           (A) SND.WND <- SEG.WND
*                           (B) SND.WL1 <- SEG.SEQ
*                           (C) SND.WL2 <- SEG.ACK
*
*                   (b) (1) RFC #793, Section 3.9 'Event Processing : SEGMENT ARRIVES : Check ACK Field :
*                           ESTABLISHED STATE' generalizes ...
*
*                           (A) ... that for the following connected states ... :
*
*                               (1) ESTABLISHED
*                               (2) FIN-WAIT-1
*                               (3) CLOSING
*                               (4) CLOSE-WAIT
*                               (5) LAST-ACK
*                                   (a) See 'NetTCP_RxPktConnHandlerLastAck()  Notes #2d2B'.
*
*                           (B) ... that "if SND.UNA < SEG.ACK <= SND.NXT, the send window should be updated" :
*
*                               (1) If ...
*
*                                   (a)  ((SND.WL1 <  SEG.SEQ)  or
*                                   (b)  ((SND.WL1 == SEG.SEQ)  and
*                                   (c)   (SND.WL2 <= SEG.ACK)) ...
*
*                               (2) ... [then] set ...
*
*                                   (a) SND.WND <- SEG.WND
*                                   (b) SND.WL1 <- SEG.SEQ
*                                   (c) SND.WL2 <- SEG.ACK
*
*                       (2) (A) RFC #1122, Section 4.2.2.20.(g) amends the transmit window update criteria 
*                               for the segment's acknowledgement to include SND.UNA : "The window should 
*                               updated if SND.UNA <= SEG.ACK <= SND.NXT."
*
*                               This permits received segments that exactly acknowledge the TCP connection's
*                               last acknowledged transmit sequence octet to update the transmit window in
*                               case the remote host's receive window size is increasing or decreasing.
*
*                           (B) However, it does NOT seem reasonable to update a TCP connection's remote
*                               transmit window for any received duplicate acknowledgement segment ; i.e. 
*                               an acknowledgement with the exact same sequence numbers & receive window 
*                               size advertisement.  Otherwise, each received duplicate acknowledgement 
*                               would incorrectly update the TCP connection's remote transmit window size.
*
*                               Therefore, it seems reasonable & is assumed that the transmit window MUST
*                               be updated for received acknowledgements that exactly acknowledge the TCP
*                               connection's last acknowledged transmit sequence octet, if & only if the
*                               received segment's receive window size advertisement has increased or
*                               decreased since the last received acknowledgement segment.
*
*                           See also RFC #1122, Section 4.2.2.16 & 'NetTCP_TxConnAck()  Note #4b1B1'.
*
*                   See also 'NetTCP_TxConnWinSizeHandlerCongCtrl()  Note #3'.
*$PAGE*
*               (2) RFC #793 does NOT provide nor suggest any logic to determine/handle sequence number
*                   comparisons for sequence number windows that overflow the sequence number space.
*
*                   (a) (1) For example, in order to update the transmit window, a received segment's
*                           acknowledgement value (SEG.ACK) MUST be greater than or equal to the last
*                           received acknowledgement number that updated the transmit window (SND.WL2)
*                           [see Note #1b1B1c] :
*
*                               (A) SEG.ACK >= SND.WL2
*
*                           However, if SEG.ACK overflows the sequence number space, it will be MUCH
*                           less than SND.WL2 until SND.WL2 also overflows :
*
*                               (B) SEG.ACK << SND.WL2
*
*                       (2) Therefore, in order to validate a received segment's acknowledgement number
*                           as valid for updating the TCP connection's transmit window, the following
*                           unsigned arithmetic comparison MUST be true :
*
*                               (A) (SND.NXT - SEG.ACK)  <=  (SND.NXT - SND.WL2)
*
*                   (b) (1) Alternatively, to update the transmit window, a received segment's  sequence
*                           number (SEG.SEQ) MUST be greater than or equal to the last received sequence
*                           number that updated the transmit window (SND.WL1) [see Notes #1b1B1a & #1b1B1b] :
*
*                               (A) SEG.SEQ >= SND.WL1
*
*                       (2) Therefore, in order to validate a received segment's sequence number as valid
*                           for updating the TCP connection's transmit window, the following unsigned
*                           arithmetic comparison MUST be true :
*
*                               (A) (RCV.NXT + RCV.WND) - SEG.SEQ  <  (RCV.NXT + RCV.WND) - SND.WL1
*
*                       See also 'NetTCP_RxPktConnIsValidAck()  Note #3'.
*********************************************************************************************************
*/
/*$PAGE*/
static  void  NetTCP_RxPktConnHandlerTxWinRemote (NET_TCP_CONN      *pconn,
                                                  NET_TCP_ACK_CODE   ack_code,
                                                  NET_BUF_HDR       *pbuf_hdr,
                                                  NET_ERR           *perr)
{
#if ((NET_CTR_CFG_ERR_EN      == DEF_ENABLED)                    && \
     (CPU_CFG_CRITICAL_METHOD == CPU_CRITICAL_METHOD_STATUS_LOCAL))
    CPU_SR           cpu_sr;
#endif
    CPU_BOOLEAN      tx_win_update;
    NET_TCP_SEQ_NBR  ack_delta_next;
    NET_TCP_SEQ_NBR  ack_delta_win_update;
    NET_TCP_SEQ_NBR  seq_win;
    NET_TCP_SEQ_NBR  seq_win_delta;
    NET_TCP_SEQ_NBR  seq_win_update_delta;


                                                                /* ------ VALIDATE TCP CONN TX REMOTE WIN UPDATE ------ */
    tx_win_update = DEF_NO;

    switch (pconn->ConnState) {
        case NET_TCP_CONN_STATE_FREE:
             NET_CTR_ERR_INC(NetTCP_ErrNotUsedCtr);
            *perr = NET_TCP_ERR_CONN_NOT_USED;
             return;                                            /* Prevent 'break NOT reachable' compiler warning.      */


        case NET_TCP_CONN_STATE_SYNC_RXD:
        case NET_TCP_CONN_STATE_SYNC_RXD_PASSIVE:
        case NET_TCP_CONN_STATE_SYNC_RXD_ACTIVE:
        case NET_TCP_CONN_STATE_SYNC_TXD:
#if (NET_ERR_CFG_ARG_CHK_DBG_EN == DEF_ENABLED)
                                                                /* Validate TCP conn tx Q state.                        */
             switch (pconn->TxQ_State) {
                 case NET_TCP_TX_Q_STATE_CONN_CLOSED:
                      break;


                 case NET_TCP_TX_Q_STATE_NONE:
                 case NET_TCP_TX_Q_STATE_CLOSED:
                 case NET_TCP_TX_Q_STATE_CONN:
                 case NET_TCP_TX_Q_STATE_CONN_CLOSING:
                 case NET_TCP_TX_Q_STATE_CONN_SUSPEND:
                 default:
                     *perr = NET_TCP_ERR_INVALID_CONN_STATE;
                      return;                                   /* Prevent 'break NOT reachable' compiler warning.      */
             }
#endif

             tx_win_update = DEF_YES;                           /* Update tx win ctrls (see Note #1a2).                 */
             break;

/*$PAGE*/
        case NET_TCP_CONN_STATE_CONN:
        case NET_TCP_CONN_STATE_FIN_WAIT_1:
        case NET_TCP_CONN_STATE_CLOSING:
        case NET_TCP_CONN_STATE_CLOSE_WAIT:
        case NET_TCP_CONN_STATE_LAST_ACK:
#if (NET_ERR_CFG_ARG_CHK_DBG_EN == DEF_ENABLED)
                                                                /* Validate TCP conn tx Q state.                        */
             switch (pconn->TxQ_State) {
                 case NET_TCP_TX_Q_STATE_CONN:
                 case NET_TCP_TX_Q_STATE_CONN_CLOSING:
                 case NET_TCP_TX_Q_STATE_CONN_SUSPEND:
                      break;


                 case NET_TCP_TX_Q_STATE_NONE:
                 case NET_TCP_TX_Q_STATE_CLOSED:
                 case NET_TCP_TX_Q_STATE_CONN_CLOSED:
                 default:
                     *perr = NET_TCP_ERR_INVALID_CONN_STATE;
                      return;                                   /* Prevent 'break NOT reachable' compiler warning.      */
             }
#endif
                                                                /* Chk tx win ctrls update      (see Note #1b1B1).      */
                                                                /* If seq = last win update seq (see Note #1b1B1b),  .. */
             if (pbuf_hdr->TCP_SeqNbr == pconn->TxWinUpdateSeqNbr) {

                 ack_delta_next       = (NET_TCP_SEQ_NBR)(pconn->TxSeqNbrNext - pbuf_hdr->TCP_AckNbr);
                 ack_delta_win_update = (NET_TCP_SEQ_NBR)(pconn->TxSeqNbrNext - pconn->TxWinUpdateAckNbr);
                 if (ack_delta_next <= ack_delta_win_update) {  /* .. (next - ack) <= (next - last win update ack),  .. */
                                                                /* .. & rx'd ack OR win != last rx'd ack or win,     .. */
                                                                /* .. update tx win (see Notes #1b1B1c, #1b2B, & #2a2A);*/
                     tx_win_update = ((pbuf_hdr->TCP_AckNbr  != pconn->TxWinUpdateAckNbr ) ||
                                      (pbuf_hdr->TCP_WinSize != pconn->TxWinUpdateWinSize)) ? DEF_YES : DEF_NO;
                 }

             } else {
                 seq_win              = (NET_TCP_SEQ_NBR)(pconn->RxSeqNbrNext + pconn->RxWinSizeActual);
                 seq_win_delta        = (NET_TCP_SEQ_NBR)(seq_win             - pbuf_hdr->TCP_SeqNbr);
                 seq_win_update_delta = (NET_TCP_SEQ_NBR)(seq_win             - pconn->TxWinUpdateSeqNbr);

                 if (seq_win_delta < seq_win_update_delta) {    /* .. else if [(next + win) -                 seq] < .. */
                                                                /* ..         [(next + win) - last win update seq],  .. */
                     tx_win_update = DEF_YES;                   /* .. update tx win (see Notes #1b1B1a & #2b2A).        */
                 }
             }
             break;


        case NET_TCP_CONN_STATE_LISTEN:
        case NET_TCP_CONN_STATE_FIN_WAIT_2:
        case NET_TCP_CONN_STATE_TIME_WAIT:
        case NET_TCP_CONN_STATE_CLOSING_DATA_AVAIL:
             NET_CTR_ERR_INC(NetTCP_ErrConnInvalidOpCtr);
            *perr = NET_TCP_ERR_INVALID_CONN_OP;
             return;                                            /* Prevent 'break NOT reachable' compiler warning.      */


        case NET_TCP_CONN_STATE_NONE:
        case NET_TCP_CONN_STATE_CLOSED:
        default:
             NetTCP_ConnClose(pconn, pbuf_hdr, DEF_YES, NET_TCP_CONN_CLOSE_ALL);
             NET_CTR_ERR_INC(NetTCP_ErrConnInvalidStateCtr);
            *perr = NET_TCP_ERR_INVALID_CONN_STATE;
             return;                                            /* Prevent 'break NOT reachable' compiler warning.      */
    }


                                                                /* ---------- UPDATE TCP CONN TX REMOTE WIN ----------- */
    if (tx_win_update == DEF_YES) {                             /* Update tx win ctrls (see Notes #1a2 & #1b1B2).       */
        NetTCP_TxConnWinSizeHandlerCongCtrl(pconn, pbuf_hdr, ack_code, 0, NET_TCP_CONN_TX_WIN_REMOTE_UPDATE, perr);
        if (*perr != NET_TCP_ERR_NONE) {
             return;
        }
    }


   *perr = NET_TCP_ERR_NONE;
}


/*$PAGE*/
/*
*********************************************************************************************************
*                                   NetTCP_RxPktConnHandlerReTxQ()
*
* Description : (1) Handle received valid acknowledgement segments :
*
*                   (a) Update TCP connection re-transmit queue :
*
*                       (1) Update TCP connection's unacknowledged transmit sequences       See Note #2c1
*                       (2) Remove acknowledged TCP segments from a TCP                     See Note #2c2
*                               connection's re-transmit queue
*                       (3) Update TCP connection's round-trip  time calculations
*                               (see 'NetTCP_TxConnRTT_RTO_Calc()  Note #2a1')
*                       (4) Update TCP connection's re-transmit timeout                     See Note #8b
*                       (5) Free   TCP packet buffer(s)
*                       (6) Start  TCP connection's    transmit idle timer
*                               (see 'NetTCP_TxConnTxQ_TimeoutIdleSet()  Note #2a1')
*
*                   (b) Update TCP connection's transmit window(s) :
*
*                       (1) Increment TCP connection's configured        transmit window size
*                       (2) Increment TCP connection's congetion control transmit window size
*
*
* Argument(s) : pconn       Pointer to a TCP connection.
*               -----       Argument validated in NetTCP_RxPktConnHandler().
*
*               ack_code    Indicates the received segment's acknowledgement condition :
*               --------
*                               NET_TCP_CONN_RX_ACK_VALID           Received acknowledgement number is
*                                                                       valid     for the TCP connection.
*
*                               NET_TCP_CONN_RX_ACK_DUP             Received acknowledgement number is a
*                                                                       duplicate for the TCP connection.
*
*                           Argument validated in NetTCP_RxPktConnHandler() functions.
*
*               pbuf_hdr    Pointer to network buffer header that received TCP packet.
*               --------    Argument validated in NetTCP_Rx().
*
*               perr        Pointer to variable that will receive the return error code from this function :
*
*                               NET_TCP_ERR_NONE                    TCP connection's re-transmit queue
*                                                                       successfully handled.
*                               NET_TCP_ERR_CONN_NOT_USED           TCP connection NOT currently used.
*                               NET_TCP_ERR_INVALID_CONN_STATE      Invalid TCP connection state.
*                               NET_TCP_ERR_INVALID_CONN_OP         Invalid TCP connection operation.
*
*                               NET_TCP_ERR_CONN_ACK_INVALID        Invalid received segment acknowledgement.
*                               NET_TCP_ERR_CONN_DATA_INVALID       TCP connection re-transmit queue contains
*                                                                       invalid or improperly sequenced data.
*
*                                                                   -- RETURNED BY NetTCP_TxConnReTxQ_TimeoutSet() : --
*                               NET_TCP_ERR_CONN_FAULT              TCP connection fault; connection(s) aborted.
*
*                                                                   - RETURNED BY NetTCP_TxConnWinSizeHandlerCfgd() : -
*                               NET_TCP_ERR_TX_Q_SIGNAL_FAULT       TCP connection transmit queue signal fault.
*
* Return(s)   : none.
*
* Caller(s)   : NetTCP_RxPktConnHandlerSeg().
*$PAGE*
* Note(s)     : (2) (a) The following sections ... :
*
*                       (1) RFC #793, Section 3.9 'Event Processing : SEGMENT ARRIVES : SYN-SENT [State] :
*                               Check SYN Bit'
*                       (2) RFC #793, Section 3.9 'Event Processing : SEGMENT ARRIVES : Check ACK Field :
*                               ESTABLISHED STATE'
*
*                   (b) ... generalize that for ...
*
*                       (1) ... the following synchronization-to-connected state transitions ... :
*
*                           (A) SYN-RECEIVED to ESTABLISHED
*                           (B) SYN-SENT     to ESTABLISHED
*
*                       (2) ... & for the following connected states ... :
*
*                           (A) ESTABLISHED
*                           (B) FIN-WAIT-1
*                           (C) CLOSING
*                           (D) CLOSE-WAIT
*                           (E) LAST-ACK
*                               (1) See 'NetTCP_RxPktConnHandlerLastAck()  Notes #2d2B'.
*
*                   (c) ... that ...
*
*                       (1) "If SND.UNA < SEG.ACK <= SND.NXT, SND.UNA should be advanced to equal SEG.ACK" :
*
*                               (A) SND.UNA <- SEG.ACK
*
*                       (2) "Any segments on the retransmission queue which are thereby entirely acknowledged
*                            are removed."
*
*               (3) A TCP connection's re-transmit queue SHOULD be updated ONLY by valid, non-duplicate
*                   received acknowledgement segments.
*
*               (4) Since valid received acknowledgement segments update a TCP connection's last
*                   unacknowledged transmit sequence number ('TxSeqNbrUnackd'), any controls &/or
*                   calculations based on the TCP connection's last unacknowledged transmit sequence
*                   number MUST use the saved/previous value of the TCP connection's last unacknowledged
*                   transmit sequence number ('TxSeqNbrUnackdPrev').
*
*               (5) Since segments enqueued to a TCP connection's re-transmit queue have already been
*                   transmitted to the remote host & reported to the application layer as having been
*                   transmitted, any TCP connection whose re-transmit queue becomes corrupted MUST be
*                   closed to prevent the further transmit of corrupted data.
*
*               (6) Although network packets are NOT required to ensure that network packet headers or
*                   data will locate on CPU word-aligned addresses; many processors may be more efficient
*                   & may even REQUIRE that memory transfers occur on CPU word-aligned addresses [e.g.
*                   processors or NICs with direct memory access (DMA) capability].
*
*                   Therefore, to ensure appropriate CPU word alignment; any segment in a TCP connection's
*                   re-transmit queue whose transmit sequences are partially acknowledged MUST acknowledge
*                   an exact number of sequences such that the remaining sequences are aligned on a CPU
*                   word-aligned address.
*
*                   (a) Since RFC #793, Section 3.9 'Event Processing : SEGMENT ARRIVES : Check
*                       Sequence Number' states that in the "SYN-RECEIVED, ESTABLISHED STATE,
*                       FIN-WAIT-1 STATE, FIN-WAIT-2 STATE, CLOSE-WAIT STATE, CLOSING STATE,
*                       LAST-ACK STATE, TIME-WAIT STATE" that "if a segment's contents straddle
*                       the boundary between old and new, only the new parts should be processed";
*                       any data segments partially acknowledged in a TCP connections' re-transmit
*                       queue may be re-transmitted in full or in part since the retransmission of
*                       previously received data is not processed.
*$PAGE*
*               (7) (a) RFC #1122, Section 4.2.3.5 states that "excessive retransmission of the same
*                       segment by TCP indicates some failure of the remote host or the Internet path
*                       ... When the number of transmissions of the same segment reaches a threshold
*                       ... close the connection."
*
*                   (b) However, any segment in a TCP connection's re-transmit queue whose transmit
*                       sequences are partially acknowledged SHOULD NOT be considered the same segment
*                       for purposes of excessive retransmission.
*
*                       Therefore, it seems reasonable that whenever a TCP connection's re-transmit
*                       queue segment's transmit sequences are partially acknowledged; that segment's
*                       re-transmit counter should be reset.
*
*                   See also 'NetTCP_TxConnReTxQ()  Note #3'.
*
*               (8) (a) (1) (A) RFC #793, Section 3.7 'Data Communication : Retransmission Timeout' states
*                               that "the Round Trip Time (RTT) ... [is] the elapsed time between" :
*
*                               (1) "sending a data octet with a particular sequence number and"   ...
*                               (2) "receiving an acknowledgment that covers that sequence number" ...
*                               (3) "(segments sent do not have to match segments received)".
*
*                           (B) (1) RFC #2988, Section 3 adds that :
*
*                                   (a) "Traditionally, TCP implementations have taken one RTT measurement at
*                                        a time (typically once per RTT)."
*
*                               (2) RFC #2988, Section 1 states that "in some situations it may be beneficial
*                                   for a TCP sender to be more conservative than the algorithms detailed in
*                                   this document allow.  However, a TCP MUST NOT be more aggressive than the
*                                   ... algorithms allow".
*
*                           See also 'NetTCP_TxConnRTT_RTO_Calc()  Note #2a2'.
*
*                       (2) RFC #2988, Section 3 states that "TCP MUST use Karn's algorithm ... for taking
*                           RTT samples.  That is, RTT samples MUST NOT be made using segments that were
*                           retransmitted (and thus for which it is ambiguous whether the reply was for
*                           the first instance of the packet or a later instance)".
*
*                           (A) (1) To determine if any segment(s) from a TCP connection's re-transmit queue
*                                   have been re-transmitted (i.e. transmitted more than once), the TCP
*                                   connection's transmit unacknowledged & un-re-transmitted sequence numbers
*                                   are compared :
*
*                                   (a) If NO  sequences in the TCP connection's re-transmit queue have been
*                                          re-transmitted,  the TCP connection's    transmit unacknowledged &
*                                       un-re-transmitted sequence numbers will be equal.
*
*                                   (b) If ANY sequences in the TCP connection's re-transmit queue have been
*                                          re-transmitted,  the TCP connection's    transmit unacknowledged
*                                          sequence number will be less than the un-re-transmitted sequence
*                                          number.
*
*                               (2) If a received acknowledgement fully acknowledges ALL re-transmitted
*                                   segment(s) from a TCP connection's re-transmit queue, the TCP connection
*                                   advances its un-re-transmitted sequence number to the received segment's
*                                   acknowledgement sequence number.
*
*                           (B) Although RTT measurements could be calculated for ALL transmitted segments;
*                               to simplify implementation of Karn's algorithm :
*
*                               (1) Only a single RTT measurement is calculated, ...        See Note #8a1B1a
*                               (2) (a) per TCP acknowledgement received         ...        See Note #8a1A2
*                                         AND
*                                   (b) the segment at the head of a TCP connection's
*                                           re-transmit queue.                              See Note #8a1A1
*
*                           See also 'NetTCP_TxConnReTxQ()  Note #4'.
*
*                   (b) RFC #2988, Section 5 states that "the following is the RECOMMENDED algorithm for
*                       managing the retransmission timer" :
*
*                       (2) "When all outstanding data has been acknowledged, turn off the retransmission
*                            timer."
*
*                       (3) "When an ACK is received that acknowledges new data, restart the retransmission
*                            timer so that it will expire after RTO seconds (for the current value of RTO)."
*
*                       See also 'NetTCP_TxConnReTxQ()  Note #2b1A'.
*$PAGE*
*               (9) RFC #793 does NOT provide nor suggest any logic to determine/handle sequence number
*                   comparisons for sequence number windows that overflow the sequence number space.
*
*                   (a) For example, the next sequence octet to transmit (SND.NXT) is typically greater
*                       than or equal to any received segment's acknowledgement number (SEG.ACK) :
*
*                           (1) SND.NXT >= SEG.ACK
*
*                       However, if SND.NXT overflows the sequence number space, it will be MUCH less
*                       than SEG.ACK until SEG.ACK also overflows :
*
*                           (2) SND.NXT << SEG.ACK
*
*                   (b) (1) Therefore, in order to determine if a received segment's acknowledgement value
*                           fully acknowledges previously transmitted segment(s) in the TCP connection's
*                           re-transmit queue, the following unsigned arithmetic comparison MUST be checked :
*
*                               (A) (SND.NXT - SEG.ACK)  <=  SND.NXT - (ReTxQCur.SeqNbr + ReTxQCur.SegLen)
*
*                           See also 'NetTCP_RxPktConnIsValidAck()  Note #3a2'.
*
*                       (2) In order to determine if a received segment's acknowledgement partially
*                           acknowledges a previously received segment in the TCP connection's re-
*                           transmit queue, the following unsigned arithmetic comparison MUST be checked :
*
*                               (A) (ReTxQCur.SeqNbr + ReTxQCur.SegLen) - SEG.ACK  <  ReTxQCur.SegLen
*
*                           See also 'NetTCP_RxPktConnHandlerRxQ_Conn()  Note #4c2'.
*
*                       (3) In order to determine if a received segment's acknowledgement should
*                           advance the TCP connection's un-re-transmitted sequence number(s), the
*                           following unsigned arithmetic comparison MUST be true :
*
*                               (A) (SEG.ACK - ReTxQ.UnReTxdSeqNbr)  <=  (SND.NXT - ReTxQ.UnReTxdSeqNbr)
*********************************************************************************************************
*/
/*$PAGE*/
static  void  NetTCP_RxPktConnHandlerReTxQ (NET_TCP_CONN      *pconn,
                                            NET_TCP_ACK_CODE   ack_code,
                                            NET_BUF_HDR       *pbuf_hdr,
                                            NET_ERR           *perr)
{
#if ((NET_ERR_CFG_ARG_CHK_DBG_EN == DEF_ENABLED)                    && \
     (NET_CTR_CFG_ERR_EN         == DEF_ENABLED)                    && \
     (CPU_CFG_CRITICAL_METHOD    == CPU_CRITICAL_METHOD_STATUS_LOCAL))
    CPU_SR                 cpu_sr;
#endif
#if (NET_ERR_CFG_ARG_CHK_DBG_EN == DEF_ENABLED)
    NET_TCP_SEQ_NBR        seq_nbr_cur;
    NET_TCP_SEQ_NBR        seq_nbr_delta;
    NET_TCP_SEQ_NBR        seq_nbr_next_qd;
#endif
    NET_TCP_SEQ_NBR        ack_delta_seq;
    NET_TCP_SEQ_NBR        ack_delta_seq_align;
    NET_TCP_SEQ_NBR        ack_delta_seq_align_offset;
    NET_TCP_SEQ_NBR        ack_delta_unretxd;
    NET_TCP_SEQ_NBR        ack_delta_next;
    NET_TCP_SEQ_NBR        seq_delta_unretxd;
    NET_TCP_SEQ_NBR        seq_delta_next;
    NET_TCP_SEQ_NBR        seq_nbr_next;
    NET_TCP_SEQ_NBR        seq_nbr;
    NET_TCP_SEG_SIZE       seg_len;
    NET_TCP_SEG_SIZE       seg_len_tot;
    NET_TCP_SEG_SIZE       seg_len_data;
    NET_TCP_SEG_SIZE       seg_len_data_tot;
    NET_TCP_TX_RTT_TS_MS   seg_rtt_ts_txd_ms;
    NET_TCP_TX_RTT_TS_MS   seg_rtt_ts_rxd_ms;
    CPU_BOOLEAN            segs_re_txd;
    CPU_BOOLEAN            seqs_ackd;
    CPU_BOOLEAN            done;
    CPU_BOOLEAN            tmr_update;
    NET_BUF               *pbuf_q;
    NET_BUF               *pbuf_q_head;
    NET_BUF               *pbuf_q_prev;
    NET_BUF               *pbuf_q_next;
    NET_BUF_HDR           *pbuf_q_hdr;
    NET_BUF_HDR           *pbuf_q_head_hdr;
    NET_BUF_HDR           *pbuf_q_prev_hdr;



#if (NET_ERR_CFG_ARG_CHK_DBG_EN == DEF_ENABLED)                 /* ---------------- VALIDATE TCP CONN ----------------- */
    switch (pconn->ConnState) {
        case NET_TCP_CONN_STATE_FREE:
             NET_CTR_ERR_INC(NetTCP_ErrNotUsedCtr);
            *perr = NET_TCP_ERR_CONN_NOT_USED;
             return;                                            /* Prevent 'break NOT reachable' compiler warning.      */

        case NET_TCP_CONN_STATE_SYNC_RXD:
        case NET_TCP_CONN_STATE_SYNC_RXD_PASSIVE:
        case NET_TCP_CONN_STATE_SYNC_RXD_ACTIVE:
        case NET_TCP_CONN_STATE_SYNC_TXD:
             switch (pconn->TxQ_State) {
                 case NET_TCP_TX_Q_STATE_CONN_CLOSED:
                      switch (ack_code) {
                          case NET_TCP_CONN_RX_ACK_VALID:
                               break;


                          case NET_TCP_CONN_RX_ACK_NONE:
                          case NET_TCP_CONN_RX_ACK_INVALID:
                          case NET_TCP_CONN_RX_ACK_DUP:
                          case NET_TCP_CONN_RX_ACK_PREV:
                          default:
                              *perr = NET_TCP_ERR_CONN_ACK_INVALID;
                               return;                          /* Prevent 'break NOT reachable' compiler warning.      */
                      }
                      break;


                 case NET_TCP_TX_Q_STATE_NONE:
                 case NET_TCP_TX_Q_STATE_CLOSED:
                 case NET_TCP_TX_Q_STATE_CONN:
                 case NET_TCP_TX_Q_STATE_CONN_CLOSING:
                 case NET_TCP_TX_Q_STATE_CONN_SUSPEND:
                 default:
                     *perr = NET_TCP_ERR_INVALID_CONN_STATE;
                      return;                                   /* Prevent 'break NOT reachable' compiler warning.      */
             }
             break;

/*$PAGE*/
        case NET_TCP_CONN_STATE_CONN:
        case NET_TCP_CONN_STATE_FIN_WAIT_1:
        case NET_TCP_CONN_STATE_CLOSING:
        case NET_TCP_CONN_STATE_CLOSE_WAIT:
        case NET_TCP_CONN_STATE_LAST_ACK:
             switch (pconn->TxQ_State) {
                 case NET_TCP_TX_Q_STATE_CONN:
                 case NET_TCP_TX_Q_STATE_CONN_CLOSING:
                 case NET_TCP_TX_Q_STATE_CONN_SUSPEND:
                      switch (ack_code) {
                          case NET_TCP_CONN_RX_ACK_VALID:
                          case NET_TCP_CONN_RX_ACK_DUP:
                               break;


                          case NET_TCP_CONN_RX_ACK_NONE:
                          case NET_TCP_CONN_RX_ACK_INVALID:
                          case NET_TCP_CONN_RX_ACK_PREV:
                          default:
                              *perr = NET_TCP_ERR_CONN_ACK_INVALID;
                               return;                          /* Prevent 'break NOT reachable' compiler warning.      */
                      }
                      break;


                 case NET_TCP_TX_Q_STATE_NONE:
                 case NET_TCP_TX_Q_STATE_CLOSED:
                 case NET_TCP_TX_Q_STATE_CONN_CLOSED:
                 default:
                     *perr = NET_TCP_ERR_INVALID_CONN_STATE;
                      return;                                   /* Prevent 'break NOT reachable' compiler warning.      */
             }
             break;


        case NET_TCP_CONN_STATE_LISTEN:
        case NET_TCP_CONN_STATE_FIN_WAIT_2:
        case NET_TCP_CONN_STATE_TIME_WAIT:
        case NET_TCP_CONN_STATE_CLOSING_DATA_AVAIL:
             NET_CTR_ERR_INC(NetTCP_ErrConnInvalidOpCtr);
            *perr = NET_TCP_ERR_INVALID_CONN_OP;
             return;                                            /* Prevent 'break NOT reachable' compiler warning.      */


        case NET_TCP_CONN_STATE_NONE:
        case NET_TCP_CONN_STATE_CLOSED:
        default:
             NetTCP_ConnClose(pconn, pbuf_hdr, DEF_YES, NET_TCP_CONN_CLOSE_ALL);
             NET_CTR_ERR_INC(NetTCP_ErrConnInvalidStateCtr);
            *perr = NET_TCP_ERR_INVALID_CONN_STATE;
             return;                                            /* Prevent 'break NOT reachable' compiler warning.      */
    }
#endif



/*$PAGE*/
                                                                /* ------------- UPDATE UNACK'D TX SEQ(S) ------------- */
#if (NET_ERR_CFG_ARG_CHK_DBG_EN == DEF_ENABLED)
    seq_nbr_cur               = (NET_TCP_SEQ_NBR)pconn->TxSeqNbrUnAckd;
    seq_nbr_delta             = (NET_TCP_SEQ_NBR)pconn->TxSeqNbrUnAckdAlignDelta;
#endif
                                                                /* Save prev tx unack'd seq nbr (see Note #4).          */
    pconn->TxSeqNbrUnAckdPrev = (NET_TCP_SEQ_NBR)pconn->TxSeqNbrUnAckd;
                                                                /* Ack  prev'ly unack'd tx segs (see Note #2c1).        */
    pconn->TxSeqNbrUnAckd     = (NET_TCP_SEQ_NBR)pbuf_hdr->TCP_AckNbr;
    if (pconn->TxQ_State == NET_TCP_TX_Q_STATE_CONN_CLOSING) {
        if (pconn->TxSeqNbrUnAckd == pconn->TxSeqNbrLast) {     /* If last tx'd seq ack'd, close TCP conn tx.           */
            pconn->TxQ_State = NET_TCP_TX_Q_STATE_CONN_CLOSED;
        }
    }


                                                                /* --------- REMOVE ACK'D SEG(S) FROM RE-TX Q --------- */
    if (ack_code != NET_TCP_CONN_RX_ACK_VALID) {                /* If ack NOT valid, non-dup ack; ...                   */
       *perr = NET_TCP_ERR_NONE;                                /* ... do NOT update re-tx Q (see Note #3).             */
        return;
    }

    pbuf_q_head      = (NET_BUF *)pconn->ReTxQ_Head;
    pbuf_q_prev      = (NET_BUF *)0;
    pbuf_q           = (NET_BUF *)pbuf_q_head;
    seg_len_tot      =  0;
    seg_len_data_tot =  0;
                                                                /* Chk re-tx'd seg(s) [see Notes #8a2A1 & #4].          */
    segs_re_txd      = (pconn->TxSeqNbrUnAckdPrev == pconn->TxSeqNbrUnReTxd)
                     ?  DEF_NO : DEF_YES;
    seqs_ackd        =  DEF_NO;
    done             =  DEF_NO;

    while ((pbuf_q != (NET_BUF *)0) &&                          /* While NOT @ re-tx Q tail, ...                        */
           (done == DEF_NO)) {                                  /* ... srch for ack'd tx segs to remove (see Note #2c2).*/

        pbuf_q_hdr   = (NET_BUF_HDR    *)&pbuf_q->Hdr;
        pbuf_q_next  = (NET_BUF        *) pbuf_q_hdr->NextPrimListPtr;
        seq_nbr      = (NET_TCP_SEQ_NBR ) pbuf_q_hdr->TCP_SeqNbr;
        seg_len      = (NET_TCP_SEG_SIZE) pbuf_q_hdr->TCP_SegLen;
        seg_len_data = (NET_TCP_SEG_SIZE) seg_len;
        if (pbuf_q_hdr->TCP_SegSync  == DEF_YES) {              /* If sync  seg                           ...           */
            if (seg_len_data >= NET_TCP_SEG_LEN_SYNC) {         /* ... &        seg len >= sync  seg len, ...           */
                seg_len_data -= NET_TCP_SEG_LEN_SYNC;           /* ... dec data seg len by sync  seg len.               */
            }
        }
        if (pbuf_q_hdr->TCP_SegClose == DEF_YES) {              /* If close seg                           ...           */
            if (seg_len_data >= NET_TCP_SEG_LEN_CLOSE) {        /* ... &        seg len >= close seg len, ...           */
                seg_len_data -= NET_TCP_SEG_LEN_CLOSE;          /* ... dec data seg len by close seg len.               */
            }
        }

#if (NET_ERR_CFG_ARG_CHK_DBG_EN == DEF_ENABLED)
        seq_nbr_next_qd  = seq_nbr + pconn->TxSeqNbrUnAckdAlignDelta;
        if (seq_nbr_cur != seq_nbr_next_qd) {                   /* If next q'd seg's seq nbr NOT consecutive, ...       */
                                                                /* ... close TCP conn (see Note #5).                    */
            NetTCP_ConnClose(pconn, pbuf_hdr, DEF_YES, NET_TCP_CONN_CLOSE_ALL);
           *perr = NET_TCP_ERR_CONN_DATA_INVALID;
            return;
        }
#endif
                                                                /* Chk if rx'd seg acks cur re-tx Q seg.                */
        ack_delta_next = (NET_TCP_SEQ_NBR)(pconn->TxSeqNbrNext - pbuf_hdr->TCP_AckNbr);
        seq_nbr_next   = (NET_TCP_SEQ_NBR)(seq_nbr             + seg_len);
        seq_delta_next = (NET_TCP_SEQ_NBR)(pconn->TxSeqNbrNext - seq_nbr_next);

        if (ack_delta_next <= seq_delta_next) {                 /* If seg fully acks cur re-tx Q seg (see Note #9b1A),  */
            pbuf_q_prev                      = pbuf_q;
            pbuf_q                           = pbuf_q_next;     /* ... adv to next re-tx Q seg.                         */
            pconn->TxSeqNbrUnAckdAlignDelta  = 0;
            seg_len_tot                     += seg_len;
            seg_len_data_tot                += seg_len_data;
            seqs_ackd                        = DEF_YES;

#if (NET_ERR_CFG_ARG_CHK_DBG_EN == DEF_ENABLED)
            seq_nbr_cur   += (NET_TCP_SEQ_NBR)(seg_len - seq_nbr_delta);
            seq_nbr_delta  = (NET_TCP_SEQ_NBR) 0;
#endif

/*$PAGE*/
        } else {                                                /* Else chk partial re-tx Q seg ack (see Note #9b2A) :  */
            ack_delta_seq = (NET_TCP_SEQ_NBR)(pbuf_hdr->TCP_AckNbr - seq_nbr);
            if (ack_delta_seq == 0) {                           /* If NO   seqs ack'd for cur re-tx Q seg, ...          */
                ;                                               /* ... do NOT update seg.                               */

            } else if (ack_delta_seq < seg_len) {               /* If SOME seqs ack'd for cur re-tx Q seg,  ...         */

                                                                /* Align partial ack to word boundary (see Note #6).    */
                ack_delta_seq_align_offset      = (NET_TCP_SEQ_NBR )(ack_delta_seq % sizeof(CPU_ALIGN));
                ack_delta_seq_align             = (NET_TCP_SEQ_NBR )(ack_delta_seq - ack_delta_seq_align_offset);
                pconn->TxSeqNbrUnAckdAlignDelta = (NET_TCP_SEQ_NBR ) ack_delta_seq_align_offset;

                                                                /* ...   update cur seg's seq nbr & seg len ...         */
                pbuf_q_hdr->TCP_SeqNbr         += (CPU_INT32U      ) ack_delta_seq_align;
                pbuf_q_hdr->TCP_SegLen         -= (CPU_INT16U      ) ack_delta_seq_align;
                pbuf_q_hdr->TCP_SegLenData     -= (CPU_INT16U      ) ack_delta_seq_align;
                seg_len_tot                    += (NET_TCP_SEG_SIZE) ack_delta_seq_align;
                seg_len_data_tot               += (NET_TCP_SEG_SIZE) ack_delta_seq_align;
                                                                /* ... & update TCP tx buf ctrls.                       */
                pbuf_q_hdr->DataIx             += (CPU_INT16U      ) ack_delta_seq_align;
                pbuf_q_hdr->DataLen            -= (NET_BUF_SIZE    ) ack_delta_seq_align;
                pbuf_q_hdr->TotLen             -= (NET_BUF_SIZE    ) ack_delta_seq_align;

                pbuf_q_hdr->TCP_SegReTxCtr      =  0;           /* Reset re-tx ctr (see Note #7b).                      */

                seqs_ackd                       =  DEF_YES;

#if (NET_ERR_CFG_ARG_CHK_DBG_EN == DEF_ENABLED)
            } else {                                            /* Else fully-ack'd-seg chk failed?; close TCP conn?    */
                NetTCP_ConnClose(pconn, pbuf_hdr, DEF_YES, NET_TCP_CONN_CLOSE_ALL);
               *perr = NET_TCP_ERR_CONN_DATA_INVALID;
                return;
#endif
            }

            done = DEF_YES;
        }
    }


                                                                /* --------------- UPDATE TCP CONN RTO ---------------- */
    if (seqs_ackd == DEF_YES) {                                 /* If ANY  re-tx Q seq(s) ack'd                     ..  */
        if (segs_re_txd == DEF_NO) {                            /* .. & NO re-tx Q seg(s) re-tx'd (see Note #8a2);  ..  */
                                                                /* ..   get tx'd seg RTT ts       (see Note #8a1A1) ..  */
            pbuf_q_head_hdr   = (NET_BUF_HDR        *)&pbuf_q_head->Hdr;
            seg_rtt_ts_txd_ms = (NET_TCP_TX_RTT_TS_MS) pbuf_q_head_hdr->TCP_RTT_TS_Txd_ms;
                                                                /* ..   get rx'd ack RTT ts       (see Note #8a1A2) ..  */
            seg_rtt_ts_rxd_ms = (NET_TCP_TX_RTT_TS_MS) pbuf_hdr->TCP_RTT_TS_Rxd_ms;
                                                                /* .. & calc/update RTT/RTO       (see Note #1a3).      */
            NetTCP_TxConnRTT_RTO_Calc(pconn, NET_TCP_CONN_TX_RTT_CALC, seg_rtt_ts_txd_ms, seg_rtt_ts_rxd_ms);
        }

        ack_delta_unretxd = (NET_TCP_SEQ_NBR)(pbuf_hdr->TCP_AckNbr - pconn->TxSeqNbrUnReTxd);
        seq_delta_unretxd = (NET_TCP_SEQ_NBR)(pconn->TxSeqNbrNext  - pconn->TxSeqNbrUnReTxd);
        if (ack_delta_unretxd <= seq_delta_unretxd) {           /* If (ack - un-re-tx'd) < (next - un-re-tx'd), ...     */
                                                                /* ... acks ALL re-tx'd seg(s)        [see Note #9b3A]; */
            pconn->TxSeqNbrUnReTxd = pbuf_hdr->TCP_AckNbr;      /* ... adv   un-re-tx'd seq(s) to ack (see Note #8a2A2).*/
        }
    }


/*$PAGE*/
                                                                /* ------------- UPDATE TCP CONN RE-TX Q -------------- */
    tmr_update  = seqs_ackd;                                    /* Update re-tx Q tmr if ANY re-tx Q seqs ack'd ...     */
                                                                /* ... (see Note #8b3).                                 */
    if (pbuf_q != pbuf_q_head) {                                /* If ANY re-tx Q segs fully ack'd, update re-tx Q.     */

        if (pbuf_q != (NET_BUF *)0) {                           /* If re-tx Q still NOT empty, . ..                     */
            pbuf_q_prev_hdr                  = (NET_BUF_HDR *)&pbuf_q_prev->Hdr;
            pbuf_q_prev_hdr->NextPrimListPtr = (void        *) 0;
                                                                /* ... update re-tx Q head.                             */
            pconn->ReTxQ_Head                = (NET_BUF     *) pbuf_q;
            pbuf_q_hdr->PrevPrimListPtr      = (void        *) 0;

        } else {                                                /* Else clr   re-tx Q.                                  */
            pconn->ReTxQ_Head = (NET_BUF *)0;
            pconn->ReTxQ_Tail = (NET_BUF *)0;

            if (pconn->ReTxQ_Tmr != (NET_TMR *)0) {             /* Free  re-tx Q      tmr (see Note #8b2).              */
                NetTmr_Free(pconn->ReTxQ_Tmr);
            }
            pconn->ReTxQ_Tmr = (NET_TMR *)0;
            tmr_update       =  DEF_NO;

            NetTCP_TxConnTxQ_TimeoutIdleSet(pconn);             /* Start    tx Q idle tmr (see Note #1a6).              */
        }

        NetTCP_TxPktFree(pbuf_q_head);                          /* Free ALL fully ack'd seg pkt buf(s).                 */
    }

    if (tmr_update == DEF_YES) {                                /* Update re-tx Q tmr.                                  */
        NetTCP_TxConnReTxQ_TimeoutSet(pconn, DEF_NO, NET_TCP_CONN_CLOSE_ALL, perr);
        if (*perr != NET_TCP_ERR_NONE) {
             return;
        }
    }


                                                                /* ----------- UPDATE TCP CONN TX WIN SIZES ----------- */
                                                                /* Inc TCP conn's tx win sizes (see Note #1b).          */
    NetTCP_TxConnWinSizeHandlerCfgd((NET_TCP_CONN   *)pconn,
                                    (NET_TCP_WIN_SIZE)seg_len_data_tot,
                                    (NET_TCP_WIN_CODE)NET_TCP_CONN_TX_WIN_INC,
                                    (NET_ERR        *)perr);
    if (*perr != NET_TCP_ERR_NONE) {
         return;
    }

    NetTCP_TxConnWinSizeHandlerCongCtrl((NET_TCP_CONN   *)pconn,
                                        (NET_BUF_HDR    *)0,
                                        (NET_TCP_ACK_CODE)NET_TCP_CONN_RX_ACK_NONE,
                                        (NET_TCP_WIN_SIZE)seg_len_data_tot,
                                        (NET_TCP_WIN_CODE)NET_TCP_CONN_TX_WIN_INC,
                                        (NET_ERR        *)perr);
    if (*perr != NET_TCP_ERR_NONE) {
         return;
    }



   *perr = NET_TCP_ERR_NONE;
}


/*$PAGE*/
/*
*********************************************************************************************************
*                              NetTCP_RxPktConnHandlerListenQ_IsAvail()
*
* Description : Check if application layer listen queue is available to queue a new connection.
*
* Argument(s) : pconn       Pointer to a TCP connection.
*               -----       Argument validated in NetTCP_RxPktConnHandlerListen().
*
*               perr        Pointer to variable that will receive the return error code from this function :
*
*                               NET_TCP_ERR_NONE                    Application layer listen queue successfully
*                                                                       checked; check return value for listen 
*                                                                       queue availablity.
*
*                               NET_TCP_ERR_CONN_NOT_USED           TCP connection NOT currently used.
*                               NET_TCP_ERR_INVALID_CONN_ID         Invalid application connection.
*                               NET_TCP_ERR_INVALID_CONN_STATE      Invalid TCP connection state.
*                               NET_TCP_ERR_INVALID_CONN_OP         Invalid TCP connection operation.
*                               NET_CONN_ERR_INVALID_FAMILY         Invalid network connection family.
*
*                                                                   ---- RETURNED BY NetConn_ID_AppGet() : ----
*                               NET_ERR_INIT_INCOMPLETE             Network initialization NOT complete.
*                               NET_CONN_ERR_INVALID_CONN           Invalid network connection number.
*                               NET_CONN_ERR_NOT_USED               Network connection NOT currently used.
*
* Return(s)   : DEF_YES, if application connection's listen queue is available to queue a new connection.
*
*               DEF_NO,  otherwise.
*
* Caller(s)   : NetTCP_RxPktConnHandlerListen().
*
* Note(s)     : (1) (a) Stevens, TCP/IP Illustrated, Volume 1, 8th Printing, Section 18.11, Pages 257-258 states
*                       that :
*
*                       (1) "Each listening end point has a fixed length queue of connections that have been
*                            accepted by TCP (i.e., the three-way handshake is complete), but not yet accepted
*                            by the application."
*
*                       (2) "The application specifies a limit to this queue, commonly called the backlog" :
*
*                           (A) "This backlog must be between 0 and 5, inclusive."
*                           (B) "(Most applications specify the maximum value of 5.)"
*
*                       (3) "When a connection request arrives (i.e., the SYN segment), ... the current number
*                            of connections already queued for this listening end point [is checked] to see
*                            whether to accept the connection or not."
*
*                       (4) "If there is room on this listening end point's queue for this new connection, ...
*                            the TCP module ACKs the SYN and completes the connection."
*
*                       (5) "If there is not room on the queue for the new connection" ... :
*
*                           (A) "TCP just ignores the received SYN."
*                           (B) "Nothing is sent back (i.e., no RST segment)."
*
*                   (b) (A) Wright/Stevens, TCP/IP Illustrated, Volume 2, 3rd Printing, Section 15.9, Page 455 
*                           reiterates that :
*
*                           (2) A "listen ... socket ... specifies a limit on the number of connections that can
*                               be queued on the socket," ...
*
*                           (5) "after which the socket layer refuses to queue additional connection requests.
*                                When this occurs, TCP ignores incoming connection requests."
*
*                       (B) Wright/Stevens, TCP/IP Illustrated, Volume 2, 3rd Printing, Section 28.2, Page 930
*                           also states that :
*
*                           (5) (A) "By silently dropping the segment" ...
*                               (B) "and not replying with an RST,"    ...
*                               (C) "The client's connection request should time out, causing the client to
*                                    retransmit the SYN."
*
*                       (C) Stevens, TCP/IP Illustrated, Volume 1, 8th Printing, Section 18.11, Pages 259-260
*                           summarizes that :
*
*                           (5) (A) "TCP ignores the incoming SYN when the queue is full," ...
*                               (B) "and doesn't respond with an RST,"                     ...
*
*                               (C) (1) "because ... this condition could change in a short while ... [and] by
*                                        ignoring the SYN, the server forces the client TCP to re-transmit the
*                                        SYN later, hoping that the queue will then have room for the new
*                                        connection".
*
*                                   (2) Whereas page 259-260 counters that "if the server's TCP responded with
*                                       a reset, the client's active open would abort".
*
*                   See also 'net_sock.c  NetSock_ListenQ_IsAvail()  Note #2'.
*
*               (2) The 'NET_CONN_CFG_FAMILY' pre-processor 'else'-conditional code will never be compiled/linked
*                   since 'net_conn.h' ensures that the family type configuration constant (NET_CONN_CFG_FAMILY)
*                   is configured with an appropriate family type value (see 'net_conn.h  CONFIGURATION ERRORS').
*                   The 'else'-conditional code is included for completeness & as an extra precaution in case
*                   'net_conn.h' is incorrectly modified.
*********************************************************************************************************
*/
/*$PAGE*/
static  CPU_BOOLEAN  NetTCP_RxPktConnHandlerListenQ_IsAvail (NET_TCP_CONN  *pconn,
                                                             NET_ERR       *perr)
{
#if ((NET_ERR_CFG_ARG_CHK_DBG_EN == DEF_ENABLED)                    && \
     (NET_CTR_CFG_ERR_EN         == DEF_ENABLED)                    && \
     (CPU_CFG_CRITICAL_METHOD    == CPU_CRITICAL_METHOD_STATUS_LOCAL))
    CPU_SR       cpu_sr;
#endif
    NET_CONN_ID  conn_id;
    NET_CONN_ID  conn_id_app;
    CPU_BOOLEAN  q_avail;
    NET_ERR      err;


#if (NET_ERR_CFG_ARG_CHK_DBG_EN == DEF_ENABLED)                 /* ------------- VALIDATE TCP CONN STATE -------------- */
    switch (pconn->ConnState) {
        case NET_TCP_CONN_STATE_FREE:
             NET_CTR_ERR_INC(NetTCP_ErrNotUsedCtr);
            *perr =  NET_TCP_ERR_CONN_NOT_USED;
             return (DEF_NO);                                   /* Prevent 'break NOT reachable' compiler warning.      */


        case NET_TCP_CONN_STATE_LISTEN:
             break;


        case NET_TCP_CONN_STATE_CLOSED:
        case NET_TCP_CONN_STATE_SYNC_RXD:
        case NET_TCP_CONN_STATE_SYNC_RXD_PASSIVE:
        case NET_TCP_CONN_STATE_SYNC_RXD_ACTIVE:
        case NET_TCP_CONN_STATE_SYNC_TXD:
        case NET_TCP_CONN_STATE_CONN:
        case NET_TCP_CONN_STATE_FIN_WAIT_1:
        case NET_TCP_CONN_STATE_FIN_WAIT_2:
        case NET_TCP_CONN_STATE_CLOSING:
        case NET_TCP_CONN_STATE_TIME_WAIT:
        case NET_TCP_CONN_STATE_CLOSE_WAIT:
        case NET_TCP_CONN_STATE_LAST_ACK:
             NET_CTR_ERR_INC(NetTCP_ErrConnInvalidOpCtr);
            *perr =  NET_TCP_ERR_INVALID_CONN_OP;
             return (DEF_NO);                                   /* Prevent 'break NOT reachable' compiler warning.      */


        case NET_TCP_CONN_STATE_NONE:
        default:
             NetTCP_ConnClose((NET_TCP_CONN     *)pconn,
                              (NET_BUF_HDR      *)0,
                              (CPU_BOOLEAN       )DEF_YES,
                              (NET_TCP_CLOSE_CODE)NET_TCP_CONN_CLOSE_ALL);
             NET_CTR_ERR_INC(NetTCP_ErrConnInvalidStateCtr);
            *perr =  NET_TCP_ERR_INVALID_CONN_STATE;
             return (DEF_NO);                                   /* Prevent 'break NOT reachable' compiler warning.      */
    }
#endif


    conn_id     = pconn->ID_Conn;
    conn_id_app = NetConn_ID_AppGet(conn_id, perr);             /* Get TCP listen conn's app conn id.                   */
    if (*perr != NET_CONN_ERR_NONE) {
         return (DEF_NO);
    }

    if (conn_id_app == NET_CONN_ID_NONE) {
       *perr =  NET_TCP_ERR_INVALID_CONN_ID;
        return (DEF_NO);
    }


                                                                /* -------------- CHK APP LISTEN Q AVAIL -------------- */
#if (NET_CONN_CFG_FAMILY == NET_CONN_FAMILY_IP_V4_SOCK)
    q_avail = NetSock_ListenQ_IsAvail((NET_SOCK_ID) conn_id_app,
                                      (NET_ERR   *)&err);

#else                                                           /* See Note #2.                                         */
   (void)&q_avail;                                              /* Prevent compiler warnings.                           */
   (void)&err;
   *perr =  NET_CONN_ERR_INVALID_FAMILY;
    return (DEF_NO);
#endif


   *perr =  NET_TCP_ERR_NONE;

    return (q_avail);
}


/*$PAGE*/
/*
*********************************************************************************************************
*                                 NetTCP_RxPktConnHandlerSignalConn()
*
* Description : (1) Signal application layer that TCP/transport layer connection's state is now connected :
*
*                   (a) From passive SYN-RECEIVED             state,  signal application layer that
*                             connection request received; connection accept now available.
*
*                   (b) From active  SYN-RECEIVED or SYN-SENT states, signal application layer that
*                             connection request complete.
*
*
* Argument(s) : pconn       Pointer to a TCP connection.
*               -----       Argument validated in NetTCP_RxPktConnHandlerSyncRxd(),
*                                                 NetTCP_RxPktConnHandlerSyncTxd().
*
*               state       Current TCP connection state.
*
*               perr        Pointer to variable that will receive the return error code from this function :
*
*                               NET_TCP_ERR_NONE                    Application layer successfully signaled.
*                               NET_TCP_ERR_CONN_NOT_USED           TCP connection NOT currently used.
*                               NET_TCP_ERR_CONN_FAIL               Application layer signal failed.
*                               NET_TCP_ERR_INVALID_CONN_ID         Invalid application connection.
*                               NET_TCP_ERR_INVALID_CONN_STATE      Invalid TCP connection state.
*                               NET_TCP_ERR_INVALID_CONN_OP         Invalid TCP connection operation.
*                               NET_CONN_ERR_INVALID_FAMILY         Invalid network connection family.
*
*                                                                   --- RETURNED BY NetConn_ID_AppGet() : ----
*                                                                   - RETURNED BY NetConn_ID_AppCloneGet() : -
*                               NET_ERR_INIT_INCOMPLETE             Network initialization NOT complete.
*                               NET_CONN_ERR_INVALID_CONN           Invalid network connection number.
*                               NET_CONN_ERR_NOT_USED               Network connection NOT currently used.
*
* Return(s)   : none.
*
* Caller(s)   : NetTCP_RxPktConnHandlerSyncRxd(),
*               NetTCP_RxPktConnHandlerSyncTxd().
*
* Note(s)     : (2) The 'NET_CONN_CFG_FAMILY' pre-processor 'else'-conditional code will never be compiled/linked
*                   since 'net_conn.h' ensures that the family type configuration constant (NET_CONN_CFG_FAMILY)
*                   is configured with an appropriate family type value (see 'net_conn.h  CONFIGURATION ERRORS').
*                   The 'else'-conditional code is included for completeness & as an extra precaution in case
*                   'net_conn.h' is incorrectly modified.
*********************************************************************************************************
*/
/*$PAGE*/
static  void  NetTCP_RxPktConnHandlerSignalConn (NET_TCP_CONN        *pconn,
                                                 NET_TCP_CONN_STATE   state,
                                                 NET_ERR             *perr)
{
#if ((NET_CTR_CFG_ERR_EN      == DEF_ENABLED)                    && \
     (CPU_CFG_CRITICAL_METHOD == CPU_CRITICAL_METHOD_STATUS_LOCAL))
    CPU_SR       cpu_sr;
#endif
    NET_CONN_ID  conn_id;
    NET_CONN_ID  conn_id_app;
    NET_ERR      err;
    CPU_BOOLEAN  err_conn;


    conn_id = pconn->ID_Conn;

                                                                /* ------------------- SIGNAL CONN -------------------- */
    switch (state) {
        case NET_TCP_CONN_STATE_FREE:
             NET_CTR_ERR_INC(NetTCP_ErrNotUsedCtr);
            *perr = NET_TCP_ERR_CONN_NOT_USED;
             return;                                            /* Prevent 'break NOT reachable' compiler warning.      */



        case NET_TCP_CONN_STATE_SYNC_RXD_PASSIVE:               /* See Note #1a.                                        */
                                                                /* Get app conn id clone.                               */
             conn_id_app = NetConn_ID_AppCloneGet(conn_id, perr);
             if (*perr != NET_CONN_ERR_NONE) {
                  return;
             }

             if (conn_id_app == NET_CONN_ID_NONE) {
                *perr = NET_TCP_ERR_INVALID_CONN_ID;
                 return;
             }
                                                                /* Signal app conn accept.                              */
#if (NET_CONN_CFG_FAMILY == NET_CONN_FAMILY_IP_V4_SOCK)
             NetSock_ConnSignalAccept((NET_SOCK_ID) conn_id_app,
                                      (NET_CONN_ID) conn_id,
                                      (NET_ERR   *)&err);
            *perr = (err != NET_SOCK_ERR_NONE) ? NET_TCP_ERR_CONN_FAIL
                                               : NET_TCP_ERR_NONE;

#else                                                           /* See Note #2.                                         */
            (void)&err;                                         /* Prevent compiler warning.                            */
            *perr = NET_CONN_ERR_INVALID_FAMILY;
             return;
#endif
             if (*perr != NET_TCP_ERR_NONE) {
                  return;
             }
             break;



        case NET_TCP_CONN_STATE_SYNC_RXD_ACTIVE:                /* See Note #1b.                                        */
        case NET_TCP_CONN_STATE_SYNC_TXD:
                                                                /* Get app conn id.                                     */
             conn_id_app = NetConn_ID_AppGet(conn_id, perr);
             if (*perr != NET_CONN_ERR_NONE) {
                  return;
             }

             if (conn_id_app == NET_CONN_ID_NONE) {
                *perr = NET_TCP_ERR_INVALID_CONN_ID;
                 return;
             }
                                                                /* Signal app conn req.                                 */
#if (NET_CONN_CFG_FAMILY == NET_CONN_FAMILY_IP_V4_SOCK)
             NetSock_ConnSignalReq((NET_SOCK_ID) conn_id_app,
                                   (NET_ERR   *)&err);
            *perr = (err != NET_SOCK_ERR_NONE) ? NET_TCP_ERR_CONN_FAIL
                                               : NET_TCP_ERR_NONE;

#else                                                           /* See Note #2.                                         */
            (void)&err;                                         /* Prevent compiler warning.                            */
            *perr = NET_CONN_ERR_INVALID_FAMILY;
             return;
#endif
             if (*perr != NET_TCP_ERR_NONE) {
                  return;
             }
             break;



/*$PAGE*/
        case NET_TCP_CONN_STATE_SYNC_RXD:                       /* See Notes #1a & #1b.                                 */
                                                                /* Get app conn id.                                     */
             err_conn    = DEF_NO;
             conn_id_app = NetConn_ID_AppGet(conn_id, perr);
             if (*perr != NET_CONN_ERR_NONE) {
                 err_conn = DEF_YES;
             }

             if (conn_id_app == NET_CONN_ID_NONE) {
                 err_conn = DEF_YES;
             }

             if (err_conn == DEF_YES) {                         /* If app conn id get failed, get app conn id clone.    */
                 conn_id_app = NetConn_ID_AppCloneGet(conn_id, perr);
                 if (*perr != NET_CONN_ERR_NONE) {
                      return;
                 }

                 if (conn_id_app == NET_CONN_ID_NONE) {
                    *perr = NET_TCP_ERR_INVALID_CONN_ID;
                     return;
                 }
             }

#if (NET_CONN_CFG_FAMILY == NET_CONN_FAMILY_IP_V4_SOCK)
                                                                /* Signal app conn req.                                 */
             NetSock_ConnSignalReq((NET_SOCK_ID) conn_id_app,
                                   (NET_ERR   *)&err);
            *perr = (err != NET_SOCK_ERR_NONE) ? NET_TCP_ERR_CONN_FAIL
                                               : NET_TCP_ERR_NONE;
             if (*perr != NET_TCP_ERR_NONE) {
                  return;
             }

                                                                /* Signal app conn accept.                              */
             NetSock_ConnSignalAccept((NET_SOCK_ID) conn_id_app,
                                      (NET_CONN_ID) conn_id,
                                      (NET_ERR   *)&err);
            *perr = (err != NET_SOCK_ERR_NONE) ? NET_TCP_ERR_CONN_FAIL
                                               : NET_TCP_ERR_NONE;

#else                                                           /* See Note #2.                                         */
            (void)&err;                                         /* Prevent compiler warning.                            */
            *perr = NET_CONN_ERR_INVALID_FAMILY;
             return;
#endif

             if (*perr != NET_TCP_ERR_NONE) {
                  return;
             }
             break;



        case NET_TCP_CONN_STATE_CLOSED:
        case NET_TCP_CONN_STATE_LISTEN:
        case NET_TCP_CONN_STATE_CONN:
        case NET_TCP_CONN_STATE_FIN_WAIT_1:
        case NET_TCP_CONN_STATE_FIN_WAIT_2:
        case NET_TCP_CONN_STATE_CLOSING:
        case NET_TCP_CONN_STATE_TIME_WAIT:
        case NET_TCP_CONN_STATE_CLOSE_WAIT:
        case NET_TCP_CONN_STATE_LAST_ACK:
             NET_CTR_ERR_INC(NetTCP_ErrConnInvalidOpCtr);
            *perr = NET_TCP_ERR_INVALID_CONN_OP;
             return;                                            /* Prevent 'break NOT reachable' compiler warning.      */


        case NET_TCP_CONN_STATE_NONE:
        default:
             NetTCP_ConnClose((NET_TCP_CONN     *)pconn,
                              (NET_BUF_HDR      *)0,
                              (CPU_BOOLEAN       )DEF_YES,
                              (NET_TCP_CLOSE_CODE)NET_TCP_CONN_CLOSE_ALL);
             NET_CTR_ERR_INC(NetTCP_ErrConnInvalidStateCtr);
            *perr = NET_TCP_ERR_INVALID_CONN_STATE;
             return;                                            /* Prevent 'break NOT reachable' compiler warning.      */
    }


   *perr = NET_TCP_ERR_NONE;
}


/*$PAGE*/
/*
*********************************************************************************************************
*                                 NetTCP_RxPktConnHandlerSignalClose()
*
* Description : Signal application layer that TCP/transport layer connection's state is now closed.
*
* Argument(s) : pconn           Pointer to a TCP connection.
*               -----           Argument validated in NetTCP_ConnReqClose(),
*                                                     NetTCP_RxPktConnHandlerFinWait1(),
*                                                     NetTCP_RxPktConnHandlerClosing(),
*                                                     NetTCP_RxPktConnHandlerLastAck().
*
*               data_avail      Indicate whether application data is still available on the TCP connection's
*                                   application receive queue :
*
*                                   DEF_YES                         Application data is     available on the
*                                                                       closing TCP connection's application
*                                                                       receive queue.
*                                   DEF_NO                          Application data is NOT available for the
*                                                                       closing TCP connection's application
*                                                                       receive queue.
*
*               perr        Pointer to variable that will receive the return error code from this function :
*
*                               NET_TCP_ERR_NONE                    Application layer successfully signaled.
*                               NET_TCP_ERR_CONN_NOT_USED           TCP connection NOT currently used.
*                               NET_TCP_ERR_CONN_FAIL               Application layer signal failed.
*                               NET_TCP_ERR_INVALID_CONN_ID         Invalid application connection.
*                               NET_TCP_ERR_INVALID_CONN_STATE      Invalid TCP connection state.
*                               NET_TCP_ERR_INVALID_CONN_OP         Invalid TCP connection operation.
*                               NET_CONN_ERR_INVALID_FAMILY         Invalid network connection family.
*
*                                                                   -- RETURNED BY NetConn_ID_AppGet() : ---
*                               NET_ERR_INIT_INCOMPLETE             Network initialization NOT complete.
*                               NET_CONN_ERR_INVALID_CONN           Invalid network connection number.
*                               NET_CONN_ERR_NOT_USED               Network connection NOT currently used.
*
* Return(s)   : none.
*
* Caller(s)   : NetTCP_ConnReqClose(),
*               NetTCP_RxPktConnHandlerFinWait1(),
*               NetTCP_RxPktConnHandlerClosing(),
*               NetTCP_RxPktConnHandlerLastAck().
*
* Note(s)     : (1) (a) RFC #793, Section 3.9 'Event Processing : SEGMENT ARRIVES : Check ACK Field :
*                       FIN-WAIT-2 STATE' states that "if the retransmission queue is empty, the user's
*                       CLOSE can be acknowledged".
*
*                   (b) However, TCP connection should signal the application layer that "the user's close
*                       [is] acknowledged" whenever its re-transmit queue becomes &/or is empty :
*
*                       (1) Transition from LISTEN     to CLOSED
*                       (2) Transition from SYN-SENT   to CLOSED
*
*                       (3) Transition from FIN-WAIT-1 to ...           See also 'NetTCP_RxPktConnHandlerFinWait1()
*                                                                                    Note #2d2B2'
*                           (A) FIN-WAIT-2
*                           (B) TIME-WAIT
*
*                       (4) Transition from CLOSING    to TIME-WAIT     See also 'NetTCP_RxPktConnHandlerClosing()
*                                                                                    Note #2d2B2a2'
*
*                       (5) Transition from LAST-ACK   to CLOSED
*
*               (2) Once an application connection has been signaled of its close, the application connection is
*                   responsible for closing its remaining connection(s).
*
*                   See also 'NetTCP_ConnCloseHandler()  Note #2b1B'.
*
*               (3) The 'NET_CONN_CFG_FAMILY' pre-processor 'else'-conditional code will never be compiled/linked
*                   since 'net_conn.h' ensures that the family type configuration constant (NET_CONN_CFG_FAMILY)
*                   is configured with an appropriate family type value (see 'net_conn.h  CONFIGURATION ERRORS').
*                   The 'else'-conditional code is included for completeness & as an extra precaution in case
*                   'net_conn.h' is incorrectly modified.
*********************************************************************************************************
*/
/*$PAGE*/
static  void  NetTCP_RxPktConnHandlerSignalClose (NET_TCP_CONN  *pconn,
                                                  CPU_BOOLEAN    data_avail,
                                                  NET_ERR       *perr)
{
#if ((NET_CTR_CFG_ERR_EN      == DEF_ENABLED)                    && \
     (CPU_CFG_CRITICAL_METHOD == CPU_CRITICAL_METHOD_STATUS_LOCAL))
    CPU_SR       cpu_sr;
#endif
    NET_CONN_ID  conn_id;
    NET_CONN_ID  conn_id_app;
    NET_ERR      err;

                                                                /* Get conn id's.                                       */
    conn_id     = pconn->ID_Conn;
    conn_id_app = NetConn_ID_AppGet(conn_id, perr);
    if (*perr != NET_CONN_ERR_NONE) {
         return;
    }

    if (conn_id_app == NET_CONN_ID_NONE) {
       *perr = NET_TCP_ERR_INVALID_CONN_ID;
        return;
    }


                                                                /* ------------- VALIDATE TCP CONN STATE -------------- */
    switch (pconn->ConnState) {
        case NET_TCP_CONN_STATE_FREE:
             NET_CTR_ERR_INC(NetTCP_ErrNotUsedCtr);
            *perr = NET_TCP_ERR_CONN_NOT_USED;
             return;                                            /* Prevent 'break NOT reachable' compiler warning.      */


        case NET_TCP_CONN_STATE_SYNC_RXD_PASSIVE:
        case NET_TCP_CONN_STATE_SYNC_RXD_ACTIVE:
        case NET_TCP_CONN_STATE_SYNC_RXD:
        case NET_TCP_CONN_STATE_CONN:
        case NET_TCP_CONN_STATE_FIN_WAIT_2:
        case NET_TCP_CONN_STATE_TIME_WAIT:
        case NET_TCP_CONN_STATE_CLOSE_WAIT:
        case NET_TCP_CONN_STATE_CLOSING_DATA_AVAIL:
             NET_CTR_ERR_INC(NetTCP_ErrConnInvalidOpCtr);
            *perr = NET_TCP_ERR_INVALID_CONN_OP;
             return;                                            /* Prevent 'break NOT reachable' compiler warning.      */


        case NET_TCP_CONN_STATE_LISTEN:                         /* See Note #1b1.                                       */
        case NET_TCP_CONN_STATE_SYNC_TXD:                       /* See Note #1b2.                                       */
        case NET_TCP_CONN_STATE_FIN_WAIT_1:                     /* See Note #1b3.                                       */
        case NET_TCP_CONN_STATE_CLOSING:                        /* See Note #1b4.                                       */
        case NET_TCP_CONN_STATE_LAST_ACK:                       /* See Note #1b5.                                       */
             break;


        case NET_TCP_CONN_STATE_NONE:
        case NET_TCP_CONN_STATE_CLOSED:
        default:
             NetTCP_ConnClose((NET_TCP_CONN     *)pconn,
                              (NET_BUF_HDR      *)0,
                              (CPU_BOOLEAN       )DEF_YES,
                              (NET_TCP_CLOSE_CODE)NET_TCP_CONN_CLOSE_ALL);
             NET_CTR_ERR_INC(NetTCP_ErrConnInvalidStateCtr);
            *perr = NET_TCP_ERR_INVALID_CONN_STATE;
             return;                                            /* Prevent 'break NOT reachable' compiler warning.      */
    }


/*$PAGE*/
                                                                /* ------------------- SIGNAL CLOSE ------------------- */
#if (NET_CONN_CFG_FAMILY == NET_CONN_FAMILY_IP_V4_SOCK)
                                                                /* Signal app conn close.                               */
    NetSock_ConnSignalClose((NET_SOCK_ID) conn_id_app,
                            (CPU_BOOLEAN) data_avail,
                            (NET_ERR   *)&err);
   *perr = (err != NET_SOCK_ERR_NONE) ? NET_TCP_ERR_CONN_FAIL
                                      : NET_TCP_ERR_NONE;

#else                                                           /* See Note #3.                                         */
   (void)&data_avail;                                           /* Prevent compiler warnings.                           */
   (void)&err;
   *perr = NET_CONN_ERR_INVALID_FAMILY;
    return;
#endif

    if (*perr != NET_TCP_ERR_NONE) {
         return;
    }

                                                                /* Clr app close flag; ...                              */
    pconn->ConnCloseAppFlag = DEF_NO;                           /* ... app closes rem'ing conn(s) [see Note #2].        */


   *perr = NET_TCP_ERR_NONE;
}


/*$PAGE*/
/*
*********************************************************************************************************
*                                      NetTCP_RxPktConnIsValidSeq()
*
* Description : Validate a received segment's sequence number with current TCP connection.
*
* Argument(s) : pconn       Pointer to a TCP connection.
*
*               pbuf_hdr    Pointer to network buffer header that received TCP packet.
*               --------    Argument validated in NetTCP_Rx().
*
*               perr        Pointer to variable that will receive the return error code from this function :
*
*                               NET_TCP_ERR_NONE                    Sequence number successfully validated;
*                                                                       check return value.
*                               NET_TCP_ERR_CONN_NOT_USED           TCP connection NOT currently used.
*                               NET_TCP_ERR_INVALID_CONN_STATE      Invalid TCP connection state.
*                               NET_TCP_ERR_INVALID_LEN_SEG         Invalid TCP sequence-segment length.
*
* Return(s)   : NET_TCP_CONN_RX_SEQ_INVALID,      if received sequence number invalid for the TCP connection.
*
*               NET_TCP_CONN_RX_SEQ_VALID,        if received sequence number   valid for the TCP connection.
*
*               NET_TCP_CONN_RX_SEQ_SYNC_INVALID, if received sequence number is an invalid synchronization
*                                                    for the TCP connection.
*
*               NET_TCP_CONN_RX_SEQ_SYNC,         if received sequence number is a    valid synchronization
*                                                    for the TCP connection.
*
* Caller(s)   : various.
*
* Note(s)     : (1) Validate received TCP connection sequence numbers :
*
*                       (A) Some TCP receive sequence number validation logic implemented in previous
*                           functions; include duplicate validation logic in NetTCP_RxPktConnIsValidSeq()
*                           only if debug/validation code is enabled (i.e. NET_ERR_CFG_ARG_CHK_DBG_EN is
*                           DEF_ENABLED in 'net_cfg.h').
*
*                   (a) RFC #793, Section 3.4 'Establishing a Connection : Reset Generation : 1' states
*                       that "if [a] connection [is] ... CLOSED then a reset is sent in response to any
*                       incoming segment".  Thus, ALL received segments are invalid.
*
*                   (b) RFC #793, Section 3.9 'Event Processing : SEGMENT ARRIVES : LISTEN [State]' :
*
*                       (1) "If the SYN bit is set ... the connection state should be changed to SYN-
*                            RECEIVED ... and any other control or text should be queued for processing
*                            later ... Note that any other incoming control or data ... will be processed
*                            in the SYN-RECEIVED state."
*
*                           Therefore, the ONLY TCP segment data that may be queued in the LISTEN state
*                           MUST be received in a TCP connection request segment.
*
*                       (2) Otherwise "any other control or text-bearing segment (not containing SYN)
*                           must have an ACK and thus would be discarded by the ACK processing ...
*                           [so] drop the segment".
*
*                   (c) RFC #793, Section 3.9 'Event Processing : SEGMENT ARRIVES : SYN-SENT [State] :
*                       Check SYN Bit' :
*
*                       (1) "If ... our SYN has been ACKed ... change the connection state to
*                            ESTABLISHED ... [and] if there are other controls or text in the
*                            segment then continue processing" as for the ESTABLISHED state
*                            (see Note #1d).
*
*                       (2) "Otherwise enter SYN-RECEIVED ... [and] if there are other controls or
*                            text in the segment, queue them for processing after the ESTABLISHED
*                            state has been reached."
*
*                       (3) Otherwise "if neither the SYN or RST bits is set then drop the segment".
*
*                           Therefore, the ONLY TCP segment data that may be queued in the SYN-SENT
*                           state MUST be received in a TCP connection request segment.
*$PAGE*
*                   (d) RFC #793, Section 3.9 'Event Processing : SEGMENT ARRIVES : Check Sequence
*                       Number' states that for the "SYN-RECEIVED STATE, ESTABLISHED STATE, FIN-
*                       WAIT-1 STATE, FIN-WAIT-2 STATE, CLOSE-WAIT STATE, CLOSING STATE, LAST-ACK
*                       STATE, TIME-WAIT STATE ... there are four cases for the acceptability test
*                       for an incoming segment :
*
*                                      Local
*                            Segment  Receive
*                            Length   Window   Test
*                            -------  -------  -------------------------------------------------------
*
*                       (1)     0        0        SEG.SEQ =  RCV.NXT
*
*                       (2)     0       >0        RCV.NXT =< SEG.SEQ               < RCV.NXT + RCV.WND
*
*                       (3)    >0        0        not acceptable
*
*                       (4)    >0       >0        RCV.NXT =< SEG.SEQ               < RCV.NXT + RCV.WND
*                                              or RCV.NXT =< SEG.SEQ + SEG.LEN - 1 < RCV.NXT + RCV.WND
*
*
*                       If the RCV.WND is zero, no segments will be acceptable, but special allowance
*                       should be made to accept valid ACKs ... and RSTs.
*
*                       If an incoming segment is not acceptable, an acknowledgment should be sent in
*                       reply".
*
*                       See also Note #2.
*
*                   (e) RFC #793, Section 3.9 'Event Processing : SEGMENT ARRIVES : Check SYN Bit'
*                       states that in the "SYN-RECEIVED [STATE], ESTABLISHED STATE, FIN-WAIT STATE-1,
*                       FIN-WAIT STATE-2, CLOSE-WAIT STATE, CLOSING STATE, LAST-ACK STATE, TIME-WAIT
*                       STATE ... if the SYN is in the window it is an error, send a reset, any
*                       outstanding RECEIVEs and SEND[s] should receive 'reset' responses, all segment
*                       queues should be flushed, the user should also receive an unsolicited general
*                      'connection reset' signal[, and] enter the CLOSED state".
*
*               (2) RFC #793 does NOT provide nor suggest any logic to determine/handle sequence number
*                   comparisons for sequence number windows that overflow the sequence number space.
*
*                   (a) For example, the next sequence octet to receive (RCV.NXT) is typically less than
*                       or equal to  the next received sequence octet (SEG.SEQ) :
*
*                           (1) RCV.NXT <= SEG.SEQ
*
*                       SEG.SEQ itself is also typically less than RCV.NXT plus the current receive window
*                       size (RCV.WND) :
*
*                           (2) SEG.SEQ < (RCV.NXT + RCV.WND)
*
*                       However, if (RCV.NXT + RCV.WND) or SEG.SEQ overflows the sequence number space,
*                       these values will be MUCH less than SEG.SEQ or RCV.NXT, respectively, until
*                       SEG.SEQ & RCV.NXT also overflow :
*
*                           (3) RCV.NXT + RCV.WND << RCV.NXT
*                                                 << SEG.SEQ
*
*                           (4) SEG.SEQ           << RCV.NXT
*
*                   (b) Therefore, in order to validate a received segment's sequence value as within the
*                       TCP connection's current receive window, one of the following unsigned arithmetic
*                       comparisons MUST be true :
*
*                           (1) (A) (RCV.NXT + RCV.WND) -  SEG.SEQ       <=  (RCV.NXT + RCV.WND) - RCV.NXT
*
*                               (B) (RCV.NXT + RCV.WND) -  SEG.SEQ       <=             RCV.WND
*
*                               (C) (RCV.NXT + RCV.WND) -  SEG.SEQ - 1   <   RCV.WND
*
*                               (D) (RCV.NXT + RCV.WND) - (SEG.SEQ + 1)  <   RCV.WND
*
*                                   (a) Comparison #2b1C's left-hand side decremented by one to modify the
*                                       conditional test from less-than-or-equal-to to just less-than in
*                                       order to satisfy the exact boundary conditions shown in the incoming
*                                       segment acceptability test comparisons (see Notes #1d2 & #1d4).
*
*                           (2) Substituting (SEG.SEQ + SEG.LEN - 1) into SEG.SEQ :
*
*                               (A) (RCV.NXT + RCV.WND)  -  (SEG.SEQ + SEG.LEN - 1 + 1)  <  RCV.WND
*
*                               (B) (RCV.NXT + RCV.WND)  -  (SEG.SEQ + SEG.LEN)          <  RCV.WND
*
*                   (c) In order to determine if a received segment's sequence value is within but NOT
*                       following a closing TCP connection's last valid receive sequence numbers, the
*                       following unsigned arithmetic comparison MUST be checked :
*
*                           (1)  RX.LAST  - (SEG.SEQ + SEG.LEN)  <=  (RX.LAST - RX.NXT)
*********************************************************************************************************
*/
/*$PAGE*/
static  NET_TCP_SEQ_CODE  NetTCP_RxPktConnIsValidSeq (NET_TCP_CONN  *pconn,
                                                      NET_BUF_HDR   *pbuf_hdr,
                                                      NET_ERR       *perr)
{
#if ((NET_CTR_CFG_ERR_EN      == DEF_ENABLED)                    && \
     (CPU_CFG_CRITICAL_METHOD == CPU_CRITICAL_METHOD_STATUS_LOCAL))
    CPU_SR            cpu_sr;
#endif
#if (NET_ERR_CFG_ARG_CHK_DBG_EN == DEF_ENABLED)
    NET_TCP_ACK_CODE  ack_code;
#endif
    NET_TCP_SEQ_CODE  seq_code;
    NET_TCP_SEQ_NBR   seq_nbr;
    NET_TCP_SEQ_NBR   seq_win;
    NET_TCP_SEQ_NBR   seq_win_next;
    NET_TCP_SEQ_NBR   seq_win_delta;


   *perr     = NET_TCP_ERR_NONE;
    seq_code = NET_TCP_CONN_RX_SEQ_INVALID;

    if (pconn != (NET_TCP_CONN *)0) {
        switch (pconn->ConnState) {
            case NET_TCP_CONN_STATE_FREE:
                 NET_CTR_ERR_INC(NetTCP_ErrNotUsedCtr);
                *perr =  NET_TCP_ERR_CONN_NOT_USED;
                 return (NET_TCP_CONN_RX_SEQ_INVALID);                  /* Prevent 'break NOT reachable' warning.       */


            case NET_TCP_CONN_STATE_CLOSED:                             /* See Note #1a.                                */
                 break;


            case NET_TCP_CONN_STATE_LISTEN:                             /* See Note #1b.                                */
                 if (pbuf_hdr->TCP_SegSync == DEF_YES) {                /* If sync rx'd, ..                             */
                     seq_code = NET_TCP_CONN_RX_SEQ_SYNC;               /* .. sync's seq nbr valid (see Note #1b1).     */
                 }
                 break;


            case NET_TCP_CONN_STATE_SYNC_TXD:                           /* See Note #1c.                                */
#if (NET_ERR_CFG_ARG_CHK_DBG_EN == DEF_ENABLED)                         /* See Note #1A.                                */
                 ack_code = NetTCP_RxPktConnIsValidAck(pconn, pbuf_hdr, perr);
                 if (*perr != NET_TCP_ERR_NONE) {
                      return (NET_TCP_CONN_RX_SEQ_INVALID);
                 }
                 if (ack_code != NET_TCP_CONN_RX_ACK_VALID) {
                     return (NET_TCP_CONN_RX_SEQ_INVALID);
                 }
#endif
                 if (pbuf_hdr->TCP_SegSync == DEF_YES) {                /* If valid sync rx'd, ..                       */
                     seq_code = NET_TCP_CONN_RX_SEQ_SYNC;               /* .. sync's seq nbr valid.                     */
                 }
                 break;

/*$PAGE*/
            case NET_TCP_CONN_STATE_SYNC_RXD:                           /* See Notes #1d & #1e.                         */
            case NET_TCP_CONN_STATE_SYNC_RXD_PASSIVE:
            case NET_TCP_CONN_STATE_SYNC_RXD_ACTIVE:
            case NET_TCP_CONN_STATE_CONN:
            case NET_TCP_CONN_STATE_FIN_WAIT_1:
            case NET_TCP_CONN_STATE_FIN_WAIT_2:
            case NET_TCP_CONN_STATE_CLOSING:
            case NET_TCP_CONN_STATE_TIME_WAIT:
            case NET_TCP_CONN_STATE_CLOSE_WAIT:
            case NET_TCP_CONN_STATE_LAST_ACK:
                 if (pbuf_hdr->TCP_SegSync != DEF_NO) {                 /* If sync rx'd, ...                            */
                     return (NET_TCP_CONN_RX_SEQ_SYNC_INVALID);         /* ... rtn invalid sync (see Note #1e).         */
                 }

                 if (pconn->RxWinSizeActual > 0) {                      /* If rx win size > 0, ...                      */
                                                                        /* ... chk for seg seq within rx win.           */
                     switch (pconn->RxQ_State) {
                         case NET_TCP_RX_Q_STATE_CONN_SYNC:
                         case NET_TCP_RX_Q_STATE_CONN:
                              seq_win_next  = (NET_TCP_SEQ_NBR)(pconn->RxSeqNbrNext  + pconn->RxWinSizeActual);
                              seq_nbr       = (NET_TCP_SEQ_NBR)(pbuf_hdr->TCP_SeqNbr + 1);
                              seq_win_delta = (NET_TCP_SEQ_NBR)(seq_win_next         - seq_nbr);

                                                                        /* If [(next + win) -     seq    ] < win size,  */
                              if (seq_win_delta < pconn->RxWinSizeActual) {
                                  seq_code = NET_TCP_CONN_RX_SEQ_VALID; /* .. seq nbr within rx win (see Note #1d2).    */

                              } else if (pbuf_hdr->TCP_SegLen > 0) {
                                  seq_nbr       = (NET_TCP_SEQ_NBR)(pbuf_hdr->TCP_SeqNbr + pbuf_hdr->TCP_SegLen);
                                  seq_win_delta = (NET_TCP_SEQ_NBR)(seq_win_next         - seq_nbr);
                                                                        /* If [(next + win) - (seq + len)] < win size,  */
                                  if (seq_win_delta < pconn->RxWinSizeActual) {
                                                                        /* .. seq nbr within rx win (see Note #1d4).    */
                                      seq_code = NET_TCP_CONN_RX_SEQ_VALID;
                                  }
                              }
                              break;


                         case NET_TCP_RX_Q_STATE_CONN_CLOSED:
                         case NET_TCP_RX_Q_STATE_CONN_CLOSING:
                              seq_win_next  = (NET_TCP_SEQ_NBR) pconn->RxSeqNbrLast;
                              seq_nbr       = (NET_TCP_SEQ_NBR)(pbuf_hdr->TCP_SeqNbr + pbuf_hdr->TCP_SegLen);
                              seq_win_delta = (NET_TCP_SEQ_NBR)(seq_win_next         - seq_nbr);
                              seq_win       = (NET_TCP_SEQ_NBR)(pconn->RxSeqNbrLast  - pconn->RxSeqNbrNext);
                              if (seq_win_delta <= seq_win) {           /* If [last - (seq + len)] <= [last - next], .. */
                                  seq_code = NET_TCP_CONN_RX_SEQ_VALID; /* .. seq nbr within close win (see Note #2c1). */
                              }
                              break;


                         case NET_TCP_RX_Q_STATE_NONE:
                         case NET_TCP_RX_Q_STATE_CLOSED:
                         default:
                              return (NET_TCP_CONN_RX_SEQ_INVALID);
                     }

                 } else {                                               /* Else chk for valid, zero-len seg.            */
                     if (pbuf_hdr->TCP_SegLen > 0) {                    /* If seg len > 0, ...                          */
                        *perr =  NET_TCP_ERR_INVALID_LEN_SEG;           /* ... rtn invalid seg len (see Note #1d3).     */
                         return (NET_TCP_CONN_RX_SEQ_INVALID);
                     }

                     if (pbuf_hdr->TCP_SeqNbr == pconn->RxSeqNbrNext) { /* If seq nbr equals next rx seq expected, ..   */
                         seq_code = NET_TCP_CONN_RX_SEQ_VALID;          /* .. seq nbr valid (see Note #1d1).            */
                     }
                 }
                 break;


            case NET_TCP_CONN_STATE_CLOSING_DATA_AVAIL:
                 break;


            case NET_TCP_CONN_STATE_NONE:
            default:
                 NetTCP_ConnClose(pconn, pbuf_hdr, DEF_YES, NET_TCP_CONN_CLOSE_ALL);
                 NET_CTR_ERR_INC(NetTCP_ErrConnInvalidStateCtr);
                *perr =  NET_TCP_ERR_INVALID_CONN_STATE;
                 return (NET_TCP_CONN_RX_SEQ_INVALID);                  /* Prevent 'break NOT reachable' warning.       */
        }
    }

    return (seq_code);
}


/*$PAGE*/
/*
*********************************************************************************************************
*                                      NetTCP_RxPktConnIsValidAck()
*
* Description : Validate a received segment's acknowledgement number with current TCP connection.
*
* Argument(s) : pconn       Pointer to a TCP connection.
*
*               pbuf_hdr    Pointer to network buffer header that received TCP packet.
*               --------    Argument validated in NetTCP_Rx().
*
*               perr        Pointer to variable that will receive the return error code from this function :
*
*                               NET_TCP_ERR_NONE                    Acknowledgement number successfully
*                                                                       validated; check return value.
*                               NET_TCP_ERR_CONN_NOT_USED           TCP connection NOT currently used.
*                               NET_TCP_ERR_INVALID_CONN_STATE      Invalid TCP connection state.
*
* Return(s)   : NET_TCP_CONN_RX_ACK_INVALID, if    received acknowledgement number invalid for the TCP connection.
*
*               NET_TCP_CONN_RX_ACK_VALID,   if    received acknowledgement number   valid for the TCP connection.
*
*               NET_TCP_CONN_RX_ACK_NONE,    if NO received acknowledgement number.
*
*               NET_TCP_CONN_RX_ACK_DUP,     if    received acknowledgement number is a          duplicate for the
*                                               TCP connection.
*
*               NET_TCP_CONN_RX_ACK_PREV,    if    received acknowledgement number is a previous duplicate for the
*                                               TCP connection.
*
* Caller(s)   : various.
*
* Note(s)     : (1) Validate received TCP connection acknowledgements :
*
*                   (a) RFC #793, Section 3.4 'Establishing a Connection : Reset Generation : 1' states
*                       that "if [a] connection [is] ... CLOSED then a reset is sent in response to any
*                       incoming segment".  Thus, ALL received segments, including acknowledgement
*                       segments, are invalid.
*
*                   (b) RFC #793, Section 3.9 'Event Processing : SEGMENT ARRIVES : LISTEN [State] :
*                       Check for ACK' states that "any acknowledgment is bad if it arrives on a
*                       connection still in the LISTEN state".
*
*                   (c) (1) The following sections generalize that "if SND.UNA < SEG.ACK =< SND.NXT then
*                           the ACK is acceptable", whereas "if SEG.ACK =< SND.UNA, or SEG.ACK > SND.NXT"
*                           then the acknowledgement is unacceptable :
*
*                           (A) RFC #793, Section 3.9 'Event Processing : SEGMENT ARRIVES : SYN-SENT
*                                   [State] : Check ACK Bit'
*                           (B) RFC #793, Section 3.9 'Event Processing : SEGMENT ARRIVES : Check ACK
*                                   Field : SYN-RECEIVED STATE'
*                           (C) RFC #793, Section 3.9 'Event Processing : SEGMENT ARRIVES : Check ACK
*                                   Field : ESTABLISHED  STATE'
*
*                           Including states with similar "processing as for the ESTABLISHED STATE" (see
*                           RFC #793, Section 3.9 'Event Processing : SEGMENT ARRIVES : Check ACK Field') :
*
*                           (D) FIN-WAIT-1 STATE
*                           (E) FIN-WAIT-2 STATE
*                           (F) CLOSING    STATE
*                           (G) CLOSE-WAIT STATE
*
*                           See also Note #3a.
*
*                       (2) However, RFC #793, Section 3.9 'Event Processing : SEGMENT ARRIVES : SYN-SENT
*                           [State] : Check SYN Bit' also states to "check the SYN bit ... if the ACK is
*                           ok, or there is no ACK".
*
*                           Therefore, the lack of an acknowledgement in the SYN-SENT state is acceptable.
*
*                       (3) However, RFC #793, Section 3.9 'Event Processing : SEGMENT ARRIVES : Check
*                           ACK Field : ESTABLISHED STATE' also states that in the "ESTABLISHED STATE"
*                           or any state with similar "processing as for the ESTABLISHED STATE ... if
*                           the ACK is a duplicate (SEG.ACK =< SND.UNA), it can be ignored".
*
*                           See also Note #3b.
*
*                   (d) (1) (A) RFC #793, Section 3.9 'Event Processing : SEGMENT ARRIVES : Check ACK Field :
*                               TIME-WAIT STATE' states that "the only thing that can arrive in this state is
*                               a retransmission of the remote FIN".
*
*                           (B) RFC #793, Section 3.9 'Event Processing : SEGMENT ARRIVES : Check ACK Field :
*                               LAST-ACK STATE' states that "the only thing that can arrive in this state is
*                               an acknowledgement of our FIN".
*
*                       (2) However, it is possible that some but NOT all transmitted data has been received
*                           by the remote host.  In other words, the remote host may have received some but
*                           NOT ALL transmitted data preceding this host's connection close request.
*
*                           ???? Therefore, acknowledgements validated by as within the transmit window MUST
*                           be received & processed as in connected states.
*$PAGE*
*               (2) ???? RFC #793 contains multiple errors/inconsistencies regarding the boundary conditions
*                   of TCP sequence/acknowledgement inequalities -- i.e. some of the expressions incorrectly
*                   include or exclude the equality condition.
*
*                   RFC #1122, Section 4.2.2.20 corrects some but NOT all of these errors/inconsistencies.
*
*               (3) RFC #793 does NOT provide nor suggest any logic to determine/handle sequence number
*                   comparisons for sequence number windows that overflow the sequence number space.
*
*                   (a) (1) For example, the next sequence octet to transmit (SND.NXT) is typically greater
*                           than or equal to the last unacknowledged transmit sequence octet (SND.UNA) :
*
*                               (A) SND.NXT >= SND.UNA
*
*                           However, when SND.NXT overflows the sequence number space, it will be MUCH less
*                           than SND.UNA until SND.UNA also overflows :
*
*                               (B) SND.NXT << SND.UNA
*
*                       (2) Therefore, in order to validate a received segment's acknowledgement value
*                           (SEG.ACK) as within the TCP connection's current transmit acknowledgement
*                           window, the following unsigned arithmetic comparison MUST be true :
*
*                               (A) (SND.NXT - SEG.ACK)  <  (SND.NXT - SND.UNA)
*
*                   (b) (1) Typically, duplicate acknowledgements are less than or equal to the last
*                           unacknowledged transmit sequence octet (SND.UNA) :
*
*                               (A) SEG.ACK <= SND.UNA
*
*                           However, when SND.UNA overflows the sequence number space, it will be MUCH less
*                           than duplicate acknowledgements until these duplicates also overflow :
*
*                               (B) SEG.ACK >> SND.UNA
*
*                       (2) Therefore, in order to validate SEG.ACK as a recent duplicate acknowledgement
*                           for the TCP connection's current transmit acknowledgement window, the following
*                           unsigned arithmetic comparison MUST be true :
*
*                               (A) (SND.UNA - SEG.ACK)  <=  (WIN_SIZE_SCALE * TxWinSizeRemote)
*
*                                       where
*
*                                           WIN_SIZE_SCALE          is some window-size scalar multiplier
*                                           TxWinSizeRemote         is the remote host's last-advertised 
*                                                                       receive window size, which is this
*                                                                       host's transmit remote window size
*********************************************************************************************************
*/

static  NET_TCP_ACK_CODE  NetTCP_RxPktConnIsValidAck (NET_TCP_CONN  *pconn,
                                                      NET_BUF_HDR   *pbuf_hdr,
                                                      NET_ERR       *perr)
{
#if ((NET_CTR_CFG_ERR_EN      == DEF_ENABLED)                    && \
     (CPU_CFG_CRITICAL_METHOD == CPU_CRITICAL_METHOD_STATUS_LOCAL))
    CPU_SR            cpu_sr;
#endif
    NET_TCP_ACK_CODE  ack_code;
    NET_TCP_SEQ_NBR   ack_delta_next;
    NET_TCP_SEQ_NBR   ack_delta_unackd;
    NET_TCP_SEQ_NBR   ack_win;
    NET_TCP_SEQ_NBR   ack_dup_win;


/*$PAGE*/
   *perr     = NET_TCP_ERR_NONE;
    ack_code = NET_TCP_CONN_RX_ACK_INVALID;

    if (pconn != (NET_TCP_CONN *)0) {
        switch (pconn->ConnState) {
            case NET_TCP_CONN_STATE_FREE:
                 NET_CTR_ERR_INC(NetTCP_ErrNotUsedCtr);
                *perr =  NET_TCP_ERR_CONN_NOT_USED;
                 return (NET_TCP_CONN_RX_ACK_INVALID);              /* Prevent 'break NOT reachable' compiler warning.  */


            case NET_TCP_CONN_STATE_CLOSED:                         /* See Note #1a.                                    */
            case NET_TCP_CONN_STATE_LISTEN:                         /* See Note #1b.                                    */
                 if (pbuf_hdr->TCP_SegAck != DEF_NO) {              /* If ack rx'd, ...                                 */
                     return (NET_TCP_CONN_RX_ACK_INVALID);          /* ... rtn invalid ack.                             */
                 }
                 ack_code = NET_TCP_CONN_RX_ACK_NONE;
                 break;


            case NET_TCP_CONN_STATE_SYNC_TXD:
                 if (pbuf_hdr->TCP_SegAck == DEF_NO) {              /* If NO ack rx'd, ...                              */
                     return (NET_TCP_CONN_RX_ACK_NONE);             /* ... rtn valid ack (see Note #1c2).               */
                 }
                                                                    /* 'break' intentionally omitted; do NOT move    .. */
                                                                    /* .. from the following case (see Note #1c1A) : .. */
                                                                    /* .. 'NET_TCP_CONN_STATE_SYNC_RXD'.                */

            case NET_TCP_CONN_STATE_SYNC_RXD:                       /* See Note #1c1B.                                  */
            case NET_TCP_CONN_STATE_SYNC_RXD_PASSIVE:
            case NET_TCP_CONN_STATE_SYNC_RXD_ACTIVE:
                 if (pbuf_hdr->TCP_SegAck != DEF_YES) {             /* If NO ack rx'd, ...                              */
                     return (NET_TCP_CONN_RX_ACK_NONE);             /* ... rtn NO ack.                                  */
                 }

                 ack_delta_next = (NET_TCP_SEQ_NBR)(pconn->TxSeqNbrNext - pbuf_hdr->TCP_AckNbr);
                 ack_win        = (NET_TCP_SEQ_NBR)(pconn->TxSeqNbrNext - pconn->TxSeqNbrUnAckd);
                 if (ack_delta_next < ack_win) {                    /* If (next - ack) < ack win, ...                   */
                     ack_code = NET_TCP_CONN_RX_ACK_VALID;          /* ... ack is within ack win (see Note #3a2A).      */
                 }
                 break;


            case NET_TCP_CONN_STATE_CONN:                           /* See Note #1c1C.                                  */
            case NET_TCP_CONN_STATE_FIN_WAIT_1:                     /* See Note #1c1D.                                  */
            case NET_TCP_CONN_STATE_FIN_WAIT_2:                     /* See Note #1c1E.                                  */
            case NET_TCP_CONN_STATE_CLOSING:                        /* See Note #1c1F.                                  */
            case NET_TCP_CONN_STATE_CLOSE_WAIT:                     /* See Note #1c1G.                                  */
            case NET_TCP_CONN_STATE_TIME_WAIT:                      /* See Note #1d2.                                   */
            case NET_TCP_CONN_STATE_LAST_ACK:                       /* See Note #1d2.                                   */
                 if (pbuf_hdr->TCP_SegAck != DEF_YES) {             /* If NO ack rx'd, ...                              */
                     return (NET_TCP_CONN_RX_ACK_NONE);             /* ... rtn NO ack.                                  */
                 }

                 ack_delta_next = (NET_TCP_SEQ_NBR)(pconn->TxSeqNbrNext - pbuf_hdr->TCP_AckNbr);
                 ack_win        = (NET_TCP_SEQ_NBR)(pconn->TxSeqNbrNext - pconn->TxSeqNbrUnAckd);
                 if (ack_delta_next < ack_win) {                    /* If (next - ack) < ack win, ...                   */
                     ack_code = NET_TCP_CONN_RX_ACK_VALID;          /* ... ack is within ack win (see Note #3a2A).      */

                 } else {
                     ack_delta_unackd = (NET_TCP_SEQ_NBR)(pconn->TxSeqNbrUnAckd - pbuf_hdr->TCP_AckNbr);
                     if (ack_delta_unackd == 0) {                   /* If (unackd - ack) = 0, ...                       */
                         ack_code = NET_TCP_CONN_RX_ACK_DUP;        /* ... ack is           dup ack.                    */
                                                                    /* ... (see Note  #1c3).                            */

                     } else {
                         ack_dup_win  = (NET_TCP_SEQ_NBR)(NET_TCP_ACK_NBR_DUP_WIN_SIZE_SCALE * pconn->TxWinSizeRemote);
                         if (ack_delta_unackd <= ack_dup_win) {     /* If (unackd - ack) <= dup ack win, ...            */
                             ack_code =  NET_TCP_CONN_RX_ACK_PREV;  /* ... ack is recent    dup ack      ...            */
                                                                    /* ... (see Notes #1c3 & #3b2A).                    */
                         }
                     }
                 }
                 break;


            case NET_TCP_CONN_STATE_CLOSING_DATA_AVAIL:
                 break;


            case NET_TCP_CONN_STATE_NONE:
            default:
                 NetTCP_ConnClose(pconn, pbuf_hdr, DEF_YES, NET_TCP_CONN_CLOSE_ALL);
                 NET_CTR_ERR_INC(NetTCP_ErrConnInvalidStateCtr);
                *perr =  NET_TCP_ERR_INVALID_CONN_STATE;
                 return (NET_TCP_CONN_RX_ACK_INVALID);              /* Prevent 'break NOT reachable' compiler warning.  */
        }
    }

    return (ack_code);
}


/*$PAGE*/
/*
*********************************************************************************************************
*                                     NetTCP_RxPktConnIsValidReset()
*
* Description : Validate a received segment's reset flag, if any, with current TCP connection.
*
* Argument(s) : pconn       Pointer to a TCP connection.
*
*               pbuf_hdr    Pointer to network buffer header that received TCP packet.
*               --------    Argument validated in NetTCP_Rx().
*
*               perr        Pointer to variable that will receive the return error code from this function :
*
*                               NET_TCP_ERR_NONE                    Received segment's reset flag successfully
*                                                                       validated; check return value.
*                               NET_TCP_ERR_CONN_NOT_USED           TCP connection NOT currently used.
*                               NET_TCP_ERR_INVALID_CONN_STATE      Invalid TCP connection state.
*
*                                                                   - RETURNED BY NetTCP_RxPktConnIsValidSeq() : -
*                               NET_TCP_ERR_INVALID_LEN_SEG         Invalid TCP sequence-segment length.
*
* Return(s)   : NET_TCP_CONN_RX_RESET_INVALID, if    received reset flag invalid for the TCP connection.
*
*               NET_TCP_CONN_RX_RESET_VALID,   if    received reset flag   valid for the TCP connection;
*                                                 i.e. reset the TCP connection.
*
*               NET_TCP_CONN_RX_RESET_NONE,    if NO received reset flag.
*
* Caller(s)   : various.
*
* Note(s)     : (1) See the following RFC's for TCP reset validation summary :
*
*                   (a) RFC #793, Section 3.4 'Establishing a Connection : Reset Processing'
*                   (b) RFC #793, Section 3.9 'Event Processing : SEGMENT ARRIVES'
*                   (c) RFC Draft-IETF-TCPm-TCPSecure #00, Section 2
*
*               (2) Validate received TCP connection resets :
*
*                       (A) Some TCP receive reset validation logic implemented in previous functions; include
*                           duplicate validation logic in NetTCP_RxPktConnIsValidReset() only if debug/validation
*                           code is enabled (i.e. NET_ERR_CFG_ARG_CHK_DBG_EN is DEF_ENABLED in 'net_cfg.h').
*
*                   (a) (1) RFC #793, Section 3.9 'Event Processing : SEGMENT ARRIVES : CLOSED [State]' states
*                           that "if the state is CLOSED ... an incoming segment containing a RST is discarded".
*
*                       (2) (A) RFC #793, Section 3.9 'Event Processing : SEGMENT ARRIVES : LISTEN [State]'
*                               states that if "the state is LISTEN ... an incoming RST should be ignored".
*
*                           (B) RFC #793, Section 3.4 'Establishing a Connection : Reset Processing' reiterates
*                               that "if the receiver ... of a RST ... was in the LISTEN state, it ignores it".
*
*                       (3) (A) RFC #793, Section 3.9 'Event Processing : SEGMENT ARRIVES : SYN-SENT [State] :
*                               Check RST Bit' states that "if the RST bit is set [and] if the ACK was
*                               acceptable then ... enter CLOSED state".
*
*                           (B) RFC #793, Section 3.4 'Establishing a Connection : Reset Processing' reiterates
*                               that "in the SYN-SENT state (a RST received in response to an initial SYN), the
*                               RST is acceptable if the ACK field acknowledges the SYN".
*
*                               (1) However, since receiving a TCP connection request/synchronization segment 
*                                   with no acknowledgement number in the SYN-SENT state is permitted, then
*                                   a received TCP reset segment with no acknowledgement number MUST also be
*                                   acceptable.
*
*                           See also Note #2a5C.
*$PAGE*
*                       (4) (A) (1) RFC #793, Section 3.4 'Establishing a Connection : Reset Processing'
*                                   summarizes that "in all states except SYN-SENT, all reset (RST) segments
*                                   are validated by checking their SEQ-fields.  A reset is valid if its
*                                   sequence number is in the window".
*
*                               (2) RFC #793, Section 3.9 'Event Processing : SEGMENT ARRIVES : Check RST Bit'
*                                   reiterates that the received segment's reset is valid if and only if its
*                                   sequence number is valid since it follows RFC #793, Section 3.9 'Event
*                                   Processing : SEGMENT ARRIVES : Check Sequence Number'.
*
*                               (3) RFC #793, Section 3.3 states "that when the receive window is zero no
*                                   segments should be acceptable except ACK segments ... However, even when
*                                   the receive window is zero, a TCP must process the RST ... fields of all
*                                   incoming segments".
*
*                                   However, this contradicts the following sections which state that a
*                                   "received segment's reset is valid if and only if its sequence number if
*                                   valid" & that "if an incoming segment is not acceptable ... [and] the RST
*                                   bit is set, ... drop the segment" :
*
*                                   (a) RFC #793, Section 3.4 'Establishing a Connection : Reset Processing'
*                                   (b) RFC #793, Section 3.9 'Event Processing : SEGMENT ARRIVES : Check
*                                           Sequence Number'
*
*                               See also Note #2a5B.
*
*                           (B) (1) RFC #793, Section 3.9 'Event Processing : SEGMENT ARRIVES : Check RST Bit'
*                                   states that in the "SYN-RECEIVED STATE" that "if the RST bit is set [and]
*                                   this connection was initiated with a passive OPEN (i.e., came from the
*                                   LISTEN state), then return this connection to the LISTEN state ... If this
*                                   connection was initiated with an active OPEN (i.e., came from SYN-SENT state)
*                                   then the connection was refused, ... enter the CLOSED state".
*
*                               (2) RFC #793, Section 3.4 'Establishing a Connection : Reset Processing'
*                                   reiterates that "if the receiver ... of a RST ... was in SYN-RECEIVED state
*                                   and had previously been in the LISTEN state, then the receiver returns to
*                                   the LISTEN state, otherwise the receiver aborts the connection and goes to
*                                   the CLOSED state".
*
*                               (3) However, since TCP connections opened from the LISTEN state are cloned from
*                                   the original LISTEN-state TCP connection, it is NOT necessary to return ANY
*                                   reset TCP connection from the SYN-RECEIVED state back to the LISTEN state.
*
*                               See also Note #2a5A.
*
*                           (C) (1) RFC #793, Section 3.4 'Establishing a Connection : Reset Processing' states
*                                   that "if the receiver ... of a RST ... was in any other state [other than
*                                   LISTEN or SYN-RECEIVED], it aborts the connection and advises the user and
*                                   goes to the CLOSED state".
*
*                               (2) RFC #793, Section 3.9 'Event Processing : SEGMENT ARRIVES : Check RST Bit'
*                                   states that in the "ESTABLISHED, FIN-WAIT-1, FIN-WAIT-2, CLOSE-WAIT" states
*                                   that "if the RST bit is set then, any outstanding RECEIVEs and SEND[s] should
*                                   receive 'reset' responses.  All segment queues should be flushed.  Users
*                                   should also receive an unsolicited general 'connection reset' signal[, and]
*                                   enter the CLOSED state".
*
*                               (3) RFC #793, Section 3.9 'Event Processing : SEGMENT ARRIVES : Check RST Bit'
*                                   states that in the "CLOSING STATE, LAST-ACK STATE, TIME-WAIT" states that
*                                   "if the RST bit is set then, enter the CLOSED state".
*
*                               See also Note #2a5A.
*$PAGE*
*                       (5) (A) RFC Draft-IETF-TCPm-TCPSecure #00, Section 2.2 amends the "handling of a segment 
*                               with the RST bit when in a synchronized state" to "provide some protection against
*                                ... blind reset attack[s] using the RST bit" :
*
*                               (a) "If the RST bit is set and the sequence number is outside the expected window,
*                                    silently drop the segment."
*
*                               (b) "If the RST bit is exactly the next expected sequence number [sic], reset the
*                                    connection"; it is assumed that this should read "if the RST bit is set and
*                                    the sequence number is exactly the next expected sequence number, reset the
*                                    connection."
*
*                               (c) "If the RST bit is set and the sequence number does not exactly match
*                                    the next expected sequence value, yet is within the acceptable window
*                                    (RCV.NXT <= SEG.SEQ < RCV.NXT+RCV.WND) send an acknowledgment."
*
*                           (B) ???? Although RFC Draft-IETF-TCPm-TCPSecure #00 explicitly states that this 
*                               amendment applies only to the "handling of a ... RST ... when in a synchronized 
*                               state", it is assumed that this should also apply to the SYN-RECEIVED state.
*
*                           (C) (1) ???? In addition, it is assumed that a similar validation should also
*                                   apply to the SYN-SENT state.  Since the SYN-SENT state validates a
*                                   received TCP reset segment based only on the segment's acknowledgement,
*                                   a similar validation could require that the acknowledgement "exactly
*                                   match the next expected sequence value" -- i.e. the initial connection
*                                   synchronization sequence number plus one.
*
*                               (2) However, a specific check for the exact acknowledgement is NOT necessary
*                                   since NO data is transmitted from the SYN-SENT state.  Therefore, the ONLY
*                                   value to be acknowledged is the initial connection synchronization sequence
*                                   number.
*
*                           (D) ???? In addition, RFC Draft-IETF-TCPm-TCPSecure #00 does NOT provide a precedence 
*                               priority for handling TCP segments received with BOTH the RST & SYN bits set.
*
*                               ???? Therefore, since it does NOT seem reasonable to reset a TCP connection
*                               due to a TCP segment that also attempted to synchronize the TCP connection,
*                               it is assumed that the amended handling of the SYN bit should take precedence
*                               over the amended handling of the RST bit.
*
*                   (b) RFC #1122, Section 4.2.2.12 states that "a TCP SHOULD allow a received RST segment
*                       to include data".
*********************************************************************************************************
*/

static  NET_TCP_RESET_CODE  NetTCP_RxPktConnIsValidReset (NET_TCP_CONN  *pconn,
                                                          NET_BUF_HDR   *pbuf_hdr,
                                                          NET_ERR       *perr)
{
#if ((NET_CTR_CFG_ERR_EN      == DEF_ENABLED)                    && \
     (CPU_CFG_CRITICAL_METHOD == CPU_CRITICAL_METHOD_STATUS_LOCAL))
    CPU_SR              cpu_sr;
#endif
#if (NET_ERR_CFG_ARG_CHK_DBG_EN == DEF_ENABLED)
    NET_TCP_ACK_CODE    ack_code;
    NET_TCP_SEQ_CODE    seq_code;
#endif
    NET_TCP_RESET_CODE  reset_code;


/*$PAGE*/
   *perr = NET_TCP_ERR_NONE;
    if (pbuf_hdr->TCP_SegReset != DEF_YES) {                        /* If NO reset rx'd, ...                            */
        return (NET_TCP_CONN_RX_RESET_NONE);                        /* ... rtn NONE.                                    */
    }


    reset_code = NET_TCP_CONN_RX_RESET_INVALID;

    if (pconn != (NET_TCP_CONN *)0) {
        switch (pconn->ConnState) {
            case NET_TCP_CONN_STATE_FREE:
                 NET_CTR_ERR_INC(NetTCP_ErrNotUsedCtr);
                *perr =  NET_TCP_ERR_CONN_NOT_USED;
                 return (NET_TCP_CONN_RX_RESET_INVALID);            /* Prevent 'break NOT reachable' compiler warning.  */


            case NET_TCP_CONN_STATE_CLOSED:                         /* See Note #2a1.                                   */
            case NET_TCP_CONN_STATE_LISTEN:                         /* See Note #2a2.                                   */
                 break;


            case NET_TCP_CONN_STATE_SYNC_TXD:                       /* See Note #2a3.                                   */
#if (NET_ERR_CFG_ARG_CHK_DBG_EN == DEF_ENABLED)                     /* See Note #2A.                                    */
                 ack_code = NetTCP_RxPktConnIsValidAck(pconn, pbuf_hdr, perr);
                 if (*perr != NET_TCP_ERR_NONE) {
                      return (NET_TCP_CONN_RX_RESET_INVALID);
                 }
                 if (ack_code == NET_TCP_CONN_RX_ACK_INVALID) {
                     return (NET_TCP_CONN_RX_RESET_INVALID);
                 }
#endif
                 reset_code = NET_TCP_CONN_RX_RESET_VALID;
                 break;


            case NET_TCP_CONN_STATE_SYNC_RXD:                       /* See Notes #2a4B & #2a5B.                         */
            case NET_TCP_CONN_STATE_SYNC_RXD_PASSIVE:
            case NET_TCP_CONN_STATE_SYNC_RXD_ACTIVE:
            case NET_TCP_CONN_STATE_CONN:                           /* See Notes #2a4C & #2a5A.                         */
            case NET_TCP_CONN_STATE_FIN_WAIT_1:
            case NET_TCP_CONN_STATE_FIN_WAIT_2:
            case NET_TCP_CONN_STATE_CLOSING:
            case NET_TCP_CONN_STATE_TIME_WAIT:
            case NET_TCP_CONN_STATE_CLOSE_WAIT:
            case NET_TCP_CONN_STATE_LAST_ACK:
#if (NET_ERR_CFG_ARG_CHK_DBG_EN == DEF_ENABLED)                     /* See Note #2A.                                    */
                 seq_code = NetTCP_RxPktConnIsValidSeq(pconn, pbuf_hdr, perr);
                 if (*perr != NET_TCP_ERR_NONE) {
                      return (NET_TCP_CONN_RX_RESET_INVALID);
                 }
                 if (seq_code != NET_TCP_CONN_RX_SEQ_VALID) {
                     return (NET_TCP_CONN_RX_RESET_INVALID);
                 }
#endif
                 if (pbuf_hdr->TCP_SeqNbr == pconn->RxSeqNbrNext) { /* If seq nbr equals next rx seq expected ...       */
                     reset_code = NET_TCP_CONN_RX_RESET_VALID;      /* ... (see Note #2a5Ab), rtn valid reset.          */
                 }
                 break;


            case NET_TCP_CONN_STATE_CLOSING_DATA_AVAIL:
                 break;


            case NET_TCP_CONN_STATE_NONE:
            default:
                 NetTCP_ConnClose(pconn, pbuf_hdr, DEF_YES, NET_TCP_CONN_CLOSE_ALL);
                 NET_CTR_ERR_INC(NetTCP_ErrConnInvalidStateCtr);
                *perr =  NET_TCP_ERR_INVALID_CONN_STATE;
                 return (NET_TCP_CONN_RX_RESET_INVALID);                /* Prevent 'break NOT reachable' warning.       */
        }
    }

    return (reset_code);
}


/*$PAGE*/
/*
*********************************************************************************************************
*                                         NetTCP_RxPktFree()
*
* Description : Free network buffer(s).
*
* Argument(s) : pbuf_q      Pointer to network buffer queue.
*
* Return(s)   : none.
*
* Caller(s)   : NetTCP_RxAppData(),
*               NetTCP_RxPktConnHandler(),
*               NetTCP_RxPktConnHandlerRxQ_AppData().
*
* Note(s)     : none.
*********************************************************************************************************
*/

static  void  NetTCP_RxPktFree (NET_BUF  *pbuf_q)
{
    NetBuf_FreeBufQ_PrimList((NET_BUF *)pbuf_q,
                             (NET_CTR *)0);
}


/*
*********************************************************************************************************
*                                        NetTCP_RxPktDiscard()
*
* Description : On any TCP Receive errors, discard TCP packet(s) & buffer(s).
*
* Argument(s) : pbuf        Pointer to network buffer.
*
*               perr        Pointer to variable that will receive the return error code from this function :
*
*                               NET_ERR_RX                      Receive error; packet discarded.
*
* Return(s)   : none.
*
* Caller(s)   : NetTCP_Rx(),
*               NetTCP_RxPktConnHandler().
*
* Note(s)     : none.
*********************************************************************************************************
*/

static  void  NetTCP_RxPktDiscard (NET_BUF  *pbuf,
                                   NET_ERR  *perr)
{
    NET_CTR  *pctr;


#if (NET_CTR_CFG_ERR_EN == DEF_ENABLED)
    pctr = (NET_CTR *)&NetTCP_ErrRxPktDiscardedCtr;
#else
    pctr = (NET_CTR *) 0;
#endif
    NetBuf_FreeBufQ_PrimList((NET_BUF *)pbuf,
                             (NET_CTR *)pctr);

   *perr = NET_ERR_RX;
}


/*$PAGE*/
/*
*********************************************************************************************************
*                                      NetTCP_RxConnWinSizeCfg()
*
* Description : (1) Configure TCP connection's receive window controls :
*
*                   (a) Configure TCP connection's receive window update threshold
*
*
* Argument(s) : pconn       Pointer to a TCP connection.
*               -----       Argument validated in NetTCP_ConnCfg().
*
* Return(s)   : none.
*
* Caller(s)   : NetTCP_ConnCfg(),
*               NetTCP_ConnCfgRxWinSize().
*
* Note(s)     : (2) A TCP connection's receive window controls should NOT be updated until after the
*                   following TCP connection control(s) have been configured :
*
*                       (a) TCP connection's configured receive window  size ('RxWinSizeCfgd')
*                              [see 'NetTCP_RxConnWinSizeCfgUpdateTh()  Note #2a']
*
*                       (b) TCP connection's connection maximum segment size ('MaxSegSizeConn')
*                              [see 'NetTCP_RxConnWinSizeCfgUpdateTh()  Note #2b']
*********************************************************************************************************
*/

static  void  NetTCP_RxConnWinSizeCfg (NET_TCP_CONN  *pconn)
{
    NetTCP_RxConnWinSizeCfgUpdateTh(pconn);
}


/*$PAGE*/
/*
*********************************************************************************************************
*                                  NetTCP_RxConnWinSizeCfgUpdateTh()
*
* Description : Configure TCP connection's receive window update threshold.
*
* Argument(s) : pconn       Pointer to a TCP connection.
*               -----       Argument validated in NetTCP_RxConnWinSizeCfg().
*
* Return(s)   : none.
*
* Caller(s)   : NetTCP_RxConnWinSizeCfg().
*
* Note(s)     : (1) RFC #1122, Section 4.2.3.3 states that "the suggested SWS avoidance algorithm for
*                   the receiver is ... to avoid advancing the right window edge RCV.NXT+RCV.WND ...
*                   until the reduction satisfies" :
*
*                       (a) RCV.BUFF - RCV.USER - RCV.WND  >=  min(Fr * RCV.BUFF, Eff.snd.MSS)
*
*                               where
*                                   (1) RCV.BUFF        Total receive buffer space
*                                   (2) RCV.USER        Data  received but not yet consumed
*                                   (3) RCV.WND         Space advertised to sender
*                                   (4) Fr              Fraction whose recommended value is 1/2
*                                   (5) Eff.snd.MSS     Effective send MSS for the connection
*
*               (2) A TCP connection's receive window update threshold should NOT be updated until
*                   after the following TCP connection control(s) have been configured :
*
*                       (a) TCP connection's configured receive window  size ('RxWinSizeCfgd')
*                               [see 'NetTCP_ConnClr()  Note #4']
*
*                       (b) TCP connection's connection maximum segment size ('MaxSegSizeConn')
*                               [see 'NetTCP_ConnCfgMaxSegSize()  Note #1']
*********************************************************************************************************
*/

static  void  NetTCP_RxConnWinSizeCfgUpdateTh (NET_TCP_CONN  *pconn)
{
    NET_TCP_WIN_SIZE  rx_win_size_th;

                                                                /* Cfg silly win min th (see Note #1a).                 */
    rx_win_size_th           = (NET_TCP_WIN_SIZE)(((CPU_INT32U)pconn->RxWinSizeCfgd * NET_TCP_RX_SILLY_WIN_NUMER)
                                                                                    / NET_TCP_RX_SILLY_WIN_DENOM);
    pconn->RxWinSizeUpdateTh =  DEF_MIN(pconn->MaxSegSizeConn,
                                        rx_win_size_th);
}


/*$PAGE*/
/*
*********************************************************************************************************
*                                    NetTCP_RxConnWinSizeHandler()
*
* Description : (1) Handle TCP connection's receive window :
*
*                   (a) Handle   TCP connection receive window                      See Notes #2 & #3
*                   (b) Transmit TCP connection acknowledgement                     See Note  #4
*
*
* Argument(s) : pconn               Pointer to a TCP connection.
*               -----               Argument validated in NetTCP_RxAppData(),
*                                                         NetTCP_RxPktConnHandlerRxQ_Sync(),
*                                                         NetTCP_RxPktConnHandlerRxQ_Conn(),
*                                                         NetTCP_RxPktConnHandlerRxQ_AppData().
*
*               pbuf_hdr            Pointer to network buffer header that received TCP packet.
*
*               win_update_size     Size to update TCP connection's receive window (in octets).
*
*               win_update_code     Indicate how to update TCP connection receive window :
*
*                                       NET_TCP_CONN_RX_WIN_RESET   Reset     TCP connection's available
*                                                                       receive window size.
*                                       NET_TCP_CONN_RX_WIN_SET     Set       TCP connection's available
*                                                                       receive window size.
*                                       NET_TCP_CONN_RX_WIN_INC     Increment TCP connection's available
*                                                                       receive window size.
*                                       NET_TCP_CONN_RX_WIN_DEC     Decrement TCP connection's available
*                                                                       receive window size.
*
* Return(s)   : none.
*
* Caller(s)   : NetTCP_RxAppData(),
*               NetTCP_RxPktConnHandlerRxQ_Sync(),
*               NetTCP_RxPktConnHandlerRxQ_Conn(),
*               NetTCP_RxPktConnHandlerRxQ_AppData().
*
* Note(s)     : (2) RFC #793, Section 3.7 'Data Communication : Managing the Window' states that ... :
*
*                   (a) "The window sent in each segment indicates the range of sequence numbers the
*                        sender of the window (the data receiver) is currently prepared to accept.
*                        There is an assumption that this is related to the currently available data
*                        buffer space available for this connection."
*
*                       (1) A TCP connection's advertised receive window MUST NEVER be decreased to zero
*                           if NO receive data is available & ready to be read by the application layer.
*
*                           In other words, if NO received data starting from the next expected receive
*                           sequence number(s) is queued, then NO data is available to be read by the
*                           application layer.  Therefore, the receive window size MUST NOT be decreased
*                           to zero, otherwise the receive window would deadlock since the application
*                           layer would NOT be able to read & extract any data from the receive window
*                           & the TCP connection would NOT be able to receive any more data into the
*                           receive window.
*
*                       See also 'NetTCP_RxPktConnHandlerRxQ_AppData()  Note #6b'.
*
*                   (b) "The mechanisms provided allow a TCP to advertise a large window and to
*                        subsequently advertise a much smaller window without having accepted that
*                        much data.  This ... 'shrinking the window' is strongly discouraged.  The
*                        robustness principle dictates that TCPs will not shrink the window ... but
*                        will be prepared for such behavior on the part of other TCPs."
*
*                   (c) "Note that ... acknowledgments should not be delayed or unnecessary
*                        retransmissions will result.  One strategy would be to send an acknowledgment
*                        when a small segment arrives (with out [sic] updating the window information),
*                        and then to send another acknowledgment with new window information when the
*                        window is larger."
*
*                       (1) However, the following sections retract this delayed acknowledgement
*                           prohibition & state that "a TCP SHOULD implement a delayed ACK" :
*
*                           (A) RFC # 813, Section 5
*                           (B) RFC #1122, Section 4.2.3.2
*                           (C) RFC #2581, Section 4.2
*
*                       See also Note #4 & 'NetTCP_TxConnAck()  Note #6'.
*$PAGE*
*               (3) (a) RFC #813, Section 2 states that "a bad implementation of the window algorithm
*                       can lead to extremely poor performance ... This particular phenomenon ... has
*                       been given the name of Silly Window Syndrome, or SWS".
*
*                       Section 3 elaborates that "SWS is a degeneration in the throughput which develops
*                       ... whenever the acknowledgement of a small segment ... cause[s] another segment
*                       of the same small size to be sent, until ... the network ... becomes clogged with
*                       many small segments, and an equal number of acknowledgements".
*
*                   (b) (1) RFC #813, Section 4 states that "the receiver of data can take a very simple
*                           step to eliminate SWS.  When it disposes of a small amount of data, it can
*                           artificially reduce the offered window in subsequent acknowledgements, so
*                           that the useable window computed by the sender does not permit the sending
*                           of any further data.
*
*                           At some later time, when the receiver has processed a substantially larger
*                           amount of incoming data, the artificial limitation on the offered window
*                           can be removed all at once, so that the sender computes a sudden large jump
*                           rather than a sequence of small jumps in the useable window.
*
*                           For a simple implementation, ... artificially reduce the offered window until
*                           the reduction constitutes one half of the available space ... [or] at least
*                           permit one reasonably large segment".
*
*                       (2) RFC #1122, Section 4.2.3.3 reiterates that "a TCP MUST include a SWS avoidance
*                           algorithm in the receiver ... This algorithm combines with the delayed ACK
*                           algorithm ... to determine when an ACK segment containing the current window
*                           will really be sent to the receiver [sic]".
*
*                          "The solution to receiver SWS is to avoid advancing the right window edge
*                           RCV.NXT+RCV.WND in small increments, even if data is received from the
*                           network in small segments ...  The suggested SWS avoidance algorithm for
*                           the receiver is to keep RCV.NXT+RCV.WND fixed until the reduction satisfies :
*
*                               (A) RCV.BUFF - RCV.USER - RCV.WND  >=  min(Fr * RCV.BUFF, Eff.snd.MSS)
*
*                                       where
*                                           (1) RCV.BUFF        Total receive buffer space
*                                           (2) RCV.USER        Data  received but not yet consumed
*                                           (3) RCV.WND         Space advertised to sender
*                                           (4) Fr              Fraction whose recommended value is 1/2
*                                           (5) Eff.snd.MSS     Effective send MSS for the connection
*
*
*                           Note that the general effect of this algorithm is to advance RCV.WND in
*                           increments of the Eff.snd.MSS."
*
*               (4) (a) RFC #813, Section 5 states that "the receiver of data will refrain from
*                       sending an acknowledgement under certain circumstances ... Postpone
*                       sending an acknowledgement if ... the following conditions hold" :
*
*                       (1) "There is no revised window information to be sent back."
*
*                           (A) However, if any local receive window size is available to update to
*                               the remote host, an acknowledgement should be immediately transmitted.
*
*                               (1) HOWEVER, since  local receive window size updates will continually
*                                   occur for "a host that is receiving a stream of TCP data segments"
*                                   (RFC #1122, Section 4.2.3.2); it is NOT possible to both update the
*                                   local receive window & implement a delayed acknowledgement.
*
*                                   (a) #### Therefore, in order to implement a delayed acknowledgement,
*                                       the only local receive window size updates that SHOULD transmit
*                                       an immediate acknowledgement :
*
*                                       (1) Local receive window size sets/resets
*                                       (2) Local receive window size increases
*                                       (3) Local receive window size decreases to zero-sized
*
*                                   (b) #### The following local receive window size updates SHOULD NOT
*                                       transmit an immediate acknowledgement :
*
*                                       (1) Local receive window size decreases
*
*                   (b) RFC #1122, Section 4.2.3.2 states that "a delayed ACK gives the application an
*                       opportunity to update the window and perhaps to send an immediate response".
*
*                   See also 'NetTCP_TxConnAck()  Notes #4b1, #6, & #7'.
*$PAGE*
*               (5) Since the configured receive window size may be asynchronously modified by the
*                   application layer, changes in the calculated &/or advertised receive window size
*                   MUST be appropriately validated to any possible new value for the configured
*                   receive window size :
*
*                   (a) During receive window size increases, if the currently calculated receive
*                       window size is already greater than the currently configured receive window
*                       size; then the calculated window size is NOT increased, but is allowed to
*                       remain greater than  the configured window size until the calculated window
*                       size decreases below the configured window size.
*
*                   (b) During receive window size decreases, if the currently calculated receive
*                       window size is already greater than the currently configured receive window
*                       size; then the calculated window size is further decreased, but is allowed to
*                       remain greater than  the configured window size until the calculated window
*                       size decreases below the configured window size.
*
*                   (c) During receive window size decreases, if the currently configured receive
*                       window size is less than the actual configured receive window size; then
*                       the actual configured receive window size is also decremented by the window
*                       size decrease.
*********************************************************************************************************
*/

static  void  NetTCP_RxConnWinSizeHandler (NET_TCP_CONN      *pconn,
                                           NET_BUF_HDR       *pbuf_hdr,
                                           NET_TCP_WIN_SIZE   win_update_size,
                                           NET_TCP_WIN_CODE   win_update_code)
{
    CPU_BOOLEAN       tx_ack;
    NET_TCP_ACK_CODE  tx_ack_code;
    NET_TCP_WIN_SIZE  win_size_avail;
    NET_TCP_WIN_SIZE  win_size_delta;
    NET_ERR           err;


                                                                        /* ---------- HANDLE TCP CONN RX WIN ---------- */
    tx_ack = DEF_NO;

    switch (win_update_code) {
        case NET_TCP_CONN_RX_WIN_RESET:
        default:
                                                                        /* If < cfg'd win size  (see Note #5a), ...     */
             if (pconn->RxWinSizeCalcd               < pconn->RxWinSizeCfgd) {
                                                                        /* ... reset calc'd win size to cfg'd win size. */
                 pconn->RxWinSizeCalcd               = pconn->RxWinSizeCfgd;
                 pconn->RxWinSizeCfgdActual          = pconn->RxWinSizeCfgd;
                 pconn->RxWinSizeCfgdActualUpdateRem = 0;
             }
             if (pconn->RxWinSizeActual < pconn->RxWinSizeCalcd) {      /* Do NOT shrink rx win (see Note #2b).         */
                 pconn->RxWinSizeActual = pconn->RxWinSizeCalcd;
                 tx_ack                 = DEF_YES;
                 tx_ack_code            = NET_TCP_CONN_TX_ACK_IMMED;    /* See Note #4a1A1a1.                           */
             }
             break;


        case NET_TCP_CONN_RX_WIN_SET:
             if (pconn->RxWinSizeActual < win_update_size) {            /* If actual rx win size < win update, ...      */
                 pconn->RxWinSizeActual = win_update_size;              /* ... set   rx win size.                       */
                 pconn->RxWinSizeCalcd  = win_update_size;
                 tx_ack                 = DEF_YES;
                 tx_ack_code            = NET_TCP_CONN_TX_ACK_IMMED;    /* See Note #4a1A1a1.                           */
                 break;
             }                                                          /* Else inc; do NOT shrink win (see Note #2b).  */
                                                                        /* 'break' intentionally omitted; do NOT ..     */
                                                                        /* ..  move from the following case :    ..     */
                                                                        /* .. 'NET_TCP_CONN_RX_WIN_INC'.                */
/*$PAGE*/
        case NET_TCP_CONN_RX_WIN_INC:
             if (win_update_size == 0) {                                /* If NO win update, MUST NOT update win.       */
                 break;
             }

             if (pconn->RxWinSizeCalcd <= pconn->RxWinSizeCfgdActual) { /* If <= cfg'd win size (see Note #5a), ...     */
                                                                        /* ... inc  rx win size.                        */
                 win_size_avail = pconn->RxWinSizeCfgdActual - pconn->RxWinSizeCalcd;
                 if (win_size_avail > win_update_size) {                /* If avail rx win size >  win update, ...      */
                     pconn->RxWinSizeCalcd += win_update_size;          /* ... inc  rx win size by win update.          */
                 } else {                                               /* Else limit to cfg'd rx  win size.            */
                     pconn->RxWinSizeCalcd  = pconn->RxWinSizeCfgdActual;
                 }

                 if (pconn->RxWinSizeCalcd > pconn->RxWinSizeActual) {
                     win_size_delta = pconn->RxWinSizeCalcd - pconn->RxWinSizeActual;
                     if (win_size_delta >= pconn->RxWinSizeUpdateTh) {  /* If calc'd - actual rx win size >= th, ...    */
                         pconn->RxWinSizeActual = pconn->RxWinSizeCalcd;/* ... update rx win size (see Note #3b2).      */
                         tx_ack                 = DEF_YES;
                         tx_ack_code            = NET_TCP_CONN_TX_ACK_IMMED;    /* See Note #4a1A1a2.                   */
                     }

                 } else {                                               /* Prevent rx win shrink (see Note #2b).        */
                     pconn->RxWinSizeCalcd = pconn->RxWinSizeActual;
                 }
             }
             break;


        case NET_TCP_CONN_RX_WIN_DEC:
             if (win_update_size == 0) {                                /* If NO win update, MUST NOT update win.       */
                 break;
             }

             if (pconn->RxWinSizeCfgdActualUpdateRem > 0) {             /* If cfg'd win update > 0 (see Note #5c),  ..  */
                                                                        /* .. cfg actual cfg'd win update to :      ..  */
                 if (pconn->RxWinSizeCfgdActualUpdateRem > win_update_size) {
                     win_size_avail = win_update_size;                  /* .. win update size                       ..  */
                 } else {                                               /* .. or limit to cfg'd win update rem'ing; ..  */
                     win_size_avail = pconn->RxWinSizeCfgdActualUpdateRem;
                 }
                 pconn->RxWinSizeCfgdActualUpdateRem -= win_size_avail; /* .. dec cfg'd win update rem'ing; &       ..  */

                 if (pconn->RxWinSizeCfgdActual  > win_size_avail) {
                     pconn->RxWinSizeCfgdActual -= win_size_avail;      /* .. dec actual cfg'd win size.                */
                 } else {
                     pconn->RxWinSizeCfgdActual  = 0;
                 }
             }

             if (pconn->RxWinSizeCalcd  > win_update_size) {            /* If calc'd rx win size >  win update, ...     */
                 pconn->RxWinSizeCalcd -= win_update_size;              /* ... dec   rx win size by win update.         */
             } else {
                 pconn->RxWinSizeCalcd  = 0;                            /* Else limit to min rx win size.               */
             }

             if (pconn->RxWinSizeActual > 0) {
                 if (pconn->RxWinSizeActual  > win_update_size) {       /* If actual rx win size >  win update, ...     */
                     pconn->RxWinSizeActual -= win_update_size;         /* ... dec   rx win size by win update.         */
                     tx_ack_code             = NET_TCP_CONN_TX_ACK;     /*     See Note #4a1A1b1.                       */
                 } else {
                     pconn->RxWinSizeActual  = 0;                           /* Else limit to min rx win size.           */
                     tx_ack_code             = NET_TCP_CONN_TX_ACK_IMMED;   /* See Note #4a1A1a3.                       */
                 }
                 tx_ack = DEF_YES;
             }
             break;
    }


                                                                        /* --------------- TX TCP CONN ACK ------------ */
    if (tx_ack == DEF_YES) {                                            /* If rx win updated, tx ack (see Note #4a1A).  */
        if (pbuf_hdr != (NET_BUF_HDR *)0) {                             /* If rx'd pkt avail, req tx ack; but ack ...   */
            pbuf_hdr->TCP_SegAckTxReqCode =   tx_ack_code;              /* ... NOT tx'd until after rx'd pkt handling.  */
        } else {
            NetTCP_TxConnAck(pconn, pbuf_hdr, tx_ack_code, NET_TCP_CONN_CLOSE_ALL, &err);
        }
    }
}


/*$PAGE*/
/*
*********************************************************************************************************
*                                      NetTCP_TxConnWinSizeCfg()
*
* Description : (1) Configure TCP connection's transmit window controls :
*
*                   (a) Configure TCP connection's transmit window congestion controls
*                   (b) Configure TCP connection's transmit window minimum    threshold
*
*
* Argument(s) : pconn       Pointer to a TCP connection.
*               -----       Argument validated in NetTCP_ConnCfg().
*
* Return(s)   : none.
*
* Caller(s)   : NetTCP_ConnCfg().
*
* Note(s)     : (2) A TCP connection's transmit window controls should NOT be updated until after the
*                   following TCP connection control(s) have been configured :
*
*                       (a) TCP connection's maximum   transmit remote window size ('TxWinSizeRemoteMax')
*                              [see 'NetTCP_TxConnWinSizeCfgCongCtrl()  Note #5a'
*                                 & 'NetTCP_TxConnWinSizeCfgMinTh()     Note #2a']
*
*                       (b) TCP connection's remaining transmit remote window size ('TxWinSizeRemoteRem')
*                              [see 'NetTCP_TxConnWinSizeCfgCongCtrl()  Note #5b']
*
*                       (c) TCP connection's connection maximum segment size ('MaxSegSizeConn')
*                              [see 'NetTCP_TxConnWinSizeCfgCongCtrl()  Note #5c']
*********************************************************************************************************
*/

static  void  NetTCP_TxConnWinSizeCfg (NET_TCP_CONN  *pconn)
{
    NetTCP_TxConnWinSizeCfgCongCtrl(pconn);
    NetTCP_TxConnWinSizeCfgMinTh(pconn);
}


/*$PAGE*/
/*
*********************************************************************************************************
*                                  NetTCP_TxConnWinSizeCfgCongCtrl()
*
* Description : (1) Configure TCP connection's transmit window congestion controls :
*
*                   (a) Configure TCP connection's transmit window slow start threshold         See Note #2
*                   (b) Configure TCP connection's transmit window congestion controls          See Note #3
*                   (c) Reset     TCP connection's transmit window duplicate acknowledgement
*                           controls
*
* Argument(s) : pconn       Pointer to a TCP connection.
*               -----       Argument validated in NetTCP_TxConnWinSizeCfg(),
*                                                 NetTCP_TxConnWinSizeHandlerCongCtrl().
*
* Return(s)   : none.
*
* Caller(s)   : NetTCP_TxConnWinSizeCfg(),
*               NetTCP_TxConnWinSizeHandlerCongCtrl().
*
* Note(s)     : (2) RFC #2581, Section 3.1 states that "the initial value of ssthresh [slow start
*                   threshold] MAY be arbitrarily high (for example, some implementations use the
*                   size of the advertised window)".
*
*                   (a) This amends RFC #2001, Section 2.1 which previously stated that "initialization
*                       for a given connection sets ... ssthresh to 65535 bytes".
*
*                   (b) To always ensure a sufficiently high initial value, the slow start threshold
*                       initializes to the TCP connection's maximum remote window size.
*
*               (3) "The initial value of cwnd [congestion window], MUST be less than or equal to 2*SMSS
*                    bytes and MUST NOT be more than 2 segments."
*
*                   (a) This amends RFC #2001, Section 2.1 which previously stated that "initialization
*                       for a given connection sets cwnd to one segment".
*
*               (4) (a) RFC #2001, Section 2.2 states that "the TCP output routine never sends more than
*                       the minimum of cwnd and the receiver's advertised window".
*
*                   (b) RFC #2581, Section 3.1 reiterates that "the minimum of cwnd and rwnd [receiver's
*                       advertised window] governs data transmission".
*
*                   See also 'NetTCP_TxConnWinSizeUpdateAvail()  Note #1'.
*
*               (5) A TCP connection's transmit window congestion controls should NOT be updated until
*                   after the following TCP connection control(s) have been configured :
*
*                       (a) TCP connection's maximum    transmit remote window size ('TxWinSizeRemoteMax')
*                               [see 'NetTCP_RxPktConnHandlerTxWinRemote()   Note  #1a2A'
*                                  & 'NetTCP_TxConnWinSizeHandlerCongCtrl()  Notes #3a2A & #3b']
*
*                       (b) TCP connection's remaining  transmit remote window size ('TxWinSizeRemoteRem')
*                               [see 'NetTCP_RxPktConnHandlerTxWinRemote()   Note  #1a2A'
*                                  & 'NetTCP_TxConnWinSizeHandlerCongCtrl()  Notes #3a2A']
*
*                       (c) TCP connection's connection maximum segment size ('MaxSegSizeConn')
*                               [see 'NetTCP_ConnCfgMaxSegSize()  Note #1']
*********************************************************************************************************
*/

static  void  NetTCP_TxConnWinSizeCfgCongCtrl (NET_TCP_CONN  *pconn)
{
                                                                /* Cfg tx slow start th (see Note #2b).                 */
    pconn->TxWinSizeSlowStartThInit = (NET_TCP_WIN_SIZE)pconn->TxWinSizeRemoteMax;
    pconn->TxWinSizeSlowStartTh     = (NET_TCP_WIN_SIZE)pconn->TxWinSizeSlowStartThInit;

                                                                /* Cfg tx cong ctrls    (see Note #3a).                 */
    pconn->TxWinSizeCongInit        = (NET_TCP_WIN_SIZE)pconn->MaxSegSizeConn * NET_TCP_CONG_WIN_MSS_SCALAR_INIT;
    pconn->TxWinSizeCongCalcdActual = (NET_TCP_WIN_SIZE)pconn->TxWinSizeCongInit;
    pconn->TxWinSizeCongCalcdCur    = (NET_TCP_WIN_SIZE)0;
    pconn->TxWinSizeCongRem         = (NET_TCP_WIN_SIZE)pconn->TxWinSizeCongCalcdActual;

                                                                /* Cfg tx win avail     (see Note #4).                  */
    NetTCP_TxConnWinSizeUpdateAvail(pconn);


    NetTCP_TxConnWinSizeDupAckCtrlReset(pconn);                 /* Reset dup ack ctrls.                                 */
}


/*$PAGE*/
/*
*********************************************************************************************************
*                                   NetTCP_TxConnWinSizeCfgMinTh()
*
* Description : Configure TCP connection's transmit silly window minimum threshold.
*
* Argument(s) : pconn       Pointer to a TCP connection.
*               -----       Argument validated in NetTCP_TxConnWinSizeCfg(),
*                                                 NetTCP_TxConnWinSizeHandlerCongCtrl().
*
* Return(s)   : none.
*
* Caller(s)   : NetTCP_TxConnWinSizeCfg(),
*               NetTCP_TxConnWinSizeHandlerCongCtrl().
*
* Note(s)     : (1) RFC #1122, Section 4.2.3.4 states that "the sender's SWS avoidance algorithm is ...
*                   [to] send data ... if at least a fraction Fs of the maximum window can be sent ...
*                   Fs is a fraction whose recommended value is 1/2".
*
*               (2) A TCP connection's transmit window minimum threshold should NOT be updated until
*                   after the following TCP connection control(s) have been configured :
*
*                       (a) TCP connection's maximum transmit remote window size ('TxWinSizeRemoteMax')
*                               [see 'NetTCP_RxPktConnHandlerTxWinRemote()   Note  #1a2A'
*                                  & 'NetTCP_TxConnWinSizeHandlerCongCtrl()  Notes #3a2A & #3b']
*********************************************************************************************************
*/

static  void  NetTCP_TxConnWinSizeCfgMinTh (NET_TCP_CONN  *pconn)
{
                                                                /* Cfg silly win min th (see Note #1).                  */
    pconn->TxWinSizeMinTh = (NET_TCP_WIN_SIZE)(((CPU_INT32U)pconn->TxWinSizeRemoteMax * NET_TCP_TX_SILLY_WIN_NUMER)
                                                                                      / NET_TCP_TX_SILLY_WIN_DENOM);
}


/*$PAGE*/
/*
*********************************************************************************************************
*                                  NetTCP_TxConnWinSizeHandlerCfgd()
*
* Description : (1) Handle TCP connection's configured transmit window :
*
*                   (a) Update TCP connection configured transmit window
*                   (b) Update TCP connection total transmit data queued
*
*
* Argument(s) : pconn               Pointer to a TCP connection.
*               -----               Argument validated in NetTCP_TxConnAppData(),
*                                                         NetTCP_RxPktConnHandlerReTxQ().
*
*               win_update_size     Size to update TCP connection's transmit window (in octets).
*
*               win_update_code     Indicate how to update TCP connection transmit window :
*
*                                       NET_TCP_CONN_TX_WIN_RESET       Reset     TCP connection's available
*                                                                           transmit window size.
*                                       NET_TCP_CONN_TX_WIN_SET         Set       TCP connection's available
*                                                                           transmit window size.
*                                       NET_TCP_CONN_TX_WIN_INC         Increment TCP connection's available
*                                                                           transmit window size.
*                                       NET_TCP_CONN_TX_WIN_DEC         Decrement TCP connection's available
*                                                                           transmit window size.
*
*               perr        Pointer to variable that will receive the return error code from this function :
*
*                               NET_TCP_ERR_NONE                        TCP connection's configured transmit window
*                                                                           successfully updated.
*
*                                                                       --- RETURNED BY NetOS_TCP_TxQ_Signal() : ---
*                               NET_TCP_ERR_TX_Q_SIGNAL_FAULT           TCP connection transmit queue signal fault.
*
* Return(s)   : none.
*
* Caller(s)   : NetTCP_TxConnAppData(),
*               NetTCP_RxPktConnHandlerReTxQ().
*
* Note(s)     : (2) (a) RFC #793, Section 3.7 'Data Communication : Managing the Window' states
*                       that "the window sent in each segment indicates the range of sequence
*                       numbers the sender of the window (the data receiver) is currently
*                       prepared to accept.  There is an assumption that this is related to the
*                       currently available data buffer space available for this connection".
*
*                   (b) Thus, a TCP connection's configured transmit window is constrained by
*                       the available network resources; of which, network buffers are the
*                       primary transmit window network resource.
*
*                       However, since network buffers are discrete resources with non-discrete
*                       packet size; it is NOT necessary to enforce exact/strict compliance with
*                       a TCP connection's configured transmit window.
*
*                       In other words, network buffers allocated for TCP connection transmit
*                       SHOULD be fully used even if the TCP connection's configured transmit
*                       window is zero.
*
*               (3) Since the configured transmit window size may be asynchronously modified by
*                   the application layer, changes in the remaining transmit window size MUST be
*                   appropriately validated to any possible new value for the configured transmit
*                   window size :
*
*                   (a) During transmit window size increases, if the remaining transmit window
*                       size is already greater than the currently configured   transmit window
*                       size; then the remaining window size is NOT increased, but is allowed to
*                       remain greater than  the configured window size until the remaining window
*                       size decreases below the configured window size.
*
*                   (b) During transmit window size decreases, if the remaining transmit window
*                       size is already greater than the currently configured   transmit window
*                       size; then the remaining window size is further decreased, but is allowed
*                       to remain greater than the configured window size until the remaining
*                       window size decreases below the configured window size.
*
*                   (c) Window size update is NOT validated for transmit window size resets.
*********************************************************************************************************
*/
/*$PAGE*/
static  void  NetTCP_TxConnWinSizeHandlerCfgd (NET_TCP_CONN      *pconn,
                                               NET_TCP_WIN_SIZE   win_update_size,
                                               NET_TCP_WIN_CODE   win_update_code,
                                               NET_ERR           *perr)
{
    CPU_BOOLEAN       q_prevly_full;
    NET_TCP_WIN_SIZE  win_size_avail;
    NET_TCP_CONN_ID   conn_id_tcp;


    switch (win_update_code) {
        case NET_TCP_CONN_TX_WIN_RESET:                                 /* Reset cfg'd tx win size (see Note #1c).      */
        default:
             pconn->TxWinSizeCfgdRem = pconn->TxWinSizeCfgd;
             break;


        case NET_TCP_CONN_TX_WIN_SET:
             if (pconn->TxWinSizeCfgdRem < win_update_size) {           /* If rem cfg'd win size < win update, ...      */
                 pconn->TxWinSizeCfgdRem = win_update_size;             /* .. set cfg'd win size.                       */
                 break;
             }                                                          /* Else inc; do NOT shrink win.                 */
                                                                        /* 'break' intentionally omitted; do NOT ..     */
                                                                        /* ..  move from the following case :    ..     */
                                                                        /* .. 'NET_TCP_CONN_TX_WIN_INC'.                */

        case NET_TCP_CONN_TX_WIN_INC:
             if (win_update_size == 0) {                                /* If NO win update, do NOT update win.         */
                 break;
             }

             q_prevly_full = (pconn->TxWinSizeCfgdRem < 1) ? DEF_YES : DEF_NO;

             if (pconn->TxWinSizeCfgdRem < pconn->TxWinSizeCfgd) {      /* If < cfg'd  win size (see Note #3a), ...     */
                                                                        /* ... inc  tx win size.                        */
                 win_size_avail = pconn->TxWinSizeCfgd - pconn->TxWinSizeCfgdRem;
                 if (win_size_avail > win_update_size) {                /* If avail tx win size >  win update, ...      */
                     pconn->TxWinSizeCfgdRem += win_update_size;        /* ... inc  tx win size by win update.          */
                 } else {
                     pconn->TxWinSizeCfgdRem  = pconn->TxWinSizeCfgd;   /* Else limit to cfg'd tx  win size.            */
                 }
             }

             if (q_prevly_full == DEF_YES) {                            /* If tx Q prev'ly full, ...                    */
                 conn_id_tcp = pconn->ID;
                 NetOS_TCP_TxQ_Signal(conn_id_tcp, perr);               /* ... signal tx Q.                             */
                 if (*perr != NET_TCP_ERR_NONE) {                       /* #### On err, handle tx Q?; close TCP conn?   */
                      NetTCP_ConnClose((NET_TCP_CONN     *)pconn,
                                       (NET_BUF_HDR      *)0,
                                       (CPU_BOOLEAN       )DEF_YES,
                                       (NET_TCP_CLOSE_CODE)NET_TCP_CONN_CLOSE_ALL);
                      return;
                 }
             }
             break;


        case NET_TCP_CONN_TX_WIN_DEC:
             if (win_update_size == 0) {                                /* If NO win update, do NOT update win.         */
                 break;
             }

             if (pconn->TxWinSizeCfgdRem  > win_update_size) {          /* If rem tx win size >  win update, ..         */
                 pconn->TxWinSizeCfgdRem -= win_update_size;            /* .. dec tx win size by win update.            */
             } else {
                 pconn->TxWinSizeCfgdRem  = 0;                          /* Else limit to min tx  win size.              */
             }
             break;
    }


   *perr = NET_TCP_ERR_NONE;
}


/*$PAGE*/
/*
*********************************************************************************************************
*                                NetTCP_TxConnWinSizeHandlerCongCtrl()
*
* Description : (1) Handle TCP connection's transmit window congestion controls :
*
*                   (a) Perform slow start / congestion avoidance algorithms            See Note #2c2A
*                   (b) Perform fast re-transmit / fast recovery  algorithms            See Note #2c2B
*                   (c) Handle  remote host's receive window updates                    See Note #3
*
*
* Argument(s) : pconn               Pointer to a TCP connection.
*               -----               Argument validated in NetTCP_RxPktConnHandlerSeg(),
*                                                         NetTCP_RxPktConnHandlerReTxQ(),
*                                                         NetTCP_TxConnTxQ(),
*                                                         NetTCP_TxConnTxQ_TimeoutIdleSet(),
*                                                         NetTCP_TxConnTxQ_TimeoutIdle(),
*                                                         NetTCP_TxConnReTxQ().
*
*               pbuf_hdr            Pointer to network buffer header that received TCP packet.
*               --------            Argument validated in NetTCP_Rx().
*
*               ack_code            Indicates the received segment's acknowledgement condition :
*
*                                       NET_TCP_CONN_RX_ACK_NONE            NO received acknowledgement number.
*
*                                       NET_TCP_CONN_RX_ACK_INVALID            Received acknowledgement number
*                                                                              is invalid for the TCP connection.
*
*                                       NET_TCP_CONN_RX_ACK_VALID              Received acknowledgement number
*                                                                              is   valid for the TCP connection.
*
*                                       NET_TCP_CONN_RX_ACK_DUP                Received acknowledgement number
*                                                                              is a          duplicate for the
*                                                                              TCP connection.
*
*                                       NET_TCP_CONN_RX_ACK_PREV               Received acknowledgement number
*                                                                              is a previous duplicate for the
*                                                                              TCP connection.
*
*               win_update_size     Size to update TCP connection's transmit window (in octets).
*
*               win_update_code     Indicate how to update TCP connection transmit window :
*
*                                       NET_TCP_CONN_TX_WIN_RESET           Reset     TCP connection's congestion
*                                                                               control transmit window size.
*                                       NET_TCP_CONN_TX_WIN_SEG_RXD         Update    TCP connection's congestion
*                                                                               control transmit window size
*                                                                               based on received segment.
*                                       NET_TCP_CONN_TX_WIN_TIMEOUT         Update    TCP connection's congestion
*                                                                               control transmit window size
*                                                                               based on transmission timeout.
*                                       NET_TCP_CONN_TX_WIN_INC             Increment TCP connection's congestion
*                                                                               control transmit window sizes.
*                                       NET_TCP_CONN_TX_WIN_DEC             Decrement TCP connection's
*                                                                                       transmit window sizes.
*                                       NET_TCP_CONN_TX_WIN_REMOTE_UPDATE   Update    TCP connection's remote
*                                                                                       receive  window size.
*
*               perr        Pointer to variable that will receive the return error code from this function :
*
*                               NET_TCP_ERR_NONE                    TCP connection's transmit window congestion controls
*                                                                       successfully updated.
*                               NET_TCP_ERR_CONN_FAIL               TCP connection operation(s) failed.
*
*                                                                   --------- RETURNED BY NetTCP_TxConnReTxQ() : ---------
*                               NET_ERR_INIT_INCOMPLETE             Network initialization NOT complete.
*                               NET_TCP_ERR_CONN_NOT_USED           TCP connection NOT currently used.
*                               NET_TCP_ERR_INVALID_CONN_STATE      Invalid TCP connection state.
*                               NET_TCP_ERR_INVALID_CONN_OP         Invalid TCP connection operation.
*                               NET_TCP_ERR_RE_TX_SEG_TH            TCP connection closed due to excessive retransmission.
*                               NET_TCP_ERR_TX                      TCP transmit error.
*
* Return(s)   : none.
*
* Caller(s)   : NetTCP_RxPktConnHandlerSeg(),
*               NetTCP_RxPktConnHandlerReTxQ(),
*               NetTCP_RxPktConnHandlerTxWinRemote(),
*               NetTCP_TxConnTxQ(),
*               NetTCP_TxConnTxQ_TimeoutIdleSet(),
*               NetTCP_TxConnTxQ_TimeoutIdle(),
*               NetTCP_TxConnReTxQ().
*$PAGE*
* Note(s)     : (2) (a) (1) The following sections define, specify, &/or require "TCP's four intertwined congestion
*                           control algorithms: slow start, congestion avoidance, fast retransmit, and fast recovery" :
*
*                           (A) RFC #2001                                               See Note  #2c1
*                           (B) RFC #2581                                               See Notes #2c2, #2a2, & #2e
*                           (C) RFC #1122
*                               (1) Section 4.2.2.15
*                               (2) Section 4.2.2.21
*                               (3) Section 4.2.3.9                                     See 'net_tcp.c  Note #1e'
*                                   (a) 'Source Quench'                                 See Note #2e2
*                                   (b) 'Destination Unreachable -- Codes 2-4'
*
*
*                       (2) Although RFC #2581, Section 1 states that "this document is an update of [RFC #2001]";
*                           both references are included as complementary specifications of the congestion control
*                           algorithms.
*
*                           However, since RFC #2581 is the update to RFC #2001, its specifications supercede
*                           those of RFC #2001; & ALL differences are implemented by RFC #2581 specifications.
*
*                   (b) (1) (A) RFC #2581, Section 3.1 states that "the slow start and congestion avoidance
*                               algorithms MUST be used by a TCP sender to control the amount of outstanding
*                               data being injected into the network".
*
*                           (B) RFC #1122, Section 4.2.2.15 reiterates that "a TCP MUST implement ... 'slow
*                               start' with 'congestion avoidance'".
*
*                       (2) (A) RFC #2001, Section 1 states that "the sender's ... congestion window ... is
*                               flow control imposed by the sender, while the advertised window is flow control
*                               imposed by the receiver.  The former is based on the sender's assessment of
*                               perceived network congestion; the latter is related to the amount of available
*                               buffer space at the receiver for this connection".
*
*                           (B) RFC #2581, Section 3.1 reiterates that "the congestion window ... is a sender-
*                               side limit on the amount of data the sender can transmit into the network
*                               before receiving an acknowledgment (ACK), while the receiver's advertised
*                               window ... is a receiver-side limit on the amount of outstanding data."
*
*                       (3) (A) (1) RFC #2001, Section 1 states that "the sender can transmit up to the minimum
*                                   of the congestion window and the advertised window."
*
*                               (2) RFC #2001, Section 2.2 reiterates that "the TCP output routine never sends
*                                   more than the minimum of cwnd and the receiver's advertised window".
*
*                               (3) RFC #2581, Section 3.1 also reiterates that "the minimum of cwnd and rwnd
*                                   [receiver's advertised window] governs data transmission".
*
*                           (B) RFC #2581, Section 3 also states that "a TCP MUST NOT be more aggressive than
*                               the [congestion control] algorithms allow (that is, MUST NOT send data when
*                               the value of cwnd computed by the [congestion control] algorithms would not
*                               allow the data to be sent)".
*
*                           (C) TCP transmit resulting from TCP congestion controls update handled by appropriate
*                               TCP connection state receive handler function(s).
*
*                               See 'NetTCP_RxPktConnHandlerSyncRxd()    Note #1c3',
*                                   'NetTCP_RxPktConnHandlerSyncTxd()    Note #1c3',
*                                   'NetTCP_RxPktConnHandlerConn()       Note #1c',
*                                   'NetTCP_RxPktConnHandlerFinWait1()   Note #1c',
*                                   'NetTCP_RxPktConnHandlerClosing()    Note #1c',
*                                   'NetTCP_RxPktConnHandlerCloseWait()  Note #1c',
*                                 & 'NetTCP_RxPktConnHandlerLastAck()    Note #1c'.
*
*                       (4) (A) RFC #2001, Sections 3 & 4 state that "since ... a duplicate ACK is caused by
*                               a lost segment or just a reordering of segments, ... [fast retransmit] waits
*                               for a small number of duplicate ACKs to be received ... [as] a strong indication
*                               that a segment has been lost ... [and] then performs a retransmission of what
*                               appears to be the missing segment, without waiting for a retransmission timer
*                               to expire.
*
*                               After fast retransmit sends ... the missing segment, congestion avoidance,
*                               but not slow start is performed.  This is the fast recovery algorithm".
*
*                           (B) RFC #2581, Section 3.2 reiterates that "the TCP sender SHOULD use the 'fast
*                               retransmit' algorithm to detect and repair loss, based on ... the arrival of
*                               3 duplicate ACKs (4 identical ACKs without the arrival of any other intervening
*                               packets) as an indication that a segment has been lost.  After receiving 3
*                               duplicate ACKs, TCP performs a retransmission of what appears to be the missing
*                               segment, without waiting for the retransmission timer to expire.
*
*                               After the fast retransmit algorithm sends ... the missing segment, the 'fast
*                               recovery' algorithm ... can continue to transmit new segments ... (using a
*                               reduced cwnd) ... until a non-duplicate ACK arrives".
*$PAGE*
*                   (c) (1) (A) RFC #2001, Section 2 states that the "congestion avoidance and slow start ...
*                               combined algorithm operates as follows" :
*
*                               (1) "Initialization for a given connection sets" :
*
*                                   (a) "cwnd to one segment" ...
*                                   (b) "and ssthresh to 65535 bytes."
*
*                               (3) (a) (1) "When congestion occurs (indicated by" :
*
*                                           (A) "a timeout"                            ...
*                                           (B) "or the reception of duplicate ACKs)," ...
*
*                                       (2) "one-half of the current window size" :
*
*                                           (A) "the minimum of" :
*                                               (1) "cwnd"                                 ...
*                                               (2) "and the receiver's advertised window" ...
*                                           (B) "but at least two segments" ...
*
*                                       (3) "is saved in ssthresh [slow start threshold]."
*
*                                   (b) (1) "Additionally, if the congestion is indicated by a timeout," ...
*                                       (2) "cwnd is set to one segment (i.e., slow start)."
*
*                               (4) "When new data is acknowledged by the other end, increase cwnd, but the way
*                                    it increases depends on whether TCP is performing slow start or congestion
*                                    avoidance" :
*
*                                   (a) (1) (A) (1) (a) "If cwnd is less than or equal to ssthresh," ...
*                                                   (b) "TCP is in slow start."
*
*                                               (2) "Slow start continues until TCP is halfway to where it was
*                                                    when congestion occurred (since it recorded half of the
*                                                    window size that caused the problem)."
*
*                                           (B) (1) "Slow start has cwnd begin at one segment," ...
*
*                                               (2) (a) "and be incremented by one segment" ...
*                                                   (b) "every time an ACK is received."
*
*                                               (3) "The increase in cwnd ... [for] slow start increments cwnd
*                                                    by the number of ACKs received in a round-trip time ...
*                                                    [which] opens the window exponentially: send one segment,
*                                                    then two, then four, and so on."
*
*                                       (2) RFC #2001, Section 1 states that :
*
*                                           (A) "Early implementations performed slow start only if the other
*                                                end was on a different network."
*
*                                           (B) "Current implementations always perform slow start."
*
*                                   (b) (1) (A) "If cwnd is [not] less than or equal to ssthresh," ...
*                                           (B) "TCP is performing congestion avoidance."
*
*                                       (2) (A) (1) "cwnd [is] incremented by segsize*segsize/cwnd" ...
*                                                   (a) "where segsize is the segment size" ...
*                                                   (b) "and cwnd is maintained in bytes";
*                                               (2) "each time an ACK is received."
*
*                                           (B) "This is a linear growth of cwnd ... The increase in cwnd should
*                                                be at most one segment each round-trip time (regardless how many
*                                                ACKs are received in that RTT)."
*
*                           (B) RFC #2001, Section 4 states that "the fast retransmit and fast recovery
*                               algorithms are usually implemented together as follows" :
*
*                               (1) "When the third duplicate ACK in a row is received" :
*
*                                   (a) "Set ssthresh to" :
*                                       (1) "one-half the current congestion window, cwnd" ...
*                                       (2) "but no less than two segments."
*
*                                   (b) "Retransmit the missing segment."
*
*                                   (c) "Set cwnd to ssthresh plus 3 times the segment size."
*
*                               (2) "Each time another duplicate ACK arrives" :
*
*                                   (a) "Increment cwnd by the segment size."
*                                   (b) "Transmit a packet, if allowed by the new value of cwnd."
*
*                               (3) "When the next ACK arrives that acknowledges new data" :
*
*                                   (a) "Set cwnd to ssthresh" (see Note #2c1B1a).
*$PAGE*
*                       (2) (A) RFC #2581, Section 3.1 defines the "slow start and congestion avoidance algorithms"
*                               as follows :
*
*                               (1) (a) "The initial value of cwnd, MUST be" :
*
*                                       (1) "less than or equal to 2*SMSS bytes" ...
*                                       (2) "and MUST NOT be more than 2 segments."
*
*                                   (b) "The initial value of ssthresh MAY be arbitrarily high" :
*                                       (1) "some implementations use the size of the advertised window."
*
*                               (2) (a) "The slow start algorithm is used when cwnd < ssthresh," ...
*                                   (b) "while the congestion avoidance algorithm is used when cwnd > ssthresh."
*                                   (c) "When cwnd and ssthresh are equal the sender may use either slow start or
*                                        congestion avoidance."
*
*                               (3) (a) "During slow start" :
*
*                                       (1) "a TCP increments cwnd by at most SMSS bytes" ...
*                                       (2) "for each ACK received that acknowledges new data."
*
*                                   (b) "Slow start ends when" :
*
*                                       (1) "cwnd exceeds ... or ... reaches ... ssthresh" ...
*                                       (2) "or when congestion is observed."
*
*                               (4) (a) "During congestion avoidance" :
*
*                                       (1) "cwnd is incremented by 1 full-sized segment per round-trip time (RTT)."
*
*                                       (2) (A) "One formula commonly used to update cwnd during congestion avoidance
*                                                is given" by :
*
*                                               (2) cwnd += (SMSS * SMSS) / cwnd
*
*                                           (B) "Another acceptable way to increase cwnd during congestion avoidance
*                                                is to count the number of bytes that have been acknowledged by ACKs
*                                                for new data" :
*
*                                               (1) "When the number of bytes acknowledged reaches cwnd," ...
*                                               (2) "then cwnd can be incremented by up to SMSS bytes."
*
*                                       (3) "This adjustment is executed on every incoming non-duplicate ACK."
*
*                                   (b) "Congestion avoidance continues until congestion is detected."
*
*                               (5) "When a TCP sender detects segment loss using the retransmission timer" :
*
*                                   (a) "the value of ssthresh MUST be set to no more than" :
*
*                                       (3) ssthresh = max (FlightSize / 2, 2 * SMSS)
*
*                                           (A) "FlightSize is the amount of outstanding data ... that has been
*                                                sent but not yet acknowledged."
*
*                                   (b) "cwnd MUST be set to no more than ... 1 full-sized segment."
*
*                                   (c) "Therefore, after retransmitting the dropped segment the TCP sender uses
*                                        the slow start algorithm to increase the window."
*$PAGE*
*                           (B) RFC #2581, Section 3.2 states that "the fast retransmit and fast recovery algorithms
*                               are usually implemented together as follows" :
*
*                               (1) "When the third duplicate ACK is received" (see Note #2d1) :
*
*                                   (a) "set ssthresh to no more than the value given [by the] equation"
*                                           (see Note #2c2A5a3), ...
*
*                                   (b) "Retransmit the lost segment"
*                                           (see Note #2d2),     ...
*
*                                   (c) "set cwnd to ssthresh plus 3*SMSS."
*                                       (1) "This artificially 'inflates' the congestion window by the number of
*                                            segments (three) that have left the network and which the receiver
*                                            has buffered."
*
*                               (2) "For each additional duplicate ACK received" :
*
*                                   (a) "increment cwnd by SMSS."
*                                       (1) "This artificially inflates the congestion window in order to reflect
*                                            the additional segment that has left the network."
*
*                                   (b) (1) "Transmit a segment, if allowed by" :
*
*                                           (A) "the new value of cwnd" ...
*                                           (B) "and the receiver's advertised window."
*
*                                       (2) TCP transmit resulting from TCP congestion controls update handled by
*                                           appropriate TCP connection state receive handler function(s).
*
*                                           See also Note #2b3C.
*
*                               (3) (a) "When the next ACK arrives that acknowledges new data," ...
*                                   (b) "set cwnd to ssthresh" (see Note #2c2B1a).
*
*                   (d) (1) (A) RFC #1122, Section 4.2.2.21 states that "'fast retransmit' ... counts the number of
*                               ... 'redundant' ACK's ... received with" :
*
*                               (1) "the same value of SEG.ACK and" ...
*                               (2) "the same right window edge".
*
*                           (B) Although it is not directly stated, it is inferred that duplicate acknowledgements
*                               SHOULD be :
*
*                               (1) Acknowledgement-only segments
*                                   (a) i.e. with NO transmit data                              See Note #2d1C1
*                                       (1) i.e. with NO TCP segment length
*                               (2) With NO sequence number      update
*                               (3) With NO receive  window size update                         See Note #2d1C2
*
*                           (C) Also although RFC #2581, Section 3.2 states that "the TCP sender SHOULD use the
*                               'fast retransmit' algorithm ... based on ... the arrival of ... 4 identical ACKs
*                               without the arrival of any other intervening packets"; it seems reasonable that
*                               the TCP fast retransmit algorithm MUST NOT consider the arrival of non-duplicate
*                               acknowledgement segments as "intervening packets".
*
*                               In other words, TCP fast retransmit MUST ignore the following TCP packets as
*                               duplicate acknowledgement packets :
*
*                               (1) TCP data segments
*                               (2) Remote host receive window updates
*
*                       (2) RFC #1122, Section 4.2.2.21 reiterates that "with this ... 'fast retransmit' ...
*                           algorithm, the sender uses the redundant ACK's to deduce that a segment has been
*                           lost before the retransmission timer has expired.  If more than a threshold number
*                           of such ACK's is received, then the segment containing the octets starting at
*                           SEG.ACK is assumed to have been lost and is retransmitted, without awaiting a
*                           timeout".
*
*                   (e) (1) RFC #2581, Section 4.1 states that "after TCP has been idle for a relatively long period
*                           of time ... use slow start to restart transmission" :
*
*                           (A) (1) "If the TCP has not sent data in an interval exceeding the retransmission timeout"
*                               (2) "cwnd is reduced to ... no more than ... the value of the restart window"
*                                       (see Note #2c2A1).
*
*                               See also 'NetTCP_TxConnTxQ_TimeoutIdle()  Note #2a'.
*
*                           (B) Although NO RFC specifies that a TCP connection's slow start threshold should be
*                               reset following a TCP transmit idle timeout; it seems reasonable to reset the slow
*                               start threshold whenever the TCP transmit congestion window is reset.
*
*                           See also 'NetTCP_TxConnWinSizeCfgCongCtrl()  Notes #2 & #3'.
*
*                       (2) RFC #1122, Section 4.2.3.9 'Source Quench' states that "TCP MUST react to a Source Quench
*                           by slowing transmission on the connection.  The RECOMMENDED procedure is ... to trigger a
*                           'slow start', as if a retransmission timeout had occurred".
*$PAGE*
*               (3) (a) (1) The following sections ... :
*
*                           (A) RFC #793, Section 3.9 'Event Processing : SEGMENT ARRIVES : Check ACK Field :
*                                   ESTABLISHED STATE'
*                           (B) RFC #1122, Section 4.2.2.20.(c)
*                           (C) RFC #1122, Section 4.2.2.20.(f)
*
*                       (2) ... generalize that "the following variables should be set ... [when] the send
*                           window should be updated" :
*
*                           (A) SND.WND <- SEG.WND
*
*                               (1) A TCP connection's remote host receive window advertisements are relative
*                                   to the received window advertisement acknowledgement sequence number, &
*                                   are asynchronous to the TCP connection's recent transmitted sequences.
*
*                                   Therefore, the actual transmit remote window size MUST be compensated by
*                                   the difference in the remote host receive window advertisement & the TCP
*                                   connection's number of recently transmitted sequences :
*
*                                       (a) TxWinSizeRemoteActual  =  SEG.WIN  -  (SND.NXT - SEG.ACK)
*
*                                               where
*
*                                                   TxWinSizeRemoteActual   TCP connection's actual transmit 
*                                                                               remote window size
*
*                           (B) SND.WL1 <- SEG.SEQ
*                           (C) SND.WL2 <- SEG.ACK
*
*                   (b) RFC #1122, Section 4.2.3.4 'IMPLEMENTATION' states that "because the sender does not
*                       know (directly) the receiver's total buffer space RCV.BUFF ... An approach [that] has
*                       been found to work well is for the sender to calculate Max(SND.WND), the maximum send
*                       window it has seen so far on the connection, and to use this value as an estimate of
*                       RCV.BUFF".
*
*                   (c) RFC #1122, Section 4.2.2.17 states that although "a TCP MAY keep its offered receive
*                       window closed indefinitely ... the sending TCP MUST allow the connection to stay open
*                       ... as long as the receiving TCP continues to send acknowledgments in response to ...
*                       probe segments".
*
*                       See also 'NetTCP_TxConnWinSizeZeroWinHandler()  Note #1'.
*********************************************************************************************************
*/
/*$PAGE*/
static  void  NetTCP_TxConnWinSizeHandlerCongCtrl (NET_TCP_CONN      *pconn,
                                                   NET_BUF_HDR       *pbuf_hdr,
                                                   NET_TCP_ACK_CODE   ack_code,
                                                   NET_TCP_WIN_SIZE   win_update_size,
                                                   NET_TCP_WIN_CODE   win_update_code,
                                                   NET_ERR           *perr)
{
    CPU_BOOLEAN       ack_dup;
    NET_TCP_WIN_SIZE  tx_win_size_remote_actual;
    NET_TCP_WIN_SIZE  tx_win_size_remote_actual_min;


    switch (win_update_code) {
        case NET_TCP_CONN_TX_WIN_RESET:
        default:
             NetTCP_TxConnWinSizeCfgCongCtrl(pconn);                    /* Reset tx cong ctrls (see Note #2e).          */
             break;


        case NET_TCP_CONN_TX_WIN_SEG_RXD:
             switch (ack_code) {
                 case NET_TCP_CONN_RX_ACK_VALID:
                                                                        /* -------------- FAST RECOVERY --------------- */
                                                                        /* If valid ack rx'd after fast re-tx th, ..    */
                      if (pconn->TxWinRxdAckDupCtr >= NET_TCP_FAST_RE_TX_ACK_DUP_TH) {
                                                                        /* .. perform fast recovery (see Note #2c2B3) : */
                                                                        /* .. set cong win to slow start th       ..    */
                                                                        /* ..                       (see Note #2c2B3b). */
                          NetTCP_TxConnWinSizeCongSet(pconn, NET_TCP_CONN_TX_WIN_CONG_SET_SLOW_START);
                          NetTCP_TxConnWinSizeUpdateAvail(pconn);       /* Update avail tx win (see Note #2b3).         */


                      } else {                                          /* -------- SLOW START / CONG AVOIDANCE ------- */
                                                                        /* If cong win <  slow start th ..              */
                                                                        /* .. (see Notes #2c2A2a),      ..              */
                          if (pconn->TxWinSizeCongCalcdActual < pconn->TxWinSizeSlowStartTh) {
                                                                        /* .. perform slow start  (see Note #2c2A3) :   */
                                                                        /* .. inc cong win by MSS (see Note #2c2A3a1).  */
                              NetTCP_TxConnWinSizeCongInc(pconn, pbuf_hdr, 0, NET_TCP_CONN_TX_WIN_CONG_INC_SLOW_START);

                          } else {                                      /* If cong win >= slow start th     ..          */
                                                                        /* .. (see Note #2c2A2b & #2c2A2c), ..          */
                                                                        /* .. perform cong avoid  (see Note #2c2A4) :   */
                                                                        /* .. inc cong win        (see Note #2c2A4a2B). */
                              NetTCP_TxConnWinSizeCongInc(pconn, pbuf_hdr, 0, NET_TCP_CONN_TX_WIN_CONG_INC_CONG_AVOID);
                          }

                          NetTCP_TxConnWinSizeUpdateAvail(pconn);       /* Update avail tx win (see Note #2b3A).        */
                      }

#if 0                                                                   /* Tx avail seg(s)     [see Note #2b3C].        */
                      NetTCP_TxConnTxQ(pconn, pbuf_hdr, ack_code, DEF_NO, NET_TCP_CONN_CLOSE_ALL, perr);
                      switch (*perr) {
                          case NET_TCP_ERR_NONE:
                          case NET_TCP_ERR_CONN_ACK_NONE:
                          case NET_TCP_ERR_CONN_ACK_INVALID:
                          case NET_TCP_ERR_CONN_ACK_DLYD:
                          case NET_TCP_ERR_CONN_ACK_PREVLY_TXD:
                          case NET_ERR_TX:                              /* Ignore transitory tx err(s).                 */
                               break;


                          case NET_ERR_INIT_INCOMPLETE:
                          case NET_TCP_ERR_CONN_NOT_USED:
                          case NET_TCP_ERR_CONN_CLOSE:
                          case NET_TCP_ERR_CONN_FAULT:
                          case NET_TCP_ERR_CONN_FAIL:
                          case NET_TCP_ERR_INVALID_CONN_STATE:
                          case NET_TCP_ERR_INVALID_CONN_OP:
                          case NET_TCP_ERR_INVALID_LEN_SEG:
                          case NET_TCP_ERR_NONE_AVAIL:
                          case NET_TCP_ERR_TX:
                          case NET_CONN_ERR_INVALID_FAMILY:
                          case NET_CONN_ERR_INVALID_ADDR:
                          case NET_CONN_ERR_INVALID_ADDR_LEN:
                          default:
                               return;                                  /* Prevent 'break NOT reachable' warning.       */
                      }
#endif
                                                                        /* Reset dup ack ctrls.                         */
                      NetTCP_TxConnWinSizeDupAckCtrlUpdate(pconn, pbuf_hdr, DEF_YES);
                      break;

/*$PAGE*/
                 case NET_TCP_CONN_RX_ACK_DUP:                          /* -------- FAST RE-TX / FAST RECOVERY -------- */
                                                                        /* Chk dup ack (see Notes #2b4 & #2d1).         */
                      ack_dup = ((pbuf_hdr->TCP_SeqNbr  == pconn->TxWinRxdLastSeqNbr ) &&
                                 (pbuf_hdr->TCP_AckNbr  == pconn->TxWinRxdLastAckNbr ) &&
                                 (pbuf_hdr->TCP_WinSize == pconn->TxWinRxdLastWinSize) &&
                                 (pbuf_hdr->TCP_SegLen  == 0                         )) ? DEF_YES : DEF_NO;

                      if (ack_dup == DEF_YES) {                         /* If     dup ack, ..                           */
                          pconn->TxWinRxdAckDupCtr++;                   /* .. inc dup ack ctr.                          */

                                                                        /* If equal to fast re-tx th,                .. */
                          if (pconn->TxWinRxdAckDupCtr == NET_TCP_FAST_RE_TX_ACK_DUP_TH) {
                                                                        /* .. perform fast re-tx (see Note #2c2B1) : .. */
                                                                        /* .. calc slow start th (see Note #2c2B1a); .. */
                              NetTCP_TxConnWinSizeCalcSlowStartTh(pconn);
                                                                        /* .. re-tx unack'd seg  (see Note #2c2B1b); .. */
                              NetTCP_TxConnReTxQ(pconn, DEF_NO, NET_TCP_CONN_CLOSE_ALL, perr);
                              switch (*perr) {
                                  case NET_TCP_ERR_NONE:
                                  case NET_ERR_TX:                      /* Ignore transitory re-tx err(s).              */
                                       break;


                                  case NET_ERR_INIT_INCOMPLETE:
                                  case NET_TCP_ERR_CONN_NOT_USED:
                                  case NET_TCP_ERR_CONN_FAIL:
                                  case NET_TCP_ERR_INVALID_CONN_STATE:
                                  case NET_TCP_ERR_INVALID_CONN_OP:
                                  case NET_TCP_ERR_TX:
                                  case NET_TCP_ERR_RE_TX_SEG_TH:
                                  default:
                                       return;                          /* Prevent 'break NOT reachable' warning.       */
                              }
                                                                        /* .. set cong win to fast recovery th      ..  */
                                                                        /* ..                    (see Note #2c2B1c).    */
                              NetTCP_TxConnWinSizeCongSet(pconn, NET_TCP_CONN_TX_WIN_CONG_SET_FAST_RECOVERY);
                              NetTCP_TxConnWinSizeUpdateAvail(pconn);   /* Update avail tx win   (see Note #2b3).       */


                                                                        /* Else if  > fast re-tx th,                ..  */
                          } else if (pconn->TxWinRxdAckDupCtr > NET_TCP_FAST_RE_TX_ACK_DUP_TH) {
                                                                        /* .. perform fast recovery (see Note #2c2B2) : */
                                                                        /* .. inc cong win by MSS   (see Note #2c2B2a); */
                              NetTCP_TxConnWinSizeCongInc(pconn, pbuf_hdr, 0, NET_TCP_CONN_TX_WIN_CONG_INC_SLOW_START);
                              NetTCP_TxConnWinSizeUpdateAvail(pconn);   /* .. update avail tx win   (see Note #2b3) ..  */
#if 0                                                                   /* .. & tx avail seg(s)     [see Note #2c2B2b]. */
                              NetTCP_TxConnTxQ(pconn, pbuf_hdr, ack_code, DEF_NO, NET_TCP_CONN_CLOSE_ALL, perr);
                              switch (*perr) {
                                  case NET_TCP_ERR_NONE:
                                  case NET_TCP_ERR_CONN_ACK_NONE:
                                  case NET_TCP_ERR_CONN_ACK_INVALID:
                                  case NET_TCP_ERR_CONN_ACK_DLYD:
                                  case NET_TCP_ERR_CONN_ACK_PREVLY_TXD:
                                  case NET_ERR_TX:                      /* Ignore transitory tx err(s).                 */
                                       break;


                                  case NET_ERR_INIT_INCOMPLETE:
                                  case NET_TCP_ERR_CONN_NOT_USED:
                                  case NET_TCP_ERR_CONN_CLOSE:
                                  case NET_TCP_ERR_CONN_FAULT:
                                  case NET_TCP_ERR_CONN_FAIL:
                                  case NET_TCP_ERR_INVALID_CONN_STATE:
                                  case NET_TCP_ERR_INVALID_CONN_OP:
                                  case NET_TCP_ERR_INVALID_LEN_SEG:
                                  case NET_TCP_ERR_NONE_AVAIL:
                                  case NET_TCP_ERR_TX:
                                  case NET_CONN_ERR_INVALID_FAMILY:
                                  case NET_CONN_ERR_INVALID_ADDR:
                                  case NET_CONN_ERR_INVALID_ADDR_LEN:
                                  default:
                                       return;                          /* Prevent 'break NOT reachable' warning.       */
                              }
#endif
                          }


                      } else {                                          /* Else update dup ack ctrls (see Note #2d1C).  */
                          NetTCP_TxConnWinSizeDupAckCtrlUpdate(pconn, pbuf_hdr, DEF_NO);
                      }
                      break;

/*$PAGE*/
                 case NET_TCP_CONN_RX_ACK_PREV:                         /* Ignore prev dup acks.                        */
                     *perr = NET_TCP_ERR_NONE;
                      return;                                           /* Prevent 'break NOT reachable' warning.       */


                 case NET_TCP_CONN_RX_ACK_NONE:
                 case NET_TCP_CONN_RX_ACK_INVALID:
                 default:
                     *perr = NET_TCP_ERR_CONN_FAIL;
                      return;                                           /* Prevent 'break NOT reachable' warning.       */
             }
             break;


        case NET_TCP_CONN_TX_WIN_TIMEOUT:                               /* --------------- SLOW START ----------------- */
                                                                        /* On timeout (see Note #2c2A5),             .. */
                                                                        /* .. perform slow start (see Note #2c2A5c) :   */
             NetTCP_TxConnWinSizeCalcSlowStartTh(pconn);                /* .. calc slow start th (see Note #2c2A5a); .. */
                                                                        /* .. set cong win to timeout th             .. */
                                                                        /* ..                    (see Note #2c2A5b).    */
             NetTCP_TxConnWinSizeCongSet(pconn, NET_TCP_CONN_TX_WIN_CONG_SET_TIMEOUT);
             NetTCP_TxConnWinSizeUpdateAvail(pconn);                    /* Update avail tx win   (see Note #2b3).       */
             break;


        case NET_TCP_CONN_TX_WIN_INC:
             if (win_update_size == 0) {                                /* If NO win update, do NOT update win.         */
                 break;
             }
                                                                        /* Inc rem cong win size.                       */
             NetTCP_TxConnWinSizeCongInc(pconn, pbuf_hdr, win_update_size, NET_TCP_CONN_TX_WIN_CONG_INC_REM);
             NetTCP_TxConnWinSizeUpdateAvail(pconn);                    /* Update avail tx win (see Note #2b3).         */
             break;


        case NET_TCP_CONN_TX_WIN_DEC:
             if (win_update_size == 0) {                                /* If NO win update, do NOT update win.         */
                 break;
             }

             if (pconn->TxWinSizeCongRem  > win_update_size) {          /* If rem cong   win size >  win update, ..     */
                 pconn->TxWinSizeCongRem -= win_update_size;            /* .. dec cong   win size by win update.        */
             } else {
                 pconn->TxWinSizeCongRem  = 0;                          /* Else limit to min cong    win size.          */
             }

             if (pconn->TxWinSizeRemoteRem  > win_update_size) {        /* If rem remote win size >  win update, ..     */
                 pconn->TxWinSizeRemoteRem -= win_update_size;          /* .. dec remote win size by win update.        */
             } else {
                 pconn->TxWinSizeRemoteRem  = 0;                        /* Else limit to min remote  win size.          */
             }

             NetTCP_TxConnWinSizeUpdateAvail(pconn);                    /* Update avail tx win  (see Note #2b3).        */
             break;


        case NET_TCP_CONN_TX_WIN_REMOTE_UPDATE:
                                                                        /* Calc actual tx remote win (see Note #3a2A1a).*/
             tx_win_size_remote_actual     = (NET_TCP_WIN_SIZE)(pbuf_hdr->TCP_WinSize - (pconn->TxSeqNbrNext - pbuf_hdr->TCP_AckNbr));
             tx_win_size_remote_actual_min = (NET_TCP_WIN_SIZE) DEF_MIN(pbuf_hdr->TCP_WinSize, tx_win_size_remote_actual);
                                                                        /* Update      tx remote win (see Note #3a2).   */
             pconn->TxWinSizeRemote        = (NET_TCP_WIN_SIZE) pbuf_hdr->TCP_WinSize;
             pconn->TxWinSizeRemoteActual  = (NET_TCP_WIN_SIZE) tx_win_size_remote_actual_min;
             pconn->TxWinSizeRemoteRem     = (NET_TCP_WIN_SIZE) pconn->TxWinSizeRemoteActual;
             pconn->TxWinUpdateSeqNbr      = (NET_TCP_SEQ_NBR ) pbuf_hdr->TCP_SeqNbr;
             pconn->TxWinUpdateAckNbr      = (NET_TCP_SEQ_NBR ) pbuf_hdr->TCP_AckNbr;
             pconn->TxWinUpdateWinSize     = (NET_TCP_WIN_SIZE) pbuf_hdr->TCP_WinSize;

             if (pconn->TxWinSizeRemoteMax < pconn->TxWinSizeRemote) {  /* If max < updated remote win size, ...        */
                 pconn->TxWinSizeRemoteMax = pconn->TxWinSizeRemote;    /* ... set as new max   (see Note #3b).         */

                 NetTCP_TxConnWinSizeCfgMinTh(pconn);                   /* Cfg new tx silly win min th.                 */
             }
                                                                        /* Handle zero win size (see Note #3c).         */
             NetTCP_TxConnWinSizeZeroWinHandler(pconn, NET_TCP_CONN_TX_WIN_REMOTE_UPDATE, NET_TCP_CONN_CLOSE_ALL);

             NetTCP_TxConnWinSizeUpdateAvail(pconn);                    /* Update avail tx win  (see Note #2b3).        */
             break;
    }


   *perr = NET_TCP_ERR_NONE;
}


/*$PAGE*/
/*
*********************************************************************************************************
*                                NetTCP_TxConnWinSizeCalcSlowStartTh()
*
* Description : Calculate TCP connection's transmit slow start threshold.
*
* Argument(s) : pconn       Pointer to a TCP connection.
*               -----       Argument validated in NetTCP_TxConnWinSizeHandlerCongCtrl().
*
* Return(s)   : none.
*
* Caller(s)   : NetTCP_TxConnWinSizeHandlerCongCtrl().
*
* Note(s)     : (1) RFC #2581, Section 3.1 states that ... :
*
*                   (a) "the value of ssthresh MUST be set to no more than" :
*
*                       (3) ssthresh = max (FlightSize / 2, 2 * SMSS)
*
*                           (A) "FlightSize is the amount of outstanding data ... that has been sent but
*                                not yet acknowledged."
*
*                   See also 'NetTCP_TxConnWinSizeHandlerCongCtrl()  Note #2c2A5a'.
*********************************************************************************************************
*/

static  void  NetTCP_TxConnWinSizeCalcSlowStartTh (NET_TCP_CONN  *pconn)
{
    NET_TCP_SEQ_NBR   tx_data_unackd;
    NET_TCP_SEQ_NBR   tx_data_unackd_th;
    NET_TCP_SEG_SIZE  max_seg_size_th;

                                                                /* Calc slow start th (see Note #1a3).                  */
    tx_data_unackd              = (NET_TCP_SEQ_NBR ) (pconn->TxSeqNbrNext - pconn->TxSeqNbrUnAckd);
    tx_data_unackd_th           = (NET_TCP_SEQ_NBR )((tx_data_unackd * NET_TCP_SST_UNACKD_DATA_NUMER)
                                                                     / NET_TCP_SST_UNACKD_DATA_DENOM);

    max_seg_size_th             = (NET_TCP_SEG_SIZE)pconn->MaxSegSizeConn * NET_TCP_SST_MSS_SCALAR;

    pconn->TxWinSizeSlowStartTh = (NET_TCP_WIN_SIZE)DEF_MAX(tx_data_unackd_th,
                                                            max_seg_size_th);
}


/*$PAGE*/
/*
*********************************************************************************************************
*                                    NetTCP_TxConnWinSizeCongSet()
*
* Description : Set TCP connection's transmit congestion window.
*
* Argument(s) : pconn           Pointer to a TCP connection.
*               -----           Argument validated in NetTCP_TxConnWinSizeHandlerCongCtrl().
*
*               win_inc_code    Indicate how to set TCP connection transmit congestion window :
*
*                                   NET_TCP_CONN_TX_WIN_CONG_SET_SLOW_START         Set TCP connection's congestion
*                                                                                       control transmit window size
*                                                                                       based on slow start.
*
*                                   NET_TCP_CONN_TX_WIN_CONG_SET_FAST_RECOVERY      Set TCP connection's congestion
*                                                                                       control transmit window size
*                                                                                       based on fast recovery
*                                                                                       (see Note #1a).
*
*                                   NET_TCP_CONN_TX_WIN_CONG_SET_TIMEOUT            Set TCP connection's congestion
*                                                                                       control transmit window size
*                                                                                       based on transmission timeout
*                                                                                       (see Note #1b).
*
* Return(s)   : none.
*
* Caller(s)   : NetTCP_TxConnWinSizeHandlerCongCtrl().
*
* Note(s)     : (1) (a) RFC #2581, Section 3.2 states that "when the third duplicate ACK is received ...
*                       [for] fast recovery ... set cwnd to ssthresh plus 3*SMSS".
*
*                       See also 'NetTCP_TxConnWinSizeHandlerCongCtrl()  Note #2c2B1c'.
*
*                   (b) RFC #2581, Section 3.1 states that "when a TCP sender detects segment loss using the
*                       retransmission timer ... cwnd MUST be set to no more than ... 1 full-sized segment".
*
*                       See also 'NetTCP_TxConnWinSizeHandlerCongCtrl()  Note #2c2A5b'.
*********************************************************************************************************
*/

static  void  NetTCP_TxConnWinSizeCongSet (NET_TCP_CONN      *pconn,
                                           NET_TCP_WIN_CODE   win_inc_code)
{
    NET_TCP_WIN_SIZE  win_size_set;


    switch (win_inc_code) {
        case NET_TCP_CONN_TX_WIN_CONG_SET_SLOW_START:
             win_size_set  = (NET_TCP_WIN_SIZE)pconn->TxWinSizeSlowStartTh;
             break;


        case NET_TCP_CONN_TX_WIN_CONG_SET_FAST_RECOVERY:                    /* See Note #1a.                            */
             win_size_set  = (NET_TCP_WIN_SIZE)pconn->TxWinSizeSlowStartTh;
             win_size_set += (NET_TCP_WIN_SIZE)pconn->MaxSegSizeConn * NET_TCP_FAST_RECOVERY_MSS_SCALAR;
             break;


        case NET_TCP_CONN_TX_WIN_CONG_SET_TIMEOUT:                          /* See Note #1b.                            */
        default:
             win_size_set  = (NET_TCP_WIN_SIZE)pconn->MaxSegSizeConn * NET_TCP_CONG_WIN_MSS_SCALAR_TIMEOUT;
             break;
    }

    pconn->TxWinSizeCongCalcdActual = win_size_set;
    pconn->TxWinSizeCongCalcdCur    = 0;
    pconn->TxWinSizeCongRem         = pconn->TxWinSizeCongCalcdActual;
}


/*$PAGE*/
/*
*********************************************************************************************************
*                                    NetTCP_TxConnWinSizeCongInc()
*
* Description : Increment TCP connection's transmit congestion window.
*
* Argument(s) : pconn               Pointer to a TCP connection.
*               -----               Argument validated in NetTCP_TxConnWinSizeHandlerCongCtrl().
*
*               pbuf_hdr            Pointer to network buffer header that received TCP packet.
*               --------            Argument validated in NetTCP_Rx().
*
*               win_update_size     Size to increment TCP connection's transmit congestion window (in octets).
*
*               win_inc_code    Indicate how to increment TCP connection transmit congestion window :
*
*                                   NET_TCP_CONN_TX_WIN_CONG_INC_SLOW_START     Increment TCP connection's congestion
*                                                                                   control transmit window size
*                                                                                   based on slow start
*                                                                                   (see Note #1a).
*
*                                   NET_TCP_CONN_TX_WIN_CONG_INC_CONG_AVOID     Increment TCP connection's congestion
*                                                                                   control transmit window size
*                                                                                   based on congestion avoidance
*                                                                                   (see Note #1b).
*
*                                   NET_TCP_CONN_TX_WIN_CONG_INC_REM            Increment TCP connection's congestion
*                                                                                   control transmit window size
*                                                                                   remaining.
*
* Return(s)   : none.
*
* Caller(s)   : NetTCP_TxConnWinSizeHandlerCongCtrl().
*
* Note(s)     : (1) RFC #2581, Section 3.1 states that ... :
*
*                   (a) "During slow start, a TCP increments cwnd by at most SMSS bytes for each ACK received
*                        that acknowledges new data."
*
*                       See also 'NetTCP_TxConnWinSizeHandlerCongCtrl()  Note #2c2A3a'.
*
*                   (b) "During congestion avoidance, cwnd is incremented by 1 full-sized segment per round-
*                        trip time (RTT) ... [An] acceptable way to increase cwnd during congestion avoidance
*                        is to" :
*
*                       (1) "Count the number of bytes that have been acknowledged by ACKs for new data."
*
*                           (A) The following equation calculates the number of octets that acknowledge
*                               new data for a TCP connection :
*
*                                   Number of Octets Acknowledged  =  (SEG.ACK - SND.UNA)
*
*                           (B) However, since TCP connection transmit congestion controls are
*                               updated following any TCP connection re-transmit queue handling
*                               (see 'NetTCP_RxPktConnHandlerSeg()  Notes #1c & #1d'); the saved
*                               previous value of the TCP connection's last unacknowledged
*                               transmit sequence number ('TxSeqNbrUnackdPrev') MUST be used
*                               (see 'NetTCP_RxPktConnHandlerReTxQ()  Note #4').
*
*                       (2) "When the number of bytes acknowledged reaches cwnd," ...
*                       (3) "then cwnd can be incremented by up to SMSS bytes."
*
*                       See also 'NetTCP_TxConnWinSizeHandlerCongCtrl()  Note #2c2A4'.
*********************************************************************************************************
*/
/*$PAGE*/
static  void  NetTCP_TxConnWinSizeCongInc (NET_TCP_CONN      *pconn,
                                           NET_BUF_HDR       *pbuf_hdr,
                                           NET_TCP_WIN_SIZE   win_update_size,
                                           NET_TCP_WIN_CODE   win_inc_code)
{
    CPU_BOOLEAN       win_size_rem_update;
    NET_TCP_WIN_SIZE  win_size_inc;
    NET_TCP_WIN_SIZE  win_size_inc_mss;
    NET_TCP_WIN_SIZE  win_size_inc_rem;
    NET_TCP_WIN_SIZE  win_size_avail;


    win_size_rem_update =  DEF_NO;
    win_size_inc_mss    = (NET_TCP_WIN_SIZE)pconn->MaxSegSizeConn * NET_TCP_CONG_WIN_MSS_SCALAR_INC;

    switch (win_inc_code) {
        case NET_TCP_CONN_TX_WIN_CONG_INC_SLOW_START:                       /* See Note #1a.                            */
        default:
             win_size_avail = NET_TCP_WIN_SIZE_MAX - pconn->TxWinSizeCongCalcdActual;
             if (win_size_inc_mss < win_size_avail) {                       /* If inc < max avail, ..                   */
                 pconn->TxWinSizeCongCalcdActual += win_size_inc_mss;       /* .. inc cong win by MSS (see Note #1a).   */
             } else {
                 pconn->TxWinSizeCongCalcdActual  = NET_TCP_WIN_SIZE_MAX;   /* Else set cong win to max.                */
             }

             pconn->TxWinSizeCongCalcdCur = 0;
             win_size_rem_update          = DEF_YES;
             win_size_inc_rem             = win_size_inc_mss;
             break;


        case NET_TCP_CONN_TX_WIN_CONG_INC_CONG_AVOID:                       /* See Note #1b.                            */
                                                                            /* Calc nbr ack'd octets   (see Note #1b1). */
             win_size_inc   = (NET_TCP_WIN_SIZE)((NET_TCP_SEQ_NBR)pbuf_hdr->TCP_AckNbr - pconn->TxSeqNbrUnAckdPrev);

             win_size_avail =  NET_TCP_WIN_SIZE_MAX - pconn->TxWinSizeCongCalcdActual;
             if (win_size_inc < win_size_avail) {                           /* If inc < max avail, ..                   */
                 pconn->TxWinSizeCongCalcdCur += win_size_inc;              /* .. inc nbr ack'd octets (see Note #1b1). */
                                                                            /* If  >= cong win         (see Note #1b2), */
                                                                            /* .. inc cong win by MSS  (see Note #1b3). */
                 if (pconn->TxWinSizeCongCalcdCur >= pconn->TxWinSizeCongCalcdActual) {
                     pconn->TxWinSizeCongCalcdCur -= pconn->TxWinSizeCongCalcdActual;

                     win_size_avail = NET_TCP_WIN_SIZE_MAX - pconn->TxWinSizeCongCalcdActual;
                     if (win_size_inc_mss < win_size_avail) {
                          pconn->TxWinSizeCongCalcdActual += win_size_inc_mss;
                     } else {
                          pconn->TxWinSizeCongCalcdActual  = NET_TCP_WIN_SIZE_MAX;
                     }
                                                                            /* Cfg rem cong win inc by MSS.             */
                     win_size_rem_update = DEF_YES;
                     win_size_inc_rem    = win_size_inc_mss;
                 }

             } else {                                                       /* Else set cong win to max.                */
                 pconn->TxWinSizeCongCalcdActual = NET_TCP_WIN_SIZE_MAX;

                 win_size_avail = NET_TCP_WIN_SIZE_MAX - pconn->TxWinSizeCongCalcdCur;
                 if (win_size_inc < win_size_avail) {                       /* If inc < max avail, ..                   */
                     pconn->TxWinSizeCongCalcdCur += win_size_inc;          /* .. inc nbr ack'd octets (see Note #1b1). */

                 } else {                                                   /* Else set nbr ack'd octets to inc ovf ... */
                     pconn->TxWinSizeCongCalcdCur  = win_size_inc - win_size_avail;
                                                                            /* ... & cfg rem cong win inc by MSS.       */
                     win_size_rem_update           = DEF_YES;
                     win_size_inc_rem              = win_size_inc_mss;
                 }
             }
             break;


        case NET_TCP_CONN_TX_WIN_CONG_INC_REM:                              /* Cfg rem cong win inc by win update size. */
             win_size_rem_update = DEF_YES;
             win_size_inc_rem    = win_update_size;
             break;
    }


    if (win_size_rem_update == DEF_YES) {                                   /* If rem tx cong win update req'd  ...     */
        if (pconn->TxWinSizeCongRem < pconn->TxWinSizeCongCalcdActual) {    /* ... & < actual tx cong win size, ...     */
                                                                            /* ... inc rem tx cong win size.            */
            win_size_avail = pconn->TxWinSizeCongCalcdActual - pconn->TxWinSizeCongRem;
            if (win_size_inc_rem < win_size_avail) {                        /* If avail win size > rem inc, ...         */
                pconn->TxWinSizeCongRem += win_size_inc_rem;                /* ... inc rem tx cong win size by rem inc. */
            } else {                                                        /* Else limit to actual tx cong win size.   */
                pconn->TxWinSizeCongRem  = pconn->TxWinSizeCongCalcdActual;
            }
        }
    }
}


/*$PAGE*/
/*
*********************************************************************************************************
*                                  NetTCP_TxConnWinSizeUpdateAvail()
*
* Description : Update TCP connection's available transmit window.
*
* Argument(s) : pconn       Pointer to a TCP connection.
*               -----       Argument validated in NetTCP_TxConnWinSizeHandlerCongCtrl().
*
* Return(s)   : none.
*
* Caller(s)   : NetTCP_TxConnWinSizeCfgCongCtrl(),
*               NetTCP_TxConnWinSizeHandlerCongCtrl().
*
* Note(s)     : (1) (a) RFC #2001, Section 1 states that "the sender can transmit up to the minimum
*                       of the congestion window and the advertised window."
*
*                   (b) RFC #2001, Section 2.2 reiterates that "the TCP output routine never sends
*                       more than the minimum of cwnd and the receiver's advertised window".
*
*                   (c) RFC #2581, Section 3.1 also reiterates that "the minimum of cwnd and rwnd
*                       [receiver's advertised window] governs data transmission".
*
*                   See also 'NetTCP_TxConnWinSizeHandlerCongCtrl()  Note #2b3'.
*********************************************************************************************************
*/

static  void  NetTCP_TxConnWinSizeUpdateAvail (NET_TCP_CONN  *pconn)
{
                                                                /* Calc avail tx win (see Note #1).                     */
    pconn->TxWinSizeAvail = DEF_MIN(pconn->TxWinSizeCongRem,
                                    pconn->TxWinSizeRemoteRem);
}


/*$PAGE*/
/*
*********************************************************************************************************
*                                NetTCP_TxConnWinSizeDupAckCtrlReset()
*
* Description : Reset TCP connection's transmit window duplicate acknowledgement controls.
*
* Argument(s) : pconn       Pointer to a TCP connection.
*               -----       Argument validated in NetTCP_TxConnWinSizeCfgCongCtrl().
*
* Return(s)   : none.
*
* Caller(s)   : NetTCP_TxConnWinSizeCfgCongCtrl().
*
* Note(s)     : none.
*********************************************************************************************************
*/

static  void  NetTCP_TxConnWinSizeDupAckCtrlReset (NET_TCP_CONN  *pconn)
{
    pconn->TxWinRxdLastSeqNbr  = pconn->RxSeqNbrNext;
    pconn->TxWinRxdLastAckNbr  = pconn->TxSeqNbrNext;
    pconn->TxWinRxdLastWinSize = pconn->TxWinSizeRemote;
    pconn->TxWinRxdAckDupCtr   = 0;
}


/*
*********************************************************************************************************
*                               NetTCP_TxConnWinSizeDupAckCtrlUpdate()
*
* Description : Update TCP connection's transmit window duplicate acknowledgement controls.
*
* Argument(s) : pconn       Pointer to a TCP connection.
*               -----       Argument validated in NetTCP_TxConnWinSizeHandlerCongCtrl().
*
*               pbuf_hdr    Pointer to network buffer header that received TCP packet.
*               --------    Argument validated in NetTCP_Rx().
*
*               reset_ctr   Indicate whether to reset the duplicate acknowledgement counter :
*
*                               DEF_YES                Reset duplicate acknowledgement counter.
*                               DEF_NO          Do NOT reset duplicate acknowledgement counter.
*
* Return(s)   : none.
*
* Caller(s)   : NetTCP_TxConnWinSizeHandlerCongCtrl().
*
* Note(s)     : none.
*********************************************************************************************************
*/

static  void  NetTCP_TxConnWinSizeDupAckCtrlUpdate (NET_TCP_CONN  *pconn,
                                                    NET_BUF_HDR   *pbuf_hdr,
                                                    CPU_BOOLEAN    reset_ctr)
{
    pconn->TxWinRxdLastSeqNbr  = (NET_TCP_SEQ_NBR )pbuf_hdr->TCP_SeqNbr;
    pconn->TxWinRxdLastAckNbr  = (NET_TCP_SEQ_NBR )pbuf_hdr->TCP_AckNbr;
    pconn->TxWinRxdLastWinSize = (NET_TCP_WIN_SIZE)pbuf_hdr->TCP_WinSize;

    if (reset_ctr == DEF_YES) {
        pconn->TxWinRxdAckDupCtr = 0;
    }
}


/*$PAGE*/
/*
*********************************************************************************************************
*                                 NetTCP_TxConnWinSizeZeroWinHandler()
*
* Description : Handle TCP connection's transmit queue zero window.
*
* Argument(s) : pconn               Pointer to TCP connection.
*               -----               Argument validated in NetTCP_TxConnWinSizeHandlerCongCtrl(),
*                                                         NetTCP_TxConnWinSizeZeroWinTimeout().
*
*               win_update_code     Indicate how to update TCP connection transmit window :
*
*                                       NET_TCP_CONN_TX_WIN_REMOTE_UPDATE   Handle TCP connection's remote
*                                                                               receive      window size update.
*                                       NET_TCP_CONN_TX_WIN_TIMEOUT         Handle TCP connection's remote
*                                                                               receive zero window size timeout.
*
*               close_code      Select which close action(s) to perform; bit-field flags logically OR'd :
*
*                                   NET_TCP_CONN_CLOSE_NONE                 Perform NO  close actions.
*                                   NET_TCP_CONN_CLOSE_ALL                  Perform ALL close actions.
*
*                                   NET_TCP_CONN_CLOSE_CONN_TX_RESET        Perform close connection transmit reset.
*                                   NET_TCP_CONN_CLOSE_CONN_ALL             Perform ALL   connection close    actions.
*
*                                   NET_TCP_CONN_CLOSE_TMR_TX_IDLE          Close    transmit idle                  timer.
*                                   NET_TCP_CONN_CLOSE_TMR_TX_SILLY_WIN     Close    transmit silly window persist  timer.
*                                   NET_TCP_CONN_CLOSE_TMR_TX_ZERO_WIN      Close    transmit zero  window persist  timer.
*                                   NET_TCP_CONN_CLOSE_TMR_TX_ACK_DLY       Close    transmit acknowledgement delay timer.
*                                   NET_TCP_CONN_CLOSE_TMR_RE_TX            Close re-transmit                       timer.
*                                   NET_TCP_CONN_CLOSE_TMR_KEEP_ALIVE       Close connection keep-alive             timer.
*                                   NET_TCP_CONN_CLOSE_TMR_TIMEOUT          Close connection                        timer.
*                                   NET_TCP_CONN_CLOSE_TMR_ALL              Close ALL                               timers.
*
*                               See also 'TCP CONNECTION CLOSE/FREE CODE DEFINES'.
*
* Return(s)   : none.
*
* Caller(s)   : NetTCP_TxConnWinSizeZeroWinTimeout(),
*               NetTCP_TxConnWinSizeHandlerCongCtrl().
*
* Note(s)     : (1) RFC #1122, Section 4.2.2.17 states that although "a TCP MAY keep its offered receive
*                   window closed indefinitely ... the sending TCP MUST allow the connection to stay open
*                   ... as long as the receiving TCP continues to send acknowledgments in response to ...
*                   probe segments".
*
*                   (a) "Probing of zero (offered) windows MUST be supported."
*
*                       (1) "If zero window probing is not supported, a connection may hang forever when an
*                            ACK segment that re-opens the window is lost."
*
*                           See also Note #1c2.
*
*                   (b) (1) "The transmitting host SHOULD send the first zero-window probe" ...
*
*                           (A) Although NO RFC specifies whether a TCP zero window probe should or should NOT
*                               include data; Stevens, TCP/IP Illustrated, Volume 1, 8th Printing, Section 22.1, 
*                               Page 325 states that "the window probes contain 1 byte of data".
*
*                       (2) (A) "when a zero window has existed for the retransmission timeout period," ...
*
*                           (B) "and SHOULD increase exponentially the interval between successive probes."
*
*                               (1) "Exponential backoff is recommended ... similar to ... the retransmission
*                                    algorithm, and it may be possible to combine the two procedures in the
*                                    implementation."
*
*                                   See also 'NetTCP_TxConnRTO_CalcBackOff()  Notes #1 & #2'.
*
*                   (c) (1) "It is extremely important to remember that ACK (acknowledgment) segments that
*                            contain no data are not reliably transmitted by TCP."
*
*                       (2) "This procedure minimizes delay if the zero-window condition is due to a lost
*                            ACK segment containing a window-opening update."
*********************************************************************************************************
*/
/*$PAGE*/
static  void  NetTCP_TxConnWinSizeZeroWinHandler (NET_TCP_CONN        *pconn,
                                                  NET_TCP_WIN_CODE     win_update_code,
                                                  NET_TCP_CLOSE_CODE   close_code)
{
#if ((NET_CTR_CFG_ERR_EN      == DEF_ENABLED)                    && \
     (CPU_CFG_CRITICAL_METHOD == CPU_CRITICAL_METHOD_STATUS_LOCAL))
    CPU_SR              cpu_sr;
#endif
    CPU_BOOLEAN         tmr_update;
    NET_TCP_TIMEOUT_MS  timeout_ms;
    NET_TMR_TICK        timeout_tick;
    NET_ERR             err;


                                                                    /* ----------- VALIDATE TCP CONN STATE ------------ */
    switch (pconn->ConnState) {
        case NET_TCP_CONN_STATE_FREE:
             NET_CTR_ERR_INC(NetTCP_ErrNotUsedCtr);
             return;                                                /* Prevent 'break NOT reachable' compiler warning.  */


        case NET_TCP_CONN_STATE_CLOSED:
        case NET_TCP_CONN_STATE_LISTEN:
        case NET_TCP_CONN_STATE_SYNC_RXD:
        case NET_TCP_CONN_STATE_SYNC_RXD_PASSIVE:
        case NET_TCP_CONN_STATE_SYNC_RXD_ACTIVE:
        case NET_TCP_CONN_STATE_SYNC_TXD:
        case NET_TCP_CONN_STATE_FIN_WAIT_2:
        case NET_TCP_CONN_STATE_TIME_WAIT:
        case NET_TCP_CONN_STATE_CLOSING_DATA_AVAIL:
             return;                                                /* Prevent 'break NOT reachable' compiler warning.  */


        case NET_TCP_CONN_STATE_CONN:
        case NET_TCP_CONN_STATE_FIN_WAIT_1:
        case NET_TCP_CONN_STATE_CLOSING:
        case NET_TCP_CONN_STATE_CLOSE_WAIT:
        case NET_TCP_CONN_STATE_LAST_ACK:
             break;


        case NET_TCP_CONN_STATE_NONE:
        default:
             NET_CTR_ERR_INC(NetTCP_ErrConnInvalidStateCtr);
             return;                                                /* Prevent 'break NOT reachable' compiler warning.  */
    }


/*$PAGE*/
                                                                    /* --------- HANDLE TCP CONN TX ZERO WIN ---------- */
    tmr_update = DEF_NO;

    switch (win_update_code) {
        case NET_TCP_CONN_TX_WIN_REMOTE_UPDATE:
        default:
             if (pconn->TxWinSizeRemote > 0) {                      /* If remote win size > 0, ...                      */
                 if (pconn->TxQ_ZeroWinTmr != (NET_TMR *)0) {       /* ... free zero win tmr.                           */
                     NetTmr_Free(pconn->TxQ_ZeroWinTmr);
                     pconn->TxQ_ZeroWinTmr  = (NET_TMR *)0;
                 }

             } else {                                               /* Else if remote win size zero            ...      */
                 if (pconn->TxQ_ZeroWinTmr != (NET_TMR *)0) {       /* ... & NO zero win tmr;                  ...      */
                                                                    /* ... set first tx zero win probe timeout ...      */
                     timeout_ms   = pconn->TxRTT_RTO_ms;            /* ... = RTO (see Note #1b2A).                      */
                     timeout_tick = pconn->TxRTT_RTO_tick;
                     tmr_update   = DEF_YES;
                 }
             }
             break;


        case NET_TCP_CONN_TX_WIN_TIMEOUT:                           /* On timeout :                               ...   */
                                                                    /* ... tx TCP zero win probe (see Note #1b1); ...   */
             NetTCP_TxConnProbe((NET_TCP_CONN     *) pconn,
                                (CPU_BOOLEAN       ) DEF_YES,       /* Tx probe with data (see Note #1b1A).             */
                                (NET_TCP_CLOSE_CODE) close_code,
                                (NET_ERR          *)&err);          /* Ignore transitory tx err(s).                     */

                                                                    /* ... update tx probe timeout (see Note #1b2B).    */
             timeout_ms   =  (NET_TCP_TIMEOUT_MS )NetTCP_TxConnRTO_CalcBackOff(pconn, pconn->TxWinZeroWinTimeout_ms);
             timeout_tick = ((NET_TMR_TICK       )timeout_ms * NET_TMR_TIME_TICK_PER_SEC) / DEF_TIME_NBR_mS_PER_SEC;
             tmr_update   =   DEF_YES;
             break;
    }


    if (tmr_update == DEF_YES) {                                    /* If tx probe tmr update req'd, ...                */
                                                                    /* ... get tx zero win probe tmr.                   */
        pconn->TxQ_ZeroWinTmr = NetTmr_Get((void       *) pconn,
                                           (CPU_FNCT_PTR) NetTCP_TxConnWinSizeZeroWinTimeout,
                                           (NET_TMR_TICK) timeout_tick,
                                           (CPU_INT16U  ) NET_TMR_FLAG_NONE,
                                           (NET_ERR    *)&err);

        if (err == NET_TMR_ERR_NONE) {                              /* If NO err(s), cfg tx zero win probe timeout.     */
            pconn->TxWinZeroWinTimeout_ms = timeout_ms;
        }                                                           /* Else ignore transitory rsrc err(s) ...           */
                                                                    /* ... [see Note #1a1].                             */
    }
}


/*$PAGE*/
/*
*********************************************************************************************************
*                                 NetTCP_TxConnWinSizeZeroWinTimeout()
*
* Description : (1) (a) Handle TCP connection's transmit queue zero window persist timeout ... :
*
*                       (1) Clear  TCP connection's transmit zero window persist timer      See Note #4aA1
*                       (2) Handle TCP connection   transmit zero window                    See Note #2
*
*                   (b) ... for the following states :
*
*                       (1) ESTABLISHED
*                       (2) FIN-WAIT-1
*                       (3) CLOSING
*                       (4) CLOSE-WAIT
*                       (5) LAST-ACK
*
*
* Argument(s) : pconn_timeout       Pointer to TCP connection (see Note #3b).
*
* Return(s)   : none.
*
* Caller(s)   : Referenced in NetTCP_TxConnWinSizeZeroWinHandler().
*
* Note(s)     : (2) RFC #1122, Section 4.2.2.17 states that the "probing of zero (offered) windows
*                   ... SHOULD send the first zero-window probe when a zero window has existed for
*                   the retransmission timeout period and SHOULD increase exponentially the interval
*                   between successive probes".
*
*                   See also 'NetTCP_TxConnWinSizeZeroWinHandler()  Note #1'.
*
*               (3) Ideally, network timer expiration functions could be defined as '[(void) (OBJECT *)]' 
*                   type functions -- even though network timer API functions cast expiration functions 
*                   to generic 'CPU_FNCT_PTR' type (i.e. '[(void) (void *)]').
*
*                   (a) (1) Unfortunately, ISO-IEC 9899-1999 ANSI-C, Section 6.3.2.3.7 states that "a 
*                           pointer to an object ... may be converted to a pointer to a different object 
*                           ... [but] if the resulting pointer is not correctly aligned ... the behavior
*                           is undefined".
*
*                           And since compilers may NOT correctly convert 'void' pointers to non-'void' 
*                           pointer arguments, network timer expiration functions MUST avoid incorrect
*                           pointer conversion behavior between 'void' pointer parameters & non-'void' 
*                           pointer arguments & therefore CANNOT be defined as '[(void) (OBJECT *)]'.
*
*                       (2) However, Section 6.3.2.3.1 states that "a pointer to void may be converted 
*                           to or from a pointer to any ... object ... A pointer to any ... object ... 
*                           may be converted to a pointer to void and back again; the result shall 
*                           compare equal to the original pointer".
*                   
*                   (b) Therefore, to correctly convert 'void' pointer objects back to appropriate
*                       network object pointer objects, network timer expiration functions MUST :
*
*                       (1) Be defined as 'CPU_FNCT_PTR' type (i.e. '[(void) (void *)]'); &       ...
*                       (2) Explicitly cast 'void' pointer arguments to specific object pointers; ...
*                           (A) ... in this case, a 'NET_TCP_CONN' pointer.
*
*                   See also 'net_tmr.c  NetTmr_Get()  Note #3'.
*
*               (4) This function is a network timer expiration function :
*
*                   (a) (1) For the following connection timer(s) ... :
*
*                           (A) TCP connection transmit zero window persist timer ('TxQ_ZeroWinTmr')
*
*                       (2) (A) Clear the timer pointer; ...
*                               (1) Cleared prior to next handler function(s) as an extra precaution to
*                                   avoiding re-freeing the timer (see Note #4a2B).
*
*                           (B) but do NOT re-free the timer.
*
*                   (b) Do NOT set the following close timer flag(s) :
*
*                       (1) NET_TCP_CONN_CLOSE_TMR_TX_ZERO_WIN
*
*               (5) Certain network connections MUST periodically suspend network transmit(s) to handle
*                   network receive packet(s).  To protect TCP connections from transmit corruption while
*                   suspended, ALL TCP data transmits & TCP transmit queue handling MUST be blocked for
*                   suspended connections until the connection is no longer suspended.
*
*                   However, handling the TCP connection's transmit zero window timeout is permitted since
*                   NO TCP data is transmitted & the TCP connection's transmit queue is NOT handled (see
*                   Note #1a).
*
*                   See also 'NetTCP_TxConnTxQ()                  Note #10b2A2',
*                            'NetTCP_TxConnTxQ_TimeoutIdle()      Note #5',
*                            'NetTCP_TxConnTxQ_TimeoutSillyWin()  Note #5',
*                          & 'NetTCP_TxConnReTxQ_Timeout()        Note #5'.
*********************************************************************************************************
*/
/*$PAGE*/
static  void  NetTCP_TxConnWinSizeZeroWinTimeout (void  *pconn_timeout)
{
#if ((NET_ERR_CFG_ARG_CHK_DBG_EN == DEF_ENABLED)                    && \
     (NET_CTR_CFG_ERR_EN         == DEF_ENABLED)                    && \
     (CPU_CFG_CRITICAL_METHOD    == CPU_CRITICAL_METHOD_STATUS_LOCAL))
    CPU_SR               cpu_sr;
#endif
    NET_TCP_CONN        *pconn;
    NET_TCP_CLOSE_CODE   close_code;


    pconn      = (NET_TCP_CONN *)pconn_timeout;                     /* See Note #3b2A.                                  */

    close_code =  NET_TCP_CONN_CLOSE_ALL;
    DEF_BIT_CLR(close_code, NET_TCP_CONN_CLOSE_TMR_TX_ZERO_WIN);    /* See Note #4b1.                                   */

#if (NET_ERR_CFG_ARG_CHK_DBG_EN == DEF_ENABLED)                     /* -------------- VALIDATE TCP CONN --------------- */
    if (pconn == (NET_TCP_CONN *)0) {
        NET_CTR_ERR_INC(NetTCP_ErrNullPtrCtr);
        return;
    }

    if (pconn->Type != NET_TCP_TYPE_CONN) {
        NET_CTR_ERR_INC(NetTCP_ErrConnInvalidTypeCtr);
        return;
    }

    switch (pconn->ConnState) {
        case NET_TCP_CONN_STATE_FREE:
             NET_CTR_ERR_INC(NetTCP_ErrNotUsedCtr);
             return;                                                /* Prevent 'break NOT reachable' compiler warning.  */


        case NET_TCP_CONN_STATE_CLOSED:
        case NET_TCP_CONN_STATE_LISTEN:
        case NET_TCP_CONN_STATE_SYNC_RXD:
        case NET_TCP_CONN_STATE_SYNC_RXD_PASSIVE:
        case NET_TCP_CONN_STATE_SYNC_RXD_ACTIVE:
        case NET_TCP_CONN_STATE_SYNC_TXD:
        case NET_TCP_CONN_STATE_FIN_WAIT_2:
        case NET_TCP_CONN_STATE_TIME_WAIT:
        case NET_TCP_CONN_STATE_CLOSING_DATA_AVAIL:
             NET_CTR_ERR_INC(NetTCP_ErrConnInvalidOpCtr);
             return;                                                /* Prevent 'break NOT reachable' compiler warning.  */


        case NET_TCP_CONN_STATE_CONN:                               /* See Note #1.                                     */
        case NET_TCP_CONN_STATE_FIN_WAIT_1:
        case NET_TCP_CONN_STATE_CLOSING:
        case NET_TCP_CONN_STATE_CLOSE_WAIT:
        case NET_TCP_CONN_STATE_LAST_ACK:
             switch (pconn->TxQ_State) {
                 case NET_TCP_TX_Q_STATE_CONN:
                 case NET_TCP_TX_Q_STATE_CONN_CLOSING:
                 case NET_TCP_TX_Q_STATE_CONN_SUSPEND:              /* See Note #5.                                     */
                      break;


                 case NET_TCP_TX_Q_STATE_NONE:
                 case NET_TCP_TX_Q_STATE_CLOSED:
                 case NET_TCP_TX_Q_STATE_CONN_CLOSED:
                 default:
                      return;                                       /* Prevent 'break NOT reachable' compiler warning.  */
             }
             break;


        case NET_TCP_CONN_STATE_NONE:
        default:
             NetTCP_ConnClose((NET_TCP_CONN     *)pconn,
                              (NET_BUF_HDR      *)0,
                              (CPU_BOOLEAN       )DEF_YES,
                              (NET_TCP_CLOSE_CODE)close_code);
             NET_CTR_ERR_INC(NetTCP_ErrConnInvalidStateCtr);
             return;                                                /* Prevent 'break NOT reachable' compiler warning.  */
    }
#endif


                                                                    /* ----- HANDLE TCP CONN TX ZERO WIN TIMEOUT ------ */
    pconn->TxQ_ZeroWinTmr = (NET_TMR *)0;                           /* Clr tx Q zero win tmr (see Note #4a2A1).         */

                                                                    /* Handle tx zero win    (see Note #2).             */
    NetTCP_TxConnWinSizeZeroWinHandler(pconn, NET_TCP_CONN_TX_WIN_TIMEOUT, close_code);
}


/*$PAGE*/
/*
*********************************************************************************************************
*                                         NetTCP_TxConnSync()
*
* Description : (1) Prepare & transmit TCP connection synchronization :
*
*                   (a) Validate TCP connection state
*                   (b) Prepare  TCP connection synchronization :
*                       (1) Get  timer
*                       (2) Get  buffer
*                       (3) Prepare TCP segment :
*                           (A) TCP segment  addresses
*                           (B) TCP segment  sequence numbers
*                           (C) TCP segment  transmit flags :
*-                              (1) SYN
*                               (2) ACK
*                           (D) TCP segment  window size
*                           (E) TCP segment  options
*                           (F) IP  datagram parameters
*                           (G) TCP segment  packet buffer controls
*                   (c) Update  TCP connection :
*                       (1) Queue  TCP connection synchronization packet
*                       (2) Update TCP connection sequence numbers
*                   (d) Transmit   TCP connection synchronization
*
*
*               (2) (a) RFC #793, Section 3.3 'Sequence Numbers : Initial Sequence Number Selection' states
*                       that "for a [TCP] connection to be established or initialized, ... two TCP's must
*                       synchronize ... each other's initial sequence numbers" by transmitting initial
*                       connection request segments (i.e., segments with the SYN control bit set).
*
*                       RFC #793, Section 3.4 states that "this procedure normally is initiated by one TCP
*                       and responded to by another TCP ... [but] works if two TCP simultaneously initiate
*                       the procedure".
*
*                   (b) RFC #793, Section 3.9 'Event Processing : OPEN Call : CLOSED STATE' states that after
*                       "a SYN segment ... is sent ... [to] set SND.UNA to ISS [initial send sequence number],
*                       SND.NXT to ISS+1".
*
*                       The following sections confirm these sequence number configurations summary :
*
*                       (1) RFC #793, Section 3.9 'Event Processing : OPEN Call : LISTEN STATE'
*                       (2) RFC #793, Section 3.9 'Event Processing : SEND Call : LISTEN STATE'
*                       (3) RFC #793, Section 3.9 'Event Processing : SEGMENT ARRIVES : LISTEN [State] :
*                               Check for SYN'
*
*               (3) A TCP connection's transmit sequences are initialized when the initial TCP synchronization
*                   segment is queued for transmission :
*
*                   (a) 'TxSeqNbrSync' points to the initial, synchronization (SYN) transmit sequence number.
*
*                   (b) (1) 'TxSeqNbrNextQ' points to the next transmit sequence number to enqueue data octets.
*                       (2) 'TxSeqNbrNext'  points to the next transmit sequence number to transmit.
*
*
*                              -----          ------------------------        Initial Synchronization
*                                ^            |  Initial SEQ # (SYN) |  <---  Transmit Sequence Number
*                                |            ------------------------            (see Note #3a)
*                                |            |    Data Octet # 1    |  ---
*                                |            |    Data Octet # 2    |   ^
*                                |            |    Data Octet # 3    |   |
*                                             |           .          |   |         Next / Queued
*                          TCP Connection     |           .          |   |   Transmit Sequence Number(s)
*                        Transmit Sequences   |           .          |   |         (see Note #3b)
*                          (see Note #3)      | Data Octet # (N - 2) |   |
*                                             | Data Octet # (N - 1) |   v
*                                |            | Data Octet #    N    |  ---
*                                |            ------------------------
*                                |            |  Close SEQ # (FIN)   |
*                                |            ------------------------
*                                v            |   Last SEQ #         |
*                              -----          ------------------------
*
*
*                   See also 'NetTCP_TxConnClose()  Note #2'.
*
*
*$PAGE*
* Argument(s) : pconn       Pointer to a TCP connection.
*               -----       Argument validated in NetTCP_TxConnReq(),
*                                                 NetTCP_RxPktConnHandlerListen().
*
*               pbuf_hdr    Pointer to network buffer header that received TCP packet.
*
*               perr        Pointer to variable that will receive the return error code from this function :
*
*                               NET_TCP_ERR_NONE                    TCP connection synchronization successfully
*                                                                       transmitted.
*                               NET_TCP_ERR_CONN_NOT_USED           TCP connection NOT currently used.
*                               NET_TCP_ERR_INVALID_CONN_STATE      Invalid TCP connection state.
*                               NET_TCP_ERR_INVALID_CONN_OP         Invalid TCP connection operation.
*                               NET_TCP_ERR_NONE_AVAIL              Resources NOT available.
*
*                                                                   - RETURNED BY NetTCP_TxConnReTxQ_TimeoutSet() : -
*                               NET_TCP_ERR_CONN_FAULT              TCP connection fault; connection(s) aborted.
*
*                                                                   - RETURNED BY NetTCP_TxConnPrepareSegAddrs() : --
*                               NET_CONN_ERR_INVALID_FAMILY         Invalid     connection family.
*                               NET_CONN_ERR_INVALID_ADDR           Invalid TCP connection address.
*                               NET_CONN_ERR_INVALID_ADDR_LEN       Invalid TCP connection address length.
*
*                                                                   ------ RETURNED BY NetTCP_TxPktHandler() : ------
*                               NET_TCP_ERR_TX                      TCP transmit error.
*
* Return(s)   : none.
*
* Caller(s)   : NetTCP_TxConnReq(),
*               NetTCP_RxPktConnHandlerListen(),
*               NetTCP_RxPktConnHandlerSyncTxd().
*
* Note(s)     : (4) RFC #1122, Section 4.2.2.6 states that a "TCP SHOULD send an MSS (Maximum Segment Size)
*                   option in every SYN segment".
*
*               (5) Network resources MUST be appropriately allocated/deallocated :
*
*                   (a) Increment network buffer's reference counter to include the queued TCP connection
*                       synchronization as a new reference to the network buffer.
*
*                   (b) On ANY errors, network resources MUST be appropriately freed :
*
*                       (1) For any network resources NOT  yet       linked to the TCP connection, each 
*                           network resource  MUST be freed by appropriate function(s).
*                       (2) For all network resources that have been linked to the TCP connection, ALL
*                           network resources are     freed by NetTCP_ConnClose().
*
*               (6) If transmitting a TCP synchronization packet from the SYN-SENT state :
*
*                   (a) Connection timeout is reset to initial synchronization timeout value
*                   (b) Previous synchronization sequence number MUST be re-used
*                   (c) Previous synchronization packet in TCP connection's re-transmit queue is freed
*
*                   See also 'NetTCP_RxPktConnHandlerSyncTxd()  Note #2c3B2'.
*
*               (7) #### IP options currently NOT implemented.
*********************************************************************************************************
*/

static  void  NetTCP_TxConnSync (NET_TCP_CONN  *pconn,
                                 NET_BUF_HDR   *pbuf_hdr,
                                 NET_ERR       *perr)
{
#if (CPU_CFG_CRITICAL_METHOD == CPU_CRITICAL_METHOD_STATUS_LOCAL)
    CPU_SR                         cpu_sr;
#endif
    NET_BUF_SIZE                   data_len;
    NET_BUF_SIZE                   data_ix;
    NET_BUF                       *pseg_sync;
    NET_BUF_HDR                   *pseg_sync_hdr;
    NET_IP_TOS                     TOS;
    NET_IP_TTL                     TTL;
    NET_IP_ADDR                    src_addr;
    NET_IP_ADDR                    dest_addr;
    NET_TCP_PORT_NBR               src_port;
    NET_TCP_PORT_NBR               dest_port;
    NET_TCP_SEQ_NBR                seq_nbr;
    NET_TCP_SEQ_NBR                ack_nbr;
    NET_TCP_WIN_SIZE               win_size;
    NET_TCP_OPT_CFG_MAX_SEG_SIZE  *popt_cfg_max_seg_size;
    NET_TCP_OPT_CFG_MAX_SEG_SIZE   opt_cfg_max_seg_size;
    CPU_INT16U                     flags_tcp;
    CPU_INT16U                     flags_ip;
    NET_ERR                        err;


/*$PAGE*/
#if (NET_ERR_CFG_ARG_CHK_DBG_EN == DEF_ENABLED)                     /* ----------- VALIDATE TCP CONN STATE ------------ */
    switch (pconn->ConnState) {
        case NET_TCP_CONN_STATE_FREE:
             NET_CTR_ERR_INC(NetTCP_ErrNotUsedCtr);
            *perr = NET_TCP_ERR_CONN_NOT_USED;
             return;                                                /* Prevent 'break NOT reachable' compiler warning.  */


        case NET_TCP_CONN_STATE_CLOSED:
        case NET_TCP_CONN_STATE_LISTEN:
        case NET_TCP_CONN_STATE_SYNC_TXD:
             break;


        case NET_TCP_CONN_STATE_SYNC_RXD:
        case NET_TCP_CONN_STATE_SYNC_RXD_PASSIVE:
        case NET_TCP_CONN_STATE_SYNC_RXD_ACTIVE:
        case NET_TCP_CONN_STATE_CONN:
        case NET_TCP_CONN_STATE_FIN_WAIT_1:
        case NET_TCP_CONN_STATE_FIN_WAIT_2:
        case NET_TCP_CONN_STATE_CLOSING:
        case NET_TCP_CONN_STATE_TIME_WAIT:
        case NET_TCP_CONN_STATE_CLOSE_WAIT:
        case NET_TCP_CONN_STATE_LAST_ACK:
        case NET_TCP_CONN_STATE_CLOSING_DATA_AVAIL:
             NET_CTR_ERR_INC(NetTCP_ErrConnInvalidOpCtr);
            *perr = NET_TCP_ERR_INVALID_CONN_OP;
             return;                                                /* Prevent 'break NOT reachable' compiler warning.  */


        case NET_TCP_CONN_STATE_NONE:
        default:
             NetTCP_ConnClose(pconn, pbuf_hdr, DEF_YES, NET_TCP_CONN_CLOSE_CONN_ALL);
             NET_CTR_ERR_INC(NetTCP_ErrConnInvalidStateCtr);
            *perr = NET_TCP_ERR_INVALID_CONN_STATE;
             return;                                                /* Prevent 'break NOT reachable' compiler warning.  */
    }
#endif

                                                                    /* ----------- PREPARE TCP CONN SYNC SEG ---------- */
                                                                    /* ------------------- GET TMR -------------------- */
    NetTCP_TxConnReTxQ_TimeoutSet(pconn, DEF_NO, NET_TCP_CONN_CLOSE_ALL, perr);
    if (*perr != NET_TCP_ERR_NONE) {
         return;
    }


                                                                    /* ------------------- GET BUF -------------------- */
    data_len  = NET_TCP_DATA_LEN_TX_SYNC;
    data_ix   = NET_BUF_DATA_TX_IX;
    pseg_sync = NetBuf_Get((NET_BUF_SIZE) data_len,
                           (NET_BUF_SIZE) data_ix,
                           (CPU_INT16U  ) NET_BUF_FLAG_NONE,
                           (NET_ERR    *)&err);
    if ( err != NET_BUF_ERR_NONE) {                                 /* See Note #5b1.                                   */
       *perr  = NET_TCP_ERR_NONE_AVAIL;
        return;
    }


/*$PAGE*/
                                                                    /* --------------- PREPARE TCP HDR ---------------- */
                                                                    /* Prepare seg addrs.                               */
    if (pbuf_hdr != (NET_BUF_HDR *)0) {                             /* If TCP pkt rx'd, cfg TCP tx                ...   */
                                                                    /* ...  src  addr from rx'd TCP pkt dest addr ...   */
        src_port  = (NET_TCP_PORT_NBR)pbuf_hdr->TCP_UDP_PortDest;
        src_addr  = (NET_IP_ADDR     )pbuf_hdr->IP_AddrDest;
                                                                    /* .. & dest addr from rx'd TCP pkt src  addr.      */
        dest_port = (NET_TCP_PORT_NBR)pbuf_hdr->TCP_UDP_PortSrc;
        dest_addr = (NET_IP_ADDR     )pbuf_hdr->IP_AddrSrc;

    } else {                                                        /* Else cfg TCP tx pkt addrs from TCP conn addrs.   */
        NetTCP_TxConnPrepareSegAddrs((NET_TCP_CONN *) pconn,
                                     (CPU_INT08U   *)&src_port,
                                     (CPU_INT08U   *)&src_addr,
                                     (CPU_INT16U    ) sizeof(src_port),
                                     (CPU_INT16U    ) sizeof(src_addr),
                                     (CPU_INT08U   *)&dest_port,
                                     (CPU_INT08U   *)&dest_addr,
                                     (CPU_INT16U    ) sizeof(dest_port),
                                     (CPU_INT16U    ) sizeof(dest_addr),
                                     (NET_ERR      *) perr);
        if (*perr != NET_TCP_ERR_NONE) {                            /* See Note #5b1.                                   */
             NetBuf_Free(pseg_sync);
             return;
        }
    }


                                                                    /* Prepare TCP sync seq nbrs.                       */
    if (pconn->ConnState != NET_TCP_CONN_STATE_SYNC_TXD) {          /* For non-sync-tx'd states (see Note #6b), ...     */
        NET_TCP_TX_GET_SEQ_NBR(seq_nbr);                            /* ... get sync seq nbr.                            */
    } else {
        seq_nbr = pconn->TxSeqNbrSync;
    }
    ack_nbr = (pconn->ConnState != NET_TCP_CONN_STATE_CLOSED) ? pconn->RxSeqNbrNext
                                                              : NET_TCP_ACK_NBR_NONE;

                                                                    /* Prepare TCP tx flags (see Note #1b3C).           */
    flags_tcp = NET_TCP_FLAG_NONE   |
                NET_TCP_FLAG_TX_SYNC;
    if (pconn->ConnState != NET_TCP_CONN_STATE_CLOSED) {            /* For non-CLOSED state, ...                        */
        DEF_BIT_SET(flags_tcp, NET_TCP_FLAG_TX_ACK);                /* ... tx ACK.                                      */
    }

                                                                    /* Prepare TCP rx win size.                         */
    win_size = pconn->RxWinSizeActual;

                                                                    /* Prepare TCP max seg size opt (see Note #4).      */
    popt_cfg_max_seg_size             = &opt_cfg_max_seg_size;
    popt_cfg_max_seg_size->Type       =  NET_TCP_OPT_CFG_TYPE_MAX_SEG_SIZE;
    popt_cfg_max_seg_size->MaxSegSize =  pconn->MaxSegSizeLocal;
    popt_cfg_max_seg_size->NextOptPtr = (void *)0;

                                                                    /* Prepare IP params.                               */
    TOS      = pconn->TxIP_TOS;
    TTL      = pconn->TxIP_TTL;
    flags_ip = pconn->TxIP_Flags;


/*$PAGE*/
                                                                    /* Init buf ctrls.                                  */
    pseg_sync_hdr                   = &pseg_sync->Hdr;
    pseg_sync_hdr->DataIx           = (CPU_INT16U  )data_ix;
    pseg_sync_hdr->DataLen          = (NET_BUF_SIZE)data_len;
    pseg_sync_hdr->TotLen           = (NET_BUF_SIZE)pseg_sync_hdr->DataLen;
    pseg_sync_hdr->ProtocolHdrType  =  NET_PROTOCOL_TYPE_TCP;

    pseg_sync_hdr->TCP_UDP_PortSrc  = (NET_PORT_NBR)src_port;
    pseg_sync_hdr->IP_AddrSrc       = (CPU_INT32U  )src_addr;
    pseg_sync_hdr->TCP_UDP_PortDest = (NET_PORT_NBR)dest_port;
    pseg_sync_hdr->IP_AddrDest      = (CPU_INT32U  )dest_addr;

    pseg_sync_hdr->TCP_SegLenInit   = (CPU_INT16U  )NET_TCP_SEG_LEN_SYNC;
    pseg_sync_hdr->TCP_SegLen       = (CPU_INT16U  )pseg_sync_hdr->TCP_SegLenInit;
    pseg_sync_hdr->TCP_SegLenLast   = (CPU_INT16U  )pseg_sync_hdr->TCP_SegLenInit;
    pseg_sync_hdr->TCP_SegLenData   = (CPU_INT16U  )0;
    pseg_sync_hdr->TCP_SegSync      = (CPU_BOOLEAN )DEF_YES;
    pseg_sync_hdr->TCP_SegClose     = (CPU_BOOLEAN )DEF_NO;
    pseg_sync_hdr->TCP_SegAck       = (CPU_BOOLEAN )DEF_BIT_IS_SET(flags_tcp, NET_TCP_FLAG_TX_ACK);
    pseg_sync_hdr->TCP_SegReset     = (CPU_BOOLEAN )DEF_NO;

    pseg_sync_hdr->TCP_SeqNbrInit   = (CPU_INT32U  )seq_nbr;
    pseg_sync_hdr->TCP_SeqNbrLast   = (CPU_INT32U  )pseg_sync_hdr->TCP_SeqNbrInit;
    pseg_sync_hdr->TCP_SeqNbr       = (CPU_INT32U  )pseg_sync_hdr->TCP_SeqNbrInit;
    pseg_sync_hdr->TCP_AckNbr       = (CPU_INT32U  )ack_nbr;
    pseg_sync_hdr->TCP_AckNbrLast   = (CPU_INT32U  )pseg_sync_hdr->TCP_AckNbr;

    pseg_sync_hdr->TCP_WinSizeLast  = (CPU_INT16U  )win_size;

    pseg_sync_hdr->TCP_Flags        = (CPU_INT16U  )flags_tcp;

    pseg_sync_hdr->TCP_SegReTxCtr   = (CPU_INT16U  )0;
    pseg_sync_hdr->RefCtr++;                                        /* TCP maintains ref until seg ack'd (see Note #5a).*/


                                                                    /* --------------- UPDATE TCP CONN ---------------- */
                                                                    /* Q conn sync seg to TCP re-tx Q.                  */
    NetTCP_ConnFreeBufQ(&pconn->ReTxQ_Head, &pconn->ReTxQ_Tail);    /* Free re-tx Q (see Note #6c).                     */
    pconn->ReTxQ_Head            =  pseg_sync;
    pconn->ReTxQ_Tail            =  pseg_sync;
                                                                    /* Update TCP conn seq nbrs (see Notes #2 & #3).    */
    pconn->TxSeqNbrSync          = (NET_TCP_SEQ_NBR) seq_nbr;
    pconn->TxSeqNbrNext          = (NET_TCP_SEQ_NBR)(seq_nbr + pseg_sync_hdr->TCP_SegLen);
    pconn->TxSeqNbrNextQ         = (NET_TCP_SEQ_NBR) pconn->TxSeqNbrNext;
    pconn->TxSeqNbrUnAckdPrev    = (NET_TCP_SEQ_NBR) pconn->TxSeqNbrUnAckd;
    pconn->TxSeqNbrUnAckd        = (NET_TCP_SEQ_NBR) pconn->TxSeqNbrSync;
    pconn->TxSeqNbrUnReTxd       = (NET_TCP_SEQ_NBR) pconn->TxSeqNbrUnAckd;



                                                                    /* ------------- TX TCP CONN SYNC SEG ------------- */
    NetTCP_TxPktHandler((NET_BUF        *)pseg_sync,
                        (NET_IP_ADDR     )src_addr,
                        (NET_TCP_PORT_NBR)src_port,
                        (NET_IP_ADDR     )dest_addr,
                        (NET_TCP_PORT_NBR)dest_port,
                        (NET_TCP_SEQ_NBR )seq_nbr,
                        (NET_TCP_SEQ_NBR )ack_nbr,
                        (NET_TCP_WIN_SIZE)win_size,
                        (NET_IP_TOS      )TOS,
                        (NET_IP_TTL      )TTL,
                        (CPU_INT16U      )flags_tcp,
                        (CPU_INT16U      )flags_ip,
                        (void           *)popt_cfg_max_seg_size,
                        (void           *)0,                        /* See Note #7.                                     */
                        (NET_ERR        *)perr);
    switch (*perr) {
        case NET_TCP_ERR_NONE:
        case NET_ERR_INIT_INCOMPLETE:
        case NET_ERR_TX:                                            /* Ignore transitory tx err(s).                     */
             NET_CTR_STAT_INC(NetTCP_StatTxSegConnSyncCtr);
             break;


        case NET_TCP_ERR_TX:
        default:
             NetTCP_ConnClose(pconn, pbuf_hdr, pconn->ConnCloseAppFlag, NET_TCP_CONN_CLOSE_CONN_ALL);
             return;                                                /* Prevent 'break NOT reachable' compiler warning.  */
    }



   *perr = NET_TCP_ERR_NONE;
}


/*$PAGE*/
/*
*********************************************************************************************************
*                                        NetTCP_TxConnClose()
*
* Description : (1) Prepare & transmit TCP connection close :
*
*                   (a) Validate TCP connection state
*                   (b) Prepare  TCP connection close segment :
*                       (1) Get  buffer
*                       (2) Prepare TCP segment :
*                           (A) TCP segment  addresses
*                           (B) TCP segment  sequence numbers
*                           (C) TCP segment  transmit flags :
*                               (1) ACK
*                               (2) FIN
*                           (D) TCP segment  window size
*                           (E) IP  datagram parameters
*                           (F) TCP segment  packet buffer controls
*                   (c) Update  TCP connection :
*                       (1) Queue  TCP connection close packet
*                       (2) Update TCP connection sequence number(s)
*                   (d) Transmit   TCP connection close segment
*
*
*               (2) A TCP connection's transmit sequences are closed when the closing TCP segment is queued
*                   for transmission :
*
*                   (a) 'TxSeqNbrClose' points to the closing (FIN) transmit sequence number.
*
*                   (b) 'TxSeqNbrLast'  points to the last sequence number used to close the TCP connection
*                                           transmit sequences when acknowledged.
*
*
*                                -----          ------------------------
*                                  ^            |  Initial SEQ # (SYN) |
*                                  |            ------------------------
*                                  |            |    Data Octet # 1    |
*                                  |            |    Data Octet # 2    |
*                                  |            |    Data Octet # 3    |
*                                               |           .          |
*                            TCP Connection     |           .          |
*                          Transmit Sequences   |           .          |
*                            (see Note #2)      | Data Octet # (N - 2) |
*                                               | Data Octet # (N - 1) |
*                                  |            | Data Octet #    N    |        Closing Transmit
*                                  |            ------------------------        Sequence Number
*                                  |            |  Close SEQ # (FIN)   |  <---  (see Note #2a)
*                                  |            ------------------------
*                                  v            |   Last SEQ #         |  <---   Last Transmit
*                                -----          ------------------------        Sequence Number
*                                                                               (see Note #2b)
*
*
*                   See also 'NetTCP_TxConnSync()  Note #3'.
*
*
* Argument(s) : pconn       Pointer to a TCP connection.
*               -----       Argument validated in NetTCP_ConnReqClose().
*
*               perr        Pointer to variable that will receive the return error code from this function :
*
*                               NET_TCP_ERR_NONE                    TCP connection close successfully
*                                                                       transmitted.
*                               NET_TCP_ERR_CONN_NOT_USED           TCP connection NOT currently used.
*                               NET_TCP_ERR_CONN_FAULT              TCP connection fault; connection(s) aborted.
*                               NET_TCP_ERR_INVALID_CONN_STATE      Invalid TCP connection state.
*                               NET_TCP_ERR_INVALID_CONN_OP         Invalid TCP connection operation.
*                               NET_TCP_ERR_NONE_AVAIL              Resources NOT available.
*
*                                                                   ------- RETURNED BY NetTCP_TxConnTxQ() : -------
*                               NET_ERR_INIT_INCOMPLETE             Network initialization NOT complete.
*                               NET_TCP_ERR_CONN_FAIL               TCP connection operation(s) failed.
*                               NET_TCP_ERR_CONN_ACK_INVALID        TCP connection acknowledgement NOT valid for
*                                                                       current TCP connection state.
*                               NET_TCP_ERR_INVALID_LEN_SEG         Invalid TCP sequence-segment length.
*                               NET_TCP_ERR_TX                      TCP transmit error.
*
* Return(s)   : none.
*
* Caller(s)   : NetTCP_ConnReqClose().
*$PAGE*
* Note(s)     : (3) Network resources MUST be appropriately allocated/deallocated :
*
*                   (a) Network buffer's reference counter MUST include the queued TCP connection close as a
*                       new reference to the network buffer.  However, this additional reference is handled
*                       by the TCP connection transmit queue (see 'NetTCP_TxConnTxQ()  Note #9').
*
*                   (b) On ANY errors, network resources MUST be appropriately freed :
*
*                       (1) For any network resources NOT  yet       linked to the TCP connection, each network
*                           resource  MUST be freed by appropriate function(s).
*                       (2) For all network resources that have been linked to the TCP connection, ALL  network
*                           resources are     freed by NetTCP_ConnClose().
*
*               (4) Network buffer's reference counter must be incremented to include the TCP connection close
*                   segment to be enqueued to the TCP connection's re-transmit queue as a new reference to the
*                   network buffer.
*
*                   However, NetTCP_TxConnTxQ() handles the reference counter increment when it enqueues the
*                   TCP connection close segment queued to the TCP connection's re-transmit queue.
*
*                   See 'NetTCP_TxConnTxQ()  Note #9'.
*********************************************************************************************************
*/

static  void  NetTCP_TxConnClose (NET_TCP_CONN  *pconn,
                                  NET_ERR       *perr)
{
#if ((((NET_ERR_CFG_ARG_CHK_DBG_EN == DEF_ENABLED)                    && \
       (NET_CTR_CFG_ERR_EN         == DEF_ENABLED))                   || \
       (NET_CTR_CFG_STAT_EN        == DEF_ENABLED))                   && \
       (CPU_CFG_CRITICAL_METHOD    == CPU_CRITICAL_METHOD_STATUS_LOCAL))
    CPU_SR             cpu_sr;
#endif
    NET_TCP_SEG_SIZE   seg_len;
    NET_BUF_SIZE       data_len;
    NET_BUF_SIZE       data_ix;
    NET_BUF           *pseg_close;
    NET_BUF_HDR       *pseg_close_hdr;
    NET_IP_ADDR        src_addr;
    NET_IP_ADDR        dest_addr;
    NET_TCP_PORT_NBR   src_port;
    NET_TCP_PORT_NBR   dest_port;
    NET_TCP_SEQ_NBR    seq_nbr;
    CPU_INT16U         flags_tcp;
    NET_ERR            err;


#if (NET_ERR_CFG_ARG_CHK_DBG_EN == DEF_ENABLED)                     /* ----------- VALIDATE TCP CONN STATE ------------ */
    switch (pconn->ConnState) {
        case NET_TCP_CONN_STATE_FREE:
             NET_CTR_ERR_INC(NetTCP_ErrNotUsedCtr);
            *perr = NET_TCP_ERR_CONN_NOT_USED;
             return;                                                /* Prevent 'break NOT reachable' compiler warning.  */


        case NET_TCP_CONN_STATE_CLOSED:
        case NET_TCP_CONN_STATE_LISTEN:
        case NET_TCP_CONN_STATE_SYNC_TXD:
        case NET_TCP_CONN_STATE_FIN_WAIT_1:
        case NET_TCP_CONN_STATE_FIN_WAIT_2:
        case NET_TCP_CONN_STATE_CLOSING:
        case NET_TCP_CONN_STATE_TIME_WAIT:
        case NET_TCP_CONN_STATE_LAST_ACK:
        case NET_TCP_CONN_STATE_CLOSING_DATA_AVAIL:
             NET_CTR_ERR_INC(NetTCP_ErrConnInvalidOpCtr);
            *perr = NET_TCP_ERR_INVALID_CONN_OP;
             return;                                                /* Prevent 'break NOT reachable' compiler warning.  */


        case NET_TCP_CONN_STATE_SYNC_RXD:
        case NET_TCP_CONN_STATE_SYNC_RXD_PASSIVE:
        case NET_TCP_CONN_STATE_SYNC_RXD_ACTIVE:
        case NET_TCP_CONN_STATE_CONN:
        case NET_TCP_CONN_STATE_CLOSE_WAIT:
             break;


        case NET_TCP_CONN_STATE_NONE:
        default:
             NetTCP_ConnClose((NET_TCP_CONN     *)pconn,
                              (NET_BUF_HDR      *)0,
                              (CPU_BOOLEAN       )DEF_YES,
                              (NET_TCP_CLOSE_CODE)NET_TCP_CONN_CLOSE_ALL);
             NET_CTR_ERR_INC(NetTCP_ErrConnInvalidStateCtr);
            *perr = NET_TCP_ERR_INVALID_CONN_STATE;
             return;                                                /* Prevent 'break NOT reachable' compiler warning.  */
    }
#endif


/*$PAGE*/
                                                                    /* ---------- PREPARE TCP CONN CLOSE SEG ---------- */
    seg_len  = NET_TCP_SEG_LEN_CLOSE;
    data_len = NET_TCP_DATA_LEN_TX_CLOSE;

    if (pconn->TxQ_Tail != (NET_BUF *)0) {                          /* If tx Q NOT empty ...                            */
        pseg_close                      =  pconn->TxQ_Tail;         /* ... update tx Q tail seg as close seg.           */
        pseg_close_hdr                  = &pseg_close->Hdr;

        pseg_close_hdr->DataLen        += (NET_BUF_SIZE)data_len;
        pseg_close_hdr->TotLen         += (NET_BUF_SIZE)data_len;

        pseg_close_hdr->TCP_SegLenInit += (CPU_INT16U  )seg_len;
        pseg_close_hdr->TCP_SegLen     += (CPU_INT16U  )seg_len;
        pseg_close_hdr->TCP_SegLenData += (CPU_INT16U  )data_len;

        DEF_BIT_SET(pseg_close_hdr->TCP_Flags, NET_TCP_FLAG_TX_CLOSE);


    } else {                                                        /* Else get/cfg close seg buf.                      */
                                                                    /* Get buf.                                         */
        data_ix    = NET_BUF_DATA_TX_IX;
        pseg_close = NetBuf_Get((NET_BUF_SIZE) data_len,
                                (NET_BUF_SIZE) data_ix,
                                (CPU_INT16U  ) NET_BUF_FLAG_NONE,
                                (NET_ERR    *)&err);
        if ( err != NET_BUF_ERR_NONE) {
           *perr  = NET_TCP_ERR_NONE_AVAIL;
            return;
        }

                                                                    /* --------------- PREPARE TCP HDR ---------------- */
                                                                    /* Prepare seg addrs.                               */
        NetTCP_TxConnPrepareSegAddrs((NET_TCP_CONN *) pconn,
                                     (CPU_INT08U   *)&src_port,
                                     (CPU_INT08U   *)&src_addr,
                                     (CPU_INT16U    ) sizeof(src_port),
                                     (CPU_INT16U    ) sizeof(src_addr),
                                     (CPU_INT08U   *)&dest_port,
                                     (CPU_INT08U   *)&dest_addr,
                                     (CPU_INT16U    ) sizeof(dest_port),
                                     (CPU_INT16U    ) sizeof(dest_addr),
                                     (NET_ERR      *)&err);
        if ( err != NET_TCP_ERR_NONE) {                             /* See Note #3b1.                                   */
           *perr  = NET_TCP_ERR_CONN_FAULT;
            NetBuf_Free(pseg_close);
            return;
        }


                                                                    /* Prepare TCP seq nbr(s).                          */
        seq_nbr   = pconn->TxSeqNbrNextQ;

                                                                    /* Prepare TCP tx flags (see Note #1b2C).           */
        flags_tcp = NET_TCP_FLAG_NONE    |
                    NET_TCP_FLAG_TX_ACK  |
                    NET_TCP_FLAG_TX_CLOSE;


                                                                    /* Init buf ctrls.                                  */
        pseg_close_hdr                   = &pseg_close->Hdr;
        pseg_close_hdr->DataIx           = (CPU_INT16U  )data_ix;
        pseg_close_hdr->DataLen          = (NET_BUF_SIZE)data_len;
        pseg_close_hdr->TotLen           = (NET_BUF_SIZE)pseg_close_hdr->DataLen;
        pseg_close_hdr->ProtocolHdrType  =  NET_PROTOCOL_TYPE_TCP;

        pseg_close_hdr->TCP_UDP_PortSrc  = (NET_PORT_NBR)src_port;
        pseg_close_hdr->IP_AddrSrc       = (CPU_INT32U  )src_addr;
        pseg_close_hdr->TCP_UDP_PortDest = (NET_PORT_NBR)dest_port;
        pseg_close_hdr->IP_AddrDest      = (CPU_INT32U  )dest_addr;

        pseg_close_hdr->TCP_SegLenInit   = (CPU_INT16U  )seg_len;
        pseg_close_hdr->TCP_SegLen       = (CPU_INT16U  )pseg_close_hdr->TCP_SegLenInit;
        pseg_close_hdr->TCP_SegLenData   = (CPU_INT16U  )data_len;
        pseg_close_hdr->TCP_SegSync      = (CPU_BOOLEAN )DEF_NO;
        pseg_close_hdr->TCP_SegClose     = (CPU_BOOLEAN )DEF_YES;
        pseg_close_hdr->TCP_SegAck       = (CPU_BOOLEAN )DEF_YES;
        pseg_close_hdr->TCP_SegReset     = (CPU_BOOLEAN )DEF_NO;

        pseg_close_hdr->TCP_SeqNbrInit   = (CPU_INT32U  )seq_nbr;
        pseg_close_hdr->TCP_SeqNbr       = (CPU_INT32U  )pseg_close_hdr->TCP_SeqNbrInit;

        pseg_close_hdr->TCP_Flags        = (CPU_INT16U  )flags_tcp;
    }


/*$PAGE*/
                                                                    /* --------------- UPDATE TCP CONN ---------------- */
                                                                    /* Q conn close seg to TCP tx Q : ...               */
    if (pconn->TxQ_Tail == (NET_BUF *)0) {                          /* ... if tx Q empty, add close seg to empty tx Q.  */
        pconn->TxQ_Head  = (NET_BUF *)pseg_close;
        pconn->TxQ_Tail  = (NET_BUF *)pseg_close;
    }

                                                                    /* Update TCP conn seq nbrs (see Note #2).          */
    pconn->TxSeqNbrNextQ += (NET_TCP_SEQ_NBR) seg_len;              /* Update next tx Q seq nbr by close seg len.       */
    pconn->TxSeqNbrLast   = (NET_TCP_SEQ_NBR) pconn->TxSeqNbrNextQ;
    pconn->TxSeqNbrClose  = (NET_TCP_SEQ_NBR)(pconn->TxSeqNbrLast - seg_len);



                                                                    /* ------------ TX TCP CONN CLOSE SEG ------------- */
    NetTCP_TxConnTxQ((NET_TCP_CONN     *)pconn,
                     (NET_BUF_HDR      *)0,
                     (NET_TCP_ACK_CODE  )NET_TCP_CONN_TX_ACK_NONE,
                     (CPU_BOOLEAN       )DEF_NO,
                     (NET_TCP_CLOSE_CODE)NET_TCP_CONN_CLOSE_ALL,
                     (NET_ERR          *)perr);
    switch (*perr) {
        case NET_TCP_ERR_NONE:
        case NET_TCP_ERR_CONN_ACK_NONE:
        case NET_TCP_ERR_CONN_ACK_INVALID:
        case NET_TCP_ERR_CONN_ACK_DLYD:
        case NET_TCP_ERR_CONN_ACK_PREVLY_TXD:
        case NET_ERR_TX:                                            /* Ignore transitory tx err(s).                     */
             break;


        case NET_ERR_INIT_INCOMPLETE:
        case NET_TCP_ERR_CONN_NOT_USED:
        case NET_TCP_ERR_CONN_CLOSE:
        case NET_TCP_ERR_CONN_FAULT:
        case NET_TCP_ERR_CONN_FAIL:
        case NET_TCP_ERR_INVALID_CONN_STATE:
        case NET_TCP_ERR_INVALID_CONN_OP:
        case NET_TCP_ERR_INVALID_LEN_SEG:
        case NET_TCP_ERR_NONE_AVAIL:
        case NET_TCP_ERR_TX:
        case NET_CONN_ERR_INVALID_FAMILY:
        case NET_CONN_ERR_INVALID_ADDR:
        case NET_CONN_ERR_INVALID_ADDR_LEN:
        default:
             return;                                                /* Prevent 'break NOT reachable' compiler warning.  */
    }

    NET_CTR_STAT_INC(NetTCP_StatTxSegConnCloseCtr);



   *perr = NET_TCP_ERR_NONE;
}


/*$PAGE*/
/*
*********************************************************************************************************
*                                         NetTCP_TxConnAck()
*
* Description : (1) Prepare & transmit a TCP connection acknowledgement :
*
*                   (a) Validate TCP connection for TCP acknowledgement         See Notes #2, #4, #5, & #6
*                   (b) Prepare  TCP acknowledgement segment :
*                       (1) Get  buffer
*                       (2) Prepare TCP segment :
*                           (A) TCP segment  addresses
*                           (B) TCP segment  sequence numbers                   See Notes #4a1D1a1, #4a2A1
*                                                                                       & #4a1D3b1B, 
*                           (C) TCP segment  transmit flags :
*                               (1) ACK
*                           (D) TCP segment  window size
*                           (E) IP  datagram parameters
*                           (F) TCP segment  packet buffer controls
*                   (c) Transmit TCP connection acknowledgement
*
*
*               (2) NetTCP_TxConnAck() transmits TCP connection acknowledgements in response to certain
*                   received TCP packets or TCP connection events (see Note #4).  TCP acknowledgements
*                   transmitted with other TCP controls &/or data SHOULD NOT be transmitted with
*                   NetTCP_TxConnAck().
*
*                   See also 'NetTCP_TxConnTxQ()  Note #2'.
*
*
* Argument(s) : pconn           Pointer to a TCP connection.
*               -----           Argument validated in various.
*
*               pbuf_hdr        Pointer to network buffer header that received TCP packet.
*               --------        Argument validated in NetTCP_Rx().
*
*               tx_ack_code     Indicate whether & how to transmit a TCP acknowledgement segment :
*
*                                   NET_TCP_CONN_TX_ACK_NONE        Do NOT transmit a TCP acknowledgement segment.
*                                   NET_TCP_CONN_TX_ACK                    Transmit a TCP acknowledgement segment.
*                                   NET_TCP_CONN_TX_ACK_IMMED              Transmit a TCP acknowledgement segment
*                                                                              immediately (see Note #4a5).
*                                   NET_TCP_CONN_TX_ACK_FAULT              Transmit a TCP acknowledgement segment
*                                                                              immediately in response to an invalid
*                                                                              received TCP packet (see Note #4a1).
*                                   NET_TCP_CONN_TX_ACK_TIMEOUT            Transmit a TCP acknowledgement segment
*                                                                              immediately in response to a delayed
*                                                                              acknowledgement timeout (see Note #6).
*
*               close_code      Select which close action(s) to perform; bit-field flags logically OR'd :
*
*                                   NET_TCP_CONN_CLOSE_NONE                 Perform NO  close actions.
*                                   NET_TCP_CONN_CLOSE_ALL                  Perform ALL close actions.
*
*                                   NET_TCP_CONN_CLOSE_CONN_TX_RESET        Perform close connection transmit reset.
*                                   NET_TCP_CONN_CLOSE_CONN_ALL             Perform ALL   connection close    actions.
*
*                                   NET_TCP_CONN_CLOSE_TMR_TX_IDLE          Close    transmit idle                  timer.
*                                   NET_TCP_CONN_CLOSE_TMR_TX_SILLY_WIN     Close    transmit silly window persist  timer.
*                                   NET_TCP_CONN_CLOSE_TMR_TX_ZERO_WIN      Close    transmit zero  window persist  timer.
*                                   NET_TCP_CONN_CLOSE_TMR_TX_ACK_DLY       Close    transmit acknowledgement delay timer.
*                                   NET_TCP_CONN_CLOSE_TMR_RE_TX            Close re-transmit                       timer.
*                                   NET_TCP_CONN_CLOSE_TMR_KEEP_ALIVE       Close connection keep-alive             timer.
*                                   NET_TCP_CONN_CLOSE_TMR_TIMEOUT          Close connection                        timer.
*                                   NET_TCP_CONN_CLOSE_TMR_ALL              Close ALL                               timers.
*
*                               See also 'TCP CONNECTION CLOSE/FREE CODE DEFINES'.
*
*               perr        Pointer to variable that will receive the return error code from this function :
*
*                               NET_TCP_ERR_NONE                    TCP connection acknowledgement successfully
*                                                                       transmitted.
*                               NET_TCP_ERR_CONN_ACK_NONE           TCP connection acknowledgement NOT requested.
*                               NET_TCP_ERR_CONN_ACK_DLYD           TCP connection acknowledgement transmit delayed
*                                                                       (see Note #6).
*                               NET_TCP_ERR_CONN_ACK_PREVLY_TXD     TCP connection acknowledgement previously
*                                                                       transmitted for segment (see Note #7).
*                               NET_TCP_ERR_CONN_ACK_INVALID        TCP connection acknowledgement NOT valid for
*                                                                       current TCP connection state.
*                               NET_TCP_ERR_CONN_NOT_USED           TCP connection NOT currently used.
*                               NET_TCP_ERR_CONN_FAULT              TCP connection fault; connection(s) aborted.
*                               NET_TCP_ERR_INVALID_CONN_STATE      Invalid TCP connection state.
*                               NET_TCP_ERR_INVALID_CONN_OP         Invalid TCP connection operation.
*                               NET_TCP_ERR_NONE_AVAIL              Resources NOT available.
*
*                                                                   -- RETURNED BY NetTCP_RxPktConnIsValidSeq() : --
*                               NET_TCP_ERR_INVALID_LEN_SEG         Invalid TCP sequence-segment length.
*
* Return(s)   : none.
*
* Caller(s)   : various.
*$PAGE*
* Note(s)     : (3) See the following RFC's for TCP acknowledgement generation summary :
*
*                   (a) RFC # 793, Section  3.9 'Event Processing : SEGMENT ARRIVES'
*                   (b) RFC # 813, Section  5
*                   (c) RFC #1122, Section  4.2.3.2
*                   (d) RFC #2581, Sections 3.2 & 4.2
*                   (e) RFC Draft-IETF-TCPm-TCPSecure #00, Sections 2 & 3
*
*               (4) (a) TCP connection acknowledgements are transmitted when certain segments are received :
*
*                               (A) Some TCP transmit acknowledgement validation logic implemented in previous
*                                   functions; include duplicate validation logic in NetTCP_TxConnAck() only
*                                   if debug/validation code is enabled (i.e. NET_ERR_CFG_ARG_CHK_DBG_EN is
*                                   DEF_ENABLED in 'net_cfg.h').
*
*                       (1) (A) RFC #793, Section 3.4 'Establishing a Connection : Reset Generation : 1' states that
*                               "if [a] connection does not exist (CLOSED) then a reset is sent in response to any
*                               incoming segment except another reset".
*
*                               Thus, ONLY resets are transmitted from the CLOSED state; never acknowledgements.
*
*                           (B) RFC #793, Section 3.9 'Event Processing : SEGMENT ARRIVES : LISTEN [State]' allows
*                               for the transmission of TCP connection reset & connection synchronization segments
*                               ONLY; never acknowledgement-only segments (see also Note #2).
*
*                           (C) RFC #793, Section 3.9 'Event Processing : SEGMENT ARRIVES : SYN-SENT [State] :
*                               Check SYN Bit' states that "if ... our SYN has been ACKed ... change the
*                               connection state to ESTABLISHED, form an ACK segment ... and send it".
*
*                               Thus, acknowledgements MUST be immediately transmitted in reply to all valid
*                               synchronization segments received.
*
*                           (D) (1) RFC #793, Section 3.9 'Event Processing : SEGMENT ARRIVES : Check Sequence
*                                   Number' states that for the "SYN-RECEIVED STATE, ESTABLISHED STATE, FIN-WAIT-1
*                                   STATE, FIN-WAIT-2 STATE, CLOSE-WAIT STATE, CLOSING STATE, LAST-ACK STATE, TIME-
*                                   WAIT STATE ... if an incoming segment is not acceptable," ...
*
*                                   (a) "an acknowledgment should be sent in reply" :
*
*                                           (1) <SEQ=SND.NXT> <ACK=RCV.NXT> <CTL=ACK>
*
*                                   (b) (1) "(unless the RST bit is set)".
*
*                                       (2) However, RFC Draft-IETF-TCPm-TCPSecure #00, Section 2.2 requires 
*                                           transmitting a TCP acknowledgement upon receipt of certain TCP 
*                                           segments regardless of whether "the RST bit" is set (see Notes 
*                                           #4a1D2b1c & #4a1D2b3).
*
*                                   See also Notes #4a1D2b & #4a1D3b.
*$PAGE*
*                               (2) (a) RFC #793, Section 3.9 'Event Processing : SEGMENT ARRIVES : Check RST Bit'
*                                       states that "if the RST bit is set ... enter the CLOSED state".
*
*                                       Note this check is placed following the sequence check to prevent a segment
*                                       from an old connection ... from causing an abort of the current connection".
*
*                                   (b) (1) HOWEVER, RFC Draft-IETF-TCPm-TCPSecure #00, Section 2.2 amends the "handling 
*                                           of a segment with the RST bit when in a synchronized state" to "provide some 
*                                           protection against ... blind reset attack[s] using the RST bit" :
*
*                                           (a) "If the RST bit is set and the sequence number is outside the
*                                                expected window, silently drop the segment."
*
*                                           (b) "If the RST bit is exactly the next expected sequence number [sic],
*                                                reset the connection"; it is assumed that this should read "if the
*                                                RST bit is set and the sequence number is exactly the next expected
*                                                sequence number, reset the connection."
*
*                                           (c) "If the RST bit is set and the sequence number does not exactly
*                                                match the next expected sequence value, yet is within the
*                                                acceptable window (RCV.NXT <= SEG.SEQ < RCV.NXT+RCV.WND) send
*                                                an acknowledgment."
*
*                                       (2) ???? Although RFC Draft-IETF-TCPm-TCPSecure #00 explicitly states that this 
*                                           amendment applies only to the "handling of a ... RST when in a synchronized 
*                                           state", it is assumed that this should also apply to the SYN-RECEIVED state.
*
*                                       (3) ???? In addition, RFC Draft-IETF-TCPm-TCPSecure #00 does NOT provide a 
*                                           precedence priority for handling TCP segments received with BOTH the RST
*                                           & SYN bits set.
*
*                                           ???? Therefore, since it does NOT seem reasonable to reset a TCP connection
*                                           due to a TCP segment that also attempted to synchronize the  TCP connection,
*                                           it is assumed that the amended handling of the SYN bit should take precedence
*                                           over the amended handling of the RST bit.
*
*                                           See Note #4a1D3b.
*
*                               (3) (a) RFC #793, Section 3.9 'Event Processing : SEGMENT ARRIVES : Check SYN
*                                       Bit' states that for "SYN-RECEIVED [STATE], ESTABLISHED STATE, FIN-WAIT
*                                       STATE-1, FIN-WAIT STATE-2, CLOSE-WAIT STATE, CLOSING STATE, LAST-ACK
*                                       STATE, TIME-WAIT STATE ... [to next] check the SYN bit ... [and] if
*                                       the SYN is in the window it is an error, send a reset ... [and] enter
*                                       the CLOSED state ...
*
*                                       [But] if the SYN is not in the window this step would not have been
*                                       reached and an ack would have been sent".
*
*                                   (b) (1) HOWEVER, RFC Draft-IETF-TCPm-TCPSecure #00, Section 3.2 amends the 
*                                           "handling of a segment with the SYN bit set in the synchronized state
*                                            ... [by] handling ... the SYN bit" as follows :
*
*                                           (a) "If the SYN bit is set and the sequence number is outside the
*                                                expected window, send an ACK back to the peer."
*
*                                           (b) "If the SYN bit is set and the sequence number is an exact match to
*                                                the next expected sequence (RCV.NXT == SEG.SEQ) then send an ACK
*                                                segment ... but ... subtract one from value being acknowledged."
*
*                                           (c) "If the SYN bit is set and the sequence number is acceptable, i.e.:
*                                                (RCV.NXT <= SEG.SEQ < RCV.NXT+RCV.WND) then send an ACK segment."
*
*                                       (2) ???? Although RFC Draft-IETF-TCPm-TCPSecure #00 explicitly states that 
*                                           this amendment applies only to the "handling of a ... SYN ... in a 
*                                           synchronized state", it is assumed that this should also apply to the
*                                           SYN-RECEIVED state.
*
*                               (4) RFC #793, Section 3.9 'Event Processing : SEGMENT ARRIVES : Check ACK Field'
*                                   states that if in the "ESTABLISHED STATE" or any state with similar "processing
*                                   as for the ESTABLISHED STATE", that "if the ACK acks something not yet sent
*                                   (SEG.ACK > SND.NXT) then send an ACK".
*$PAGE*
*                       (2) RFC #793, Section 3.9 'Event Processing : SEGMENT ARRIVES : Process Segment Text',
*                           states that in the "ESTABLISHED STATE, FIN-WAIT-1 STATE, FIN-WAIT-2 STATE ... when
*                           ... TCP takes responsibility for ... data ... it must also acknowledge ... the data" :
*                           
*                           (A) "Send an acknowledgment of the form" :
*
*                                   (1) <SEQ=SND.NXT> <ACK=RCV.NXT> <CTL=ACK>
*
*                           (B) "This acknowledgment should be piggybacked on a segment being transmitted if
*                                possible without incurring undue delay."
*
*                               See also Note #6.
*
*                       (3) RFC #793, Section 3.9 'Event Processing : SEGMENT ARRIVES : Check FIN Bit' states
*                           that "if the FIN bit is set, ... send an acknowledgment for the FIN".
*
*                       (4) RFC #813, Section 5 states that "the receiver of data will refrain from sending an
*                           acknowledgement under certain circumstances ... The most obvious event on which to
*                           depend is the arrival of another segment.  So, if a segment arrives, postpone sending
*                           an acknowledgement if ... the following conditions hold" :
*
*                           (A) "The push bit is not set in the segment, since it is a reasonable assumption
*                                that there is more data coming in a subsequent segment."
*
*                               (1) However, if the PUSH bit is set in any received segment, an acknowledgement
*                                   should be immediately transmitted.
*
*                           See also Notes #4b1, #5b2, & #6.
*
*                       (5) (A) RFC #2581, Section 3.2 states that "a TCP receiver SHOULD send an immediate ACK" :
*
*                               (1) "When an out-of-order segment arrives.  The purpose of this ACK is to
*                                    inform the sender that a segment was received out-of-order and which
*                                    sequence number is expected."
*
*                               (2) "In addition, ... when the incoming segment fills in all or part of a
*                                    gap in the sequence space.  This will generate more timely information
*                                    for a sender recovering from a ... retransmission timeout ... [or] a
*                                    fast retransmit."
*
*                           (B) RFC #1122, Section 4.2.2.21 reiterates that "a TCP MAY send an ACK segment
*                               acknowledging RCV.NXT when a valid segment arrives that is in the window
*                               but not at the left window edge ... One reason for ACKing out-of-order
*                               segments [is] to support ... 'fast retransmit'".
*
*                   (b) TCP connection acknowledgements are transmitted for certain TCP connection events :
*
*                       (1) RFC #813, Section 5 states that "the receiver of data will refrain from sending an
*                           acknowledgement under certain circumstances ... Postpone sending an acknowledgement
*                           if ... the following conditions hold" :
*
*                           (B) "There is no revised window information to be sent back."
*
*                               (1) However, if any local receive window size is available to update to the
*                                   remote host, an acknowledgement should be immediately transmitted.
*
*                           See also Note #4a4 & 'NetTCP_RxConnWinSizeHandler()  Note #4'.
*$PAGE*
*               (5) (a) Although NO RFC specifies whether an acknowledgement should or should NOT 
*                       be transmitted in response to a received acknowledgement-only segment, it
*                       seems reasonable & is assumed that NO TCP connection acknowledgement should
*                       be transmitted in response to any acknowledgement-only segment(s) received.
*
*                       (1) A received TCP segment is considered an acknowledgement-only segment if
*                           the segment was received with zero segment length, i.e. NO received TCP
*                           sequences :
*
*                           (A) NO synchronization or close controls)
*                           (B) NO TCP data
*
*                   (b) (1) However, since acknowledgements are transmitted in response to various
*                           invalid segments received, some acknowledgements MUST be transmitted 
*                           even for certain invalid acknowledgement-only segments.
*
*                           See also Note #4a1.
*
*                       (2) Also, acknowledgements SHOULD be transmitted for received segments with
*                           the PUSH bit set, even for segments with NO received TCP data.
*
*                           See also Note #4a4.
*
*                       (3) (A) Also, RFC #1122, Section 4.2.2.17 states that the "probing of zero
*                               (offered) windows MUST be supported.  A TCP MAY keep its offered
*                               receive window closed indefinitely.  As long as the receiving TCP
*                               continues to send acknowledgements in response to the probe segments".
*
*                           (B) In order to always acknowledge a remote host's probing of the local 
*                               TCP connection's receive window size :
*
*                               (1) Since probe segments :
*
*                                   (a) may or may NOT contain data, ...
*                                   (b) sequence values may or may NOT be within the TCP connection's
*                                           current receive window;  ...
*
*                                   See also Note #4a1D1a1 & 'NetTCP_RxPktConnIsValidSeq()  Note #1d3'.
*
*                               (2) ... acknowledgements SHOULD be transmitted in reply to ALL valid
*                                   & SOME invalid received segments from the remote host whenever
*                                   the TCP connection's local receive window is zero-sized.
*
*               (6) (a) The following sections state that "a TCP SHOULD implement a delayed ACK" :
*
*                           (A) RFC # 813, Section 5
*                           (B) RFC #1122, Section 4.2.3.2
*                           (C) RFC #2581, Section 4.2
*
*                       (1) (A) (1) RFC #1122, Section 4.2.3.2 states that "in a stream of full-sized segments
*                                   there SHOULD be an ACK for at least every second segment".
*
*                               (2) RFC #2581, Section 4.2 reiterates that "an ACK SHOULD be generated for at
*                                   least every second full-sized segment".
*
*                           (B) However, RFC #2581, Section 4.2 states that "an implementation is deemed to
*                               comply with this requirement ... by acknowledging at least every second segment,
*                               regardless of size".
*
*                       (2) (A) (1) RFC #813, Section 5 states that "the receiver of data will refrain from
*                                   sending an acknowledgement under certain circumstances, in which case it
*                                   must set a timer which will cause the acknowledgement to be sent later".
*
*                               (2) RFC #1122, Section 4.2.3.2 states that "an ACK should not be excessively
*                                   delayed; in particular, the delay MUST be less than 0.5 seconds".
*
*                               (3) RFC #2581, Section 4.2 reiterates that "an ACK ... MUST be generated
*                                   within 500 ms of the arrival of the first unacknowledged packet".
*
*                           (B) If the acknowledgement delay timeout is configured with a non-zero value,
*                               at least one timer tick MUST be set to ensure that the non-zero timeout
*                               is implemented.
*
*                   (b) However, if NO network timer is available to delay the acknowledgement, the TCP
*                       connection acknowledgement SHOULD be immediately transmitted.
*$PAGE*
*               (7) (a) (1) RFC #1122, Section 4.2.2.14 states that "a careless implementation can send
*                           two or more acknowledgment segments per data segment received".
*
*                       (2) RFC #1122, Section 4.2.2.20 states that "in general, the processing of
*                           received segments MUST be implemented to aggregate ACK segments whenever
*                           possible.  For example, if the TCP is processing a series of queued
*                           segments, it MUST process them all before sending any ACK segments".
*
*                       (3) Thus, no more than one acknowledgement SHOULD be transmitted in response
*                           to any received segment.
*
*                   (b) "When the application program subsequently consumes the data and increases
*                        the available receive buffer space again, the receiver may send a second
*                        acknowledgement segment to update the window at the sender."
*
*                       However, the application layer receives data from a TCP connection's application
*                       receive queue asynchronously & irrespective of distinct or specific TCP packets
*                       (see 'NetTCP_RxAppData()  Note #5a').  Thus, any acknowledgement transmissions
*                       triggered during asynchronous application receives CANNOT be associated with, &
*                       thereby limited by, any specific received segments.
*
*               (8) (a) (1) RFC #793, Sections 3.7 & 2.6 state that "TCP uses retransmission ... to ensure 
*                           delivery of every segment".
*
*                       (2) However, RFC #1122, Section 4.2.2.17 'DISCUSSION' states that "it is extremely
*                           important to remember that ACK (acknowledgment) segments that contain no data
*                           are not reliably transmitted by TCP".
*
*                           Therefore, it is assumed that TCP acknowledgement-ONLY segments should NOT be
*                           queued for retransmission but SHOULD be silently discarded.
*
*                   (b) (1) The network buffer's reference counter is NOT incremented since the TCP layer
*                           does NOT maintain a reference to any transmitted TCP acknowledgement segments.
*
*                       (2) Therefore, the network buffer MUST be freed by lower layer(s).
*
*                   See also 'NetTCP_TxConnReset()  Note #6',
*                          & 'NetTCP_TxConnProbe()  Note #3'.
*
*               (9) On ANY errors, network resources MUST be appropriately freed :
*
*                   (a) For any network resources NOT linked to the TCP connection, each network resource
*                       MUST be freed by appropriate function(s).
*
*              (10) #### IP options currently NOT implemented.
*********************************************************************************************************
*/
/*$PAGE*/
static  void  NetTCP_TxConnAck (NET_TCP_CONN        *pconn,
                                NET_BUF_HDR         *pbuf_hdr,
                                NET_TCP_ACK_CODE     tx_ack_code,
                                NET_TCP_CLOSE_CODE   close_code,
                                NET_ERR             *perr)
{
#if (((NET_CTR_CFG_STAT_EN     == DEF_ENABLED)                    || \
      (NET_CTR_CFG_ERR_EN      == DEF_ENABLED))                   && \
      (CPU_CFG_CRITICAL_METHOD == CPU_CRITICAL_METHOD_STATUS_LOCAL))
    CPU_SR               cpu_sr;
#endif
#if (NET_ERR_CFG_ARG_CHK_DBG_EN == DEF_ENABLED)
    NET_TCP_SEQ_CODE     seq_code;
    NET_TCP_RESET_CODE   reset_code;
#endif
    CPU_BOOLEAN          tx_ack;
    CPU_BOOLEAN          tmr_free;
    CPU_BOOLEAN          push_avail;
    NET_TMR_TICK         timeout_tick;
    NET_BUF_SIZE         data_len;
    NET_BUF_SIZE         data_ix;
    NET_BUF             *pseg_ack;
    NET_BUF_HDR         *pseg_ack_hdr;
    NET_IP_TOS           TOS;
    NET_IP_TTL           TTL;
    NET_IP_ADDR          src_addr;
    NET_IP_ADDR          dest_addr;
    NET_TCP_PORT_NBR     src_port;
    NET_TCP_PORT_NBR     dest_port;
    NET_TCP_SEQ_NBR      seq_nbr;
    NET_TCP_SEQ_NBR      ack_nbr;
    NET_TCP_SEQ_NBR      ack_nbr_delta;
    NET_TCP_WIN_SIZE     win_size;
    CPU_INT16U           flags_tcp;
    CPU_INT16U           flags_ip;
    NET_ERR              err;


                                                                    /* ----------- VALIDATE TCP CONN TX ACK ----------- */
    tx_ack        = DEF_NO;
    tmr_free      = DEF_YES;
    ack_nbr_delta = 0;

    switch (pconn->ConnState) {
        case NET_TCP_CONN_STATE_FREE:
             NET_CTR_ERR_INC(NetTCP_ErrNotUsedCtr);
            *perr = NET_TCP_ERR_CONN_NOT_USED;
             return;                                                /* Prevent 'break NOT reachable' compiler warning.  */


        case NET_TCP_CONN_STATE_CLOSED:                             /* See Note #4a1A.                                  */
        case NET_TCP_CONN_STATE_LISTEN:                             /* See Note #4a1B.                                  */
             break;


        case NET_TCP_CONN_STATE_SYNC_TXD:                           /* See Note #4a1C.                                  */
             if (pbuf_hdr != (NET_BUF_HDR *)0) {
#if (NET_ERR_CFG_ARG_CHK_DBG_EN == DEF_ENABLED)                     /* See Note #4aA.                                   */
                 seq_code = NetTCP_RxPktConnIsValidSeq(pconn, pbuf_hdr, perr);
                 if (*perr != NET_TCP_ERR_NONE) {
                      return;
                 }
                 if (seq_code == NET_TCP_CONN_RX_SEQ_SYNC) {        /* If valid sync rx'd, ...                          */
                     tx_ack = DEF_YES;                              /* ... tx TCP conn ack.                             */
                 }
#else
                 tx_ack = DEF_YES;
#endif
                 if (pbuf_hdr->TCP_SegAckTxd != DEF_NO) {           /* If prev'ly tx'd TCP conn ack for rx'd seg, ..    */
                    *perr = NET_TCP_ERR_CONN_ACK_PREVLY_TXD;        /* .. do NOT re-tx TCP conn ack (see Note #7a3).    */
                     return;
                 }

             } else {
                 tx_ack = DEF_YES;
             }
             break;

/*$PAGE*/
        case NET_TCP_CONN_STATE_SYNC_RXD:
        case NET_TCP_CONN_STATE_SYNC_RXD_PASSIVE:
        case NET_TCP_CONN_STATE_SYNC_RXD_ACTIVE:
        case NET_TCP_CONN_STATE_CONN:
        case NET_TCP_CONN_STATE_FIN_WAIT_1:
        case NET_TCP_CONN_STATE_FIN_WAIT_2:
        case NET_TCP_CONN_STATE_CLOSING:
        case NET_TCP_CONN_STATE_TIME_WAIT:
        case NET_TCP_CONN_STATE_CLOSE_WAIT:
        case NET_TCP_CONN_STATE_LAST_ACK:
             if (pbuf_hdr != (NET_BUF_HDR *)0) {
                 if (pbuf_hdr->TCP_SegAckTxd != DEF_NO) {           /* If prev'ly tx'd TCP conn ack for rx'd seg, ..    */
                    *perr = NET_TCP_ERR_CONN_ACK_PREVLY_TXD;        /* .. do NOT re-tx TCP conn ack (see Note #7a3).    */
                     return;
                 }
             }

             switch (tx_ack_code) {
                 case NET_TCP_CONN_TX_ACK_NONE:
                     *perr = NET_TCP_ERR_CONN_ACK_NONE;
                      return;                                       /* Prevent 'break NOT reachable' compiler warning.  */


                 case NET_TCP_CONN_TX_ACK:
                 case NET_TCP_CONN_TX_ACK_IMMED:
                      if (pbuf_hdr != (NET_BUF_HDR *)0) {
                          push_avail = DEF_BIT_IS_SET(pbuf_hdr->TCP_HdrLen_Flags, NET_TCP_HDR_FLAG_PUSH);
                          if (push_avail == DEF_YES) {                  /* If rx'd seg push'd & en'd, ..                */
                              if (pconn->TxAckImmedRxdPushEn != DEF_DISABLED) {
                                  tx_ack  = DEF_YES;                    /* .. tx TCP conn ack (see Note #4a4A1).        */
                                  break;
                              }
                          }

                          if (pbuf_hdr->TCP_SegLen == 0) {              /* If ack-ONLY seg       (see Note #5a1);   ..  */
                              if (pconn->RxWinSizeActual > 0) {         /* .. & local rx win > 0,                   ..  */
                                 *perr = NET_TCP_ERR_CONN_ACK_INVALID;
                                  return;                               /* .. do NOT tx ack      (see Note #5a);    ..  */

                              } else {                                  /* .. & local rx win = 0 (see Note #5b3B2), ..  */
                                  tx_ack = DEF_YES;                     /* .. tx TCP conn ack.                          */
                                  break;
                              }
                          }
                      }

                      if (tx_ack_code == NET_TCP_CONN_TX_ACK_IMMED) {   /* If immed ack req'd, ...                      */
                          tx_ack = DEF_YES;                             /* ... tx TCP conn ack.                         */
                          break;
                      }

                      if (pconn->TxAckDlyTimeout_ms == 0) {             /* If ack dly timeout zero, ...                 */
                          tx_ack = DEF_YES;                             /* ... tx TCP conn ack.                         */
                          break;
                      }

                      pconn->TxAckDlyCnt++;                             /* If ack dly cnt >= th, ...                    */
                      if (pconn->TxAckDlyCnt >= NET_TCP_ACK_DLY_CNT_TH) {
                          tx_ack = DEF_YES;                             /* ... tx TCP conn ack (see Note #6a1B).        */
                          break;
                      }

                      if (pconn->TxAckDlyTmr != (NET_TMR *)0) {         /* If ack dly tmr prev'ly started, ...          */
                         *perr = NET_TCP_ERR_CONN_ACK_DLYD;             /* ... continue ack dly (see Note #6a2A1).      */
                          return;
                      }

                      timeout_tick = ((NET_TMR_TICK)pconn->TxAckDlyTimeout_ms * NET_TMR_TIME_TICK_PER_SEC) / DEF_TIME_NBR_mS_PER_SEC;
                      if (timeout_tick < 1) {                           /* If < 1 tick, ...                             */
                          timeout_tick = 1;                             /* ... set at least 1 tick (see Note #6a2B).    */
                      }
                      pconn->TxAckDlyTmr = NetTmr_Get((void       *) pconn,
                                                      (CPU_FNCT_PTR) NetTCP_TxConnAckDlyTimeout,
                                                      (NET_TMR_TICK) timeout_tick,
                                                      (CPU_INT16U  ) NET_TMR_FLAG_NONE,
                                                      (NET_ERR    *)&err);
                      if ( err == NET_TMR_ERR_NONE) {                   /* If ack dly tmr avail, ...                    */
                         *perr  = NET_TCP_ERR_CONN_ACK_DLYD;            /* ... start ack dly (see Note #6a2A1).         */
                          return;

                      } else {                                          /* Else tx TCP conn ack (see Note #6b).         */
                          tx_ack = DEF_YES;
                      }
                      break;

/*$PAGE*/
                 case NET_TCP_CONN_TX_ACK_FAULT:                        /* See Note #4a1D.                              */
                      if (pbuf_hdr != (NET_BUF_HDR *)0) {
                          if (pbuf_hdr->TCP_SegSync == DEF_YES) {       /* If sync rx'd (see Note #4a1D3b1), ...        */
                              tx_ack = DEF_YES;                         /* ... tx TCP conn ack; ignore possible reset.  */
                                                                        /* If rx'd sync equal to next rx seq nbr, ...   */
                              if (pbuf_hdr->TCP_SeqNbr == pconn->RxSeqNbrNext) {
                                  ack_nbr_delta = 1;                    /* ... sub 1 from ack (see Note #4a1D3b1B).     */
                              }

                          } else {
#if (NET_ERR_CFG_ARG_CHK_DBG_EN == DEF_ENABLED)                         /* See Note #4aA.                               */
                              seq_code = NetTCP_RxPktConnIsValidSeq(pconn, pbuf_hdr, perr);
                              if (*perr != NET_TCP_ERR_NONE) {
                                   return;
                              }
                              reset_code = NetTCP_RxPktConnIsValidReset(pconn, pbuf_hdr, perr);
                              if (*perr != NET_TCP_ERR_NONE) {
                                   return;
                              }
                              switch (seq_code) {
                                  case NET_TCP_CONN_RX_SEQ_VALID:       /* If       valid seq   rx'd  ..                */
                                                                        /* .. but invalid reset rx'd, ..                */
                                       if (reset_code == NET_TCP_CONN_RX_RESET_INVALID) {
                                           tx_ack = DEF_YES;            /* .. tx TCP conn ack  (see Note #4a1D2b1c).    */
                                       }
                                       break;


                                  case NET_TCP_CONN_RX_SEQ_SYNC:        /* If invalid sync rx'd, ..                     */
                                  case NET_TCP_CONN_RX_SEQ_SYNC_INVALID:
                                       tx_ack = DEF_YES;                /* .. tx TCP conn ack  (see Note #4a1D3b1).     */
                                       break;


                                  case NET_TCP_CONN_RX_SEQ_NONE:
                                  case NET_TCP_CONN_RX_SEQ_INVALID:     /* If invalid seq rx'd (see Note #4a1D1)    ..  */
                                  default:
                                                                        /* .. & reset NOT rx'd (see Note #4a1D1b1), ..  */
                                       if (reset_code == NET_TCP_CONN_RX_RESET_NONE) {
                                           tx_ack = DEF_YES;            /* .. tx TCP conn ack  (see Note #4a1D1a).      */
                                       }
                                       break;
                              }
#else
                              tx_ack = DEF_YES;
#endif
                          }
                      } else {
                          tx_ack = DEF_YES;
                      }
                      break;


                 case NET_TCP_CONN_TX_ACK_TIMEOUT:
                      tx_ack   = DEF_YES;
                      tmr_free = DEF_NO;
                      break;


                 default:
                      break;
             }
             break;


        case NET_TCP_CONN_STATE_CLOSING_DATA_AVAIL:
             NET_CTR_ERR_INC(NetTCP_ErrConnInvalidOpCtr);
            *perr = NET_TCP_ERR_INVALID_CONN_OP;
             return;                                                /* Prevent 'break NOT reachable' compiler warning.  */


        case NET_TCP_CONN_STATE_NONE:
        default:
             NetTCP_ConnClose(pconn, pbuf_hdr, DEF_YES, close_code);
             NET_CTR_ERR_INC(NetTCP_ErrConnInvalidStateCtr);
            *perr = NET_TCP_ERR_INVALID_CONN_STATE;
             return;                                                /* Prevent 'break NOT reachable' compiler warning.  */
    }

    if (tx_ack != DEF_YES) {                                        /* If NOT valid, abort tx TCP conn ack.             */
       *perr = NET_TCP_ERR_CONN_ACK_INVALID;
        return;
    }


    NetTCP_TxConnAckDlyReset(pconn, tmr_free);                      /* Reset ack dly ctrls.                             */

    if (pbuf_hdr != (NET_BUF_HDR *)0) {
        pbuf_hdr->TCP_SegAckTxd = DEF_YES;                          /* Set ack tx'd for rx'd seg (see Note #7a).        */
    }


/*$PAGE*/
                                                                    /* ----------- PREPARE TCP CONN ACK SEG ----------- */
                                                                    /* If valid, prepare & tx TCP conn ack.             */
                                                                    /* Get buf.                                         */
    data_len = NET_TCP_DATA_LEN_TX_ACK;
    data_ix  = NET_BUF_DATA_TX_IX;
    pseg_ack = NetBuf_Get((NET_BUF_SIZE) data_len,
                          (NET_BUF_SIZE) data_ix,
                          (CPU_INT16U  ) NET_BUF_FLAG_NONE,
                          (NET_ERR    *)&err);
    if ( err != NET_BUF_ERR_NONE) {
       *perr  = NET_TCP_ERR_NONE_AVAIL;
        return;
    }

                                                                    /* --------------- PREPARE TCP HDR ---------------- */
                                                                    /* Prepare seg addrs.                               */
    if (pbuf_hdr != (NET_BUF_HDR *)0) {                             /* If TCP pkt rx'd, cfg TCP tx                ...   */
                                                                    /* ...  src  addr from rx'd TCP pkt dest addr ...   */
        src_port  = (NET_TCP_PORT_NBR)pbuf_hdr->TCP_UDP_PortDest;
        src_addr  = (NET_IP_ADDR     )pbuf_hdr->IP_AddrDest;
                                                                    /* .. & dest addr from rx'd TCP pkt src  addr.      */
        dest_port = (NET_TCP_PORT_NBR)pbuf_hdr->TCP_UDP_PortSrc;
        dest_addr = (NET_IP_ADDR     )pbuf_hdr->IP_AddrSrc;

    } else {                                                        /* Else cfg TCP tx pkt addrs from TCP conn addrs.   */
        NetTCP_TxConnPrepareSegAddrs((NET_TCP_CONN *) pconn,
                                     (CPU_INT08U   *)&src_port,
                                     (CPU_INT08U   *)&src_addr,
                                     (CPU_INT16U    ) sizeof(src_port),
                                     (CPU_INT16U    ) sizeof(src_addr),
                                     (CPU_INT08U   *)&dest_port,
                                     (CPU_INT08U   *)&dest_addr,
                                     (CPU_INT16U    ) sizeof(dest_port),
                                     (CPU_INT16U    ) sizeof(dest_addr),
                                     (NET_ERR      *)&err);
        if ( err != NET_TCP_ERR_NONE) {                             /* See Note #9a.                                    */
           *perr  = NET_TCP_ERR_CONN_FAULT;
            NetBuf_Free(pseg_ack);
            return;
        }
    }


                                                                    /* Prepare TCP seq nbrs (see Note #1b2B).           */
    seq_nbr   = pconn->TxSeqNbrNext;
    ack_nbr   = pconn->RxSeqNbrNext - ack_nbr_delta;

                                                                    /* Prepare TCP tx flags (see Note #1b2C).           */
    flags_tcp = NET_TCP_FLAG_NONE  |
                NET_TCP_FLAG_TX_ACK;

                                                                    /* Prepare TCP win size.                            */
    win_size  = pconn->RxWinSizeActual;

                                                                    /* Prepare IP params.                               */
    TOS       = pconn->TxIP_TOS;
    TTL       = pconn->TxIP_TTL;
    flags_ip  = pconn->TxIP_Flags;


                                                                    /* Init buf ctrls.                                  */
    pseg_ack_hdr                  = &pseg_ack->Hdr;
    pseg_ack_hdr->DataIx          = (CPU_INT16U  )data_ix;
    pseg_ack_hdr->DataLen         = (NET_BUF_SIZE)data_len;
    pseg_ack_hdr->TotLen          = (NET_BUF_SIZE)pseg_ack_hdr->DataLen;
    pseg_ack_hdr->ProtocolHdrType =  NET_PROTOCOL_TYPE_TCP;

    pseg_ack_hdr->TCP_SegSync     = (CPU_BOOLEAN )DEF_NO;
    pseg_ack_hdr->TCP_SegClose    = (CPU_BOOLEAN )DEF_NO;
    pseg_ack_hdr->TCP_SegAck      = (CPU_BOOLEAN )DEF_YES;
    pseg_ack_hdr->TCP_SegReset    = (CPU_BOOLEAN )DEF_NO;

    pseg_ack_hdr->TCP_Flags       =  flags_tcp;



/*$PAGE*/
                                                                    /* ------------- TX TCP CONN ACK SEG -------------- */
    NetTCP_TxPktHandler((NET_BUF        *) pseg_ack,
                        (NET_IP_ADDR     ) src_addr,
                        (NET_TCP_PORT_NBR) src_port,
                        (NET_IP_ADDR     ) dest_addr,
                        (NET_TCP_PORT_NBR) dest_port,
                        (NET_TCP_SEQ_NBR ) seq_nbr,
                        (NET_TCP_SEQ_NBR ) ack_nbr,
                        (NET_TCP_WIN_SIZE) win_size,
                        (NET_IP_TOS      ) TOS,
                        (NET_IP_TTL      ) TTL,
                        (CPU_INT16U      ) flags_tcp,
                        (CPU_INT16U      ) flags_ip,
                        (void           *) 0,
                        (void           *) 0,                       /* See Note #10.                                    */
                        (NET_ERR        *)&err);                    /* Ignore transitory tx err(s).                     */

#if 0                                                               /* Tx buf freed by lower layer(s) [see Note #8b2].  */
    NetTCP_TxPktFree(pseg_ack);
#endif
    NET_CTR_STAT_INC(NetTCP_StatTxSegConnAckCtr);



   *perr = NET_TCP_ERR_NONE;
}


/*$PAGE*/
/*
*********************************************************************************************************
*                                     NetTCP_TxConnAckDlyReset()
*
* Description : Reset a TCP connection's delayed acknowledgement controls.
*
* Argument(s) : pconn       Pointer to TCP connection to reset delayed acknowledgement controls.
*               -----       Argument validated in NetTCP_TxConnAck(),
*                                                 NetTCP_TxConnTxQ(),
*                                                 NetTCP_TxConnReTxQ_Timeout().
*
*               tmr_free    Indicate whether to free network timer :
*
*                               DEF_YES                Free network timer for delayed acknowledgement.
*                               DEF_NO          Do NOT free network timer for delayed acknowledgement
*                                                     [Freed by  NetTmr_TaskHandler()
*                                                            via NetTCP_TxConnAckDlyTimeout()].
*
* Return(s)   : none.
*
* Caller(s)   : NetTCP_TxConnAck(),
*               NetTCP_TxConnTxQ(),
*               NetTCP_TxConnReTxQ().
*
* Note(s)     : (1) A TCP connection's delayed acknowledgement controls SHOULD be reset whenever :
*
*                   (a) TCP data segment(s) are    transmitted
*                   (b) TCP data segment(s) are re-transmitted
*
*                   ... since any transmitted or re-transmitted data segment(s) always transmit an
*                   accompanying acknowledgement.
*********************************************************************************************************
*/

static  void  NetTCP_TxConnAckDlyReset (NET_TCP_CONN  *pconn,
                                        CPU_BOOLEAN    tmr_free)
{
    pconn->TxAckDlyCnt = 0;                                     /* Reset ack dly cnts ...                               */
    if (pconn->TxAckDlyTmr != (NET_TMR *)0) {                   /* ... & free/clr ack dly tmr.                          */
        if (tmr_free == DEF_YES) {
            NetTmr_Free(pconn->TxAckDlyTmr);
        }
        pconn->TxAckDlyTmr  = (NET_TMR *)0;
    }
}


/*$PAGE*/
/*
*********************************************************************************************************
*                                    NetTCP_TxConnAckDlyTimeout()
*
* Description : (1) Handle TCP connection's delayed acknowledgement transmit for the following connected
*                   states :
*
*                   (a) SYN-RECEIVED
*                   (b) ESTABLISHED
*                   (c) FIN-WAIT-1
*                   (d) FIN-WAIT-2
*                   (e) CLOSING
*                   (f) TIME-WAIT
*                   (g) CLOSE-WAIT
*                   (h) LAST-ACK
*
*
* Argument(s) : pconn_timeout       Pointer to TCP connection to transmit delayed acknowledgement (see Note #2b).
*
* Return(s)   : none.
*
* Caller(s)   : Referenced in NetTCP_TxConnAck().
*
* Note(s)     : (2) Ideally, network timer expiration functions could be defined as '[(void) (OBJECT *)]' 
*                   type functions -- even though network timer API functions cast expiration functions 
*                   to generic 'CPU_FNCT_PTR' type (i.e. '[(void) (void *)]').
*
*                   (a) (1) Unfortunately, ISO-IEC 9899-1999 ANSI-C, Section 6.3.2.3.7 states that "a 
*                           pointer to an object ... may be converted to a pointer to a different object 
*                           ... [but] if the resulting pointer is not correctly aligned ... the behavior
*                           is undefined".
*
*                           And since compilers may NOT correctly convert 'void' pointers to non-'void' 
*                           pointer arguments, network timer expiration functions MUST avoid incorrect
*                           pointer conversion behavior between 'void' pointer parameters & non-'void' 
*                           pointer arguments & therefore CANNOT be defined as '[(void) (OBJECT *)]'.
*
*                       (2) However, Section 6.3.2.3.1 states that "a pointer to void may be converted 
*                           to or from a pointer to any ... object ... A pointer to any ... object ... 
*                           may be converted to a pointer to void and back again; the result shall 
*                           compare equal to the original pointer".
*                   
*                   (b) Therefore, to correctly convert 'void' pointer objects back to appropriate
*                       network object pointer objects, network timer expiration functions MUST :
*
*                       (1) Be defined as 'CPU_FNCT_PTR' type (i.e. '[(void) (void *)]'); &       ...
*                       (2) Explicitly cast 'void' pointer arguments to specific object pointers; ...
*                           (A) ... in this case, a 'NET_TCP_CONN' pointer.
*
*                   See also 'net_tmr.c  NetTmr_Get()  Note #3'.
*
*               (3) This function is a network timer expiration function :
*
*                   (a) (1) For the following connection timer(s) :
*
*                           (A) TCP connection transmit acknowledgement delay timer ('TxAckDlyTmr')
*
*                       (2) (A) Clear the timer pointer; ...
*                               (1) Cleared prior to next handler function(s) as an extra precaution to
*                                   avoiding re-freeing the timer (see Note #3a2B).
*
*                           (B) but do NOT re-free the timer.
*
*                   (b) Do NOT set the following close timer flag(s) :
*
*                       (1) NET_TCP_CONN_CLOSE_TMR_TX_ACK_DLY
*********************************************************************************************************
*/
/*$PAGE*/
static  void  NetTCP_TxConnAckDlyTimeout (void  *pconn_timeout)
{
#if ((NET_ERR_CFG_ARG_CHK_DBG_EN == DEF_ENABLED)                    && \
     (NET_CTR_CFG_ERR_EN         == DEF_ENABLED)                    && \
     (CPU_CFG_CRITICAL_METHOD    == CPU_CRITICAL_METHOD_STATUS_LOCAL))
    CPU_SR               cpu_sr;
#endif
    NET_TCP_CONN        *pconn;
    NET_TCP_CLOSE_CODE   close_code;
    NET_ERR              err;


    pconn      = (NET_TCP_CONN *)pconn_timeout;                         /* See Note #2b2A.                              */

    close_code =  NET_TCP_CONN_CLOSE_ALL;
    DEF_BIT_CLR(close_code, NET_TCP_CONN_CLOSE_TMR_TX_ACK_DLY);         /* See Note #3b1.                               */

#if (NET_ERR_CFG_ARG_CHK_DBG_EN == DEF_ENABLED)
                                                                        /* -------------- VALIDATE PTR ---------------- */
    if (pconn == (NET_TCP_CONN *)0) {
        NET_CTR_ERR_INC(NetTCP_ErrNullPtrCtr);
        return;
    }
                                                                        /* -------------- VALIDATE TYPE --------------- */
    if (pconn->Type != NET_TCP_TYPE_CONN) {
        NET_CTR_ERR_INC(NetTCP_ErrConnInvalidTypeCtr);
        return;
    }

    switch (pconn->ConnState) {
        case NET_TCP_CONN_STATE_FREE:
             NET_CTR_ERR_INC(NetTCP_ErrNotUsedCtr);
             return;                                                    /* Prevent 'break NOT reachable' warning.       */


        case NET_TCP_CONN_STATE_CLOSED:
        case NET_TCP_CONN_STATE_LISTEN:
        case NET_TCP_CONN_STATE_SYNC_TXD:
        case NET_TCP_CONN_STATE_CLOSING_DATA_AVAIL:
             NET_CTR_ERR_INC(NetTCP_ErrConnInvalidOpCtr);
             return;                                                    /* Prevent 'break NOT reachable' warning.       */


        case NET_TCP_CONN_STATE_SYNC_RXD:                               /* See Note #1.                                 */
        case NET_TCP_CONN_STATE_SYNC_RXD_PASSIVE:
        case NET_TCP_CONN_STATE_SYNC_RXD_ACTIVE:
        case NET_TCP_CONN_STATE_CONN:
        case NET_TCP_CONN_STATE_FIN_WAIT_1:
        case NET_TCP_CONN_STATE_FIN_WAIT_2:
        case NET_TCP_CONN_STATE_CLOSING:
        case NET_TCP_CONN_STATE_TIME_WAIT:
        case NET_TCP_CONN_STATE_CLOSE_WAIT:
        case NET_TCP_CONN_STATE_LAST_ACK:
             break;


        case NET_TCP_CONN_STATE_NONE:
        default:
             NetTCP_ConnClose((NET_TCP_CONN     *)pconn,
                              (NET_BUF_HDR      *)0,
                              (CPU_BOOLEAN       )DEF_YES,
                              (NET_TCP_CLOSE_CODE)close_code);
             NET_CTR_ERR_INC(NetTCP_ErrConnInvalidStateCtr);
             return;                                                    /* Prevent 'break NOT reachable' warning.       */
    }
#endif


                                                                        /* ------ HANDLE TCP CONN TX ACK TIMEOUT ------ */
    pconn->TxAckDlyTmr = (NET_TMR *)0;                                  /* Clr tx ack dly tmr (see Note #3a2A1).        */

    NetTCP_TxConnAck((NET_TCP_CONN     *) pconn,
                     (NET_BUF_HDR      *) 0,
                     (NET_TCP_ACK_CODE  ) NET_TCP_CONN_TX_ACK_TIMEOUT,
                     (NET_TCP_CLOSE_CODE) close_code,
                     (NET_ERR          *)&err);                         /* Ignore transitory tx err(s).                 */
}


/*$PAGE*/
/*
*********************************************************************************************************
*                                        NetTCP_TxConnReset()
*
* Description : (1) Prepare & transmit a TCP connection reset :
*
*                   (a) Validate received TCP packet  for TCP reset                     See Note #4
*                   (b) Validate TCP connection state for TCP reset                     See Note #3
*                   (c) Prepare  TCP reset segment :
*                       (1) Get  buffer
*                       (2) Prepare TCP segment :
*                           (A) TCP segment addresses 
*                           (B) TCP segment sequence numbers                            See Note #5
*                           (C) TCP segment transmit flags : 
*                               (1) RESET
*                               (2) ACK                                                 See Note #5a2A
*                           (D) TCP segment window size 
*                           (E) TCP segment packet buffer controls 
*                   (d) Transmit TCP connection reset
*
*
* Argument(s) : pconn           Pointer to a TCP connection.
*
*               pbuf_hdr        Pointer to network buffer header that received TCP packet, if available.
*
*               tx_reset_code   Indicate whether & how to transmit a TCP reset segment :
*
*                                   NET_TCP_CONN_TX_RESET           Transmit a TCP reset segment, if permitted
*                                                                       (see Notes #3 & #4).
*                                   NET_TCP_CONN_TX_RESET_FAULT     Transmit a TCP reset segment immediately for
*                                                                       a closing TCP connection fault.
*
*               close_code      Select which close action(s) to perform; bit-field flags logically OR'd :
*
*                                   NET_TCP_CONN_CLOSE_NONE                 Perform NO  close actions.
*                                   NET_TCP_CONN_CLOSE_ALL                  Perform ALL close actions.
*
*                                   NET_TCP_CONN_CLOSE_CONN_TX_RESET        Perform close connection transmit reset.
*                                   NET_TCP_CONN_CLOSE_CONN_ALL             Perform ALL   connection close    actions.
*
*                                   NET_TCP_CONN_CLOSE_TMR_TX_IDLE          Close    transmit idle                  timer.
*                                   NET_TCP_CONN_CLOSE_TMR_TX_SILLY_WIN     Close    transmit silly window persist  timer.
*                                   NET_TCP_CONN_CLOSE_TMR_TX_ZERO_WIN      Close    transmit zero  window persist  timer.
*                                   NET_TCP_CONN_CLOSE_TMR_TX_ACK_DLY       Close    transmit acknowledgement delay timer.
*                                   NET_TCP_CONN_CLOSE_TMR_RE_TX            Close re-transmit                       timer.
*                                   NET_TCP_CONN_CLOSE_TMR_KEEP_ALIVE       Close connection keep-alive             timer.
*                                   NET_TCP_CONN_CLOSE_TMR_TIMEOUT          Close connection                        timer.
*                                   NET_TCP_CONN_CLOSE_TMR_ALL              Close ALL                               timers.
*
*                               See also 'TCP CONNECTION CLOSE/FREE CODE DEFINES'.
*
*               perr        Pointer to variable that will receive the return error code from this function :
*
*                               NET_TCP_ERR_NONE                    TCP connection reset successfully transmitted.
*                               NET_TCP_ERR_CONN_RESET_INVALID      TCP connection reset NOT valid for current TCP
*                                                                       connection state.
*                               NET_TCP_ERR_CONN_NOT_USED           TCP connection NOT currently used.
*                               NET_TCP_ERR_CONN_FAULT              TCP connection fault; connection(s) aborted.
*                               NET_TCP_ERR_INVALID_CONN_STATE      Invalid TCP connection state.
*                               NET_TCP_ERR_NONE_AVAIL              Resources NOT available.
*
*                                                                   - RETURNED BY NetTCP_RxPktConnIsValidSeq() : -
*                               NET_TCP_ERR_INVALID_LEN_SEG         Invalid TCP sequence-segment length.
*
* Return(s)   : none.
*
* Caller(s)   : various.
*$PAGE*
* Note(s)     : (2) See the following RFC's for TCP reset generation summary :
*
*                   (a) RFC #793, Section 3.4 'Establishing a Connection : Reset Generation'
*                   (b) RFC #793, Section 3.9 'Event Processing : SEGMENT ARRIVES'
*                   (c) RFC Draft-IETF-TCPm-TCPSecure #00, Section 3
*
*               (3) TCP connection resets are transmitted :
*
*                   (a) When certain invalid segments are received :
*
*                               (A) Some TCP transmit reset validation logic implemented in previous functions;
*                                   include duplicate validation logic in NetTCP_TxConnReset() only if debug/
*                                   validation code is enabled (i.e. NET_ERR_CFG_ARG_CHK_DBG_EN is DEF_ENABLED 
*                                   in 'net_cfg.h').
*
*                       (1) (A) RFC #793, Section 3.9 'Event Processing : SEGMENT ARRIVES : CLOSED [State]'
*                               states that if the current TCP connection "state is CLOSED", then ...
*
*                               (1) "An incoming segment     containing a RST is discarded".
*                               (2) "An incoming segment NOT containing a RST causes a RST to be sent".
*
*                           (B) RFC #793, Section 3.4 'Establishing a Connection : Reset Generation : 1'
*                               reiterates that "if [a] connection does not exist (CLOSED) then a reset is
*                               sent in response to any incoming segment except another reset".
*
*                       (2) (A) RFC #793, Section 3.9 'Event Processing : SEGMENT ARRIVES : LISTEN [State] :
*                               Check for ACK' states that "any acknowledgment is bad if it arrives on a
*                               connection still in the LISTEN state.  An acceptable reset segment should
*                               be formed for any arriving ACK-bearing segment".
*
*                           (B) RFC #793, Section 3.9 'Event Processing : SEGMENT ARRIVES : LISTEN [State] :
*                               Check for SYN' also states that "if the security/compartment on the incoming
*                               segment does not exactly match the security/compartment in the TCB ... [or]
*                               if the SEG.PRC is ... not allowed [then] send a reset".
*
*                               However, these checks for invalid connection permissions are NOT necessary
*                               since TCP security & precedence NOT supported (see 'net_tcp.c  Note #1a').
*
*                       (3) RFC #793, Section 3.9 'Event Processing : SEGMENT ARRIVES : SYN-SENT [State] :
*                           Check ACK Bit' states that "if the state is SYN-SENT" & "the ACK bit is set" &
*                           the incoming segment's "SEG.ACK =< ISS, or SEG.ACK > SND.NXT, send a reset".
*$PAGE*
*                       (4) (A) RFC #793, Section 3.9 'Event Processing : SEGMENT ARRIVES : Check Sequence
*                               Number' states that for the "SYN-RECEIVED STATE, ESTABLISHED STATE, FIN-
*                               WAIT-1 STATE, FIN-WAIT-2 STATE, CLOSE-WAIT STATE, CLOSING STATE, LAST-ACK
*                               STATE, TIME-WAIT STATE", to "first check [the] sequence number ... [and if
*                               it] is not acceptable, an acknowledgment should be sent in reply ... unless
*                               the RST bit is set".
*
*                           (B) (1) (a) RFC #793, Section 3.9 'Event Processing : SEGMENT ARRIVES : Check SYN
*                                       Bit' states that for "SYN-RECEIVED [STATE], ESTABLISHED STATE, FIN-WAIT
*                                       STATE-1, FIN-WAIT STATE-2, CLOSE-WAIT STATE, CLOSING STATE, LAST-ACK
*                                       STATE, TIME-WAIT STATE ... [to next] check the SYN bit ... [and] if
*                                       the SYN is in the window it is an error, send a reset, any outstanding
*                                       RECEIVEs and SEND[s] should receive 'reset' responses, all segment
*                                       queues should be flushed, the user should also receive an unsolicited
*                                       general 'connection reset' signal[, and] enter the CLOSED state".
*
*                                   (b) But "if the SYN is not in the window this step would not have been
*                                       reached and an ack would have been sent" (see Note #3a4A).
*
*                               (2) (a) HOWEVER, RFC Draft-IETF-TCPm-TCPSecure #00, Section 3.2 amends the 
*                                       "handling of a segment with the SYN bit set in the synchronized state 
*                                        ... [by] handling ... the SYN bit" as follows :
*
*                                       (a) "If the SYN bit is set and the sequence number is outside the
*                                            expected window, send an ACK back to the peer."
*
*                                       (b) "If the SYN bit is set and the sequence number is an exact
*                                            match to the next expected sequence (RCV.NXT == SEG.SEQ)
*                                            then send an ACK segment ... but ... subtract one from
*                                            value being acknowledged."
*
*                                       (c) "If the SYN bit is set and the sequence number is acceptable,
*                                            i.e.: (RCV.NXT <= SEG.SEQ <= RCV.NXT+RCV.WND) then send an
*                                            ACK segment."
*
*                                   (b) ???? Although RFC Draft-IETF-TCPm-TCPSecure #00 explicitly states that 
*                                       this amendment applies only to the "handling of a ... SYN ... in a 
*                                       synchronized state", it is assumed that this should also apply to the 
*                                       SYN-RECEIVED state.
*
*                           (C) RFC #793, Section 3.9 'Event Processing : SEGMENT ARRIVES : Check ACK Field'
*                               states to next "check the ACK Field" :
*
*                               (1) If in the "SYN-RECEIVED STATE ... [and] if the segment acknowledgment
*                                   is not acceptable, form a reset segment".
*
*                               (2) If in the "ESTABLISHED STATE" or any state with similar "processing as
*                                   for the ESTABLISHED STATE", that "if the ACK acks something not yet sent
*                                   (SEG.ACK >  SND.NXT) then send an ACK" but "if the ACK is a duplicate
*                                   (SEG.ACK =< SND.UNA), it can be ignored".
*
*                           (D) RFC #793, Section 3.4 'Establishing a Connection : Reset Generation : 3'
*                               reiterates that for any TCP "connection ... in a synchronized state
*                               (ESTABLISHED, FIN-WAIT-1, FIN-WAIT-2, CLOSE-WAIT, CLOSING, LAST-ACK,
*                               TIME-WAIT), any unacceptable segment (out of window sequence number
*                               or unacceptible [sic] acknowledgment number) must elicit only an empty
*                               acknowledgment segment containing the current send-sequence number and
*                               an acknowledgment indicating the next sequence number expected to be
*                               received".
*
*                   (b) (1) When TCP connection fault-closes from the following synchronization/connected/
*                           closing states :
*
*                           (A) SYN-RECEIVED
*                           (B) SYN-SENT
*                           (C) ESTABLISHED
*                           (D) FIN-WAIT-1
*                           (E) FIN-WAIT-2
*                           (F) CLOSING
*                           (G) TIME_WAIT
*                           (H) CLOSE-WAIT
*                           (I) LAST-ACK
*
*                       (2) Although NO RFC directly states to transmit a TCP reset segment when a TCP 
*                           connection fault-closes, it is inferred & seems reasonable that a TCP reset
*                           segment SHOULD be transmitted whenever a TCP connection closes abnormally.
*$PAGE*
*               (4) The following sections reiterate the generalization that "a reset is sent in response
*                   to any [unacceptable segment] ... EXCEPT* another reset"; also "send a reset (UNLESS*
*                   the RST bit is set, if so drop the segment)" :                      [*emphasis added]
*
*                   (a) RFC #793, Section 3.9 'Event Processing : SEGMENT ARRIVES : LISTEN   [State] :
*                           Check for RST'
*                   (b) RFC #793, Section 3.9 'Event Processing : SEGMENT ARRIVES : SYN-SENT [State] :
*                           Check ACK Bit'
*                   (c) RFC #793, Section 3.9 'Event Processing : SEGMENT ARRIVES : Check ACK Field :
*                           SYN-RECEIVED STATE' (see Note #4A)
*
*                       (A) This confirms that the received segment does NOT contain a TCP reset control
*                           since it follows RFC #793, Section 3.9 'Event Processing : SEGMENT ARRIVES :
*                           Check RST Bit'.
*
*               (5) (a) (1) The following sections ... :
*
*                           (A) RFC #793, Section 3.9 'Event Processing : SEGMENT ARRIVES : CLOSED   [State]'
*                           (B) RFC #793, Section 3.9 'Event Processing : SEGMENT ARRIVES : LISTEN   [State]'
*                               (1) Amended by RFC #1122, Section 4.2.2.20.(b)
*                           (C) RFC #793, Section 3.9 'Event Processing : SEGMENT ARRIVES : SYN-SENT [State]'
*                           (D) RFC #793, Section 3.9 'Event Processing : SEGMENT ARRIVES : Check ACK Field :
*                                   SYN-RECEIVED STATE'
*
*                       (2) ... generalize that "the acknowledgment and sequence field values [for the reset
*                           segment to transmit] are selected to make the reset sequence acceptable to the
*                           TCP that sent the offending segment" (see Note #3a) :
*
*                           (A) "If the ACK bit is off, sequence number zero is used,
*
*                                  <SEQ=0> <ACK=SEG.SEQ + SEG.LEN> <CTL=RST, ACK>"
*
*                           (B) "If the ACK bit is on,
*
*                                  <SEQ=SEG.ACK> <CTL=RST>"
*
*                   (b) However, NO RFC specifies the sequence & acknowledgement numbers to use when
*                       trasmitting a reset segment for a TCP connection that closes due to any fault
*                       condition(s) [see Note #3b].
*
*                       (1) #### Therefore, TCP transmit reset segments for fault-closing TCP connections 
*                           should be prepared as follows :
*
*                           (A) With the following TCP sequence numbers :
*
*                               (1) TCP_SeqNbr  =  TxSeqNbrUnAckd
*
*                               (2) TCP_AckNbr  =  RxSeqNbrNext
*
*                                       where
*
*                                           TCP_SeqNbr          TCP transmit reset segment sequence        number
*                                           TCP_AckNbr          TCP transmit reset segment acknowledgement number
*                                           TxSeqNbrUnAckd      TCP connection's currently unacknowledged transmit
*                                                                   sequence number
*                                           RxSeqNbrNext        TCP connection's currently expected next  receive
*                                                                   sequence number
*
*                           (B) With the following TCP segment header flags set :
*
*                               (1) RESET
*
*                       (2) This TCP transmit reset segment format complies with TCP connection received 
*                           reset segment handling as specified in RFC #793, Section 3.9 'Event Processing :
*                           SEGMENT ARRIVES'.
*
*                           See also 'NetTCP_RxPktConnIsValidReset()  Notes #2a2, 2a3, 2a4A1, & 2a4B1'.
*$PAGE*
*               (6) (a) RFC #793, Sections 3.7 & 2.6 state that "TCP uses retransmission ... to ensure 
*                       delivery of every segment".
*
*                       However, NO RFC specifies whether TCP connection reset segments should be queued
*                       for retransmission.  Therefore, it is assumed that ALL TCP connection reset
*                       segments SHOULD NOT be queued for retransmission but SHOULD be silently discarded.
*
*                   (b) (1) The network buffer's reference counter is NOT incremented since the TCP layer
*                           does NOT maintain a reference to any transmitted TCP connection reset segments.
*
*                       (2) Therefore, the network buffer MUST be freed by lower layer(s).
*
*                   See also 'NetTCP_TxConnAck()    Note #8',
*                          & 'NetTCP_TxConnProbe()  Note #3'.
*
*               (7) On ANY errors :
*
*                   (a) Network resources MUST be appropriately freed :
*
*                       (1) For any network resources NOT linked to the TCP connection, each network resource
*                           MUST be freed by appropriate function(s).
*
*                   (b) TCP connection MUST NOT be re-closed.
*
*                       See also 'NetTCP_ConnClose()  Note #5'.
*********************************************************************************************************
*/
/*$PAGE*/
static  void  NetTCP_TxConnReset (NET_TCP_CONN        *pconn,
                                  NET_BUF_HDR         *pbuf_hdr,
                                  NET_TCP_RESET_CODE   tx_reset_code,
                                  NET_TCP_CLOSE_CODE   close_code,
                                  NET_ERR             *perr)
{
#if (((NET_CTR_CFG_ERR_EN      == DEF_ENABLED)                    || \
      (NET_CTR_CFG_STAT_EN     == DEF_ENABLED))                   && \
      (CPU_CFG_CRITICAL_METHOD == CPU_CRITICAL_METHOD_STATUS_LOCAL))
    CPU_SR             cpu_sr;
#endif
#if (NET_ERR_CFG_ARG_CHK_DBG_EN == DEF_ENABLED)
    NET_TCP_ACK_CODE   ack_code;
    NET_TCP_SEQ_CODE   seq_code;
#endif
    CPU_BOOLEAN        tx_reset;
    NET_BUF_SIZE       data_len;
    NET_BUF_SIZE       data_ix;
    NET_BUF           *pseg_reset;
    NET_BUF_HDR       *pseg_reset_hdr;
    NET_IP_ADDR        src_addr;
    NET_IP_ADDR        dest_addr;
    NET_TCP_PORT_NBR   src_port;
    NET_TCP_PORT_NBR   dest_port;
    NET_TCP_SEQ_NBR    seq_nbr;
    NET_TCP_SEQ_NBR    ack_nbr;
    NET_TCP_WIN_SIZE   win_size;
    CPU_INT16U         flags_tcp;
    NET_ERR            err;


                                                                    /* ------------ VALIDATE RX'D TCP PKT ------------- */
    if (pbuf_hdr != (NET_BUF_HDR *)0) {
        if (pbuf_hdr->TCP_SegReset != DEF_NO) {                     /* If TCP reset pkt rx'd, ...                       */
           *perr = NET_TCP_ERR_CONN_RESET_INVALID;                  /* ... do NOT tx TCP conn reset (see Note #4).      */
            return;
        }
    }


                                                                    /* ----------- VALIDATE TCP CONN STATE ------------ */
    tx_reset = DEF_NO;

    if (pconn != (NET_TCP_CONN *)0) {
        switch (pconn->ConnState) {
            case NET_TCP_CONN_STATE_FREE:
                 NET_CTR_ERR_INC(NetTCP_ErrNotUsedCtr);
                *perr = NET_TCP_ERR_CONN_NOT_USED;
                 return;                                            /* Prevent 'break NOT reachable' compiler warning.  */


            case NET_TCP_CONN_STATE_CLOSED:                         /* See Note #3a1.                                   */
                 tx_reset = DEF_YES;
                 break;


            case NET_TCP_CONN_STATE_LISTEN:                         /* See Note #3a2.                                   */
#if (NET_ERR_CFG_ARG_CHK_DBG_EN == DEF_ENABLED)                     /* See Note #3aA.                                   */
                 if (pbuf_hdr != (NET_BUF_HDR *)0) {                /* If seg rx'd                 ...                  */
                     ack_code = NetTCP_RxPktConnIsValidAck(pconn, pbuf_hdr, perr);
                     if (*perr != NET_TCP_ERR_NONE) {
                          return;
                     }
                     if (ack_code != NET_TCP_CONN_RX_ACK_NONE) {    /* ... with ANY (invalid) ack, ...                  */
                         tx_reset  = DEF_YES;                       /* ... tx TCP conn reset (see Note #3a2A).          */
                     }
                 }

#else
                 tx_reset = DEF_YES;
#endif
                 break;

/*$PAGE*/
            case NET_TCP_CONN_STATE_SYNC_TXD:                       /* See Note #3a3.                                   */
#if (NET_ERR_CFG_ARG_CHK_DBG_EN == DEF_ENABLED)                     /* See Note #3aA.                                   */
                 switch (tx_reset_code) {
                     case NET_TCP_CONN_TX_RESET:
                     default:
                          if (pbuf_hdr != (NET_BUF_HDR *)0) {       /* If seg rx'd            ...                       */
                              ack_code = NetTCP_RxPktConnIsValidAck(pconn, pbuf_hdr, perr);
                              if (*perr != NET_TCP_ERR_NONE) {
                                   return;
                              }
                                                                    /* ...  with invalid ack, ...                       */
                              if (ack_code == NET_TCP_CONN_RX_ACK_INVALID) { 
                                  tx_reset  = DEF_YES;              /* ...  tx TCP conn reset (see Note #3a3).          */
                              }

                          } else {                                  /* Else no seg rx'd, ...                            */
                              tx_reset = DEF_YES;                   /* ...  tx TCP conn reset (see Note #3b1B).         */
                          }
                          break;


                     case NET_TCP_CONN_TX_RESET_FAULT:
                          tx_reset = DEF_YES;
                          break;
                 }

#else
                (void)&tx_reset_code;                               /* Prevent compiler warning.                        */
                 tx_reset = DEF_YES;
#endif
                 break;


            case NET_TCP_CONN_STATE_SYNC_RXD:                       /* See Note #3a4.                                   */
            case NET_TCP_CONN_STATE_SYNC_RXD_PASSIVE:
            case NET_TCP_CONN_STATE_SYNC_RXD_ACTIVE:
#if (NET_ERR_CFG_ARG_CHK_DBG_EN == DEF_ENABLED)                     /* See Note #3aA.                                   */
                 switch (tx_reset_code) {
                     case NET_TCP_CONN_TX_RESET:
                     default:
                          if (pbuf_hdr != (NET_BUF_HDR *)0) {       /* If seg rx'd                                  ... */
                              seq_code = NetTCP_RxPktConnIsValidSeq(pconn, pbuf_hdr, perr);
                              if (*perr != NET_TCP_ERR_NONE) {
                                   return;
                              }
                                                                    /* ... with   invalid seq/sync,                 ... */
                              if (seq_code != NET_TCP_CONN_RX_SEQ_VALID) {
                                                                    /* ... tx TCP conn ack (see Notes #3a4A & #3a4B2);  */
                                  NetTCP_TxConnAck(pconn, pbuf_hdr, NET_TCP_CONN_TX_ACK_FAULT, NET_TCP_CONN_CLOSE_ALL, &err);
                                 *perr = NET_TCP_ERR_CONN_RESET_INVALID;
                                  return;
                              }

                              ack_code = NetTCP_RxPktConnIsValidAck(pconn, pbuf_hdr, perr);
                              if (*perr != NET_TCP_ERR_NONE) {
                                   return;
                              }
                                                                    /* ...  without valid ack,                      ... */
                              if (ack_code != NET_TCP_CONN_RX_ACK_VALID) {
                                  tx_reset  = DEF_YES;              /* ...  tx TCP conn reset (see Note #3a4C1).        */
                              }

                          } else {                                  /* Else no seg rx'd, ...                            */
                              tx_reset = DEF_YES;                   /* ...  tx TCP conn reset (see Note #3b1A).         */
                          }
                          break;


                     case NET_TCP_CONN_TX_RESET_FAULT:
                          tx_reset = DEF_YES;
                          break;
                 }

#else
                (void)&tx_reset_code;                               /* Prevent compiler warning.                        */
                 tx_reset = DEF_YES;
#endif
                 break;

/*$PAGE*/
            case NET_TCP_CONN_STATE_CONN:                           /* See Note #3a4.                                   */
            case NET_TCP_CONN_STATE_FIN_WAIT_1:
            case NET_TCP_CONN_STATE_FIN_WAIT_2:
            case NET_TCP_CONN_STATE_CLOSING:
            case NET_TCP_CONN_STATE_TIME_WAIT:
            case NET_TCP_CONN_STATE_CLOSE_WAIT:
            case NET_TCP_CONN_STATE_LAST_ACK:
#if (NET_ERR_CFG_ARG_CHK_DBG_EN == DEF_ENABLED)                     /* See Note #3aA.                                   */
                 switch (tx_reset_code) {
                     case NET_TCP_CONN_TX_RESET:
                     default:
                          if (pbuf_hdr != (NET_BUF_HDR *)0) {       /* If seg rx'd                ...                   */
                              seq_code = NetTCP_RxPktConnIsValidSeq(pconn, pbuf_hdr, perr);
                              if (*perr != NET_TCP_ERR_NONE) {
                                   return;
                              }
                                                                    /* ... with invalid seq/sync, ...                   */
                              if (seq_code != NET_TCP_CONN_RX_SEQ_VALID) {   
                                                                    /* ... tx TCP conn ack (see Notes #3a4A & #3a4B2).  */
                                  NetTCP_TxConnAck(pconn, pbuf_hdr, NET_TCP_CONN_TX_ACK_FAULT, NET_TCP_CONN_CLOSE_ALL, &err);
                                 *perr = NET_TCP_ERR_CONN_RESET_INVALID;
                                  return;
                              }

                          } else {                                  /* Else no seg rx'd, ...                            */
                              tx_reset = DEF_YES;                   /* ...  tx TCP conn reset (see Notes #3b1C - #3b1I).*/
                          }
                          break;


                     case NET_TCP_CONN_TX_RESET_FAULT:
                          tx_reset = DEF_YES;
                          break;
                 }

#else
                (void)&tx_reset_code;                               /* Prevent compiler warning.                        */
                 tx_reset = DEF_YES;
#endif
                 break;


            case NET_TCP_CONN_STATE_CLOSING_DATA_AVAIL:
                 tx_reset = DEF_YES;
                 break;


            case NET_TCP_CONN_STATE_NONE:
            default:
                 if (close_code != NET_TCP_CONN_CLOSE_NONE) {       /* If tx reset NOT req'd by TCP conn close fnct(s), */
                                                                    /* ... close TCP conn (see Note #7b).               */
                     DEF_BIT_CLR(close_code, NET_TCP_CONN_CLOSE_CONN_TX_RESET);
                     NetTCP_ConnClose((NET_TCP_CONN     *)pconn,
                                      (NET_BUF_HDR      *)0,
                                      (CPU_BOOLEAN       )DEF_YES,
                                      (NET_TCP_CLOSE_CODE)close_code);
                 }
                 NET_CTR_ERR_INC(NetTCP_ErrConnInvalidStateCtr);
                *perr = NET_TCP_ERR_INVALID_CONN_STATE;
                 return;                                            /* Prevent 'break NOT reachable' compiler warning.  */
        }

    } else {                                                        /* If NO demux'd TCP conn avail, handle as CLOSED.  */
        if (pbuf_hdr != (NET_BUF_HDR *)0) {                         /* If rx'd pkt avail, ...                           */
            tx_reset  =  DEF_YES;                                   /* ... tx reset.                                    */
        }
    }


    if (tx_reset != DEF_YES) {                                      /* If NOT valid, abort tx TCP conn reset.           */
       *perr = NET_TCP_ERR_CONN_RESET_INVALID;
        return;
    }


/*$PAGE*/
                                                                    /* ---------- PREPARE TCP CONN RESET SEG ---------- */
                                                                    /* If valid, prepare & tx TCP conn reset.           */
                                                                    /* Get buf.                                         */
    data_len   = NET_TCP_DATA_LEN_TX_RESET;
    data_ix    = NET_BUF_DATA_TX_IX;
    pseg_reset = NetBuf_Get((NET_BUF_SIZE) data_len,
                            (NET_BUF_SIZE) data_ix,
                            (CPU_INT16U  ) NET_BUF_FLAG_NONE,
                            (NET_ERR    *)&err);
    if ( err != NET_BUF_ERR_NONE) {
       *perr  = NET_TCP_ERR_NONE_AVAIL;
        return;
    }

                                                                    /* --------------- PREPARE TCP HDR ---------------- */
                                                                    /* Prepare seg addrs.                               */
    if (pbuf_hdr != (NET_BUF_HDR *)0) {                             /* If TCP pkt rx'd, cfg TCP tx                ...   */
                                                                    /* ...  src  addr from rx'd TCP pkt dest addr ...   */
        src_port  = (NET_TCP_PORT_NBR)pbuf_hdr->TCP_UDP_PortDest;
        src_addr  = (NET_IP_ADDR     )pbuf_hdr->IP_AddrDest;
                                                                    /* .. & dest addr from rx'd TCP pkt src  addr.      */
        dest_port = (NET_TCP_PORT_NBR)pbuf_hdr->TCP_UDP_PortSrc;
        dest_addr = (NET_IP_ADDR     )pbuf_hdr->IP_AddrSrc;

    } else {                                                        /* Else cfg TCP tx pkt addrs from TCP conn addrs.   */
        NetTCP_TxConnPrepareSegAddrs((NET_TCP_CONN *) pconn,
                                     (CPU_INT08U   *)&src_port,
                                     (CPU_INT08U   *)&src_addr,
                                     (CPU_INT16U    ) sizeof(src_port),
                                     (CPU_INT16U    ) sizeof(src_addr),
                                     (CPU_INT08U   *)&dest_port,
                                     (CPU_INT08U   *)&dest_addr,
                                     (CPU_INT16U    ) sizeof(dest_port),
                                     (CPU_INT16U    ) sizeof(dest_addr),
                                     (NET_ERR      *)&err);
        if ( err != NET_TCP_ERR_NONE) {                             /* See Note #7a.                                    */
           *perr  = NET_TCP_ERR_CONN_FAULT;
            NetBuf_Free(pseg_reset);
            return;
        }
    }


                                                                    /* Prepare TCP tx flags (see Note #1c2C).           */
    flags_tcp = NET_TCP_FLAG_NONE    |
                NET_TCP_FLAG_TX_RESET;

                                                                    /* Prepare TCP seq nbrs (see Note #5).              */
    if (pbuf_hdr != (NET_BUF_HDR *)0) {
        if (pbuf_hdr->TCP_SegAck != DEF_NO) {                       /* If TCP ack rx'd,        ... (see Note #5a2B)     */
            seq_nbr = pbuf_hdr->TCP_AckNbr;                         /* .. tx  seq = ack        ...                      */
            ack_nbr = NET_TCP_ACK_NBR_NONE;                         /* .. &   ack = none.                               */

        } else {                                                    /* Otherwise,              ... (see Note #5a2A)     */
            seq_nbr = NET_TCP_SEQ_NBR_NONE;                         /* .. tx  seq = 0 (none)   ...                      */
            ack_nbr = pbuf_hdr->TCP_SeqNbr                          /* .. &   ack = seg seq    ...                      */
                    + pbuf_hdr->TCP_SegLen;                         /* ..         + seg len.                            */
            DEF_BIT_SET(flags_tcp, NET_TCP_FLAG_TX_ACK);
        }

    } else {                                                        /* Else no seg rx'd,       ... (see Note #5b1A)     */
        seq_nbr = pconn->TxSeqNbrUnAckd;                            /* .. tx  seq = tx unack'd ...                      */
        ack_nbr = pconn->RxSeqNbrNext;                              /* .. &   ack = rx next.                            */
    }

                                                                    /* Prepare TCP win size.                            */
    win_size = NET_TCP_WIN_SIZE_NONE;


                                                                    /* Init buf ctrls.                                  */
    pseg_reset_hdr                  = &pseg_reset->Hdr;
    pseg_reset_hdr->DataIx          = (CPU_INT16U  )data_ix;
    pseg_reset_hdr->DataLen         = (NET_BUF_SIZE)data_len;
    pseg_reset_hdr->TotLen          = (NET_BUF_SIZE)pseg_reset_hdr->DataLen;
    pseg_reset_hdr->ProtocolHdrType =  NET_PROTOCOL_TYPE_TCP;

    pseg_reset_hdr->TCP_SegSync     = (CPU_BOOLEAN )DEF_NO;
    pseg_reset_hdr->TCP_SegClose    = (CPU_BOOLEAN )DEF_NO;
    pseg_reset_hdr->TCP_SegAck      = (CPU_BOOLEAN )DEF_BIT_IS_SET(flags_tcp, NET_TCP_FLAG_TX_ACK);
    pseg_reset_hdr->TCP_SegReset    = (CPU_BOOLEAN )DEF_YES;

    pseg_reset_hdr->TCP_Flags       =  flags_tcp;



/*$PAGE*/
                                                                    /* ------------ TX TCP CONN RESET SEG ------------- */
    NetTCP_TxPktHandler((NET_BUF        *) pseg_reset,
                        (NET_IP_ADDR     ) src_addr,
                        (NET_TCP_PORT_NBR) src_port,
                        (NET_IP_ADDR     ) dest_addr,
                        (NET_TCP_PORT_NBR) dest_port,
                        (NET_TCP_SEQ_NBR ) seq_nbr,
                        (NET_TCP_SEQ_NBR ) ack_nbr,
                        (NET_TCP_WIN_SIZE) win_size,
                        (NET_IP_TOS      ) NET_IP_TOS_DFLT,
                        (NET_IP_TTL      ) NET_IP_TTL_DFLT,
                        (CPU_INT16U      ) flags_tcp,
                        (CPU_INT16U      ) NET_IP_FLAG_NONE,
                        (void           *) 0,
                        (void           *) 0,
                        (NET_ERR        *)&err);                    /* Ignore transitory tx err(s).                     */

#if 0                                                               /* Tx buf freed by lower layer(s) [see Note #6b2].  */
    NetTCP_TxPktFree(pseg_reset);
#endif
    NET_CTR_STAT_INC(NetTCP_StatTxSegConnResetCtr);



   *perr = NET_TCP_ERR_NONE;
}


/*$PAGE*/
/*
*********************************************************************************************************
*                                        NetTCP_TxConnProbe()
*
* Description : (1) Prepare & transmit a TCP connection probe :
*
*                   (a) Validate TCP connection state for TCP probe
*                   (b) Prepare  TCP probe segment :                                See Note #2
*                       (1) Get  buffer
*                       (2) Prepare TCP segment :
*                           (A) TCP segment  addresses
*                           (B) TCP segment  sequence numbers                       See Note #2b1
*                           (C) TCP segment  transmit flags :
*                               (1) ACK
*                           (D) TCP segment  window size
*                           (E) IP  datagram parameters
*                           (F) TCP segment  packet buffer controls
*                   (c) Transmit TCP connection probe
*
*
* Argument(s) : pconn                   Pointer to a TCP connection.
*
*               tx_probe_data_octet     Indicate whether to transmit a single data probe octet (see Note #2b2) :
*
*                                           DEF_YES                Transmit data probe octet.
*                                           DEF_NO          Do NOT transmit data probe octet.
*
*               close_code      Select which close action(s) to perform; bit-field flags logically OR'd :
*
*                                   NET_TCP_CONN_CLOSE_NONE                 Perform NO  close actions.
*                                   NET_TCP_CONN_CLOSE_ALL                  Perform ALL close actions.
*
*                                   NET_TCP_CONN_CLOSE_CONN_TX_RESET        Perform close connection transmit reset.
*                                   NET_TCP_CONN_CLOSE_CONN_ALL             Perform ALL   connection close    actions.
*
*                                   NET_TCP_CONN_CLOSE_TMR_TX_IDLE          Close    transmit idle                  timer.
*                                   NET_TCP_CONN_CLOSE_TMR_TX_SILLY_WIN     Close    transmit silly window persist  timer.
*                                   NET_TCP_CONN_CLOSE_TMR_TX_ZERO_WIN      Close    transmit zero  window persist  timer.
*                                   NET_TCP_CONN_CLOSE_TMR_TX_ACK_DLY       Close    transmit acknowledgement delay timer.
*                                   NET_TCP_CONN_CLOSE_TMR_RE_TX            Close re-transmit                       timer.
*                                   NET_TCP_CONN_CLOSE_TMR_KEEP_ALIVE       Close connection keep-alive             timer.
*                                   NET_TCP_CONN_CLOSE_TMR_TIMEOUT          Close connection                        timer.
*                                   NET_TCP_CONN_CLOSE_TMR_ALL              Close ALL                               timers.
*
*                               See also 'TCP CONNECTION CLOSE/FREE CODE DEFINES'.
*
*               perr        Pointer to variable that will receive the return error code from this function :
*
*                               NET_TCP_ERR_NONE                    TCP connection probe successfully transmitted.
*                               NET_TCP_ERR_CONN_PROBE_INVALID      TCP connection probe NOT valid for current
*                                                                       TCP connection state.
*                               NET_TCP_ERR_CONN_NOT_USED           TCP connection NOT currently used.
*                               NET_TCP_ERR_CONN_FAULT              TCP connection fault; connection(s) aborted.
*                               NET_TCP_ERR_CONN_FAIL               TCP connection operation(s) failed.
*                               NET_TCP_ERR_INVALID_CONN_STATE      Invalid TCP connection state.
*                               NET_TCP_ERR_INVALID_CONN_OP         Invalid TCP connection operation.
*                               NET_TCP_ERR_NONE_AVAIL              Resources NOT available.
*
* Return(s)   : none.
*
* Caller(s)   : NetTCP_TxConnWinSizeZeroWinHandler(),
*               NetTCP_TxConnKeepAlive().
*$PAGE*
* Note(s)     : (2) TCP connection probes are transmitted for certain TCP conditions :
*
*                       (A) Some TCP transmit probe validation logic implemented in previous functions;
*                           include duplicate validation logic in NetTCP_TxConnProbe() only if debug/
*                           validation code is enabled (i.e. NET_ERR_CFG_ARG_CHK_DBG_EN is DEF_ENABLED
*                           in 'net_cfg.h').
*
*                   (a) RFC #1122, Section 4.2.3.6 specifies a "mechanism [that] periodically probes the
*                       other end of a connection" for the following TCP connection conditions :
*
*                       (1) Probing Zero Windows                                RFC #1122, Section 4.2.2.17
*                               (see 'NetTCP_TxConnWinSizeZeroWinHandler()  Note #1b')
*
*                       (2) TCP Keep-Alives                                     RFC #1122, Section 4.2.3.6
*                               (see 'NetTCP_TxConnKeepAlive()  Note #2c')
*
*                   (b) "Send a probe segment ... to elicit a response from the peer TCP" :
*
*                       (1) "Such a segment generally contains SEG.SEQ = SND.NXT-1" ...
*
*                           (A) "Note that on a quiet [or deadlocked] connection SND.NXT = RCV.NXT, so that
*                                this SEG.SEQ will be outside the window.  Therefore, the probe causes the
*                                receiver to return an acknowledgment segment."
*
*                           (B) "It is extremely important to remember that ACK segments that contain no data
*                                are not reliably transmitted by TCP."
*
*                       (2) "and may or may not contain one garbage octet of data."
*
*                           (A) "An implementation SHOULD send a [probe] segment with no data."
*
*                           (B) (1) "Unfortunately, some misbehaved TCP implementations fail to respond to
*                                    a segment with SEG.SEQ = SND.NXT-1 unless the segment contains data."
*
*                               (2) Stevens, TCP/IP Illustrated, Volume 1, 8th Printing, Section 23.3, 
*                                   Page 335 reiterates that "some older implementations based on 4.2BSD 
*                                   do not respond to these ... probes unless the segment contains data".
*
*                           (C) Therefore, RFC #1122, Section 4.2.3.6 states that a TCP "implementation ...
*                               MAY be configurable to send a [probe] segment containing one garbage octet,
*                               for compatibility with erroneous TCP implementations".
*
*               (3) (a) (1) RFC #793, Sections 3.7 & 2.6 state that "TCP uses retransmission ... to ensure 
*                           delivery of every segment".
*
*                       (2) However, RFC #1122, Section 4.2.2.17 'DISCUSSION' states that "it is extremely
*                           important to remember that ACK (acknowledgment) segments that contain no data
*                           are not reliably transmitted by TCP".
*
*                           Therefore, it is assumed that TCP acknowledgement/probe segments should NOT be 
*                           queued for retransmission but SHOULD be silently discarded.
*
*                   (b) (1) The network buffer's reference counter is NOT incremented since the TCP layer
*                           does NOT maintain a reference to any transmitted TCP probe segments.
*
*                       (2) Therefore, the network buffer MUST be freed by lower layer(s).
*
*                   See also 'NetTCP_TxConnAck()    Note #8',
*                          & 'NetTCP_TxConnReset()  Note #6'.
*
*               (4) On ANY errors, network resources MUST be appropriately freed :
*
*                   (a) For any network resources NOT linked to the TCP connection, each network resource
*                       MUST be freed by appropriate function(s).
*
*               (5) #### IP options currently NOT implemented.
*********************************************************************************************************
*/
/*$PAGE*/
static  void  NetTCP_TxConnProbe (NET_TCP_CONN        *pconn,
                                  CPU_BOOLEAN          tx_probe_data_octet,
                                  NET_TCP_CLOSE_CODE   close_code,
                                  NET_ERR             *perr)
{
#if ((((NET_ERR_CFG_ARG_CHK_DBG_EN == DEF_ENABLED)                    && \
       (NET_CTR_CFG_ERR_EN         == DEF_ENABLED))                   || \
       (NET_CTR_CFG_STAT_EN        == DEF_ENABLED))                   && \
       (CPU_CFG_CRITICAL_METHOD    == CPU_CRITICAL_METHOD_STATUS_LOCAL))
    CPU_SR             cpu_sr;
#endif
#if (NET_ERR_CFG_ARG_CHK_DBG_EN == DEF_ENABLED)
    CPU_BOOLEAN        tx_probe;
#endif
    NET_BUF_SIZE       data_len;
    NET_BUF_SIZE       data_ix;
    NET_BUF           *pseg_probe;
    NET_BUF_HDR       *pseg_probe_hdr;
    NET_IP_TOS         TOS;
    NET_IP_TTL         TTL;
    NET_IP_ADDR        src_addr;
    NET_IP_ADDR        dest_addr;
    NET_TCP_PORT_NBR   src_port;
    NET_TCP_PORT_NBR   dest_port;
    NET_TCP_SEQ_NBR    seq_nbr;
    NET_TCP_SEQ_NBR    ack_nbr;
    NET_TCP_WIN_SIZE   win_size;
    CPU_INT16U         flags_tcp;
    CPU_INT16U         flags_ip;
    CPU_INT08U         probe_data[NET_TCP_DATA_LEN_TX_PROBE_DATA];
    NET_ERR            err;


#if (NET_ERR_CFG_ARG_CHK_DBG_EN == DEF_ENABLED)                     /* See Note #2A.                                    */
                                                                    /* ----------- VALIDATE TCP CONN STATE ------------ */
    tx_probe = DEF_NO;

    if (pconn != (NET_TCP_CONN *)0) {
        switch (pconn->ConnState) {
            case NET_TCP_CONN_STATE_FREE:
                 NET_CTR_ERR_INC(NetTCP_ErrNotUsedCtr);
                *perr = NET_TCP_ERR_CONN_NOT_USED;
                 return;                                            /* Prevent 'break NOT reachable' compiler warning.  */


            case NET_TCP_CONN_STATE_CLOSED:
            case NET_TCP_CONN_STATE_LISTEN:
            case NET_TCP_CONN_STATE_SYNC_RXD:
            case NET_TCP_CONN_STATE_SYNC_RXD_PASSIVE:
            case NET_TCP_CONN_STATE_SYNC_RXD_ACTIVE:
            case NET_TCP_CONN_STATE_SYNC_TXD:
            case NET_TCP_CONN_STATE_TIME_WAIT:
            case NET_TCP_CONN_STATE_LAST_ACK:
            case NET_TCP_CONN_STATE_CLOSING_DATA_AVAIL:
                 NET_CTR_ERR_INC(NetTCP_ErrConnInvalidOpCtr);
                *perr = NET_TCP_ERR_INVALID_CONN_OP;
                 return;                                            /* Prevent 'break NOT reachable' compiler warning.  */


            case NET_TCP_CONN_STATE_CONN:
            case NET_TCP_CONN_STATE_FIN_WAIT_1:
            case NET_TCP_CONN_STATE_FIN_WAIT_2:
            case NET_TCP_CONN_STATE_CLOSING:
            case NET_TCP_CONN_STATE_CLOSE_WAIT:
                 tx_probe = DEF_YES;
                 break;


            case NET_TCP_CONN_STATE_NONE:
            default:
                 NetTCP_ConnClose((NET_TCP_CONN     *)pconn,
                                  (NET_BUF_HDR      *)0,
                                  (CPU_BOOLEAN       )DEF_YES,
                                  (NET_TCP_CLOSE_CODE)close_code);
                 NET_CTR_ERR_INC(NetTCP_ErrConnInvalidStateCtr);
                *perr = NET_TCP_ERR_INVALID_CONN_STATE;
                 return;                                            /* Prevent 'break NOT reachable' compiler warning.  */
        }
    }


    if (tx_probe != DEF_YES) {                                      /* If NOT valid, abort tx TCP conn probe.           */
       *perr = NET_TCP_ERR_CONN_PROBE_INVALID;
        return;
    }

#else                                                               /* Prevent compiler warning.                        */
   (void)&close_code;
#endif


/*$PAGE*/
                                                                    /* ---------- PREPARE TCP CONN PROBE SEG ---------- */
                                                                    /* If valid, prepare & tx TCP conn probe.           */
                                                                    /* Get buf.                                         */
    data_len   = (tx_probe_data_octet == DEF_YES)                   /* Cfg data len for probe data (see Note #2b2C).    */
               ?  NET_TCP_DATA_LEN_TX_PROBE_DATA
               :  NET_TCP_DATA_LEN_TX_PROBE_NO_DATA;
    data_ix    =  NET_BUF_DATA_TX_IX;
    pseg_probe =  NetBuf_Get((NET_BUF_SIZE) data_len,
                             (NET_BUF_SIZE) data_ix,
                             (CPU_INT16U  ) NET_BUF_FLAG_NONE,
                             (NET_ERR    *)&err);
    if ( err != NET_BUF_ERR_NONE) {
       *perr  = NET_TCP_ERR_NONE_AVAIL;
        return;
    }

    if (tx_probe_data_octet == DEF_YES) {                           /* If tx probe data req'd,          ...             */
        probe_data[0] = NET_TCP_TX_PROBE_DATA;                      /* ... prepare data (see Note #2b2) ...             */
        NetBuf_DataWr((NET_BUF    *) pseg_probe,                    /* ... & wr    data into TCP tx buf.                */
                      (NET_BUF_SIZE) data_ix,
                      (NET_BUF_SIZE) data_len,
                      (CPU_INT08U *)&probe_data[0],
                      (NET_ERR    *)&err);
        if ( err != NET_BUF_ERR_NONE) {                             /* See Note #4a.                                    */
            NetBuf_Free(pseg_probe);
           *perr  = NET_TCP_ERR_CONN_FAIL;
            return;
        }
    }

                                                                    /* --------------- PREPARE TCP HDR ---------------- */
                                                                    /* Prepare seg addrs.                               */
    NetTCP_TxConnPrepareSegAddrs((NET_TCP_CONN *) pconn,
                                 (CPU_INT08U   *)&src_port,
                                 (CPU_INT08U   *)&src_addr,
                                 (CPU_INT16U    ) sizeof(src_port),
                                 (CPU_INT16U    ) sizeof(src_addr),
                                 (CPU_INT08U   *)&dest_port,
                                 (CPU_INT08U   *)&dest_addr,
                                 (CPU_INT16U    ) sizeof(dest_port),
                                 (CPU_INT16U    ) sizeof(dest_addr),
                                 (NET_ERR      *)&err);
    if ( err != NET_TCP_ERR_NONE) {                                 /* See Note #4a.                                    */
       *perr  = NET_TCP_ERR_CONN_FAULT;
        NetBuf_Free(pseg_probe);
        return;
    }


                                                                    /* Prepare TCP seq nbrs (see Note #1b2B).           */
    seq_nbr   = pconn->TxSeqNbrNext - 1;                            /* Sub 1 from probe seq (see Note #2b1).            */
    ack_nbr   = pconn->RxSeqNbrNext;

                                                                    /* Prepare TCP tx flags (see Note #1b2C).           */
    flags_tcp = NET_TCP_FLAG_NONE  |
                NET_TCP_FLAG_TX_ACK;

                                                                    /* Prepare TCP win size.                            */
    win_size  = pconn->RxWinSizeActual;

                                                                    /* Prepare IP params.                               */
    TOS       = pconn->TxIP_TOS;
    TTL       = pconn->TxIP_TTL;
    flags_ip  = pconn->TxIP_Flags;


                                                                    /* Init buf ctrls.                                  */
    pseg_probe_hdr                  = &pseg_probe->Hdr;
    pseg_probe_hdr->DataIx          = (CPU_INT16U  )data_ix;
    pseg_probe_hdr->DataLen         = (NET_BUF_SIZE)data_len;
    pseg_probe_hdr->TotLen          = (NET_BUF_SIZE)pseg_probe_hdr->DataLen;
    pseg_probe_hdr->ProtocolHdrType =  NET_PROTOCOL_TYPE_TCP;

    pseg_probe_hdr->TCP_SegSync     = (CPU_BOOLEAN )DEF_NO;
    pseg_probe_hdr->TCP_SegClose    = (CPU_BOOLEAN )DEF_NO;
    pseg_probe_hdr->TCP_SegAck      = (CPU_BOOLEAN )DEF_YES;
    pseg_probe_hdr->TCP_SegReset    = (CPU_BOOLEAN )DEF_NO;

    pseg_probe_hdr->TCP_Flags       =  flags_tcp;



/*$PAGE*/
                                                                    /* ------------ TX TCP CONN PROBE SEG ------------- */
    NetTCP_TxPktHandler((NET_BUF        *) pseg_probe,
                        (NET_IP_ADDR     ) src_addr,
                        (NET_TCP_PORT_NBR) src_port,
                        (NET_IP_ADDR     ) dest_addr,
                        (NET_TCP_PORT_NBR) dest_port,
                        (NET_TCP_SEQ_NBR ) seq_nbr,
                        (NET_TCP_SEQ_NBR ) ack_nbr,
                        (NET_TCP_WIN_SIZE) win_size,
                        (NET_IP_TOS      ) TOS,
                        (NET_IP_TTL      ) TTL,
                        (CPU_INT16U      ) flags_tcp,
                        (CPU_INT16U      ) flags_ip,
                        (void           *) 0,
                        (void           *) 0,                       /* See Note #5.                                     */
                        (NET_ERR        *)&err);                    /* Ignore transitory tx err(s).                     */

#if 0                                                               /* Tx buf freed by lower layer(s) [see Note #3b2].  */
    NetTCP_TxPktFree(pseg_probe);
#endif
    NET_CTR_STAT_INC(NetTCP_StatTxSegConnProbeCtr);



   *perr = NET_TCP_ERR_NONE;
}


/*$PAGE*/
/*
*********************************************************************************************************
*                                      NetTCP_TxConnKeepAlive()
*
* Description : (1) #### Prepare & transmit a TCP connection keep-alive :
*
*
* Argument(s) : pconn       Pointer to a TCP connection.
*               -----       Argument validated in ####
*
*               perr        Pointer to variable that will receive the return error code from this function :
*
*                               NET_TCP_ERR_NONE                    TCP connection keep-alive successfully
*                                                                       transmitted.
*
* Return(s)   : none.
*
* Caller(s)   : ####
*
* Note(s)     : (2) RFC #1122, Section 4.2.3.6 states that "implementors MAY include 'keep-alives' in
*                   their TCP implementations, although this practice is not universally accepted ...
*                   A 'keep-alive' mechanism periodically probes the other end of a connection when
*                   the connection is otherwise idle, even when there is no data to be sent".
*
*                   (a) "If keep-alives are included," ...
*
*                       (1) "the application MUST be able to turn them on or off for each TCP connection,"
*                       (2) "and they MUST default to off."
*
*                   (b) "Keep-alive packets MUST only be sent when no data or acknowledgement packets have
*                        been received for the connection within an interval" :
*
*                       (1) "This interval MUST be configurable" ...
*                       (2) "and MUST default to no less than two hours."
*
*                   (c) "To confirm that an idle connection is still active ... send a probe segment ...
*                        to elicit a response from the peer TCP" :
*
*                       (1) "Such a segment generally contains SEG.SEQ = SND.NXT-1" ...
*
*                           (A) "Note that on a quiet connection SND.NXT = RCV.NXT, so that this SEG.SEQ will
*                                be outside the window.  Therefore, the probe causes the receiver to return an
*                                acknowledgment segment, confirming that the connection is still live.  If the
*                                peer has dropped the connection ... it will respond with a RST instead of an
*                                acknowledgment segment."
*
*                       (2) "and may or may not contain one garbage octet of data."
*
*                           (A) "An implementation SHOULD send a keep-alive segment with no data".
*
*                               (1) (a) "Unfortunately, some misbehaved TCP implementations fail to respond to
*                                        a segment with SEG.SEQ = SND.NXT-1 unless the segment contains data."
*
*                                   (b) Stevens, TCP/IP Illustrated, Volume 1, 8th Printing, Section 23.3, 
*                                       Page 335 reiterates that "some older implementations based on 4.2BSD do 
*                                       not respond to these keepalive probes unless the segment contains data".
*
*                               (2) (a) Therefore, RFC #1122, Section 4.2.3.6 states that a TCP "implementation ...
*                                       MAY be configurable to send a keep-alive segment containing one garbage
*                                       octet, for compatibility with erroneous TCP implementations".
*
*                                   (b) (1) "Alternatively, an implementation could determine whether a peer
*                                            responded correctly to keep-alive packets with no garbage data octet."
*
*                                       (2) (A) Or as Stevens, TCP/IP Illustrated, Volume 1, 8th Printing, Section
*                                               23.3, Page 335 states, some "systems send the 4.3BSD-style segment
*                                               (no data) for the first half of the probe period, and if no response
*                                               is received, switch to the 4.2BSD-style segment for the last half".
*
*                                           (B) Therefore, it seems reasonable to implement the combined BSD 4.3/4.2
*                                               solution since it does NOT require any non-standard configuration
*                                               for the garbage data octet & SHOULD be backwards-compatible with all
*                                               other systems.
*
*                       (3) "It is extremely important to remember that ACK segments that contain no data
*                            are not reliably transmitted by TCP.  Consequently, if a keep-alive mechanism
*                            is implemented it MUST NOT interpret failure to respond to any specific probe
*                            as a dead connection."
*********************************************************************************************************
*/

#if 0                                                           /* #### NOT yet implemented.                            */
static  void  NetTCP_TxConnKeepAlive (NET_TCP_CONN  *pconn,
                                      NET_ERR       *perr)
{
}
#endif


/*$PAGE*/
/*
*********************************************************************************************************
*                                         NetTCP_TxConnTxQ()
*
* Description : (1) Transmit TCP data segment(s) from TCP connection transmit queue :
*
*                   (a) Configure TCP connection transmit :
*
*                       (1) Configure TCP connection transmit acknowledgement request :     See Note #1d1
*
*                           (A) Do NOT transmit TCP data/acknowledgement if ...
*                               (1) NO TCP transmit data available or allowed to transmit
*                                      AND
*                               (2) NO transmit acknowledgement requested
*
*                           (B)        Transmit TCP      acknowledgement if ...
*                               (1) NO TCP transmit data available or allowed to transmit
*                                      BUT
*                               (2)    Transmit acknowledgement requested
*
*                       (2) Configure TCP connection transmit free timer request            See Note #1d4
*
*                   (b) Transmit TCP connection transmit queue data :
*
*                       (1) Control TCP connection transmit versus transmit congestion controls :
*
*                               (a) See also 'NetTCP_TxConnWinSizeHandlerCongCtrl()  Note #2'
*                                          & 'NetTCP_TxConnWinSizeUpdateAvail()      Note #1'
*
*                           (A) Available Transmit Window                            See Note  #1b1a
*                           (B) Transmit Queue Segment                               See Notes #5         & #8
*                           (C) Nagle Algorithm                                      See Notes #6, #7b2B, & #8
*                           (D) Silly Window Syndrome                                See Notes     #7     & #8
*
*                       (2) Update TCP connection transmit queue :
*                           (A) Remove TCP transmit segment(s) from
*                                      TCP connection    transmit queue                     See Note #3
*                           (B) Append TCP transmit segment(s) to
*                                      TCP connection re-transmit queue                     See Note #4
*                           (C) Update TCP connection re-transmit queue timer
*
*                       (3) Update TCP connection :
*                           (A) Update TCP connection sequence number(s)
*                           (B) Update TCP connection transmit congestion window
*
*                       (4) Prepare  TCP data/acknowledgement segment(s) :
*                           (A) TCP segment  addresses
*                           (B) TCP segment  sequence numbers
*                           (C) TCP segment  transmit flags :
*                               (1) ACK
*                           (D) TCP segment  window size
*                           (E) IP  datagram parameters
*                           (F) TCP segment  packet buffer controls
*
*                       (5) Transmit TCP data/acknowledgement segment(s)
*
*                   (c) Suspend TCP transmit :                                              See Note #10
*
*                       (1) Handle any network receive packet(s)                            See Note #10b2A
*
*                   (d) Complete TCP connection transmit :
*
*                       (1) Transmit TCP connection acknowledgement                         See Note #1a1
*                       (2) Clear    TCP connection transmit idle timer
*                               (see 'NetTCP_TxConnTxQ_TimeoutIdleClr()  Note #2b2')
*                       (3) Reset    TCP connection delayed  acknowledgement controls
*                       (4) Free     TCP connection transmit queue persist timer            See Note #1a2
*
*
*               (2) NetTCP_TxConnTxQ() transmits TCP connection data & acknowledgements.  TCP acknowledgements
*                   transmitted independently of TCP controls &/or data MAY be transmitted with NetTCP_TxConnAck().
*
*                   See also 'NetTCP_TxConnAck()  Note #2'.
*
*$PAGE*
* Argument(s) : pconn           Pointer to a TCP connection.
*               -----           Argument validated in various.
*
*               pbuf_hdr        Pointer to network buffer header that received TCP packet.
*
*               tx_ack_code     Indicate whether & how to transmit a TCP acknowledgement segment :
*
*                                   NET_TCP_CONN_TX_ACK_NONE            Do NOT transmit a TCP acknowledgement
*                                                                          segment          if TCP transmit data
*                                                                          NOT available.
*                                   NET_TCP_CONN_TX_ACK                 Transmit a TCP acknowledgement segment
*                                                                          even if TCP transmit data NOT available.
*                                   NET_TCP_CONN_TX_ACK_IMMED           Transmit a TCP acknowledgement segment
*                                                                          immediately even if TCP transmit data
*                                                                          NOT available.
*
*               tx_q_timeout    Indicate whether the TCP connection transmit queue timed out :
*
*                                   DEF_NO                              TCP connection transmit queue did
*                                                                           NOT time  out.
*                                   DEF_YES                             TCP connection transmit queue
*                                                                               timed out.
*
*               close_code      Select which close action(s) to perform; bit-field flags logically OR'd :
*
*                                   NET_TCP_CONN_CLOSE_NONE                 Perform NO  close actions.
*                                   NET_TCP_CONN_CLOSE_ALL                  Perform ALL close actions.
*
*                                   NET_TCP_CONN_CLOSE_CONN_TX_RESET        Perform close connection transmit reset.
*                                   NET_TCP_CONN_CLOSE_CONN_ALL             Perform ALL   connection close    actions.
*
*                                   NET_TCP_CONN_CLOSE_TMR_TX_IDLE          Close    transmit idle                  timer.
*                                   NET_TCP_CONN_CLOSE_TMR_TX_SILLY_WIN     Close    transmit silly window persist  timer.
*                                   NET_TCP_CONN_CLOSE_TMR_TX_ZERO_WIN      Close    transmit zero  window persist  timer.
*                                   NET_TCP_CONN_CLOSE_TMR_TX_ACK_DLY       Close    transmit acknowledgement delay timer.
*                                   NET_TCP_CONN_CLOSE_TMR_RE_TX            Close re-transmit                       timer.
*                                   NET_TCP_CONN_CLOSE_TMR_KEEP_ALIVE       Close connection keep-alive             timer.
*                                   NET_TCP_CONN_CLOSE_TMR_TIMEOUT          Close connection                        timer.
*                                   NET_TCP_CONN_CLOSE_TMR_ALL              Close ALL                               timers.
*
*                               See also 'TCP CONNECTION CLOSE/FREE CODE DEFINES'.
*
*               perr        Pointer to variable that will receive the return error code from this function :
*
*                               NET_TCP_ERR_NONE                    TCP connection transmit queue successfully
*                                                                       handled.
*                               NET_TCP_ERR_CONN_NOT_USED           TCP connection NOT currently used.
*                               NET_TCP_ERR_CONN_CLOSE              TCP connection closed.
*                               NET_TCP_ERR_CONN_FAULT              TCP connection fault; connection(s) aborted.
*                               NET_TCP_ERR_INVALID_CONN_STATE      Invalid TCP connection state.
*                               NET_TCP_ERR_INVALID_CONN_OP         Invalid TCP connection operation.
*
*                                                                   ------- RETURNED BY NetTCP_TxConnAck() : -------
*                               NET_TCP_ERR_CONN_ACK_NONE           TCP connection acknowledgement NOT requested.
*                               NET_TCP_ERR_CONN_ACK_DLYD           TCP connection acknowledgement transmit delayed.
*                               NET_TCP_ERR_CONN_ACK_PREVLY_TXD     TCP connection acknowledgement previously
*                                                                       transmitted for segment.
*                               NET_TCP_ERR_CONN_ACK_INVALID        TCP connection acknowledgement NOT valid for
*                                                                       current TCP connection state.
*                               NET_TCP_ERR_NONE_AVAIL              Resources NOT available.
*                               NET_TCP_ERR_INVALID_LEN_SEG         Invalid TCP sequence-segment length.
*                               NET_CONN_ERR_INVALID_FAMILY         Invalid     connection family.
*                               NET_CONN_ERR_INVALID_ADDR           Invalid TCP connection address.
*                               NET_CONN_ERR_INVALID_ADDR_LEN       Invalid TCP connection address length.
*
*                                                                   ----- RETURNED BY NetTCP_TxPktHandler() : ------
*                               NET_ERR_INIT_INCOMPLETE             Network initialization NOT complete.
*                               NET_TCP_ERR_TX                      TCP transmit error (see Note #12a).
*                               NET_ERR_TX                              Transmit error.
*
* Return(s)   : none.
*
* Caller(s)   : various.
*$PAGE*
* Note(s)     : (3) See 'NetTCP_TxConnAppData()  Note #4' for TCP connection Transmit Queue diagram.
*
*               (4) TCP segments that have been transmitted but NOT yet acknowledged are sequenced into
*                   the TCP connection's re-transmit queue to await acknowledgement or retransmission.
*
*                   (a) Transmitted TCP segments are inserted into a doubly-linked Re-Transmit Queue,
*                       ordered consecutively by sequence number(s) [see also Note #4b].
*
*                       (1) 'ReTxQ_Head' points to the head of the Re-Transmit Queue;
*                           'ReTxQ_Tail' points to the tail of the Re-Transmit Queue.
*
*                       (2) Segment buffers' 'PrevPrimListPtr' & 'NextPrimListPtr'  doubly-link each
*                           segment to form the Re-Transmit Queue.
*
*                   (b) Transmit segments are transmitted & await acknowledgement in sequence-order.
*                       Therefore, newly-transmitted segments are sequenced after previously transmitted
*                       segments starting at the tail of the Re-Transmit Queue.
*
*                   (c) Segments at the head of the Re-Transmit Queue are awaiting acknowledgement &
*                       removal from the Re-Transmit Queue; & are ready to be re-transmitted until
*                       acknowledged & removed from the queue.
*
*
*                                      |                                               |
*                                      |<----- TCP Connection Re-Transmit Queue ------>|
*                                      |                (see Note #4)                  |
*
*                                 Segments Awaiting
*                                 Acknowledgement or                        Segments Sequenced
*                                    Re-Transmit                          into Re-Transmit Queue
*                                   start at head                           starting at tail
*                                  (see Note #4c)                             (see Note #4b)
*
*                                         |        NextPrimListPtr                  |
*                                         |        (see Note #4a2)                  |
*                                         v                   |                     v
*                                                             |
*                      Head of         -------       -------  v    -------       -------     (see Note #4a1)
*                    Re-Transmit  ---->|     |------>|     |------>|     |------>|     |
*                       Queue          |     |       |     |       |     |       |     |         Tail of
*                                      |     |<------|     |<------|     |<------|     |<----  Re-Transmit
*                 (see Note #4a1)      |     |       |     |  ^    |     |       |     |          Queue
*                                      |     |       |     |  |    |     |       |     |
*                                      -------       -------  |    -------       -------
*                                                             |
*                                                  PrevPrimListPtr
*                                                  (see Note #4a2)
*
*$PAGE*
*               (5) In order to simply TCP transmit buffer management, TCP transmit does NOT transmit
*                   partial network-buffer segments (i.e. portions of  TCP segments in the same network
*                   buffer).  This avoids the complexity of queuing & handling partially transmitted
*                   segments on both the TCP transmit & re-transmit queues.
*
*                   (a) However, in order to avoid transmit window deadlock with a remote host's receive
*                       window, the TCP connection's connection maximum segment size MUST be configured
*                       to ensure that full, maximum-segment-sized segments will transmit even for receive
*                       windows less than the default maximum segment size.
*
*                       See also 'NetTCP_ConnCfgMaxSegSize()  Note #2'.
*
*               (6) (a) (1) RFC #896, Section 'The small-packet problem' states that "there is a special
*                           problem associated with small packets ... the congestion ... can result in
*                           lost datagrams and retransmissions, as well as excessive propagation time ...
*                           In practice, throughput may drop so low that TCP connections are aborted".
*
*                       (2) RFC #896, Section 'The solution to the small-packet problem' states that "the
*                           solution to the small-packet problem ... is" :
*
*                           (A) "to inhibit the sending of new TCP segments when new outgoing data arrives
*                                from the user" ...
*
*                           (B) "if any previously transmitted data on the connection remains unacknowledged."
*
*                           (C) "This inhibition is to be unconditional;" :
*                               (1) "no timers,"                      ...
*                               (2) "tests for size of data received, ...
*                               (3) "or other conditions are required."
*
*                   (b) (1) RFC #1122, Section 4.2.3.4 states that "the Nagle algorithm is ... as follows" :
*
*                           (A) "If there is unacknowledged data (i.e., SND.NXT > SND.UNA)," ...
*                           (B) "then the sending TCP buffers all user data" ...
*                               (1) "(regardless of the PSH bit)," ...
*                               (2) "until" :
*                                   (a) "the outstanding data has been acknowledged" ...
*                                   (b) "or until the TCP can send a full-sized segment."
*
*                       (2) (A) "A TCP SHOULD implement the Nalge Algorithm ... to coalesce short segments."
*
*                           (B) (1) "However, there MUST be a way for an application to disable the Nagle
*                                    algorithm on an individual connection."
*
*                               (2) Thus, it is assumed from these two requirements that the Nagle algorithm
*                                   should be enabled by default.
*
*                       See also Note #7b2Ba2A.
*$PAGE*
*               (7) (a) RFC #813, Section 2 states that "a bad implementation of the window algorithm can
*                       lead to extremely poor performance ... This particular phenomenon ... has been
*                       given the name of Silly Window Syndrome, or SWS".
*
*                       Section 3 elaborates that "SWS is a degeneration in the throughput which develops
*                       ... whenever the acknowledgement of a small segment ... cause[s] another segment
*                       of the same small size to be sent, until ... the network ... becomes clogged with
*                       many small segments, and an equal number of acknowledgements".
*
*                   (b) (1) RFC #813, Section 4 states that "there is an algorithm that the sender can use
*                           ... [which] compares the useable window to the offered window, and refrains from
*                           anything if the ratio of useable to offered is less than a certain fraction ...
*                           Until the useable window reaches a certain amount, the sender should simply refuse
*                           to send anything".
*
*                       (2) (A) RFC #1122, Section 4.2.3.4 reiterates that "a TCP MUST include a SWS avoidance
*                               algorithm in the sender".  However, "the SWS avoidance algorithm ... specified"
*                               in RFC #1122 "is to be used instead of the sender-side algorithm contained in
*                               [RFC #813]".
*
*                           (B) (a) RFC #1122, Section 4.2.3.4 states that "the sender's SWS avoidance algorithm
*                                   is ... [to] send data" :
*
*                                   (1) "If a maximum-sized segment can be sent, i.e, [sic] if" :
*
*                                       (A) "min(D,U) >= Eff.snd.MSS"
*                                           (1) (a) This threshold subtly assumes that the amount of data queued
*                                                   on the TCP connection's transmit queue is queued in maximum-
*                                                   sized segments.
*                                               (b) Although this assumption is typically satisfied since all
*                                                   new TCP transmit data is usually aggregated & appended onto
*                                                   the TCP connection's transmit queue in maximum-sized segments
*                                                   (see 'NetTCP_TxConnAppData()  Note #7b1'); to ensure that the
*                                                   maximum-sized-segment threshold is satisfied the transmit
*                                                   segment's length is also checked.
*
*                                   (2) "Or if the data is pushed and all queued data can be sent now, i.e., if" :
*
*                                       (A) "[SND.NXT = SND.UNA and] ...
*                                           (1) "(the bracketed condition is imposed by the Nagle algorithm)"
*                                           (2) (a) This condition is required ONLY if the Nagle algorithm
*                                                   is enabled (see Note #6b2B).
*                                               (b) However, if the Nagle algorithm is disabled, the silly
*                                                   window syndrome threshold conditions MUST be checked
*                                                   (see Note #7b2Ba3).
*
*                                       (B) "PUSHED and"             ...
*                                           (1) See also 'NetTCP_TxConnAppData()  Note #7b3B1b'.
*
*                                       (C) "D <= U"
*                                           (1) (a) This threshold subtly assumes that the amount of data queued
*                                                   on the TCP connection's transmit queue is queued in maximum-
*                                                   sized segments.
*                                               (b) To ensure that the next actual transmit segment is compared
*                                                   to the available transmit window, the following threshold is
*                                                   actually checked :
*
*                                                   (1) min(D, SEG.LEN) <= U
*
*                                               See also Note #7b2Ba1A1.
*
*                                   (3) "Or if at least a fraction Fs of the maximum window can be sent, i.e., if" :
*
*                                       (A) "[SND.NXT = SND.UNA and]" ...
*                                           (1) This condition is required ONLY if the Nagle algorithm is enabled
*                                               (see Note #6b2B).
*
*                                       (B) "min(D,U) >= Fs * Max(SND.WND)"
*$PAGE*
*                                   (4) "or if" :
*
*                                       (A) "data is PUSHed and" ...
*                                           (1) Although it is not directly stated, it is inferred that if
*                                               the segment(s)' data is NOT pushed, the segment transmit
*                                               SHOULD be postponed until the previous transmit silly window
*                                               syndrome avoidance conditions have NOT been satisfied (see
*                                               Notes #7b2Ba1, #7b2Ba2, & #7b2Ba3).
*
*                                           (2) See also 'NetTCP_TxConnAppData()  Note #7b3B1b'.
*
*                                       (B) "the override timeout occurs."
*                                           (1) Although it is not directly stated, it is inferred that the
*                                               transmit silly window override timer should be set when :
*
*                                               (a) The previous transmit silly window syndrome avoidance
*                                                   conditions have NOT been satisfied (see Notes #7b2Ba1,
*                                                   #7b2Ba2, & #7b2Ba3) ...
*                                               (b) BUT                                ...
*                                                   (1) the TCP segment data is pushed ...
*                                                   (2) & no current timeout exists.
*
*                                           (2) However, if NO network timer is available to delay the TCP
*                                               data segment(s), the TCP data segment(s) SHOULD be immediately
*                                               transmitted.
*
*                                           See also Note #7b2Bb.
*
*
*                                   where
*                                       (A) D               Amount of data queued in the sending TCP but not
*                                                               yet sent
*
*                                       (B) U              'Useable window' ... i.e., the offered window less
*                                                               the amount of data sent but not acknowledged :
*
*                                                           (1) U = SND.UNA + SND.WND - SND.NXT
*
*                                                           (2) The 'useable window' is also constrained by the
*                                                               available window & other TCP congestion controls
*                                                               (see 'NetTCP_TxConnWinSizeUpdateAvail()  Note #1').
*
*                                       (C) Eff.snd.MSS     Effective send MSS for the connection
*                                       (D) SND.NXT         Next sequence number to transmit
*                                       (E) SND.UNA         Oldest unacknowledged sequence number
*                                       (F) Max(SND.WND)    Maximum send window ... seen ... on the connection
*                                       (G) Fs              Fraction whose recommended value is 1/2
*
*
*                               (b) (1) Although RFC #813, Section 4 stated "that it is not necessary to set
*                                       a timer to protect against protocol lockup when postponing the send
*                                       operation"; RFC #1122, Section 4.2.3.4 amends that "to avoid a ...
*                                       deadlock, it is necessary to have a timeout to force transmission of
*                                       data, overriding the SWS avoidance algorithm".
*
*                                   (2) "The override timeout should be in the range 0.1 - 1.0 seconds."
*
*                                   (3) "In practice, this timeout should seldom occur."
*$PAGE*
*               (8) (a) Although it is not directly stated, it is inferred that the limitations of
*                       the Nagle & transmit silly window syndrome avoidance algorithms apply only
*                       to discrete, individually-queued data segments & NOT to any stream of data
*                       segments.
*
*                       Therefore, a data segment -- especially the last queued data segment in the
*                       TCP connection's transmit queue -- should NOT be constrained by the Nagle &
*                       transmit silly window syndrome avoidance algorithms if this last queued data
*                       segment is immediately transmitted after the transmission of the preceding
*                       queued data segments.
*
*                       See also 'NetTCP_TxConnAppData()  Notes #7b1 & #7b3B2'.
*
*                   (b) Also, although NO RFC specifies the Nagle algorithm's or the transmit silly
*                       window syndrome avoidance algorithm's compliance, effect, or limitation on
*                       TCP connection closes; it does NOT seem reasonable for the Nagle algorithm
*                       or the transmit silly window syndrome avoidance algorithm to inhibit or
*                       delay the transmission of a TCP connection close segment.
*
*               (9) Increment network buffer's reference counter to include the TCP segment now enqueued
*                   to the TCP connection's re-transmit queue as a new reference to the network buffer.
*
*              (10) To balance network receive versus transmit packet loads for certain network connection
*                   types (e.g. stream-type connections), network receive & transmit packets SHOULD be
*                   handled in an APPROXIMATELY balanced ratio.
*
*                   (a) Network task priorities & lock mechanisms partially maintain a balanced ratio
*                       between network receive versus transmit packet handling.
*
*                       However, the handling of network receive & transmit packets :
*
*                       (1) SHOULD be interleaved so that for every few packet(s) received & handled,
*                           several packet(s) should be transmitted; & vice versa.
*
*                       (2) SHOULD NOT exclusively handle receive nor transmit packets, even for a
*                           short period of time.
*
*                   (b) To implement network receive versus transmit load balancing :
*
*                       (2) Certain network connections MUST periodically suspend network transmit(s)
*                           to handle network receive packet(s) :
*
*                           (A) Suspend network transmit(s) if network receive packets are available.
*
*                               (1) To approximate a balanced ratio of network receive versus transmit
*                                   packets handled; the number of consecutive times that a network
*                                   transmit suspends itself to check for & handle any network receive
*                                   packet(s) SHOULD APPROXIMATELY correspond to the number of queued
*                                   network receive packet(s) availabile.
*
*                                   See also 'net.c  Net_RxPktIsAvail()  Note #2'.
*
*                               (2) To protect TCP connections from transmit corruption while suspended,
*                                   ALL TCP data transmits & TCP transmit queue handling MUST be blocked
*                                   for suspended connections until the connection is no longer suspended.
*
*                           (B) Signal or timeout network transmit suspend(s) to restart transmit(s).
*
*                   See also 'net.h  NETWORK RECEIVE PACKET MACRO'S  Note #1'.
*
*              (11) On ANY errors, network resources MUST be appropriately freed :
*
*                   (a) For all network resources that have been linked to the TCP connection, ALL
*                       network resources are freed by NetTCP_ConnClose().
*
*              (12) (a) Since segments enqueued to a TCP connection's transmit queue have already been
*                       reported as transmitted to the application & since no mechanism exists for a TCP
*                       connection to re-request previously transmitted data, any TCP connection whose
*                       transmit queue(s) becomes corrupted MUST be closed to force the application layer
*                       to abort &/or recover from the corrupted data.
*
*                   (b) For any internal errors where the TCP connection's transmit queue is NOT corrupted,
*                       the TCP connection is NOT closed.
*
*                   See also 'NetTCP_TxConnAppData()  Note #10'
*                          & 'NetTCP_TxConnReTxQ()    Note #11'.
*********************************************************************************************************
*/
/*$PAGE*/
static  void  NetTCP_TxConnTxQ (NET_TCP_CONN        *pconn,
                                NET_BUF_HDR         *pbuf_hdr,
                                NET_TCP_ACK_CODE     tx_ack_code,
                                CPU_BOOLEAN          tx_q_timeout,
                                NET_TCP_CLOSE_CODE   close_code,
                                NET_ERR             *perr)
{
#if (((NET_CTR_CFG_STAT_EN     == DEF_ENABLED)                    || \
      (NET_CTR_CFG_ERR_EN      == DEF_ENABLED))                   && \
      (CPU_CFG_CRITICAL_METHOD == CPU_CRITICAL_METHOD_STATUS_LOCAL))
    CPU_SR               cpu_sr;
#endif
    NET_BUF             *pseg;
    NET_BUF             *pseg_next;
    NET_BUF             *pbuf_q_tail;
    NET_BUF_HDR         *pseg_hdr;
    NET_BUF_HDR         *pseg_next_hdr;
    NET_BUF_HDR         *pbuf_q_tail_hdr;
    NET_TMR_TICK         timeout_tick;
    NET_IP_TOS           TOS;
    NET_IP_TTL           TTL;
    NET_IP_ADDR          src_addr;
    NET_IP_ADDR          dest_addr;
    NET_TCP_PORT_NBR     src_port;
    NET_TCP_PORT_NBR     dest_port;
    NET_TCP_SEQ_NBR      seq_nbr;
    NET_TCP_SEQ_NBR      ack_nbr;
    NET_TCP_WIN_SIZE     win_size;
    NET_TCP_WIN_SIZE     tx_data_qd;
    NET_TCP_WIN_SIZE     tx_data_min;
    NET_TCP_WIN_SIZE     tx_th_q_min;
    NET_TCP_TX_Q_STATE   state;
    CPU_INT16U           flags_tcp;
    CPU_INT16U           flags_ip;
    CPU_BOOLEAN          tx_ack;
    CPU_BOOLEAN          tx_seg;
    CPU_BOOLEAN          tx_seg_push;
    CPU_BOOLEAN          tx_seg_close;
    CPU_BOOLEAN          tx_segs_txd;
    CPU_BOOLEAN          tx_segs;
    CPU_BOOLEAN          tx_done;
    CPU_BOOLEAN          tx_th_seg;
    CPU_BOOLEAN          tx_th_mss;
    CPU_BOOLEAN          tx_th_nagle;
    CPU_BOOLEAN          tx_th_silly_win;
    CPU_BOOLEAN          tx_tmr_free;
    CPU_BOOLEAN          net_rx_avail;
    NET_CTR              net_rx_nbr;
    NET_ERR              err;
    NET_ERR              err_rtn;


                                                                    /* ------------------ CFG TCP TX ------------------ */
    switch (tx_ack_code) {                                          /* Cfg tx ack req.                                  */
        case NET_TCP_CONN_TX_ACK_NONE:
        default:
             tx_ack = DEF_NO;
             break;


        case NET_TCP_CONN_TX_ACK:
        case NET_TCP_CONN_TX_ACK_IMMED:
             tx_ack = DEF_YES;
             break;
    }

                                                                    /* Cfg tx tmr free req.                             */
    tx_tmr_free = (pconn->TxQ_Head == (NET_BUF *)0) ? DEF_YES : DEF_NO;


/*$PAGE*/
    switch (pconn->ConnState) {                                     /* Cfg tx Q seg(s).                                 */
        case NET_TCP_CONN_STATE_FREE:
             NET_CTR_ERR_INC(NetTCP_ErrNotUsedCtr);
            *perr = NET_TCP_ERR_CONN_NOT_USED;
             return;                                                /* Prevent 'break NOT reachable' compiler warning.  */


        case NET_TCP_CONN_STATE_SYNC_RXD:
        case NET_TCP_CONN_STATE_SYNC_RXD_PASSIVE:
        case NET_TCP_CONN_STATE_SYNC_RXD_ACTIVE:
        case NET_TCP_CONN_STATE_SYNC_TXD:
             switch (pconn->TxQ_State) {
                 case NET_TCP_TX_Q_STATE_CONN_CLOSED:
                      tx_segs = DEF_YES;
                      break;


                 case NET_TCP_TX_Q_STATE_NONE:
                 case NET_TCP_TX_Q_STATE_CLOSED:
                 case NET_TCP_TX_Q_STATE_CONN:
                 case NET_TCP_TX_Q_STATE_CONN_CLOSING:
                 case NET_TCP_TX_Q_STATE_CONN_SUSPEND:
                 default:
                     *perr = NET_TCP_ERR_INVALID_CONN_STATE;
                      return;                                       /* Prevent 'break NOT reachable' compiler warning.  */
             }
             break;


        case NET_TCP_CONN_STATE_CONN:
        case NET_TCP_CONN_STATE_FIN_WAIT_1:
        case NET_TCP_CONN_STATE_CLOSING:
        case NET_TCP_CONN_STATE_CLOSE_WAIT:
        case NET_TCP_CONN_STATE_LAST_ACK:
             switch (pconn->TxQ_State) {
                 case NET_TCP_TX_Q_STATE_CONN:
                 case NET_TCP_TX_Q_STATE_CONN_CLOSING:
                      tx_segs = DEF_YES;
                      break;


                 case NET_TCP_TX_Q_STATE_CONN_CLOSED:
                 case NET_TCP_TX_Q_STATE_CONN_SUSPEND:              /* See Note #10b2A2.                                */
                      tx_segs = DEF_NO;
                      break;


                 case NET_TCP_TX_Q_STATE_NONE:
                 case NET_TCP_TX_Q_STATE_CLOSED:
                 default:
                     *perr = NET_TCP_ERR_INVALID_CONN_STATE;
                      return;                                       /* Prevent 'break NOT reachable' compiler warning.  */
             }
             break;


        case NET_TCP_CONN_STATE_LISTEN:
        case NET_TCP_CONN_STATE_FIN_WAIT_2:
        case NET_TCP_CONN_STATE_TIME_WAIT:
        case NET_TCP_CONN_STATE_CLOSING_DATA_AVAIL:
             NET_CTR_ERR_INC(NetTCP_ErrConnInvalidOpCtr);
            *perr = NET_TCP_ERR_INVALID_CONN_OP;
             return;                                                /* Prevent 'break NOT reachable' compiler warning.  */


        case NET_TCP_CONN_STATE_NONE:
        case NET_TCP_CONN_STATE_CLOSED:
        default:
             NetTCP_ConnClose(pconn, pbuf_hdr, DEF_YES, close_code);
             NET_CTR_ERR_INC(NetTCP_ErrConnInvalidStateCtr);
            *perr = NET_TCP_ERR_INVALID_CONN_STATE;
             return;                                                /* Prevent 'break NOT reachable' compiler warning.  */
    }


    err_rtn = NET_TCP_ERR_NONE;



/*$PAGE*/
                                                                    /* ---------- TX DATA FROM TCP CONN TX Q ---------- */
    pseg_next   =  pconn->TxQ_Head;

    tx_done     = (tx_segs == DEF_YES) ? DEF_NO : DEF_YES;
    tx_segs_txd =  DEF_NO;

    while (tx_done == DEF_NO) {                                     /* Tx ALL TCP conn tx Q seg(s) ...                  */
                                                                    /* ... allowed by cong ctrls (see Note #1b1).       */
        tx_seg = DEF_NO;

        pseg   = pseg_next;
        if (pseg != (NET_BUF *)0) {
            pseg_hdr  = (NET_BUF_HDR *)&pseg->Hdr;
            pseg_next = (NET_BUF     *) pseg_hdr->NextPrimListPtr;
                                                                    /* ----------------- CTRL TCP TX ------------------ */
                                                                    /* Validate tx win cong th's :                  ... */
            if (pconn->TxWinSizeAvail >= pseg_hdr->TCP_SegLenData) {/* ... chk avail tx win >= seg len (see Note #5);   */
                tx_seg = DEF_YES;
                                                                    /* ... chk prev'ly tx'd  seg(s) [see Note #8a]; ... */
                                                                    /* ... or TCP conn close seg    [see Note #8b]; ... */
                tx_seg_close = DEF_BIT_IS_SET(pseg_hdr->TCP_Flags, NET_TCP_FLAG_TX_CLOSE);
                tx_th_seg    = ((tx_segs_txd  == DEF_YES) ||
                                (tx_seg_close == DEF_YES)) ? DEF_OK : DEF_FAIL;

                if (tx_th_seg != DEF_OK) {
                                                                    /* ... chk MSS       th (see Note #7b2Ba1);     ... */
                    tx_data_qd  = (NET_TCP_WIN_SIZE)(pconn->TxSeqNbrNextQ - pconn->TxSeqNbrNext);
                    tx_data_min = (NET_TCP_WIN_SIZE) DEF_MIN(tx_data_qd,    pseg_hdr->TCP_SegLenData);
                    tx_th_q_min = (NET_TCP_WIN_SIZE) DEF_MIN(tx_data_min,   pconn->TxWinSizeAvail);
                    tx_th_mss   = (tx_th_q_min >= pconn->MaxSegSizeConn) ? DEF_OK : DEF_FAIL;

                    if (tx_th_mss != DEF_OK) {
                                                                    /* ... chk Nagle     th (see Note #7b2Ba2);     ... */
                        tx_seg_push = DEF_BIT_IS_SET(pseg_hdr->TCP_Flags, NET_TCP_FLAG_TX_PUSH);
                        tx_th_nagle = ((pconn->TxWinSizeNagleEn != DEF_DISABLED         ) &&
                                       (pconn->TxSeqNbrNext     == pconn->TxSeqNbrUnAckd) &&
                                       (tx_seg_push             == DEF_YES              ) &&
                                       (tx_data_min             <= pconn->TxWinSizeAvail)) ? DEF_OK : DEF_FAIL;

                        if (tx_th_nagle != DEF_OK) {
                                                                    /* ... chk silly win th (see Note #7b2Ba3);     ... */
                            tx_th_silly_win = (((pconn->TxWinSizeNagleEn == DEF_DISABLED         )  ||
                                                (pconn->TxSeqNbrNext     == pconn->TxSeqNbrUnAckd)) &&
                                                (tx_th_q_min             >= pconn->TxWinSizeMinTh))  ? DEF_OK : DEF_FAIL;

                            if (tx_th_silly_win != DEF_OK) {
                                                                    /* ... chk push timeout (see Note #7b2Ba4).         */
                                if (tx_seg_push == DEF_YES) {       /* If data seg pushed   (see Note #7b2Ba4A),    ... */
                                    if (tx_q_timeout == DEF_NO) {   /* ... & no cur timeout (see Note #7b2Ba4B1b2), ... */
                                                                    /* ... & tx Q tmr NOT yet cfg'd,                ... */
                                        if (pconn->TxQ_SillyWinTmr == (NET_TMR *)0) {
                                            timeout_tick           = ((NET_TMR_TICK)pconn->TxWinSillyWinTimeout_ms * NET_TMR_TIME_TICK_PER_SEC)
                                                                                                                   / DEF_TIME_NBR_mS_PER_SEC;
                                            pconn->TxQ_SillyWinTmr =   NetTmr_Get((void       *) pconn,
                                                                                  (CPU_FNCT_PTR) NetTCP_TxConnTxQ_TimeoutSillyWin,
                                                                                  (NET_TMR_TICK) timeout_tick,
                                                                                  (CPU_INT16U  ) NET_TMR_FLAG_NONE,
                                                                                  (NET_ERR    *)&err);
                                                                    /* ... & tx Q tmr avail,                        ... */
                                            if (err == NET_TMR_ERR_NONE) {
                                                tx_seg = DEF_NO;    /* ... dly  tx seg (see Note #7b2Ba4B1);        ... */
                                            }                       /* ... else tx seg (see Note #7b2Ba4B2).            */

                                        } else {                    /* Else  tx Q tmr already cfg'd, ...                */
                                            tx_seg = DEF_NO;        /* ... dly  tx seg (see Note #7b2Ba4B1).            */
                                        }
                                    }

                                } else {                            /* If data seg NOT pushed, ...                      */
                                    tx_seg = DEF_NO;                /* ... dly tx seg (see Note #7b2Ba4A1).             */
                                }
                            }
                        }
                    }
                }
            }
        }


/*$PAGE*/
                                                                    /* ----------------- TX TCP SEGS ------------------ */
        if (tx_seg == DEF_YES) {                                    /* If avail & rdy, tx Q seg(s).                     */

                                                                    /* ------------ UPDATE TCP CONN TX Q's ------------ */
                                                                    /* Move seg from tx Q to re-tx Q :                  */

            if (pseg_next != (NET_BUF *)0) {                        /* If tx Q next seg(s) avail, ...                   */
                                                                    /* ... update TCP conn tx Q.                        */
                pseg_next_hdr                  = (NET_BUF_HDR *)&pseg_next->Hdr;
                pseg_next_hdr->PrevPrimListPtr = (void        *) 0;
                pconn->TxQ_Head                = (NET_BUF     *) pseg_next;

            } else {                                                /* Else clr tx Q.                                   */
                pconn->TxQ_Head = (NET_BUF *)0;
                pconn->TxQ_Tail = (NET_BUF *)0;

                tx_tmr_free     =  DEF_YES;
            }

            pseg_hdr->PrevPrimListPtr = (void *)pconn->ReTxQ_Tail;
            pseg_hdr->NextPrimListPtr = (void *)0;

            if (pconn->ReTxQ_Tail != (NET_BUF *)0) {                /* If re-tx Q NOT empty, ...                        */
                                                                    /* ... append seg(s) @ Q tail (see Note #4b).       */
                pbuf_q_tail                      = (NET_BUF     *) pconn->ReTxQ_Tail;
                pbuf_q_tail_hdr                  = (NET_BUF_HDR *)&pbuf_q_tail->Hdr;
                pbuf_q_tail_hdr->NextPrimListPtr = (void        *) pseg;

                pconn->ReTxQ_Tail                = (NET_BUF     *) pseg;

            } else {                                                /* Else add seg to empty re-tx Q.                   */
                pconn->ReTxQ_Head                = (NET_BUF     *) pseg;
                pconn->ReTxQ_Tail                = (NET_BUF     *) pseg;
            }


            if (pconn->ReTxQ_Tmr == (NET_TMR *)0) {                 /* If unavail, get & update re-tx Q tmr.            */
                NetTCP_TxConnReTxQ_TimeoutSet(pconn, DEF_NO, close_code, perr);
                if (*perr != NET_TCP_ERR_NONE) {
                     return;
                }
            }

                                                                    /* --------------- UPDATE TCP CONN ---------------- */
                                                                    /* Update TCP conn tx seq nbr(s).                   */
            pconn->TxSeqNbrNext += (NET_TCP_SEQ_NBR)pseg_hdr->TCP_SegLen;

                                                                    /* Update TCP conn tx win ctrls (see Note #3a2).    */
            NetTCP_TxConnWinSizeHandlerCongCtrl((NET_TCP_CONN   *) pconn,
                                                (NET_BUF_HDR    *) 0,
                                                (NET_TCP_ACK_CODE) NET_TCP_CONN_RX_ACK_NONE,
                                                (NET_TCP_WIN_SIZE) pseg_hdr->TCP_SegLenData,
                                                (NET_TCP_WIN_CODE) NET_TCP_CONN_TX_WIN_DEC,
                                                (NET_ERR        *)&err);
            if ( err != NET_TCP_ERR_NONE) {
               *perr  = NET_TCP_ERR_CONN_FAULT;
                return;
            }


/*$PAGE*/
                                                                    /* --------- PREPARE TCP TX DATA/ACK SEG ---------- */
                                                                    /* Prepare TCP seg addrs.                           */
            src_port  = (NET_TCP_PORT_NBR)pseg_hdr->TCP_UDP_PortSrc;
            src_addr  = (NET_IP_ADDR     )pseg_hdr->IP_AddrSrc;

            dest_port = (NET_TCP_PORT_NBR)pseg_hdr->TCP_UDP_PortDest;
            dest_addr = (NET_IP_ADDR     )pseg_hdr->IP_AddrDest;

                                                                    /* Prepare TCP seq nbrs.                            */
            seq_nbr   = (NET_TCP_SEQ_NBR )pseg_hdr->TCP_SeqNbr;
            ack_nbr   = (NET_TCP_SEQ_NBR )pconn->RxSeqNbrNext;

                                                                    /* Prepare TCP tx flags.                            */
            flags_tcp =  pseg_hdr->TCP_Flags;

                                                                    /* Prepare TCP win size.                            */
            win_size  =  pconn->RxWinSizeActual;

                                                                    /* Prepare IP params.                               */
            TOS       =  pconn->TxIP_TOS;
            TTL       =  pconn->TxIP_TTL;
            flags_ip  =  pconn->TxIP_Flags;

                                                                    /* Update TCP tx buf ctrls.                         */
            pseg_hdr->TCP_SeqNbrLast  = (CPU_INT32U)seq_nbr;
            pseg_hdr->TCP_AckNbrLast  = (CPU_INT32U)ack_nbr;
            pseg_hdr->TCP_SegLenLast  = (CPU_INT16U)pseg_hdr->TCP_SegLen;
            pseg_hdr->TCP_WinSizeLast = (CPU_INT16U)win_size;

            pseg_hdr->TCP_SegReTxCtr  = (CPU_INT16U)0;
            pseg_hdr->RefCtr++;                                     /* TCP maintains ref until seg ack'd (see Note #9). */


                                                                    /* ------------- TX TCP DATA/ACK SEG -------------- */
            NetTCP_TxPktHandler((NET_BUF        *) pseg,
                                (NET_IP_ADDR     ) src_addr,
                                (NET_TCP_PORT_NBR) src_port,
                                (NET_IP_ADDR     ) dest_addr,
                                (NET_TCP_PORT_NBR) dest_port,
                                (NET_TCP_SEQ_NBR ) seq_nbr,
                                (NET_TCP_SEQ_NBR ) ack_nbr,
                                (NET_TCP_WIN_SIZE) win_size,
                                (NET_IP_TOS      ) TOS,
                                (NET_IP_TTL      ) TTL,
                                (CPU_INT16U      ) flags_tcp,
                                (CPU_INT16U      ) flags_ip,
                                (void           *) 0,
                                (void           *) 0,
                                (NET_ERR        *)&err_rtn);

            switch (err_rtn) {
                case NET_TCP_ERR_NONE:                              /* If NO tx err(s);          ...                    */
                     tx_segs_txd = DEF_YES;                         /* ... indicate seg(s) tx'd, ...                    */
                     NET_CTR_STAT_INC(NetTCP_StatTxSegConnTxQ_Ctr); /* ... & inc tx seg stat ctr.                       */
                     break;


                case NET_ERR_INIT_INCOMPLETE:                       /* Else indicate tx done.                           */
                case NET_ERR_TX:
                     tx_done = DEF_YES;
                     break;


                case NET_TCP_ERR_TX:                                /* See Note #12a.                                   */
                default:
                     NetTCP_ConnClose(pconn, pbuf_hdr, pconn->ConnCloseAppFlag, close_code);
                    *perr = err_rtn;
                     return;                                        /* Prevent 'break NOT reachable' compiler warning.  */
            }


        } else {                                                    /* Else if seg NOT tx'd, ...                        */
            tx_done = DEF_YES;                                      /* ... indicate tx done.                            */
        }


/*$PAGE*/
                                                                    /* ---------------- SUSPEND TCP TX ---------------- */
        if (tx_done == DEF_NO) {                                    /* If tx NOT done                                .. */
            net_rx_nbr   = 0;
            net_rx_avail = Net_RxPktIsAvail(net_rx_nbr);
            if (net_rx_avail == DEF_YES) {                          /* .. & net rx avail;                            .. */
                state            = pconn->TxQ_State;                /* .. save TCP conn tx Q state,                  .. */
                pconn->TxQ_State = NET_TCP_TX_Q_STATE_CONN_SUSPEND; /* .. set  TCP conn tx Q state to SUSPEND;       .. */

                NetOS_Unlock();
                do {
                    Net_TxSuspend();                                /* .. suspend tx to handle net rx (see Note #10b2A) */

                    net_rx_nbr++;
                    net_rx_avail = Net_RxPktIsAvail(net_rx_nbr);
                } while (net_rx_avail == DEF_YES);                  /* .. while net rx avail (see Note #10b2A1).        */

                NetOS_Lock(&err);
                if ( err != NET_OS_ERR_NONE) {
                    NetTCP_ConnClose(pconn, pbuf_hdr, pconn->ConnCloseAppFlag, close_code);
                   *perr  = NET_TCP_ERR_CONN_CLOSE;
                    return;
                }

                switch (pconn->TxQ_State) {                         /* Validate   TCP conn tx Q state.                  */
                    case NET_TCP_TX_Q_STATE_CONN_SUSPEND:           /* If still SUSPEND state, ..                       */
                         pconn->TxQ_State = state;                  /* .. restore TCP conn tx Q state.                  */
                         break;


                    case NET_TCP_TX_Q_STATE_NONE:
                    case NET_TCP_TX_Q_STATE_CLOSED:                 /* If CLOSED state, close TCP conn.                 */
                    case NET_TCP_TX_Q_STATE_CONN:
                    case NET_TCP_TX_Q_STATE_CONN_CLOSED:
                    case NET_TCP_TX_Q_STATE_CONN_CLOSING:
                    default:
                         NetTCP_ConnClose(pconn, pbuf_hdr, pconn->ConnCloseAppFlag, close_code);
                        *perr = NET_TCP_ERR_CONN_CLOSE;
                         return;                                    /* Prevent 'break NOT reachable' compiler warning.  */
                }
            }
        }
    }


                                                                    /* --------------- COMPLETE TCP TX ---------------- */
    if (tx_segs_txd != DEF_YES) {                                   /* If NO   tx Q seg(s) tx'd, ...                    */
        if (tx_ack  == DEF_YES) {                                   /* ... but tx ack req'd;     ...                    */
                                                                    /* ... tx TCP conn ack (see Note #1c1).             */
            NetTCP_TxConnAck(pconn, pbuf_hdr, tx_ack_code, close_code, &err_rtn);
        }

    } else {                                                        /* Else if ANY tx Q seg(s) tx'd;         ..         */
        NetTCP_TxConnTxQ_TimeoutIdleClr(pconn);                     /* .. clr tx Q idle tmr (see Note #1c2), ..         */
        NetTCP_TxConnAckDlyReset(pconn, DEF_YES);                   /* .. reset ack dly ctrls,               ..         */
        tx_tmr_free  = DEF_YES;                                     /* .. free tx Q tmr.                                */
    }


    if (tx_tmr_free == DEF_YES) {                                   /* If free tx Q tmr req'd, ..                       */
        if (pconn->TxQ_SillyWinTmr != (NET_TMR *)0) {               /* .. &    tx Q tmr avail, ..                       */
            if (tx_q_timeout == DEF_NO) {                           /* .. & NOT timed out,     ..                       */
                                                                    /* .. free tx Q tmr.                                */
                NetTmr_Free(pconn->TxQ_SillyWinTmr);
            }
            pconn->TxQ_SillyWinTmr  = (NET_TMR *)0;
        }
    }



   *perr = err_rtn;                                                 /* Rtn err from tx handler(s).                      */
}


/*$PAGE*/
/*
*********************************************************************************************************
*                                   NetTCP_TxConnTxQ_TimeoutIdle()
*
* Description : (1) (a) Handle TCP connection's transmit queue idle timeout ... :
*
*                       (1) Clear TCP connection's transmit idle timer                      See Note #4aA1
*                       (2) Reset TCP connection's transmit congestion window controls      See Note #2a
*                       (3) Reset TCP connection's transmit round-trip time   controls      See Note #2b
*
*                   (b) ... for the following states :
*
*                       (1) ESTABLISHED
*                       (2) FIN-WAIT-1
*                       (3) CLOSING
*                       (4) CLOSE-WAIT
*                       (5) LAST-ACK
*
*
* Argument(s) : pconn_timeout       Pointer to TCP connection (see Note #3b).
*
* Return(s)   : none.
*
* Caller(s)   : Referenced in NetTCP_TxConnTxQ_TimeoutIdleSet().
*
* Note(s)     : (2) (a) RFC #2581, Section 4.1 states that "after TCP has been idle for a relatively long period
*                       of time ... use slow start to restart transmission" :
*
*                       (1) (A) "When TCP has not received a segment for more than one retransmission timeout," ...
*                           (B) "cwnd is reduced to the value of the restart window."
*
*                       (2) However, RFC #2581, Section 4.1 re-states that "using the last time a segment was
*                           received to determine whether or not to decrease cwnd fails to deflate cwnd in the
*                           common case of persistent ... connections ... The reception of [segments] makes the
*                           test for an idle connection fail, and allows the TCP to begin transmission with a
*                           possibly inappropriately large cwnd."
*
*                           (A) "Therefore, ... if the TCP has not sent data ... in an interval exceeding the
*                                retransmission timeout" ...
*
*                           (B) "a TCP SHOULD set cwnd to no more than RW before beginning transmission."
*
*                       See also 'NetTCP_TxConnWinSizeHandlerCongCtrl()  Note #2e1'.
*
*                   (b) Similarly, although NO RFC specifies that a TCP connection's RTT average & deviation
*                       should be reset following a TCP transmit idle timeout; it seems reasonable to reset a
*                       TCP connection's RTT average & deviation controls whenever a TCP connection's transmit
*                       is idle for a period exceeding the re-transmit timeout.
*
*                       See also 'NetTCP_TxConnRTT_RTO_Calc()  Note #2a4B'.
*$PAGE*
*               (3) Ideally, network timer expiration functions could be defined as '[(void) (OBJECT *)]' 
*                   type functions -- even though network timer API functions cast expiration functions 
*                   to generic 'CPU_FNCT_PTR' type (i.e. '[(void) (void *)]').
*
*                   (a) (1) Unfortunately, ISO-IEC 9899-1999 ANSI-C, Section 6.3.2.3.7 states that "a 
*                           pointer to an object ... may be converted to a pointer to a different object 
*                           ... [but] if the resulting pointer is not correctly aligned ... the behavior
*                           is undefined".
*
*                           And since compilers may NOT correctly convert 'void' pointers to non-'void' 
*                           pointer arguments, network timer expiration functions MUST avoid incorrect
*                           pointer conversion behavior between 'void' pointer parameters & non-'void' 
*                           pointer arguments & therefore CANNOT be defined as '[(void) (OBJECT *)]'.
*
*                       (2) However, Section 6.3.2.3.1 states that "a pointer to void may be converted 
*                           to or from a pointer to any ... object ... A pointer to any ... object ... 
*                           may be converted to a pointer to void and back again; the result shall 
*                           compare equal to the original pointer".
*                   
*                   (b) Therefore, to correctly convert 'void' pointer objects back to appropriate
*                       network object pointer objects, network timer expiration functions MUST :
*
*                       (1) Be defined as 'CPU_FNCT_PTR' type (i.e. '[(void) (void *)]'); &       ...
*                       (2) Explicitly cast 'void' pointer arguments to specific object pointers; ...
*                           (A) ... in this case, a 'NET_TCP_CONN' pointer.
*
*                   See also 'net_tmr.c  NetTmr_Get()  Note #3'.
*
*               (4) This function is a network timer expiration function :
*
*                   (a) (1) For the following connection timer(s) ... :
*
*                           (A) TCP connection transmit queue idle timer ('TxQ_IdleTmr')
*
*                       (2) (A) Clear the timer pointer; ...
*                               (1) Cleared prior to next handler function(s) as an extra precaution to avoiding
*                                   re-freeing the timer (see Note #4a2B).
*
*                           (B) but do NOT re-free the timer.
*
*                   (b) Do NOT set the following close timer flag(s) :
*
*                       (1) NET_TCP_CONN_CLOSE_TMR_TX_IDLE
*
*               (5) Certain network connections MUST periodically suspend network transmit(s) to handle
*                   network receive packet(s).  To protect TCP connections from transmit corruption while
*                   suspended, ALL TCP data transmits & TCP transmit queue handling MUST be blocked for
*                   suspended connections until the connection is no longer suspended.
*
*                   However, handling the TCP connection's transmit queue idle timeout is permitted since
*                   NO TCP data is transmitted & the TCP connection's transmit queue is NOT handled (see
*                   Note #1a).
*
*                   See also 'NetTCP_TxConnTxQ()                    Note #10b2A2',
*                            'NetTCP_TxConnTxQ_TimeoutSillyWin()    Note #5',
*                            'NetTCP_TxConnReTxQ_Timeout()          Note #5',
*                          & 'NetTCP_TxConnWinSizeZeroWinTimeout()  Note #5'.
*********************************************************************************************************
*/
/*$PAGE*/
static  void  NetTCP_TxConnTxQ_TimeoutIdle (void  *pconn_timeout)
{
#if ((NET_ERR_CFG_ARG_CHK_DBG_EN == DEF_ENABLED)                    && \
     (NET_CTR_CFG_ERR_EN         == DEF_ENABLED)                    && \
     (CPU_CFG_CRITICAL_METHOD    == CPU_CRITICAL_METHOD_STATUS_LOCAL))
    CPU_SR               cpu_sr;
#endif
#if (NET_ERR_CFG_ARG_CHK_DBG_EN == DEF_ENABLED)
    NET_TCP_CLOSE_CODE   close_code;
#endif
    NET_TCP_CONN        *pconn;
    NET_ERR              err;


    pconn      = (NET_TCP_CONN *)pconn_timeout;                         /* See Note #3b2A.                              */

#if (NET_ERR_CFG_ARG_CHK_DBG_EN == DEF_ENABLED)
    close_code =  NET_TCP_CONN_CLOSE_ALL;
    DEF_BIT_CLR(close_code, NET_TCP_CONN_CLOSE_TMR_TX_IDLE);            /* See Note #4b1.                               */


                                                                        /* ------------ VALIDATE TCP CONN ------------- */
    if (pconn == (NET_TCP_CONN *)0) {
        NET_CTR_ERR_INC(NetTCP_ErrNullPtrCtr);
        return;
    }

    if (pconn->Type != NET_TCP_TYPE_CONN) {
        NET_CTR_ERR_INC(NetTCP_ErrConnInvalidTypeCtr);
        return;
    }

    switch (pconn->ConnState) {
        case NET_TCP_CONN_STATE_FREE:
             NET_CTR_ERR_INC(NetTCP_ErrNotUsedCtr);
             return;                                                    /* Prevent 'break NOT reachable' warning.       */


        case NET_TCP_CONN_STATE_CLOSED:
        case NET_TCP_CONN_STATE_LISTEN:
        case NET_TCP_CONN_STATE_SYNC_RXD:
        case NET_TCP_CONN_STATE_SYNC_RXD_PASSIVE:
        case NET_TCP_CONN_STATE_SYNC_RXD_ACTIVE:
        case NET_TCP_CONN_STATE_SYNC_TXD:
        case NET_TCP_CONN_STATE_FIN_WAIT_2:
        case NET_TCP_CONN_STATE_TIME_WAIT:
        case NET_TCP_CONN_STATE_CLOSING_DATA_AVAIL:
             NET_CTR_ERR_INC(NetTCP_ErrConnInvalidOpCtr);
             return;                                                    /* Prevent 'break NOT reachable' warning.       */


        case NET_TCP_CONN_STATE_CONN:                                   /* See Note #1.                                 */
        case NET_TCP_CONN_STATE_FIN_WAIT_1:
        case NET_TCP_CONN_STATE_CLOSING:
        case NET_TCP_CONN_STATE_CLOSE_WAIT:
        case NET_TCP_CONN_STATE_LAST_ACK:
             switch (pconn->TxQ_State) {
                 case NET_TCP_TX_Q_STATE_CONN:
                 case NET_TCP_TX_Q_STATE_CONN_CLOSING:
                 case NET_TCP_TX_Q_STATE_CONN_SUSPEND:                  /* See Note #5.                                 */
                      break;


                 case NET_TCP_TX_Q_STATE_NONE:
                 case NET_TCP_TX_Q_STATE_CLOSED:
                 case NET_TCP_TX_Q_STATE_CONN_CLOSED:
                 default:
                      return;                                           /* Prevent 'break NOT reachable' warning.       */
             }
             break;


        case NET_TCP_CONN_STATE_NONE:
        default:
             NetTCP_ConnClose((NET_TCP_CONN     *)pconn,
                              (NET_BUF_HDR      *)0,
                              (CPU_BOOLEAN       )DEF_YES,
                              (NET_TCP_CLOSE_CODE)close_code);
             NET_CTR_ERR_INC(NetTCP_ErrConnInvalidStateCtr);
             return;                                                    /* Prevent 'break NOT reachable' warning.       */
    }
#endif


/*$PAGE*/
                                                                        /* ---- HANDLE TCP CONN TX Q IDLE TIMEOUT ----- */
    pconn->TxQ_IdleTmr = (NET_TMR *)0;                                  /* Clr tx Q idle tmr  (see Note #4a2A1).        */

                                                                        /* Reset tx win ctrls (see Note #2a2B).         */
    NetTCP_TxConnWinSizeHandlerCongCtrl((NET_TCP_CONN   *) pconn,
                                        (NET_BUF_HDR    *) 0,
                                        (NET_TCP_ACK_CODE) NET_TCP_CONN_RX_ACK_NONE,
                                        (NET_TCP_WIN_SIZE) 0,
                                        (NET_TCP_WIN_CODE) NET_TCP_CONN_TX_WIN_RESET,
                                        (NET_ERR        *)&err);

                                                                        /* Reset RTT ctrls (see Note #2b).              */
    NetTCP_TxConnRTT_RTO_Calc(pconn, NET_TCP_CONN_TX_RTT_RESET, NET_TCP_TX_RTT_NONE, NET_TCP_TX_RTT_NONE);
}


/*$PAGE*/
/*
*********************************************************************************************************
*                                  NetTCP_TxConnTxQ_TimeoutIdleSet()
*
* Description : (1) Start TCP connection's transmit queue idle timeout for the following states :
*
*                   (a) SYN-RECEIVED
*                   (b) SYN-SENT
*                   (c) ESTABLISHED
*                   (d) FIN-WAIT-1
*                   (e) CLOSING
*                   (f) CLOSE-WAIT
*                   (g) LAST-ACK
*
*
* Argument(s) : pconn       Pointer to a TCP connection.
*               -----       Argument validated in NetTCP_RxPktConnHandlerReTxQ().
*
* Return(s)   : none.
*
* Caller(s)   : NetTCP_RxPktConnHandlerReTxQ().
*
* Note(s)     : (2) (a) RFC #2581, Section 4.1 states that "after TCP has been idle for a relatively long period
*                       of time ... use slow start to restart transmission" :
*
*                       (1) "If the TCP has not sent data in an interval exceeding the retransmission timeout" ...
*                       (2) "cwnd is reduced to ... no more than ... the value of the restart window."
*
*                       See also 'NetTCP_TxConnTxQ_TimeoutIdle()  Note #2a'.
*
*                   (b) However, if NO network timer is available to time the transmit queue idle interval, the
*                       TCP connection SHOULD be immediately slow started.
*********************************************************************************************************
*/

static  void  NetTCP_TxConnTxQ_TimeoutIdleSet (NET_TCP_CONN  *pconn)
{
#if ((NET_CTR_CFG_ERR_EN      == DEF_ENABLED)                    && \
     (CPU_CFG_CRITICAL_METHOD == CPU_CRITICAL_METHOD_STATUS_LOCAL))
    CPU_SR        cpu_sr;
#endif
    NET_TMR_TICK  timeout_tick;
    NET_ERR       err;


/*$PAGE*/
                                                                        /* ------------ VALIDATE TCP CONN ------------- */
    switch (pconn->ConnState) {
        case NET_TCP_CONN_STATE_FREE:
             NET_CTR_ERR_INC(NetTCP_ErrNotUsedCtr);
             return;                                                    /* Prevent 'break NOT reachable' warning.       */


        case NET_TCP_CONN_STATE_CLOSED:
        case NET_TCP_CONN_STATE_LISTEN:
        case NET_TCP_CONN_STATE_FIN_WAIT_2:
        case NET_TCP_CONN_STATE_TIME_WAIT:
        case NET_TCP_CONN_STATE_CLOSING_DATA_AVAIL:
             NET_CTR_ERR_INC(NetTCP_ErrConnInvalidOpCtr);
             return;                                                    /* Prevent 'break NOT reachable' warning.       */


        case NET_TCP_CONN_STATE_SYNC_RXD:                               /* See Note #1a.                                */
        case NET_TCP_CONN_STATE_SYNC_RXD_PASSIVE:
        case NET_TCP_CONN_STATE_SYNC_RXD_ACTIVE:
        case NET_TCP_CONN_STATE_SYNC_TXD:                               /* See Note #1b.                                */
             switch (pconn->TxQ_State) {
                 case NET_TCP_TX_Q_STATE_CONN_CLOSED:
                      break;


                 case NET_TCP_TX_Q_STATE_NONE:
                 case NET_TCP_TX_Q_STATE_CLOSED:
                 case NET_TCP_TX_Q_STATE_CONN:
                 case NET_TCP_TX_Q_STATE_CONN_CLOSING:
                 case NET_TCP_TX_Q_STATE_CONN_SUSPEND:
                 default:
                      return;                                           /* Prevent 'break NOT reachable' warning.       */
             }
             break;


        case NET_TCP_CONN_STATE_CONN:                                   /* See Note #1c.                                */
        case NET_TCP_CONN_STATE_FIN_WAIT_1:
        case NET_TCP_CONN_STATE_CLOSING:
        case NET_TCP_CONN_STATE_CLOSE_WAIT:
        case NET_TCP_CONN_STATE_LAST_ACK:
             switch (pconn->TxQ_State) {
                 case NET_TCP_TX_Q_STATE_CONN:
                 case NET_TCP_TX_Q_STATE_CONN_CLOSING:
                 case NET_TCP_TX_Q_STATE_CONN_SUSPEND:
                      break;


                 case NET_TCP_TX_Q_STATE_NONE:
                 case NET_TCP_TX_Q_STATE_CLOSED:
                 case NET_TCP_TX_Q_STATE_CONN_CLOSED:
                 default:
                      return;                                           /* Prevent 'break NOT reachable' warning.       */
             }
             break;


        case NET_TCP_CONN_STATE_NONE:
        default:
             NET_CTR_ERR_INC(NetTCP_ErrConnInvalidStateCtr);
             return;                                                    /* Prevent 'break NOT reachable' warning.       */
    }


                                                                        /* ------ START TCP CONN TX Q IDLE TMR  ------- */
    timeout_tick = pconn->TxRTT_RTO_tick;                               /* Tx Q idle timeout = RTO (see Note #2a1).     */
    if (pconn->TxQ_IdleTmr == (NET_TMR *)0) {                           /* If       tx Q idle tmr NOT avail, ...        */
        pconn->TxQ_IdleTmr  =  NetTmr_Get((void       *) pconn,         /* ...  get tx Q idle tmr.                      */
                                          (CPU_FNCT_PTR) NetTCP_TxConnTxQ_TimeoutIdle,
                                          (NET_TMR_TICK) timeout_tick,
                                          (CPU_INT16U  ) NET_TMR_FLAG_NONE,
                                          (NET_ERR    *)&err);
    } else {                                                            /* Else set tx Q idle tmr.                      */
        NetTmr_Set((NET_TMR    *) pconn->TxQ_IdleTmr,
                   (CPU_FNCT_PTR) NetTCP_TxConnTxQ_TimeoutIdle,
                   (NET_TMR_TICK) timeout_tick,
                   (NET_ERR    *)&err);
    }

    if (err != NET_TMR_ERR_NONE) {                                      /* If any err(s), ...                           */
                                                                        /* ... reset tx win ctrls (see Note #2b).       */
        NetTCP_TxConnWinSizeHandlerCongCtrl((NET_TCP_CONN   *) pconn,
                                            (NET_BUF_HDR    *) 0,
                                            (NET_TCP_ACK_CODE) NET_TCP_CONN_RX_ACK_NONE,
                                            (NET_TCP_WIN_SIZE) 0,
                                            (NET_TCP_WIN_CODE) NET_TCP_CONN_TX_WIN_RESET,
                                            (NET_ERR        *)&err);
    }
}


/*$PAGE*/
/*
*********************************************************************************************************
*                                  NetTCP_TxConnTxQ_TimeoutIdleClr()
*
* Description : (1) Clear TCP connection's transmit queue idle timer for the following states :
*
*                   (a) ESTABLISHED
*                   (b) FIN-WAIT-1
*                   (c) CLOSING
*                   (d) CLOSE-WAIT
*                   (e) LAST-ACK
*
*
* Argument(s) : pconn       Pointer to a TCP connection.
*               -----       Argument validated in NetTCP_TxConnTxQ().
*
* Return(s)   : none.
*
* Caller(s)   : NetTCP_TxConnTxQ().
*
* Note(s)     : (2) (a) RFC #2581, Section 4.1 states that "after TCP has been idle for a relatively long period
*                       of time ... use slow start to restart transmission" :
*
*                       (1) "If the TCP has not sent data in an interval exceeding the retransmission timeout" ...
*                       (2) "cwnd is reduced to ... no more than ... the value of the restart window."
*
*                       See also 'NetTCP_TxConnTxQ_TimeoutIdle()  Note #2a'.
*
*                   (b) (1) However, if the TCP connection's re-transmit queue is NOT empty, then TCP data has
*                           has been transmitted & is awaiting acknowledgement.
*
*                       (2) Therefore, NO transmit queue idle timeout is currently needed.
*********************************************************************************************************
*/
/*$PAGE*/
static  void  NetTCP_TxConnTxQ_TimeoutIdleClr (NET_TCP_CONN  *pconn)
{
#if ((NET_CTR_CFG_ERR_EN      == DEF_ENABLED)                    && \
     (CPU_CFG_CRITICAL_METHOD == CPU_CRITICAL_METHOD_STATUS_LOCAL))
    CPU_SR       cpu_sr;
#endif
    CPU_BOOLEAN  tmr_free;


                                                                        /* ------------ VALIDATE TCP CONN ------------- */
    switch (pconn->ConnState) {
        case NET_TCP_CONN_STATE_FREE:
             NET_CTR_ERR_INC(NetTCP_ErrNotUsedCtr);
             return;                                                    /* Prevent 'break NOT reachable' warning.       */


        case NET_TCP_CONN_STATE_CLOSED:
        case NET_TCP_CONN_STATE_LISTEN:
        case NET_TCP_CONN_STATE_SYNC_RXD:
        case NET_TCP_CONN_STATE_SYNC_RXD_PASSIVE:
        case NET_TCP_CONN_STATE_SYNC_RXD_ACTIVE:
        case NET_TCP_CONN_STATE_SYNC_TXD:
        case NET_TCP_CONN_STATE_FIN_WAIT_2:
        case NET_TCP_CONN_STATE_TIME_WAIT:
        case NET_TCP_CONN_STATE_CLOSING_DATA_AVAIL:
             NET_CTR_ERR_INC(NetTCP_ErrConnInvalidOpCtr);
             return;                                                    /* Prevent 'break NOT reachable' warning.       */


        case NET_TCP_CONN_STATE_CONN:                                   /* See Note #1.                                 */
        case NET_TCP_CONN_STATE_FIN_WAIT_1:
        case NET_TCP_CONN_STATE_CLOSING:
        case NET_TCP_CONN_STATE_CLOSE_WAIT:
        case NET_TCP_CONN_STATE_LAST_ACK:
             switch (pconn->TxQ_State) {
                 case NET_TCP_TX_Q_STATE_CONN:
                 case NET_TCP_TX_Q_STATE_CONN_CLOSING:
                 case NET_TCP_TX_Q_STATE_CONN_SUSPEND:
                      break;


                 case NET_TCP_TX_Q_STATE_NONE:
                 case NET_TCP_TX_Q_STATE_CLOSED:
                 case NET_TCP_TX_Q_STATE_CONN_CLOSED:
                 default:
                      return;                                           /* Prevent 'break NOT reachable' warning.       */
             }
             break;


        case NET_TCP_CONN_STATE_NONE:
        default:
             NET_CTR_ERR_INC(NetTCP_ErrConnInvalidStateCtr);
             return;                                                    /* Prevent 'break NOT reachable' warning.       */
    }


                                                                        /* ------- CLR TCP CONN TX Q IDLE TMR  -------- */
    tmr_free = (pconn->ReTxQ_Head != (NET_BUF *)0) ? DEF_YES : DEF_NO;

    if (tmr_free == DEF_YES) {                                          /* If re-tx Q NOT empty   (see Note #2b1), ...  */
        if (pconn->TxQ_IdleTmr != (NET_TMR *)0) {
            NetTmr_Free(pconn->TxQ_IdleTmr);                            /* ... free tx Q idle tmr (see Note #2b2).      */
            pconn->TxQ_IdleTmr  = (NET_TMR *)0;
        }
    }
}


/*$PAGE*/
/*
*********************************************************************************************************
*                                 NetTCP_TxConnTxQ_TimeoutSillyWin()
*
* Description : (1) (a) Handle TCP connection's transmit queue silly window timeout ... :
*
*                       (1) Clear    TCP connection's transmit silly window persist timer   See Note #4aA1
*                       (2) Transmit TCP connection's transmit data                         See Note #2
*
*                   (b) ... for the following states :
*
*                       (1) ESTABLISHED
*                       (2) FIN-WAIT-1
*                       (3) CLOSING
*                       (4) CLOSE-WAIT
*                       (5) LAST-ACK
*
*
* Argument(s) : pconn_timeout       Pointer to TCP connection (see Note #3b).
*
* Return(s)   : none.
*
* Caller(s)   : Referenced in NetTCP_TxConnTxQ().
*
* Note(s)     : (2) RFC #1122, Section 4.2.3.4 states that on "timeout ... force transmission of data,
*                   overriding the SWS avoidance algorithm".
*
*                   See also 'NetTCP_TxConnTxQ()  Note #7b2Bb'.
*
*               (3) Ideally, network timer expiration functions could be defined as '[(void) (OBJECT *)]' 
*                   type functions -- even though network timer API functions cast expiration functions 
*                   to generic 'CPU_FNCT_PTR' type (i.e. '[(void) (void *)]').
*
*                   (a) (1) Unfortunately, ISO-IEC 9899-1999 ANSI-C, Section 6.3.2.3.7 states that "a 
*                           pointer to an object ... may be converted to a pointer to a different object 
*                           ... [but] if the resulting pointer is not correctly aligned ... the behavior
*                           is undefined".
*
*                           And since compilers may NOT correctly convert 'void' pointers to non-'void' 
*                           pointer arguments, network timer expiration functions MUST avoid incorrect
*                           pointer conversion behavior between 'void' pointer parameters & non-'void' 
*                           pointer arguments & therefore CANNOT be defined as '[(void) (OBJECT *)]'.
*
*                       (2) However, Section 6.3.2.3.1 states that "a pointer to void may be converted 
*                           to or from a pointer to any ... object ... A pointer to any ... object ... 
*                           may be converted to a pointer to void and back again; the result shall 
*                           compare equal to the original pointer".
*                   
*                   (b) Therefore, to correctly convert 'void' pointer objects back to appropriate
*                       network object pointer objects, network timer expiration functions MUST :
*
*                       (1) Be defined as 'CPU_FNCT_PTR' type (i.e. '[(void) (void *)]'); &       ...
*                       (2) Explicitly cast 'void' pointer arguments to specific object pointers; ...
*                           (A) ... in this case, a 'NET_TCP_CONN' pointer.
*
*                   See also 'net_tmr.c  NetTmr_Get()  Note #3'.
*
*               (4) This function is a network timer expiration function :
*
*                   (a) (1) For the following connection timer(s) ... :
*
*                           (A) TCP connection transmit silly window persist timer ('TxQ_SillyWinTmr')
*
*                       (2) (A) Clear the timer pointer; ...
*                               (1) Cleared prior to next handler function(s) as an extra precaution to
*                                   avoiding re-freeing the timer (see Note #4a2B).
*
*                           (B) but do NOT re-free the timer.
*
*                   (b) Do NOT set the following close timer flag(s) :
*
*                       (1) NET_TCP_CONN_CLOSE_TMR_TX_SILLY_WIN
*
*               (5) Certain network connections MUST periodically suspend network transmit(s) to handle
*                   network receive packet(s).  To protect TCP connections from transmit corruption while
*                   suspended, ALL TCP data transmits & TCP transmit queue handling MUST be blocked for
*                   suspended connections until the connection is no longer suspended.
*
*                   (a) The transmit queue silly window timeout is re-configured with one timer tick to
*                       ensure that a non-zero delay is implemented.
*
*                   (b) If NO timer is available, a TCP connection will NOT be able to re-schedule the
*                       transmission of its TCP transmit queue data.  Thus, the TCP transmit queue data
*                       will be delayed until triggered by any received acknowledgement packets or by
*                       additional data transmits from the applications layer.
*
*                   See also 'NetTCP_TxConnTxQ()                    Note #10b2A2',
*                            'NetTCP_TxConnTxQ_TimeoutIdle()        Note #5',
*                            'NetTCP_TxConnReTxQ_Timeout()          Note #5',
*                          & 'NetTCP_TxConnWinSizeZeroWinTimeout()  Note #5'.
*********************************************************************************************************
*/
/*$PAGE*/
static  void  NetTCP_TxConnTxQ_TimeoutSillyWin (void  *pconn_timeout)
{
#if ((NET_CTR_CFG_ERR_EN      == DEF_ENABLED)                    && \
     (CPU_CFG_CRITICAL_METHOD == CPU_CRITICAL_METHOD_STATUS_LOCAL))
    CPU_SR               cpu_sr;
#endif
    NET_TCP_CONN        *pconn;
    NET_TCP_CLOSE_CODE   close_code;
    NET_TMR_TICK         timeout_tick;
    NET_ERR              err;


    pconn      = (NET_TCP_CONN *)pconn_timeout;                     /* See Note #3b2A.                                  */

    close_code =  NET_TCP_CONN_CLOSE_ALL;
    DEF_BIT_CLR(close_code, NET_TCP_CONN_CLOSE_TMR_TX_SILLY_WIN);   /* See Note #4b1.                                   */


                                                                    /* -------------- VALIDATE TCP CONN --------------- */
#if (NET_ERR_CFG_ARG_CHK_DBG_EN == DEF_ENABLED)
    if (pconn == (NET_TCP_CONN *)0) {
        NET_CTR_ERR_INC(NetTCP_ErrNullPtrCtr);
        return;
    }

    if (pconn->Type != NET_TCP_TYPE_CONN) {
        NET_CTR_ERR_INC(NetTCP_ErrConnInvalidTypeCtr);
        return;
    }
#endif

    switch (pconn->ConnState) {
        case NET_TCP_CONN_STATE_FREE:
             NET_CTR_ERR_INC(NetTCP_ErrNotUsedCtr);
             return;                                                /* Prevent 'break NOT reachable' compiler warning.  */


        case NET_TCP_CONN_STATE_CLOSED:
        case NET_TCP_CONN_STATE_LISTEN:
        case NET_TCP_CONN_STATE_SYNC_RXD:
        case NET_TCP_CONN_STATE_SYNC_RXD_PASSIVE:
        case NET_TCP_CONN_STATE_SYNC_RXD_ACTIVE:
        case NET_TCP_CONN_STATE_SYNC_TXD:
        case NET_TCP_CONN_STATE_FIN_WAIT_2:
        case NET_TCP_CONN_STATE_TIME_WAIT:
        case NET_TCP_CONN_STATE_CLOSING_DATA_AVAIL:
             NET_CTR_ERR_INC(NetTCP_ErrConnInvalidOpCtr);
             return;                                                /* Prevent 'break NOT reachable' compiler warning.  */


        case NET_TCP_CONN_STATE_CONN:                               /* See Note #1.                                     */
        case NET_TCP_CONN_STATE_FIN_WAIT_1:
        case NET_TCP_CONN_STATE_CLOSING:
        case NET_TCP_CONN_STATE_CLOSE_WAIT:
        case NET_TCP_CONN_STATE_LAST_ACK:
             switch (pconn->TxQ_State) {
                 case NET_TCP_TX_Q_STATE_CONN:
                 case NET_TCP_TX_Q_STATE_CONN_CLOSING:
                      break;


                 case NET_TCP_TX_Q_STATE_CONN_SUSPEND:              /* See Note #5.                                     */
                      timeout_tick           = (NET_TMR_TICK)1;     /* See Note #5a.                                    */
                      pconn->TxQ_SillyWinTmr =  NetTmr_Get((void       *) pconn,
                                                           (CPU_FNCT_PTR) NetTCP_TxConnTxQ_TimeoutSillyWin,
                                                           (NET_TMR_TICK) timeout_tick,
                                                           (CPU_INT16U  ) NET_TMR_FLAG_NONE,
                                                           (NET_ERR    *)&err);
                     (void)err;                                     /* Ignore transitory rsrc err(s) [see Note #5b].    */
                      return;                                       /* Prevent 'break NOT reachable' compiler warning.  */


                 case NET_TCP_TX_Q_STATE_NONE:
                 case NET_TCP_TX_Q_STATE_CLOSED:
                 case NET_TCP_TX_Q_STATE_CONN_CLOSED:
                 default:
                      return;                                       /* Prevent 'break NOT reachable' compiler warning.  */
             }
             break;


        case NET_TCP_CONN_STATE_NONE:
        default:
             NetTCP_ConnClose((NET_TCP_CONN     *)pconn,
                              (NET_BUF_HDR      *)0,
                              (CPU_BOOLEAN       )DEF_YES,
                              (NET_TCP_CLOSE_CODE)close_code);
             NET_CTR_ERR_INC(NetTCP_ErrConnInvalidStateCtr);
             return;                                                /* Prevent 'break NOT reachable' compiler warning.  */
    }


/*$PAGE*/
                                                                    /* ---- HANDLE TCP CONN TX Q SILL WIN TIMEOUT ----- */
    pconn->TxQ_SillyWinTmr = (NET_TMR *)0;                          /* Clr tx Q silly win tmr (see Note #4a2A1).        */

    NetTCP_TxConnTxQ((NET_TCP_CONN     *) pconn,                    /*     Tx Q data          (see Note #2).            */
                     (NET_BUF_HDR      *) 0,
                     (NET_TCP_ACK_CODE  ) NET_TCP_CONN_TX_ACK_NONE,
                     (CPU_BOOLEAN       ) DEF_YES,
                     (NET_TCP_CLOSE_CODE) close_code,
                     (NET_ERR          *)&err);                     /* Ignore ALL tx err(s), transitory or fatal.       */

}


/*$PAGE*/
/*
*********************************************************************************************************
*                                        NetTCP_TxConnReTxQ()
*
* Description : (1) Re-transmit TCP data segment(s) from TCP connection re-transmit queue :
*
*                   (a) Update TCP connection :
*                       (1) Update     TCP connection's re-transmit queue timeout :
*                           (A) Update TCP connection's re-transmit queue timer             See Note #2b
*                           (B) Reset  TCP connection's    transmit round-trip time         See Note #2b2A2
*                                   controls
*                       (2) Update     TCP connection's    transmit congestion controls :
*                           (A) Update TCP connection's transmit congestion window          See Note #5
*                           (B) Reset  TCP connection's delayed acknowledgement controls    See Note #6
*
*                   (b) Prepare TCP segment re-transmit :
*                       (1) Prepare unchanged TCP segment for re-transmit                   See Note #7
*
*                       (2) Prepare updated   TCP segment for re-transmit :
*                           (A) TCP segment   sequence numbers
*                           (B) TCP segment   window size
*                           (C) TCP segment   addresses
*                           (D) TCP segment   transmit flags
*                           (E) IP  datagram  parameters
*                           (F) Update TCP    segment's last transmit values :
*                               (1) Sequence        Number
*                               (2) Acknowledgement Number
*                               (3) Segment Length
*                               (4) Window  Size
*                           (G) Unlink TCP segment packet buffer from any other network layer(s)
*                           (H) Update TCP segment packet buffer controls
*
*                   (c) Re-transmit TCP segment                                             See Note #2a
*
*
* Argument(s) : pconn               Pointer to a TCP connection.
*               -----               Argument validated in NetTCP_TxConnReTxQ_Timeout(),
*                                                         NetTCP_TxConnWinSizeHandlerCongCtrl().
*
*               re_tx_q_timeout     Indicate whether the TCP connection re-transmit queue timed out :
*
*                                       DEF_NO                      TCP connection re-transmit queue did
*                                                                       NOT time  out.
*                                       DEF_YES                     TCP connection re-transmit queue
*                                                                           timed out.
*
*               close_code      Select which close action(s) to perform; bit-field flags logically OR'd :
*
*                                   NET_TCP_CONN_CLOSE_NONE                 Perform NO  close actions.
*                                   NET_TCP_CONN_CLOSE_ALL                  Perform ALL close actions.
*
*                                   NET_TCP_CONN_CLOSE_CONN_TX_RESET        Perform close connection transmit reset.
*                                   NET_TCP_CONN_CLOSE_CONN_ALL             Perform ALL   connection close    actions.
*
*                                   NET_TCP_CONN_CLOSE_TMR_TX_IDLE          Close    transmit idle                  timer.
*                                   NET_TCP_CONN_CLOSE_TMR_TX_SILLY_WIN     Close    transmit silly window persist  timer.
*                                   NET_TCP_CONN_CLOSE_TMR_TX_ZERO_WIN      Close    transmit zero  window persist  timer.
*                                   NET_TCP_CONN_CLOSE_TMR_TX_ACK_DLY       Close    transmit acknowledgement delay timer.
*                                   NET_TCP_CONN_CLOSE_TMR_RE_TX            Close re-transmit                       timer.
*                                   NET_TCP_CONN_CLOSE_TMR_KEEP_ALIVE       Close connection keep-alive             timer.
*                                   NET_TCP_CONN_CLOSE_TMR_TIMEOUT          Close connection                        timer.
*                                   NET_TCP_CONN_CLOSE_TMR_ALL              Close ALL                               timers.
*
*                               See also 'TCP CONNECTION CLOSE/FREE CODE DEFINES'.
*
*               perr        Pointer to variable that will receive the return error code from this function :
*
*                               NET_TCP_ERR_NONE                    TCP connection re-transmit queue successfully handled.
*                               NET_TCP_ERR_RE_TX_SEG_TH            TCP connection closed due to excessive retransmission.
*
*                                                                   --- RETURNED BY NetTCP_TxConnReTxQ_TimeoutSet() : ----
*                               NET_TCP_ERR_CONN_NOT_USED           TCP connection NOT currently used.
*                               NET_TCP_ERR_CONN_FAULT              TCP connection fault; connection(s) aborted.
*                               NET_TCP_ERR_INVALID_CONN_STATE      Invalid TCP connection state.
*                               NET_TCP_ERR_INVALID_CONN_OP         Invalid TCP connection operation.
*
*                                                                   -------- RETURNED BY NetTCP_TxPktHandler() : ---------
*                                                                   ------------- RETURNED BY NetIP_ReTx() : -------------
*                               NET_ERR_INIT_INCOMPLETE             Network initialization NOT complete.
*                               NET_ERR_TX                          Transmit error.
*
*                                                                   -------- RETURNED BY NetTCP_TxPktHandler() : ---------
*                               NET_TCP_ERR_TX                      TCP transmit error (see Note #11a).
*
* Return(s)   : none.
*
* Caller(s)   : NetTCP_TxConnReTxQ_Timeout(),
*               NetTCP_TxConnWinSizeHandlerCongCtrl().
*$PAGE*
* Note(s)     : (2) RFC #793, Section 3.9 'Event Processing : USER TIMEOUT : RETRANSMISSION TIMEOUT'
*                   states that "for any state if the retransmission timeout expires on a segment in
*                   the retransmission queue" :
*
*                       (A) RFC #1122, Section 4.2.3.1 reiterates that "retransmission of SYN segments
*                           SHOULD use the same algorithm as data segments".
*
*                   (a) "Send the segment at the front of the retransmission queue."
*
*                           (A) RFC #2988, Section 5.4 reiterates that "when the retransmission timer
*                               expires ... retransmit the earliest segment that has not been acknowledged
*                               by the TCP receiver".
*
*                       (1) RFC #1122, Section 4.2.2.16 states that "a TCP receiver SHOULD NOT shrink the
*                           window ... However, a sending TCP MUST be robust against window shrinking ...
*                           If this happens, the sender SHOULD NOT send new data, but SHOULD retransmit
*                           normally the old unacknowledged data between SND.UNA and SND.UNA+SND.WND.  The
*                           sender MAY also retransmit old data beyond SND.UNA+SND.WND, but SHOULD NOT time
*                           out the connection if data beyond the right window edge is not acknowledged".
*
*                           Therefore, ALL data segments previously transmitted & awaiting acknowledgement
*                           in a TCP connections' re-transmit queue may be re-transmitted regardless of the
*                           TCP connection's current transmit congestion control window size or the remote
*                           host's receive window size.
*
*                       (2) (A) RFC #2581, Section 3.2 states that "the fast retransmit algorithm uses the
*                               arrival of 3 duplicate ACKs ... as an indication that a segment has been
*                               lost ... [and] performs a retransmission of what appears to be the missing
*                               segment".
*
*                           (B) RFC #1122, Section 4.2.2.21 reiterates that "'fast retransmit' ... uses the
*                               redundant ACK's to deduce that a segment has been lost ... If more than a
*                               threshold number of such ACK's is received, then the segment containing the
*                               octets starting at SEG.ACK is assumed to have been lost and is retransmitted".
*
*                   (b) "Reinitialize the retransmission timer."
*
*                       (1) RFC #2988, Section 5 states that "an implementation MUST manage the retransmission
*                           timer(s) in such a way that a segment is never retransmitted too early, i.e. less
*                           than one RTO after the previous transmission of that segment".
*
*                           (A) "The following is the RECOMMENDED algorithm for managing the retransmission
*                                timer" :
*
*                               (1) "Every time a packet containing data is sent (including a retransmission),
*                                    if the timer is not running, start it running so that it will expire after
*                                    RTO seconds (for the current value of RTO)."
*
*                                    Therefore, the TCP connection re-transmit queue timer is reset whenever a
*                                    segment is re-transmitted.
*
*                               (2) "When all outstanding data has been acknowledged, turn off the retransmission
*                                    timer."
*
*                               (3) "When an ACK is received that acknowledges new data, restart the retransmission
*                                    timer so that it will expire after RTO seconds (for the current value of RTO)."
*
*                           (B) "When the retransmission timer expires, do the following" :
*
*                               (5) "The host MUST set RTO <- RTO * 2 ('back off the timer')."
*
*                                    See also Note #2b2A1.
*
*                               (6) "Start the retransmission timer, such that it expires after RTO seconds
*                                    (for the value of RTO after the doubling operation)."
*$PAGE*
*                       (2) (A) (1) RFC #1122, Section 4.2.3.1 reiterates that an "implementation MUST also
*                                   include 'exponential backoff' for successive RTO values for the same
*                                   segment".
*
*                                   (a) RFC #2988, Section 5.5 states that "when the retransmission timer
*                                       expires ... the host MUST set RTO <- RTO * 2 ('back off the timer')".
*
*                                       Thus, the TCP retransmission timer exponential back-off scalar
*                                       value is 2.
*
*                                   (b) Stevens, TCP/IP Illustrated, Volume 1, 8th Printing, Section 21.2,
*                                       Page 299 reiterates that "this doubling is called an 'exponential
*                                       backoff'".
*
*                                   See also 'NetTCP_TxConnRTT_RTO_Calc()  Note #2b2'.
*
*                               (2) RFC #2988, Section 5 adds "that a TCP implementation MAY clear SRTT [TCP
*                                   smoothed round-trip time] and RTTVAR [TCP round-trip time variance] after
*                                   backing off the timer multiple times as it is likely that the current SRTT
*                                   and RTTVAR are bogus in this situation.  Once SRTT and RTTVAR are cleared
*                                   they should be initialized with the next RTT sample taken".
*
*                                   See also 'NetTCP_TxConnRTT_RTO_Calc()  Note #2a4A'.
*
*                           (B) (1) (a) RFC #2581, Section 3.2 states that "after receiving 3 duplicate ACKs
*                                       ... the fast retransmit algorithm ... performs a retransmission of
*                                       what appears to be the missing segment, without waiting for the
*                                       retransmission timer to expire".
*
*                                   (b) RFC #1122, Section 4.2.2.21 reiterates that with "'fast retransmit' ...
*                                       the [lost] segment ... is retransmitted, without awaiting a timeout".
*
*                               (2) If a segment is re-transmitted due to the TCP fast re-transmit algorithm
*                                   & NOT due to the TCP connection's re-transmit queue timer expiring, the
*                                   TCP connection's re-transmit queue timer is :
*
*                                   (a) NOT backed-off because the re-transmit queue        See Note #2b1B
*                                           timer did NOT expire
*                                   (b) Restarted with its current RTO value                See Note #2b1A1
*
*               (3) RFC #1122, Section 4.2.3.5 states that "excessive retransmission of the same segment
*                   by TCP indicates some failure of the remote host or the Internet path ... The following
*                   procedure MUST be used to handle excessive retransmissions of data segments" :
*
*                   (c) "When the number of transmissions of the same segment reaches a threshold ...
*                        close the connection."
*
*                   See also 'NetTCP_RxPktConnHandlerReTxQ()  Note #7'.
*
*               (4) RFC #2988, Section 3 states that "TCP MUST use Karn's algorithm ... for taking RTT samples.
*                   That is, RTT samples MUST NOT be made using segments that were retransmitted (and thus for
*                   which it is ambiguous whether the reply was for the first instance of the packet or a later
*                   instance)".
*
*                   (a) To ensure implementation of Karn's algorithm, while ANY re-transmitted segment(s)
*                       remain unacknowledged in a TCP connection's re-transmit queue :
*
*                       (1) (A) NO RTT calculations are performed; ...                      See Note #4
*
*                           (B) The TCP connection's re-transmit timeout :
*                               (1) MAY be backed-off ...                                   See Note #2b1B5
*                                     OR
*                               (2) MAY be latched at a previously backed-off value;        See Note #2b1B6
*                                     BUT
*                               (3) MUST NOT be updated by RTT calculations.                See Note #4a1A
*
*                       (2) Each time a TCP connection re-transmits a segment, the TCP connection advances
*                           its un-re-transmitted sequence number to the TCP connection's next sequence
*                           number to transmit.  This ensures that NO RTT or RTO calculations are performed
*                           until ALL re-transmitted data is acknowledged & remove from the TCP connection's
*                           re-transmit queue.
*
*               (5) RFC #2581, Section 3.1 states that "when a TCP sender detects segment loss using the
*                   retransmission timer, the value of ssthresh [TCP transmit congestion control slow start
*                   threshold] ... [and] cwnd [TCP transmit congestion control window] MUST be set".
*
*                   See also 'NetTCP_TxConnWinSizeHandlerCongCtrl()  Notes #2c2A5a & #2c2A5b'.
*
*               (6) A TCP connection's delayed acknowledgement controls :
*
*                   (a) SHOULD be reset whenever a TCP connection re-transmits data segment(s) since
*                           any re-transmit always transmits an accompanying acknowledgement;
*                   (b) MAY    be reset whenever a TCP connection re-transmits a connection request
*                           segment since NO delayed acknowledgement controls should be active.
*
*                   See also 'NetTCP_TxConnAckDlyReset()  Note #1'.
*$PAGE*
*               (7) RFC #1122, Section 4.2.2.15 states that "if a retransmitted packet is identical to the
*                   original packet (which implies not only that the data boundaries have not changed, but
*                   also that the window and acknowledgment fields of the header have not changed), then
*                   the same IP Identification field MAY be used".
*
*                   In other words, if the following TCP segment header values are unchanged since the
*                   last transmission of the TCP segment, then the TCP segment may be transmitted without
*                   re-calculation of the TCP header :
*
*                       (a) Sequence        Number
*                       (b) Acknowledgement Number
*                       (c) Segment Length
*                       (d) Window  Size
*
*               (8) (a) Some network interfaces require a minimum packet size & may also require that
*                       packets smaller than the minimum packet size be appended with trailing pad
*                       octets.  Therefore, all network transmit packets MUST be prepared to satisfy
*                       a possible network interface minimum packet size requirement.
*
*                   (b) To ensure that TCP re-transmit segments will be properly prepared to satisfy
*                       a network interface minimum packet size requirement, the following equations
*                       are used to validate a TCP re-transmit segment size :
*
*                           (A) (1) TCP Re-transmit Segment Size  =  Segment's Re-transmit Protocol Header Sizes +
*                                                                    Segment's Remaining   Segment  Data   Size
*
*                               (2)                               =  Segment's Previous    Protocol Header Sizes +
*                                                                    Segment's Remaining   Segment  Data   Size
*
*                               (3)                               = (Segment's Previous    Total    Packet Size  -
*                                                                    Segment's Previous             Data   Size) +
*                                                                    Segment's Remaining   Segment  Data   Size
*
*                           (B) (1) TCP Re-transmit Minimum Segment Size         =  Network Interface Minimum Packet Size
*
*                               (2) [(Segment's          Total   Packet Size  -
*                                     Segment's                  Data   Size) +
*                                     Segment's Minimum  Segment Data   Size ]   =  Network Interface Minimum Packet Size
*
*                               (3)   Segment's Minimum  Segment Data   Size     =  Network Interface Minimum Packet Size  -
*                                                                                  (Segment's         Total   Packet Size  -
*                                                                                   Segment's                 Data   Size)
*
*                       (1) Equation #8bA2 subtly assumes that the TCP re-transmit segment's network
*                           protocol header sizes equal the segment's previously transmitted network
*                           protocol header sizes.  In other words, it is assumed that a TCP transmit
*                           segment's network protocol header sizes will remain constant for the
*                           segment's initial transmission & any subsequent retransmissions.
*
*                           This assumption is true if & only if the TCP segment is re-transmitted
*                           with no changes in any of the segment's network protocol header sizes,
*                           which typically vary only for changes in the network protocol header
*                           types or in the number of network protocol header options.
*
*                           #### However, since TCP segments that have already been transmitted can
*                           NOT modify their segment data (see 'NetTCP_TxConnAppData()  Note #10a'),
*                           it seems reasonable that TCP segments that have already been transmitted
*                           will NOT likely modify their network protocol header types & SHOULD NOT
*                           modify their network protocol header options.
*
*                           #### Therefore, it seems reasonable that TCP segments that have already
*                           been transmitted will NOT likely vary their network protocol header sizes.
*                           Thus, TCP segments may validate their re-transmit segment size versus any
*                           possible network interface minimum packet size requirement based on their
*                           previously transmitted network protocol header & packet sizes.
*
*                       (2) (A) Equation #8bB calculates a TCP re-transmit segment's minimum data size
*                               as required by a possible network interface minimum packet size.  If
*                               the TCP re-transmit segment's data size is smaller than the network
*                               interface minimum packet size, the network buffer MUST be checked for
*                               sufficient & available trailing octets, as required by the network
*                               interface layer to append pad octets.
*
*                           (B) (1) (a) (1) If the TCP re-transmit segment's minimum data size is smaller
*                                           than the required network interface minimum packet size ...
*                                             AND
*                                       (2) there is insufficient network buffer octets available for
*                                           the network interface layer to append pad octets, ...
*
*                                   (b) then the TCP segment's remaining data octets MUST be moved to
*                                       the network buffer's transmit index to provide sufficient
*                                       network buffer data octets for the network interface layer to
*                                       append pad octets.
*
*                               (2) A network interface that appends cleared trailing pad octets MAY be
*                                   optimized to skip clearing the trailing pad octets if the network
*                                   buffer's memory clear flag is set.  Since a partially-acknowledged
*                                   TCP segment's network buffer contains previously acknowledged data
*                                   octets, the network buffer's memory clear flag MUST be cleared to
*                                   ensure that the network interface layer clears the trailing pad
*                                   octets.
*$PAGE*
*               (9) If a packet buffer's unlink function is available, it is assumed that the function ...
*
*                   (a) Correctly unlinks the packet buffer from any other network protocol layers
*                         AND
*                   (b) Correctly updates the network buffer's reference counter to decrement the
*                       number of network protocol layers that no longer maintain a reference to
*                       the packet buffer.
*                         AND
*                   (c) Clears both the unlink function & object pointers.
*
*              (10) Increment network buffer's reference counter to include the TCP segment STILL enqueued
*                   to the TCP connection's re-transmit queue as a reference to the network buffer.
*
*              (11) (a) Since segments enqueued to a TCP connection's transmit queue have already been
*                       reported as transmitted to the application & since no mechanism exists for a TCP
*                       connection to re-request previously transmitted data, any TCP connection whose
*                       transmit queue(s) becomes corrupted MUST be closed to force the application layer
*                       to abort &/or recover from the corrupted data.
*
*                   (b) For any internal errors where the TCP connection's transmit queue is NOT corrupted,
*                       the TCP connection is NOT closed.
*
*                   See also 'NetTCP_TxConnAppData()  Note #10'
*                          & 'NetTCP_TxConnTxQ()      Note #12'.
*********************************************************************************************************
*/

static  void  NetTCP_TxConnReTxQ (NET_TCP_CONN        *pconn,
                                  CPU_BOOLEAN          re_tx_q_timeout,
                                  NET_TCP_CLOSE_CODE   close_code,
                                  NET_ERR             *perr)
{
#if ((NET_CTR_CFG_STAT_EN     == DEF_ENABLED)                    && \
     (CPU_CFG_CRITICAL_METHOD == CPU_CRITICAL_METHOD_STATUS_LOCAL))
    CPU_SR             cpu_sr;
#endif
    NET_BUF           *pseg;
    NET_BUF_HDR       *pseg_hdr;
    NET_IP_TOS         TOS;
    NET_IP_TTL         TTL;
    NET_IP_ADDR        src_addr;
    NET_IP_ADDR        dest_addr;
    NET_TCP_PORT_NBR   src_port;
    NET_TCP_PORT_NBR   dest_port;
    NET_TCP_SEQ_NBR    seq_nbr;
    NET_TCP_SEQ_NBR    ack_nbr;
    NET_TCP_SEG_SIZE   seg_len;
    NET_TCP_WIN_SIZE   win_size;
    NET_BUF_SIZE       seg_len_tot;
    NET_BUF_SIZE       seg_len_hdr;
    NET_BUF_SIZE       seg_len_data_min;
    NET_BUF_SIZE       buf_size_max;
    NET_BUF_SIZE       data_ix_cur;
    NET_BUF_SIZE       data_ix_re_tx;
    NET_BUF_SIZE       data_len_cur;
    CPU_INT16U         flags_tcp;
    CPU_INT16U         flags_ip;
    CPU_INT08U        *pdata_re_tx;
    CPU_FNCT_PTR       unlink_fnct;
    CPU_BOOLEAN        seg_chngd;
    CPU_BOOLEAN        seg_updated;
    CPU_BOOLEAN        seg_data_moved;
    NET_ERR            err;


/*$PAGE*/
                                                                /* ----------------- VALIDATE RE-TX Q ----------------- */
    if (pconn->ReTxQ_Head == (NET_BUF *)0) {
       *perr = NET_TCP_ERR_NONE;
        return;
    }

    pseg     =  pconn->ReTxQ_Head;                              /* Re-tx seg @ head of re-tx Q (see Note #2a).          */
    pseg_hdr = &pseg->Hdr;

    pseg_hdr->TCP_SegReTxCtr++;
    if (pseg_hdr->TCP_SegReTxCtr >= pconn->TxSegReTxTh) {       /* If nbr re-tx's >= th, close TCP conn (see Note #3).  */
        NetTCP_ConnClose((NET_TCP_CONN     *)pconn,
                         (NET_BUF_HDR      *)0,
                         (CPU_BOOLEAN       )pconn->ConnCloseAppFlag,
                         (NET_TCP_CLOSE_CODE)close_code);
       *perr = NET_TCP_ERR_RE_TX_SEG_TH;
        return;
    }


                                                                /* ----------------- UPDATE TCP CONN ------------------ */
    if (re_tx_q_timeout != DEF_NO) {                            /* If           re-tx Q timeout,                  ...   */
                                                                /* ... back-off re-tx Q timeout (see Note #2b1B5) ...   */
        NetTCP_TxConnRTT_RTO_Calc(pconn, NET_TCP_CONN_TX_RTT_BACKOFF, NET_TCP_TX_RTT_NONE, NET_TCP_TX_RTT_NONE);
#if 0                                                           /* Implemented with backoff     (see Note #2b2A2).      */
                                                                /* ... & reset RTT ctrls        (see Note #2b2A2).      */
        NetTCP_TxConnRTT_RTO_Calc(pconn, NET_TCP_CONN_TX_RTT_RESET,   NET_TCP_TX_RTT_NONE, NET_TCP_TX_RTT_NONE);
#endif
    }
                                                                /* Update re-tx Q tmr (see Note #2b1A1).                */
    NetTCP_TxConnReTxQ_TimeoutSet(pconn, re_tx_q_timeout, close_code, perr);
    if (*perr != NET_TCP_ERR_NONE) {
         return;
    }
                                                                /* Adv   un-re-tx'd seq(s) to ...                       */
    pconn->TxSeqNbrUnReTxd = pconn->TxSeqNbrNext;               /* ... not-yet-tx'd seq(s) [see Note #4a2].             */


    if (re_tx_q_timeout != DEF_NO) {                            /* If re-tx Q timeout, ...                              */
                                                                /* ... update tx cong win  (see Note #5).               */
        NetTCP_TxConnWinSizeHandlerCongCtrl((NET_TCP_CONN   *)pconn,
                                            (NET_BUF_HDR    *)0,
                                            (NET_TCP_ACK_CODE)NET_TCP_CONN_RX_ACK_NONE,
                                            (NET_TCP_WIN_SIZE)0,
                                            (NET_TCP_WIN_CODE)NET_TCP_CONN_TX_WIN_TIMEOUT,
                                            (NET_ERR        *)perr);
        if (*perr != NET_TCP_ERR_NONE) {
             return;
        }
    }

    NetTCP_TxConnAckDlyReset(pconn, DEF_YES);                   /* Reset ack dly ctrls (see Note #6).                   */


/*$PAGE*/
                                                                /* -------------- PREPARE TCP RE-TX SEG --------------- */
                                                                /* Prepare TCP seq nbrs.                                */
    seq_nbr     = (NET_TCP_SEQ_NBR )pseg_hdr->TCP_SeqNbr;
    ack_nbr     = (NET_TCP_SEQ_NBR )pconn->RxSeqNbrNext;

    seg_len     = (NET_TCP_SEG_SIZE)pseg_hdr->TCP_SegLen;
                                                                /* Prepare TCP win size.                                */
    win_size    = (NET_TCP_WIN_SIZE)pconn->RxWinSizeActual;

                                                                /* Chk for re-tx seg update (see Note #7).              */
    seg_updated = ((pseg_hdr->TCP_SeqNbrLast  != seq_nbr ) ||
                   (pseg_hdr->TCP_AckNbrLast  != ack_nbr ) ||
                   (pseg_hdr->TCP_SegLenLast  != seg_len ) ||
                   (pseg_hdr->TCP_WinSizeLast != win_size)) ? DEF_YES : DEF_NO;


    seg_data_moved =  DEF_NO;
    seg_len_tot    = (NET_BUF_SIZE)(pseg_hdr->TotLen        -   /* Seg cur tot len = prev'ly tx'd/ack'd pkt tot  len -  */
                                    pseg_hdr->DataLen       +   /* ...               prev'ly tx'd/ack'd pkt data len +  */
                                    pseg_hdr->TCP_SegLenData);  /* ...               rem'ing            seg data len    */
                                                                /* ... (see Note #8bA).                                 */
    if (seg_len_tot < NET_IF_PKT_SIZE_MIN) {                    /* If TCP re-tx seg tot len                         ... */
                                                                /* ...    < min IF pkt size (see Note #8b2B1a2),    ... */
                                                                /* ... calc min IF seg data len (see Note #8bB);    ... */
        seg_len_hdr      = pseg_hdr->TotLen      - pseg_hdr->DataLen;
        seg_len_data_min = NET_IF_FRAME_MIN_SIZE - seg_len_hdr;
        buf_size_max     = NetBuf_GetMaxSize((NET_BUF    *)pseg,
                                             (NET_BUF_SIZE)pseg_hdr->DataIx);
        if (seg_len_data_min > buf_size_max) {                  /* ... & if min IF seg data len                     ... */
                                                                /* ...    > max buf size       (see Note #8b2B1a2), ... */
            data_ix_cur   = (NET_BUF_SIZE) pseg_hdr->DataIx;
            data_ix_re_tx = (NET_BUF_SIZE) NET_BUF_DATA_TX_IX;
            data_len_cur  = (NET_BUF_SIZE) pseg_hdr->TCP_SegLenData;
            pdata_re_tx   = (CPU_INT08U *)&pseg->Data[data_ix_re_tx];

            NetBuf_DataRd((NET_BUF    *) pseg,                  /* ... rd rem'ing TCP seg data                      ... */
                          (NET_BUF_SIZE) data_ix_cur,
                          (NET_BUF_SIZE) data_len_cur,
                          (CPU_INT08U *) pdata_re_tx,           /* ... & move to base re-tx ix (see Note #8b2B1b).      */
                          (NET_ERR    *)&err);
            if (err != NET_BUF_ERR_NONE) {                      /* See Note #11a.                                       */
                NetTCP_ConnClose((NET_TCP_CONN     *)pconn,
                                 (NET_BUF_HDR      *)0,
                                 (CPU_BOOLEAN       )DEF_YES,
                                 (NET_TCP_CLOSE_CODE)close_code);
               *perr = NET_TCP_ERR_CONN_FAULT;
                return;
            }

            DEF_BIT_CLR(pseg_hdr->Flags, NET_BUF_FLAG_CLR_MEM); /* MUST clr buf mem clr flag (see Note #8b2B2).         */

            seg_data_moved = DEF_YES;
        }
    }


    seg_chngd = ((seg_updated    != DEF_NO) ||
                 (seg_data_moved != DEF_NO)) ? DEF_YES : DEF_NO;


/*$PAGE*/
    if (seg_chngd != DEF_NO) {                                  /* If chng'd, prepare seg for re-tx (see Note #1b2).    */
                                                                /* Prepare TCP seg addrs.                               */
        src_port  = (NET_TCP_PORT_NBR)pseg_hdr->TCP_UDP_PortSrc;
        src_addr  = (NET_IP_ADDR     )pseg_hdr->IP_AddrSrc;

        dest_port = (NET_TCP_PORT_NBR)pseg_hdr->TCP_UDP_PortDest;
        dest_addr = (NET_IP_ADDR     )pseg_hdr->IP_AddrDest;

                                                                /* Prepare TCP tx flags.                                */
        flags_tcp =  pseg_hdr->TCP_Flags;

                                                                /* Prepare IP params.                                   */
        TOS       =  pconn->TxIP_TOS;
        TTL       =  pconn->TxIP_TTL;
        flags_ip  =  pconn->TxIP_Flags;

                                                                /* Update re-tx seg's last tx ctrls (see Note #1b2F).   */
        pseg_hdr->TCP_SeqNbrLast  = (CPU_INT32U)seq_nbr;
        pseg_hdr->TCP_AckNbrLast  = (CPU_INT32U)ack_nbr;
        pseg_hdr->TCP_SegLenLast  = (CPU_INT16U)seg_len;
        pseg_hdr->TCP_WinSizeLast = (CPU_INT16U)win_size;

                                                                /* Reset protocol & tot len for re-tx.                  */
        pseg_hdr->ProtocolHdrType =  NET_PROTOCOL_TYPE_TCP;
        pseg_hdr->TotLen          =  pseg_hdr->DataLen;
    }



    unlink_fnct = pseg_hdr->UnlinkFnctPtr;
    if (unlink_fnct != (CPU_FNCT_PTR)0) {                       /* If unlink fnct avail, ..                             */
        unlink_fnct((void *)pseg);                              /* .. unlink seg from other layer(s) [see Note #9].     */
    }

    if (pseg_hdr->RefCtr <= 1) {
        pseg_hdr->RefCtr++;                                     /* TCP STILL maintains ref to seg    (see Note #10).    */
    }



                                                                /* ---------------- RE-TX TCP CONN SEG ---------------- */
    if (seg_updated == DEF_NO) {                                /* If seg NOT updated,                                  */
        NetIP_ReTx((NET_BUF *)pseg,                             /* ... re-tx unchng'd seg (see Note #7).                */
                   (NET_ERR *)perr);
        if (*perr != NET_IP_ERR_NONE) {
             return;
        }

    } else {                                                    /* Else re-tx updated seg.                              */
        NetTCP_TxPktHandler((NET_BUF        *)pseg,
                            (NET_IP_ADDR     )src_addr,
                            (NET_TCP_PORT_NBR)src_port,
                            (NET_IP_ADDR     )dest_addr,
                            (NET_TCP_PORT_NBR)dest_port,
                            (NET_TCP_SEQ_NBR )seq_nbr,
                            (NET_TCP_SEQ_NBR )ack_nbr,
                            (NET_TCP_WIN_SIZE)win_size,
                            (NET_IP_TOS      )TOS,
                            (NET_IP_TTL      )TTL,
                            (CPU_INT16U      )flags_tcp,
                            (CPU_INT16U      )flags_ip,
                            (void           *)0,
                            (void           *)0,
                            (NET_ERR        *)perr);
        switch (*perr) {
            case NET_TCP_ERR_NONE:
            case NET_ERR_INIT_INCOMPLETE:
            case NET_ERR_TX:                                    /* Ignore transitory tx err(s).                         */
                 break;


            case NET_TCP_ERR_TX:                                /* See Note #11a.                                       */
            default:
                 NetTCP_ConnClose((NET_TCP_CONN     *)pconn,
                                  (NET_BUF_HDR      *)0,
                                  (CPU_BOOLEAN       )pconn->ConnCloseAppFlag,
                                  (NET_TCP_CLOSE_CODE)close_code);
                 return;                                        /* Prevent 'break NOT reachable' compiler warning.      */
        }
    }

    NET_CTR_STAT_INC(NetTCP_StatTxSegConnReTxQ_Ctr);



   *perr = NET_TCP_ERR_NONE;
}


/*$PAGE*/
/*
*********************************************************************************************************
*                                    NetTCP_TxConnReTxQ_Timeout()
*
* Description : (1) (a) Handle TCP connection re-transmit queue timeout ... :
*
*                       (1) Clear  TCP connection's re-transmit timer                   See Note #4aA1
*                       (2) Handle TCP connection   re-transmit                         See Note #2
*
*                   (b) ... for the following synchronization/connected states :
*
*                       (1) SYN-RECEIVED
*                       (2) SYN-SENT
*                       (3) ESTABLISHED
*                       (4) FIN-WAIT-1
*                       (5) CLOSING
*                       (6) CLOSE-WAIT
*                       (7) LAST-ACK
*
*
* Argument(s) : pconn_timeout       Pointer to TCP connection to perform re-transmit (see Note #3b).
*
* Return(s)   : none.
*
* Caller(s)   : Referenced in NetTCP_TxConnReTxQ_TimeoutSet().
*
* Note(s)     : (2) RFC #793, Section 3.9 'Event Processing : USER TIMEOUT : RETRANSMISSION TIMEOUT'
*                   states that "if the retransmission timeout expires ... send the segment at the
*                   front of the retransmission queue ... [and] reinitialize the retransmission timer".
*
*                   See also 'NetTCP_TxConnReTxQ()  Note #2'.
*
*               (3) Ideally, network timer expiration functions could be defined as '[(void) (OBJECT *)]' 
*                   type functions -- even though network timer API functions cast expiration functions 
*                   to generic 'CPU_FNCT_PTR' type (i.e. '[(void) (void *)]').
*
*                   (a) (1) Unfortunately, ISO-IEC 9899-1999 ANSI-C, Section 6.3.2.3.7 states that "a 
*                           pointer to an object ... may be converted to a pointer to a different object 
*                           ... [but] if the resulting pointer is not correctly aligned ... the behavior
*                           is undefined".
*
*                           And since compilers may NOT correctly convert 'void' pointers to non-'void' 
*                           pointer arguments, network timer expiration functions MUST avoid incorrect
*                           pointer conversion behavior between 'void' pointer parameters & non-'void' 
*                           pointer arguments & therefore CANNOT be defined as '[(void) (OBJECT *)]'.
*
*                       (2) However, Section 6.3.2.3.1 states that "a pointer to void may be converted 
*                           to or from a pointer to any ... object ... A pointer to any ... object ... 
*                           may be converted to a pointer to void and back again; the result shall 
*                           compare equal to the original pointer".
*                   
*                   (b) Therefore, to correctly convert 'void' pointer objects back to appropriate
*                       network object pointer objects, network timer expiration functions MUST :
*
*                       (1) Be defined as 'CPU_FNCT_PTR' type (i.e. '[(void) (void *)]'); &       ...
*                       (2) Explicitly cast 'void' pointer arguments to specific object pointers; ...
*                           (A) ... in this case, a 'NET_TCP_CONN' pointer.
*
*                   See also 'net_tmr.c  NetTmr_Get()  Note #3'.
*
*               (4) This function is a network timer expiration function :
*
*                   (a) (1) For the following connection timer(s) ... :
*
*                           (A) TCP connection re-transmit queue timer ('ReTxQ_Tmr')
*
*                       (2) (A) Clear the timer pointer; ...
*                               (1) Cleared prior to next handler function(s) as an extra precaution to
*                                   avoiding re-freeing the timer (see Note #4a2B).
*
*                           (B) but do NOT re-free the timer.
*
*                   (b) Do NOT set the following close timer flag(s) :
*
*                       (1) NET_TCP_CONN_CLOSE_TMR_RE_TX
*
*               (5) Certain network connections MUST periodically suspend network transmit(s) to handle
*                   network receive packet(s).  To protect TCP connections from transmit corruption while
*                   suspended, ALL TCP data transmits & TCP transmit queue handling MUST be blocked for
*                   suspended connections until the connection is no longer suspended.
*
*                   However, handling the TCP connection's re-transmit timeout is permitted since NO TCP
*                   data is transmitted & the TCP connection's transmit queue is NOT handled (see Note #1a).
*
*                   See also 'NetTCP_TxConnTxQ()                    Note #10b2A2',
*                            'NetTCP_TxConnTxQ_TimeoutIdle()        Note #5',
*                            'NetTCP_TxConnTxQ_TimeoutSillyWin()    Note #5',
*                          & 'NetTCP_TxConnWinSizeZeroWinTimeout()  Note #5'.
*********************************************************************************************************
*/
/*$PAGE*/
static  void  NetTCP_TxConnReTxQ_Timeout (void  *pconn_timeout)
{
#if ((NET_ERR_CFG_ARG_CHK_DBG_EN == DEF_ENABLED)                    && \
     (NET_CTR_CFG_ERR_EN         == DEF_ENABLED)                    && \
     (CPU_CFG_CRITICAL_METHOD    == CPU_CRITICAL_METHOD_STATUS_LOCAL))
    CPU_SR               cpu_sr;
#endif
    NET_TCP_CONN        *pconn;
    NET_TCP_CLOSE_CODE   close_code;
    NET_ERR              err;


    pconn      = (NET_TCP_CONN *)pconn_timeout;                 /* See Note #3b2A.                                      */

    close_code =  NET_TCP_CONN_CLOSE_ALL;
    DEF_BIT_CLR(close_code, NET_TCP_CONN_CLOSE_TMR_RE_TX);      /* See Note #4b1.                                       */


#if (NET_ERR_CFG_ARG_CHK_DBG_EN == DEF_ENABLED)                 /* ---------------- VALIDATE TCP CONN ----------------- */
    if (pconn == (NET_TCP_CONN *)0) {
        NET_CTR_ERR_INC(NetTCP_ErrNullPtrCtr);
        return;
    }

    if (pconn->Type != NET_TCP_TYPE_CONN) {
        NET_CTR_ERR_INC(NetTCP_ErrConnInvalidTypeCtr);
        return;
    }

    switch (pconn->ConnState) {
        case NET_TCP_CONN_STATE_FREE:
             NET_CTR_ERR_INC(NetTCP_ErrNotUsedCtr);
             return;                                            /* Prevent 'break NOT reachable' compiler warning.      */


        case NET_TCP_CONN_STATE_CLOSED:
        case NET_TCP_CONN_STATE_LISTEN:
        case NET_TCP_CONN_STATE_FIN_WAIT_2:
        case NET_TCP_CONN_STATE_TIME_WAIT:
        case NET_TCP_CONN_STATE_CLOSING_DATA_AVAIL:
             NET_CTR_ERR_INC(NetTCP_ErrConnInvalidOpCtr);
             return;                                            /* Prevent 'break NOT reachable' compiler warning.      */


        case NET_TCP_CONN_STATE_SYNC_RXD:                       /* See Note #1.                                         */
        case NET_TCP_CONN_STATE_SYNC_RXD_PASSIVE:
        case NET_TCP_CONN_STATE_SYNC_RXD_ACTIVE:
        case NET_TCP_CONN_STATE_SYNC_TXD:
        case NET_TCP_CONN_STATE_CONN:
        case NET_TCP_CONN_STATE_FIN_WAIT_1:
        case NET_TCP_CONN_STATE_CLOSING:
        case NET_TCP_CONN_STATE_CLOSE_WAIT:
        case NET_TCP_CONN_STATE_LAST_ACK:
             switch (pconn->TxQ_State) {
                 case NET_TCP_TX_Q_STATE_CONN:
                 case NET_TCP_TX_Q_STATE_CONN_CLOSING:
                 case NET_TCP_TX_Q_STATE_CONN_SUSPEND:          /* See Note #5.                                         */
                      break;


                 case NET_TCP_TX_Q_STATE_NONE:
                 case NET_TCP_TX_Q_STATE_CLOSED:
                 case NET_TCP_TX_Q_STATE_CONN_CLOSED:
                 default:
                      return;                                   /* Prevent 'break NOT reachable' compiler warning.      */
             }
             break;


        case NET_TCP_CONN_STATE_NONE:
        default:
             NetTCP_ConnClose((NET_TCP_CONN     *)pconn,
                              (NET_BUF_HDR      *)0,
                              (CPU_BOOLEAN       )DEF_YES,
                              (NET_TCP_CLOSE_CODE)close_code);
             NET_CTR_ERR_INC(NetTCP_ErrConnInvalidStateCtr);
             return;                                            /* Prevent 'break NOT reachable' compiler warning.      */
    }
#endif


                                                                /* --------- HANDLE TCP CONN RE-TX Q TIMEOUT ---------- */
    pconn->ReTxQ_Tmr = (NET_TMR *)0;                            /* Clr    re-tx Q tmr (see Note #4a2A1).                */

    NetTCP_TxConnReTxQ(pconn, DEF_YES, close_code, &err);       /* Handle re-tx Q     (see Note #2).                    */
   (void)err;                                                   /* Ignore ALL re-tx err(s), transitory or fatal.        */
}


/*$PAGE*/
/*
*********************************************************************************************************
*                                  NetTCP_TxConnReTxQ_TimeoutSet()
*
* Description : (1) (a) Set TCP connection's re-transmit queue timer for the following synchronization/
*                       connected states :
*
*                       (1) CLOSED
*                       (2) LISTEN
*                       (3) SYN-RECEIVED
*                       (4) SYN-SENT
*                       (5) ESTABLISHED
*                       (6) FIN-WAIT-1
*                       (7) CLOSING
*                       (8) CLOSE-WAIT
*                       (9) LAST-ACK
*
*                           (A) (1) RFC #793, Section 3.9 'Event Processing : USER TIMEOUT : RETRANSMISSION
*                               TIMEOUT' reiterates that "for any state if the retransmission timeout expires
*                               on a segment in the retransmission queue ... reinitialize the retransmission
*                               timer".
*
*                   (b) However, since a TCP connection's transmit & re-transmit queue SHOULD be closed for
*                       the following states, it does NOT seem reasonable to set or reset a TCP connection's
*                       re-transmit queue timer for these states :
*
*                       (1) FIN-WAIT-2
*                       (2) TIME-WAIT
*
*
* Argument(s) : pconn               Pointer to a TCP connection.
*               -----               Argument validated in NetTCP_TxConnSync(),
*                                                         NetTCP_TxConnTxQ(),
*                                                         NetTCP_TxConnReTxQ(),
*                                                         NetTCP_RxPktConnHandlerReTxQ().
*
*               re_tx_q_timeout     Indicate whether the TCP connection re-transmit queue timed out :
*
*                                       DEF_NO                      TCP connection re-transmit queue did
*                                                                       NOT time  out.
*                                       DEF_YES                     TCP connection re-transmit queue
*                                                                           timed out.
*
*               close_code      Select which close action(s) to perform; bit-field flags logically OR'd :
*
*                                   NET_TCP_CONN_CLOSE_NONE                 Perform NO  close actions.
*                                   NET_TCP_CONN_CLOSE_ALL                  Perform ALL close actions.
*
*                                   NET_TCP_CONN_CLOSE_CONN_TX_RESET        Perform close connection transmit reset.
*                                   NET_TCP_CONN_CLOSE_CONN_ALL             Perform ALL   connection close    actions.
*
*                                   NET_TCP_CONN_CLOSE_TMR_TX_IDLE          Close    transmit idle                  timer.
*                                   NET_TCP_CONN_CLOSE_TMR_TX_SILLY_WIN     Close    transmit silly window persist  timer.
*                                   NET_TCP_CONN_CLOSE_TMR_TX_ZERO_WIN      Close    transmit zero  window persist  timer.
*                                   NET_TCP_CONN_CLOSE_TMR_TX_ACK_DLY       Close    transmit acknowledgement delay timer.
*                                   NET_TCP_CONN_CLOSE_TMR_RE_TX            Close re-transmit                       timer.
*                                   NET_TCP_CONN_CLOSE_TMR_KEEP_ALIVE       Close connection keep-alive             timer.
*                                   NET_TCP_CONN_CLOSE_TMR_TIMEOUT          Close connection                        timer.
*                                   NET_TCP_CONN_CLOSE_TMR_ALL              Close ALL                               timers.
*
*                               See also 'TCP CONNECTION CLOSE/FREE CODE DEFINES'.
*
*               perr        Pointer to variable that will receive the return error code from this function :
*
*                               NET_TCP_ERR_NONE                    TCP connection re-transmit queue timer
*                                                                       successfully set.
*                               NET_TCP_ERR_CONN_NOT_USED           TCP connection NOT currently used.
*                               NET_TCP_ERR_CONN_FAULT              TCP connection fault; connection(s) aborted.
*                               NET_TCP_ERR_INVALID_CONN_STATE      Invalid TCP connection state.
*                               NET_TCP_ERR_INVALID_CONN_OP         Invalid TCP connection operation.
*
* Return(s)   : none.
*
* Caller(s)   : NetTCP_TxConnSync(),
*               NetTCP_TxConnTxQ(),
*               NetTCP_TxConnReTxQ(),
*               NetTCP_RxPktConnHandlerReTxQ().
*
* Note(s)     : none.
*********************************************************************************************************
*/
/*$PAGE*/
static  void  NetTCP_TxConnReTxQ_TimeoutSet (NET_TCP_CONN        *pconn,
                                             CPU_BOOLEAN          re_tx_q_timeout,
                                             NET_TCP_CLOSE_CODE   close_code,
                                             NET_ERR             *perr)
{
#if ((NET_ERR_CFG_ARG_CHK_DBG_EN == DEF_ENABLED)                    && \
     (NET_CTR_CFG_ERR_EN         == DEF_ENABLED)                    && \
     (CPU_CFG_CRITICAL_METHOD    == CPU_CRITICAL_METHOD_STATUS_LOCAL))
    CPU_SR        cpu_sr;
#endif
    NET_TMR_TICK  timeout_tick;
    NET_ERR       err;


#if (NET_ERR_CFG_ARG_CHK_DBG_EN == DEF_ENABLED)                 /* ------------- VALIDATE TCP CONN STATE -------------- */
    switch (pconn->ConnState) {
        case NET_TCP_CONN_STATE_FREE:
             NET_CTR_ERR_INC(NetTCP_ErrNotUsedCtr);
            *perr = NET_TCP_ERR_CONN_NOT_USED;
             return;                                            /* Prevent 'break NOT reachable' compiler warning.      */


        case NET_TCP_CONN_STATE_FIN_WAIT_2:                     /* See Note #1b.                                        */
        case NET_TCP_CONN_STATE_TIME_WAIT:
        case NET_TCP_CONN_STATE_CLOSING_DATA_AVAIL:
             NET_CTR_ERR_INC(NetTCP_ErrConnInvalidOpCtr);
            *perr = NET_TCP_ERR_INVALID_CONN_OP;
             return;                                            /* Prevent 'break NOT reachable' compiler warning.      */


        case NET_TCP_CONN_STATE_CLOSED:                         /* See Note #1a.                                        */
        case NET_TCP_CONN_STATE_LISTEN:
        case NET_TCP_CONN_STATE_SYNC_RXD:
        case NET_TCP_CONN_STATE_SYNC_RXD_PASSIVE:
        case NET_TCP_CONN_STATE_SYNC_RXD_ACTIVE:
        case NET_TCP_CONN_STATE_SYNC_TXD:
        case NET_TCP_CONN_STATE_CONN:
        case NET_TCP_CONN_STATE_FIN_WAIT_1:
        case NET_TCP_CONN_STATE_CLOSING:
        case NET_TCP_CONN_STATE_CLOSE_WAIT:
        case NET_TCP_CONN_STATE_LAST_ACK:
             break;


        case NET_TCP_CONN_STATE_NONE:
        default:
             NetTCP_ConnClose((NET_TCP_CONN     *)pconn,
                              (NET_BUF_HDR      *)0,
                              (CPU_BOOLEAN       )DEF_YES,
                              (NET_TCP_CLOSE_CODE)close_code);
             NET_CTR_ERR_INC(NetTCP_ErrConnInvalidStateCtr);
            *perr = NET_TCP_ERR_INVALID_CONN_STATE;
             return;                                            /* Prevent 'break NOT reachable' compiler warning.      */
    }
#endif


                                                                /* ------------ SET TCP CONN RE-TX Q TMR  ------------- */
    timeout_tick = pconn->TxRTT_RTO_tick;

    if ((pconn->ReTxQ_Tmr != (NET_TMR *)0) &&                   /* If re-tx Q tmr avail  ..                             */
        (re_tx_q_timeout  ==  DEF_NO)) {                        /* .. but NOT timed out, ..                             */
        NetTmr_Set((NET_TMR    *) pconn->ReTxQ_Tmr,             /* .. reset re-tx Q tmr.                                */
                   (CPU_FNCT_PTR) NetTCP_TxConnReTxQ_Timeout,
                   (NET_TMR_TICK) timeout_tick,
                   (NET_ERR    *)&err);
    } else {                                                    /* Else get re-tx Q tmr.                                */
        pconn->ReTxQ_Tmr = NetTmr_Get((void       *) pconn,
                                      (CPU_FNCT_PTR) NetTCP_TxConnReTxQ_Timeout,
                                      (NET_TMR_TICK) timeout_tick,
                                      (CPU_INT16U  ) NET_TMR_FLAG_NONE,
                                      (NET_ERR    *)&err);
    }

    if ( err != NET_TMR_ERR_NONE) {                             /* #### On err, handle re-tx Q?; close TCP conn?        */
        NetTCP_ConnClose((NET_TCP_CONN     *)pconn, 
                         (NET_BUF_HDR      *)0,
                         (CPU_BOOLEAN       )pconn->ConnCloseAppFlag,
                         (NET_TCP_CLOSE_CODE)close_code);
       *perr  = NET_TCP_ERR_CONN_FAULT;
        return;
    }


   *perr = NET_TCP_ERR_NONE;
}


/*$PAGE*/
/*
*********************************************************************************************************
*                                   NetTCP_TxConnPrepareSegAddrs()
*
* Description : Prepare TCP transmit segment addresses from TCP connection addresses.
*
* Argument(s) : pconn           Pointer to a TCP connection.
*               -----           Argument validated in NetTCP_TxConnAppData();
*                                        checked   in NetTCP_TxConnSync(),
*                                                     NetTCP_TxConnClose(),
*                                                     NetTCP_TxConnAck(),
*                                                     NetTCP_TxConnReset(),
*                                                     NetTCP_TxConnProbe().
*
*               psrc_port       Pointer to  variable buffer that will receive the return source      port number
*               ---------           (see Note #1), if NO errors.
*
*                               Argument validated in NetTCP_TxConnAppData(),
*                                                     NetTCP_TxConnSync(),
*                                                     NetTCP_TxConnClose(),
*                                                     NetTCP_TxConnAck(),
*                                                     NetTCP_TxConnReset(),
*                                                     NetTCP_TxConnProbe().
*
*               psrc_addr       Pointer to  variable buffer that will receive the return source      address
*               ---------           (see Note #1), if NO errors.
*
*                               Argument validated in NetTCP_TxConnAppData(),
*                                                     NetTCP_TxConnSync(),
*                                                     NetTCP_TxConnClose(),
*                                                     NetTCP_TxConnAck(),
*                                                     NetTCP_TxConnReset(),
*                                                     NetTCP_TxConnProbe().
*
*               src_port_len    Size of the variable buffer that will receive the return source      port number.
*
*               src_addr_len    Size of the variable buffer that will receive the return source      address.
*
*               pdest_port      Pointer to  variable buffer that will receive the return destination port number
*               ----------          (see Note #1), if NO errors.
*
*                               Argument validated in NetTCP_TxConnAppData(),
*                                                     NetTCP_TxConnSync(),
*                                                     NetTCP_TxConnClose(),
*                                                     NetTCP_TxConnAck(),
*                                                     NetTCP_TxConnReset(),
*                                                     NetTCP_TxConnProbe().
*
*               pdest_addr      Pointer to  variable buffer that will receive the return destination address
*               ----------          (see Note #1), if NO errors.
*
*                               Argument validated in NetTCP_TxConnAppData(),
*                                                     NetTCP_TxConnSync(),
*                                                     NetTCP_TxConnClose(),
*                                                     NetTCP_TxConnAck(),
*                                                     NetTCP_TxConnReset(),
*                                                     NetTCP_TxConnProbe().
*
*               dest_port_len   Size of the variable buffer that will receive the return destination port number.
*
*               dest_addr_len   Size of the variable buffer that will receive the return destination address.
*
*               perr            Pointer to variable that will receive the return error code from this function :
*
*                                   NET_TCP_ERR_NONE                TCP connection addresses successfully
*                                                                       prepared.
*
*                                   NET_CONN_ERR_INVALID_FAMILY     Invalid     connection family.
*                                   NET_CONN_ERR_INVALID_ADDR       Invalid TCP connection address.
*                                   NET_CONN_ERR_INVALID_ADDR_LEN   Invalid TCP connection address length.
*
* Return(s)   : none.
*
* Caller(s)   : NetTCP_TxConnAppData(),
*               NetTCP_TxConnSync(),
*               NetTCP_TxConnClose(),
*               NetTCP_TxConnAck(),
*               NetTCP_TxConnReset(),
*               NetTCP_TxConnProbe().
*
* Note(s)     : (1) Variable buffers to receive the returned port & address values may start on any CPU address, 
*                   word-aligned or not.
*
*                   See also 'net_util.h  NETWORK DATA VALUE MACRO'S  Note #2b'.
*
*               (2) The 'NET_CONN_CFG_FAMILY' pre-processor 'else'-conditional code will never be compiled/linked
*                   since 'net_conn.h' ensures that the family type configuration constant (NET_CONN_CFG_FAMILY)
*                   is configured with an appropriate family type value (see 'net_conn.h  CONFIGURATION ERRORS').
*                   The 'else'-conditional code is included for completeness & as an extra precaution in case
*                   'net_conn.h' is incorrectly modified.
*********************************************************************************************************
*/
/*$PAGE*/
static  void  NetTCP_TxConnPrepareSegAddrs (NET_TCP_CONN  *pconn,
                                            CPU_INT08U    *psrc_port,
                                            CPU_INT08U    *psrc_addr,
                                            CPU_INT16U     src_port_len,
                                            CPU_INT16U     src_addr_len,
                                            CPU_INT08U    *pdest_port,
                                            CPU_INT08U    *pdest_addr,
                                            CPU_INT16U     dest_port_len,
                                            CPU_INT16U     dest_addr_len,
                                            NET_ERR       *perr)
{
    NET_CONN_ID        conn_id;
    NET_CONN_ADDR_LEN  addr_len;
    CPU_INT08U         addr[NET_CONN_CFG_ADDR_LEN];
    CPU_INT08U         port[NET_CONN_CFG_ADDR_LEN];
    CPU_INT08U         addr_local[NET_CONN_CFG_ADDR_LEN];
    CPU_INT08U         addr_remote[NET_CONN_CFG_ADDR_LEN];
    NET_ERR            err;


#if (NET_ERR_CFG_ARG_CHK_DBG_EN == DEF_ENABLED)
                                                                /* ---------------- VALIDATE ADDR LENS ---------------- */
#if (NET_CONN_CFG_FAMILY == NET_CONN_FAMILY_IP_V4_SOCK)
    if (src_port_len  != NET_CONN_ADDR_IP_LEN_PORT) {
       *perr = NET_CONN_ERR_INVALID_ADDR_LEN;
        return;
    }
    if (src_addr_len  != NET_CONN_ADDR_IP_LEN_ADDR) {
       *perr = NET_CONN_ERR_INVALID_ADDR_LEN;
        return;
    }

    if (dest_port_len != NET_CONN_ADDR_IP_LEN_PORT) {
       *perr = NET_CONN_ERR_INVALID_ADDR_LEN;
        return;
    }
    if (dest_addr_len != NET_CONN_ADDR_IP_LEN_ADDR) {
       *perr = NET_CONN_ERR_INVALID_ADDR_LEN;
        return;
    }

#else                                                           /* See Note #2.                                         */
    NetTCP_ConnClose((NET_TCP_CONN     *)pconn,
                     (NET_BUF_HDR      *)0,
                     (CPU_BOOLEAN       )DEF_YES,
                     (NET_TCP_CLOSE_CODE)NET_TCP_CONN_CLOSE_ALL);
   *perr = NET_CONN_ERR_INVALID_FAMILY;
    return;
#endif

#else                                                           /* Prevent compiler warnings.                           */
   (void)&src_port_len;
   (void)&src_addr_len;
   (void)&dest_port_len;
   (void)&dest_addr_len;
#endif


/*$PAGE*/
                                                                /* ------------------ PREPARE ADDRS ------------------- */
    conn_id  = pconn->ID_Conn;

    addr_len = sizeof(addr_local);
    NetConn_AddrLocalGet((NET_CONN_ID        ) conn_id,         /* Get local/src addr.                                  */
                         (CPU_INT08U        *)&addr_local[0],
                         (NET_CONN_ADDR_LEN *)&addr_len,
                         (NET_ERR           *)&err);
    if (err != NET_CONN_ERR_NONE) {
       *perr = NET_CONN_ERR_INVALID_ADDR;
        return;
    }
#if (NET_ERR_CFG_ARG_CHK_DBG_EN == DEF_ENABLED)
    if (addr_len != NET_CONN_CFG_ADDR_LEN) {
        NetTCP_ConnClose((NET_TCP_CONN     *)pconn,
                         (NET_BUF_HDR      *)0,
                         (CPU_BOOLEAN       )DEF_YES,
                         (NET_TCP_CLOSE_CODE)NET_TCP_CONN_CLOSE_ALL);
       *perr = NET_CONN_ERR_INVALID_ADDR_LEN;
        return;
    }
#endif

    addr_len = sizeof(addr_remote);
    NetConn_AddrRemoteGet((NET_CONN_ID        ) conn_id,        /* Get remote/dest addr.                                */
                          (CPU_INT08U        *)&addr_remote[0],
                          (NET_CONN_ADDR_LEN *)&addr_len,
                          (NET_ERR           *)&err);
    if (err != NET_CONN_ERR_NONE) {
       *perr = NET_CONN_ERR_INVALID_ADDR;
        return;
    }
#if (NET_ERR_CFG_ARG_CHK_DBG_EN == DEF_ENABLED)
    if (addr_len != NET_CONN_CFG_ADDR_LEN) {
        NetTCP_ConnClose((NET_TCP_CONN     *)pconn,
                         (NET_BUF_HDR      *)0,
                         (CPU_BOOLEAN       )DEF_YES,
                         (NET_TCP_CLOSE_CODE)NET_TCP_CONN_CLOSE_ALL);
       *perr = NET_CONN_ERR_INVALID_ADDR_LEN;
        return;
    }
#endif


                                                                /* Prepare src/dest addrs (see Note #1).                */
#if (NET_CONN_CFG_FAMILY == NET_CONN_FAMILY_IP_V4_SOCK)
    Mem_Copy((void     *)&port[0],
             (void     *)&addr_local[NET_CONN_ADDR_IP_IX_PORT],
             (CPU_SIZE_T) NET_CONN_ADDR_IP_LEN_PORT);
    Mem_Copy((void     *)&addr[0],
             (void     *)&addr_local[NET_CONN_ADDR_IP_IX_ADDR],
             (CPU_SIZE_T) NET_CONN_ADDR_IP_LEN_ADDR);

    NET_UTIL_VAL_COPY_GET_NET_16(psrc_port, &port[0]);
    NET_UTIL_VAL_COPY_GET_NET_32(psrc_addr, &addr[0]);


    Mem_Copy((void     *)&port[0],
             (void     *)&addr_remote[NET_CONN_ADDR_IP_IX_PORT],
             (CPU_SIZE_T) NET_CONN_ADDR_IP_LEN_PORT);
    Mem_Copy((void     *)&addr[0],
             (void     *)&addr_remote[NET_CONN_ADDR_IP_IX_ADDR],
             (CPU_SIZE_T) NET_CONN_ADDR_IP_LEN_ADDR);

    NET_UTIL_VAL_COPY_GET_NET_16(pdest_port, &port[0]);
    NET_UTIL_VAL_COPY_GET_NET_32(pdest_addr, &addr[0]);


#else                                                           /* See Note #2.                                         */
    NetTCP_ConnClose((NET_TCP_CONN     *)pconn,
                     (NET_BUF_HDR      *)0,
                     (CPU_BOOLEAN       )DEF_YES,
                     (NET_TCP_CLOSE_CODE)NET_TCP_CONN_CLOSE_ALL);
   *perr = NET_CONN_ERR_INVALID_FAMILY;
    return;
#endif


   *perr = NET_TCP_ERR_NONE;
}


/*$PAGE*/
/*
*********************************************************************************************************
*                                       NetTCP_TxConnRTT_Init()
*
* Description : Initialize TCP connection's transmit round-trip time (RTT) controls.
*
* Argument(s) : pconn       Pointer to a TCP connection.
*               -----       Argument validated in NetTCP_TxConnRTT_Reset(),
*                                                 NetTCP_TxConnRTT_RTO_Init().
*
* Return(s)   : none.
*
* Caller(s)   : NetTCP_TxConnRTT_Reset(),
*               NetTCP_TxConnRTT_RTO_Init().
*
* Note(s)     : (1) (A) RFC #1122, Section 4.2.3.1 states that "the following values SHOULD be
*                       used to initialize the estimation parameters for a new connection" :
*
*                           (a) RTT = 0 seconds
*
*                                   where
*                                           RTT                 Round-Trip Time
*
*                       (1) Furthermore, RFC #1122, Section 4.2.3.1.(b) states that "the
*                           smoothed variance is to be initialized to the value that will
*                           result in" these values.
*
*                   (B) However, since RFC #2988, Section 2.2 amends the RFC #1122, Section
*                       4.2.3.1 RTT initialization; the smoothed RTT average & deviation do
*                       NOT truly require explicit initialization.  Nonetheless, these RTT
*                       values are initialized to conform with RFC #1122, Section 4.2.3.1.
*********************************************************************************************************
*/

static  void  NetTCP_TxConnRTT_Init (NET_TCP_CONN  *pconn)
{
                                                                            /* Init RTT     (see Note #1).              */
    pconn->TxRTT_Avg_ms_scaled = NET_TCP_TX_RTT_AVG_INIT_MS_SCALED;         /* Init RTT avg (see Note #1Aa).            */
    pconn->TxRTT_Dev_ms_scaled = NET_TCP_TX_RTT_DEV_INIT_MS_SCALED;         /* Init RTT dev (see Note #1A1).            */

    NetTCP_TxConnRTT_CalcUpdate(pconn);
}


/*$PAGE*/
/*
*********************************************************************************************************
*                                      NetTCP_TxConnRTT_Reset()
*
* Description : Reset TCP connection's transmit round-trip time (RTT) controls.
*
* Argument(s) : pconn       Pointer to a TCP connection.
*               -----       Argument validated in NetTCP_TxConnRTT_RTO_Calc().
*
* Return(s)   : none.
*
* Caller(s)   : NetTCP_TxConnRTT_RTO_Calc().
*
* Note(s)     : (1) (a) RFC #2988, Section 5 states "that a TCP implementation MAY clear SRTT and
*                       RTTVAR after backing off the timer multiple times as it is likely that the
*                       current SRTT and RTTVAR are bogus in this situation.  Once SRTT and RTTVAR
*                       are cleared they should be initialized with the next RTT sample taken".
*
*                   (b) RFC #2581, Section 4.1 states that "after TCP has been idle for ... an
*                       interval exceeding the retransmission timeout ... use slow start to
*                       restart transmission".
*
*                       Similarly, although NO RFC specifies that a TCP connection's RTT average &
*                       deviation should be reset following a TCP transmit idle timeout; it seems
*                       reasonable to reset a TCP connection's RTT average & deviation controls
*                       whenever a TCP connection's transmit is idle for a period exceeding the
*                       re-transmit timeout.
*
*                   See also 'NetTCP_TxConnRTT_RTO_Calc()  Note #2a4'.
*********************************************************************************************************
*/

static  void  NetTCP_TxConnRTT_Reset (NET_TCP_CONN  *pconn)
{
    NetTCP_TxConnRTT_Init(pconn);

    pconn->TxRTT_RTO_State = NET_TCP_TX_RTT_RTO_STATE_RESET;
}


/*$PAGE*/
/*
*********************************************************************************************************
*                                    NetTCP_TxConnRTT_CalcUpdate()
*
* Description : Update TCP connection's transmit round-trip time (RTT) control calculations.
*
* Argument(s) : pconn       Pointer to a TCP connection.
*               -----       Argument validated in NetTCP_TxConnRTT_Init(),
*                                                 NetTCP_TxConnRTT_RTO_Calc().
*
* Return(s)   : none.
*
* Caller(s)   : NetTCP_TxConnRTT_Init(),
*               NetTCP_TxConnRTT_RTO_Calc().
*
* Note(s)     : (1) A TCP connection's transmit round-trip time controls should NOT be updated until
*                   after the following TCP connection control(s) have been configured :
*
*                       (a) TCP connection's transmit round-trip time average   (in scaled milliseconds)
*                                                                                ['TxRTT_Avg_ms_scaled']
*
*                       (b) TCP connection's transmit round-trip time deviation (in scaled milliseconds)
*                                                                                ['TxRTT_Dev_ms_scaled']
*********************************************************************************************************
*/

static  void  NetTCP_TxConnRTT_CalcUpdate (NET_TCP_CONN  *pconn)
{
    pconn->TxRTT_Avg_ms = (NET_TCP_TIMEOUT_MS)(pconn->TxRTT_Avg_ms_scaled / NET_TCP_TX_RTT_SCALE);
    pconn->TxRTT_Dev_ms = (NET_TCP_TIMEOUT_MS)(pconn->TxRTT_Dev_ms_scaled / NET_TCP_TX_RTT_SCALE);
}


/*$PAGE*/
/*
*********************************************************************************************************
*                                       NetTCP_TxConnRTO_Init()
*
* Description : (1) Initialize TCP connection's re-transmit timeout (RTO) controls :
*
*                   (a) Initialize RTO                                      See Note #2
*                   (b) Configure  RTO maximum timeout                      See Note #3
*
*
* Argument(s) : pconn       Pointer to a TCP connection.
*               -----       Argument validated in NetTCP_TxConnRTT_RTO_Init().
*
* Return(s)   : none.
*
* Caller(s)   : NetTCP_TxConnRTT_RTO_Init().
*
* Note(s)     : (2) RFC #1122, Section 4.2.3.1 states that "the following values SHOULD be
*                   used to initialize the estimation parameters for a new connection" :
*
*                       (b) RTO = 3 seconds
*
*                               where
*                                       RTO                 Retransmission Timeout
*
*                   (A) RFC #2988, Section 2.1 reiterates that "until a round-trip time (RTT)
*                       measurement has been made ... the sender SHOULD set RTO <- 3 seconds".
*
*               (3) A TCP connection's re-transmit timeout controls should NOT be updated until
*                   after the following TCP connection control(s) have been configured :
*
*                       (a) TCP connection's maximum re-transmit timeout (in seconds)  ['TxRTT_RTO_Max_sec']
*                              [see 'NetTCP_TxConnRTO_CfgMaxTimeout()  Note #2a']
*********************************************************************************************************
*/

static  void  NetTCP_TxConnRTO_Init (NET_TCP_CONN  *pconn)
{
    pconn->TxRTT_RTO_ms_scaled = NET_TCP_TX_RTT_RTO_INIT_MS_SCALED;         /* Init RTO (see Note #2).                  */

    NetTCP_TxConnRTO_CalcUpdate(pconn);


    NetTCP_TxConnRTO_CfgMaxTimeout(pconn);                                  /* Cfg RTO max timeout (see Note #3).       */
}


/*$PAGE*/
/*
*********************************************************************************************************
*                                  NetTCP_TxConnRTO_CfgMaxTimeout()
*
* Description : Configure TCP connection's maximum re-transmit timeout (RTO).
*
* Argument(s) : pconn       Pointer to a TCP connection.
*               -----       Argument validated in NetTCP_TxConnRTO_Init(),
*                                                 NetTCP_ConnCfgReTxMaxTimeout().
*
* Return(s)   : none.
*
* Caller(s)   : NetTCP_TxConnRTO_Init(),
*               NetTCP_ConnCfgReTxMaxTimeout().
*
* Note(s)     : (1) (a) RFC #2988, Section 2.4 states that "a maximum value MAY be placed on RTO provided
*                       it is at least 60 seconds".
*
*                   (b) RFC #1122, Section 4.2.3.1 states that "the recommended ... RTO ... upper bound
*                       should be 2*MSL".
*
*                   (c) Stevens, TCP/IP Illustrated, Volume 1, 8th Printing, Section 21.2, Page 299 states
*                       that "the timeout value ... [has] an upper limit of 64 seconds".
*
*               (2) A TCP connection's maximum re-transmit timeouts (in scaled milliseconds or milliseconds) 
*                   should NOT be updated until after the following TCP connection control(s) have been
*                   configured :
*
*                       (a) TCP connection's maximum re-transmit timeout (in seconds)  ['TxRTT_RTO_Max_sec']
*                               [see 'NetTCP_ConnClr()  Note #11'
*                                  & 'NetTCP_ConnCfgReTxMaxTimeout()  Note #1']
*********************************************************************************************************
*/

static  void  NetTCP_TxConnRTO_CfgMaxTimeout (NET_TCP_CONN  *pconn)
{
    pconn->TxRTT_RTO_Max_ms_scaled = (NET_TCP_TX_RTT_MS_SCALED)pconn->TxRTT_RTO_Max_sec * NET_TCP_TX_RTT_MS_SCALE;
    pconn->TxRTT_RTO_Max_ms        = (NET_TCP_TIMEOUT_MS      )pconn->TxRTT_RTO_Max_sec * DEF_TIME_NBR_mS_PER_SEC;
}


/*$PAGE*/
/*
*********************************************************************************************************
*                                    NetTCP_TxConnRTO_CalcUpdate()
*
* Description : Update TCP connection's re-transmit timeout (RTO) control calculations.
*
* Argument(s) : pconn       Pointer to a TCP connection.
*               -----       Argument validated in NetTCP_TxConnRTO_Init(),
*                                                 NetTCP_TxConnRTT_RTO_Calc().
*
* Return(s)   : none.
*
* Caller(s)   : NetTCP_TxConnRTO_Init(),
*               NetTCP_TxConnRTT_RTO_Calc().
*
* Note(s)     : (1) A TCP connection's re-transmit timeout controls should NOT be updated until
*                   after the following TCP connection control(s) have been configured :
*
*                       (a) TCP connection's re-transmit timeout (in scaled milliseconds)
*                                                                 ['TxRTT_RTO_ms_scaled']
*********************************************************************************************************
*/

static  void  NetTCP_TxConnRTO_CalcUpdate (NET_TCP_CONN  *pconn)
{
    pconn->TxRTT_RTO_ms   =  (NET_TCP_TIMEOUT_MS )(pconn->TxRTT_RTO_ms_scaled / NET_TCP_TX_RTT_SCALE);
    pconn->TxRTT_RTO_sec  =  (NET_TCP_TIMEOUT_SEC)(pconn->TxRTT_RTO_ms_scaled / NET_TCP_TX_RTT_MS_SCALE);
    pconn->TxRTT_RTO_tick = ((NET_TMR_TICK       ) pconn->TxRTT_RTO_ms * NET_TMR_TIME_TICK_PER_SEC) / DEF_TIME_NBR_mS_PER_SEC;
}


/*$PAGE*/
/*
*********************************************************************************************************
*                                   NetTCP_TxConnRTO_CalcBackOff()
*
* Description : Calculate next backed-off re-transmit timeout (RTO) value.
*
* Argument(s) : pconn       Pointer to a TCP connection.
*               -----       Argument validated in NetTCP_TxConnRTT_RTO_Calc(),
*                                                 NetTCP_TxConnWinSizeZeroWinHandler().
*
*               rto_ms      Current re-transmit timeout value (in milliseconds).
*
* Return(s)   : Backed-off re-transmit timeout value (in milliseconds).
*
* Caller(s)   : NetTCP_TxConnRTT_RTO_Calc(),
*               NetTCP_TxConnWinSizeZeroWinHandler().
*
* Note(s)     : (1) (a) RFC #1122, Section 4.2.3.1 states that an "implementation MUST also include
*                       'exponential backoff' for successive RTO values for the same segment".
*
*                       (1) RFC #2988, Section 5.5 states that "when the retransmission timer expires
*                           ... the host MUST set RTO <- RTO * 2 ('back off the timer')".
*
*                           Thus, the TCP retransmission timer exponential back-off scalar value is 2.
*
*                       (2) Stevens, TCP/IP Illustrated, Volume 1, 8th Printing, Section 21.2, Page 299
*                           reiterates that "this doubling is called an 'exponential backoff'".
*
*                   (b) (1) RFC #2988, Section 2.4 adds that "a maximum value MAY be placed on RTO
*                           provided it is at least 60 seconds".
*
*                       (2) RFC #1122, Section 4.2.3.1 states that "the recommended ... RTO ... upper
*                           bound should be 2*MSL".
*
*                       (3) Stevens, TCP/IP Illustrated, Volume 1, 8th Printing, Section 21.2, Page 299
*                           states that "the timeout value is doubled for each retransmission, with an
*                           upper limit of 64 seconds".
*
*                       See also 'NetTCP_TxConnRTO_CfgMaxTimeout()  Note #1'.
*
*               (2) RFC #1122, Section 4.2.2.17 states that "zero-window probe[s] ... SHOULD increase
*                   exponentially the interval between successive probes ... Exponential backoff is
*                   recommended ... similar to ... the retransmission algorithm, and it may be possible
*                   to combine the two procedures in the implementation".
*********************************************************************************************************
*/

static  NET_TCP_TIMEOUT_MS  NetTCP_TxConnRTO_CalcBackOff (NET_TCP_CONN        *pconn,
                                                          NET_TCP_TIMEOUT_MS   rto_ms)
{
    NET_TCP_TIMEOUT_MS  rto_ms_backoff_calcd;
    NET_TCP_TIMEOUT_MS  rto_ms_backoff;

                                                                /* Calc  backed-off RTO timeout value (see Note #1a).   */
    rto_ms_backoff_calcd = (rto_ms < pconn->TxRTT_RTO_Max_ms)
                         ? (rto_ms * NET_TCP_TX_RTO_TIMEOUT_BACKOFF_SCALAR)
                         :  pconn->TxRTT_RTO_Max_ms;
                                                                /* Limit backed-off RTO timeout value (see Note #1b).   */
    rto_ms_backoff       =  DEF_MIN(rto_ms_backoff_calcd, pconn->TxRTT_RTO_Max_ms);

    return (rto_ms_backoff);
}


/*$PAGE*/
/*
*********************************************************************************************************
*                                     NetTCP_TxConnRTT_RTO_Init()
*
* Description : Initialize TCP connection's transmit round-trip time (RTT) & re-transmit timeout (RTO) values.
*
* Argument(s) : pconn       Pointer to a TCP connection.
*               -----       Argument validated in NetTCP_ConnCfg().
*
* Return(s)   : none.
*
* Caller(s)   : NetTCP_ConnCfg().
*
* Note(s)     : (1) A TCP connection's re-transmit timeout controls should NOT be updated until
*                   after the following TCP connection control(s) have been configured :
*
*                       (a) TCP connection's maximum re-transmit timeout (in seconds)  ['TxRTT_RTO_Max_sec']
*                              [see 'NetTCP_TxConnRTO_Init()  Note #3']
*********************************************************************************************************
*/

static  void  NetTCP_TxConnRTT_RTO_Init (NET_TCP_CONN  *pconn)
{
    NetTCP_TxConnRTT_Init(pconn);
    NetTCP_TxConnRTO_Init(pconn);

    pconn->TxRTT_RTO_State = NET_TCP_TX_RTT_RTO_STATE_INIT;
}


/*$PAGE*/
/*
*********************************************************************************************************
*                                     NetTCP_TxConnRTT_RTO_Calc()
*
* Description : (1) Calculate TCP connection's transmit round-trip time (RTT) & re-transmit timeout (RTO) values :
*
*                   (a) Perform requested RTT/RTO calculation operation(s)
*                   (b) Prepare & perform RTT     calculations
*                   (c) Prepare & perform RTO     calculations
*
*
* Argument(s) : pconn           Pointer to a TCP connection.
*               -----           Argument validated in NetTCP_RxPktConnHandlerReTxQ(),
*                                                     NetTCP_TxConnReTxQ(),
*                                                     NetTCP_TxConnTxQ_TimeoutIdle().
*
*               calc_code       Indicate which TCP connection's transmit round-trip time calculations to perform
*                                   (see Note #1a) :
*
*                                   NET_TCP_CONN_TX_RTT_INIT        Initialize         TCP connection's transmit
*                                                                       round-trip time controls
*                                                                       (see 'NetTCP_TxConnRTT_Init()  Note #1'
*                                                                          & 'NetTCP_TxConnRTO_Init()  Note #2').

*                                   NET_TCP_CONN_TX_RTT_RESET       Reset              TCP connection's transmit
*                                                                       round-trip time controls.
*
*                                   NET_TCP_CONN_TX_RTT_CALC        Calculate & update TCP connection's transmit
*                                                                       round-trip time controls.
*
*                                   NET_TCP_CONN_TX_RTT_BACKOFF     Back-off  & update TCP connection's transmit
*                                                                       round-trip time controls for a TCP re-
*                                                                       transmit timeout.
*
*               rtt_ts_txd_ms   Round-trip timestamp when transmitted (in milliseconds).
*
*               rtt_ts_rxd_ms   Round-trip timestamp when received    (in milliseconds).
*
* Return(s)   : none.
*
* Caller(s)   : NetTCP_RxPktConnHandlerReTxQ(),
*               NetTCP_TxConnReTxQ(),
*               NetTCP_TxConnTxQ_TimeoutIdle().
*$PAGE*
* Note(s)     : (2) (a) (1) RFC #2988, Section 2 states that "the rules governing the computation of SRTT
*                           (smoothed round-trip time), RTTVAR RTTVAR (round-trip time variation), and RTO
*                           are as follows" :
*
*                           (A) RFC #2988, Section 2.2 states that for "the first RTT measurement R ...
*                               the host MUST set" :
*
*                                   (1) SRTT    <-  R
*                                   (2) RTTVAR  <-  R/2
*                                   (3) RTO     <-  SRTT  +  max(G, K * RTTVAR)
*
*                                            where
*                                                   SRTT                    RTT Smoothed Average
*                                                   RTTVAR                  RTT Variance/Deviation
*                                                   RTO                         Retransmission Timeout
*                                                   R                       RTT First Measurement
*                                   (4)             R   = R * 1             RTT First Average   Gain
*                                   (5)             R/2 = R * 1/2           RTT First Deviation Gain
*                                                   G                       RTT Clock Granularity (resolution)
*                                   (6)             K = 4                   RTT-RTO Gain
*
*
*                           (B) RFC #2988, Section 2.3 states that for "subsequent RTT measurement R' ...
*                               a host MUST set" :
*
*                                   (1) RTTVAR  <-  (1 - beta ) * RTTVAR  +  beta  * |SRTT - R'|
*                                   (2) SRTT    <-  (1 - alpha) * SRTT    +  alpha * R'
*                                   (3) RTO     <-  SRTT  +  max(G, K * RTTVAR)
*
*                                            where
*                                                   SRTT                    RTT Smoothed Average
*                                                   RTTVAR                  RTT Variance/Deviation
*                                                   RTO                         Retransmission Timeout
*                                                   R'                      RTT Subsequent Measurement(s)
*                                   (4)             alpha = 1/8             RTT-Average    Gain
*                                   (5)             beta  = 1/4             RTT-Deviation  Gain
*                                                   G                       RTT Clock Granularity (resolution)
*                                   (6)             K = 4                   RTT-RTO Gain
*
*
*                               (a) RFC #2988, Section 2.3 states tht "updating RTTVAR and SRTT MUST be
*                                   computed in ... order ... [since] the value of SRTT used in the update
*                                   to RTTVAR is its value before updating SRTT itself".
*
*                               (b) To reduce the total number of operations for both RTT calculations,
*                                   the equations SHOULD be factored & rearranged as follows :
*
*                                       (1) (A) RTTVAR  <-       (1 - beta) * RTTVAR  +  beta * |SRTT - R'|
*
*                                           (B) RTTVAR  <-  RTTVAR  -  beta * RTTVAR  +  beta * |SRTT - R'|
*
*                                           (C) RTTVAR  <-  RTTVAR  +  beta * (|SRTT - R'| - RTTVAR)
*
*                                           (D) RTTVAR  <-  RTTVAR  +  beta * (|R' - SRTT| - RTTVAR)
*
*
*                                       (2) (A) SRTT    <-     (1 - alpha) * SRTT  +  alpha * R'
*
*                                           (B) SRTT    <-  SRTT  -  alpha * SRTT  +  alpha * R'
*
*                                           (C) SRTT    <-  SRTT  +  alpha * (R' - SRTT)
*
*
*                       (2) (A) RFC #793, Section 3.7 'Data Communication : Retransmission Timeout' states
*                               that "the Round Trip Time (RTT) ... [is] the elapsed time between" :
*
*                               (1) "sending a data octet with a particular sequence number and"   ...
*                               (2) "receiving an acknowledgment that covers that sequence number" ...
*                               (3) "(segments sent do not have to match segments received)".
*
*                           (B) (1) RFC #2988, Section 3 adds that :
*
*                                   (a) "Traditionally, TCP implementations have taken one RTT measurement at
*                                        a time (typically once per RTT)."
*                                   (b) "A TCP implementation MUST take at least one RTT measurement per RTT
*                                        (unless that is not possible per Karn's algorithm) [see Note #2a5]".
*                                   (c) "For fairly modest congestion window sizes research suggests that
*                                        timing each segment does not lead to a better RTT estimator."
*                                   (d) "Additionally, when multiple samples are taken per RTT the alpha and
*                                        beta ... may keep an inadequate RTT history."
*
*                               (2) RFC #2988, Section 1 states that "in some situations it may be beneficial
*                                   for a TCP sender to be more conservative than the algorithms detailed in
*                                   this document allow.  However, a TCP MUST NOT be more aggressive than the
*                                   ... algorithms allow".
*
*                                   Thus, the following TCP algorithm(s) are permitted; even if the algorithms
*                                   delay or decrease the number of received acknowledgements, which thereby
*                                   increases the measured time values for RTT samples :
*
*                                       (a) Karn's Algorithm                    See  Note #2a5
*                                       (b) TCP Delayed Acknowledgements        See 'NetTCP_TxConnAck()  Note #6'
*$PAGE*
*                       (3) Jacobson/Karels, "Congestion Avoidance and Control", Appendix A.2 states that RTT
*                           calculations "should be done in integer arithmetic".  RFC #2988, Section 2.3 adds
*                           that RTT calculations "SHOULD be computed using ... 1/8 and ... 1/4" gains (see
*                           Notes #2a1B4 & #2a1B5).
*
*                       (4) (A) RFC #2988, Section 5 states "that a TCP implementation MAY clear SRTT and
*                               RTTVAR after backing off the timer multiple times as it is likely that the
*                               current SRTT and RTTVAR are bogus in this situation.  Once SRTT and RTTVAR
*                               are cleared they should be initialized with the next RTT sample taken per
*                               [Note #2a1A] rather than using [Note #2a1B]".
*
*                           (B) RFC #2581, Section 4.1 states that "after TCP has been idle for ... an
*                               interval exceeding the retransmission timeout ... use slow start to
*                               restart transmission".
*
*                               Similarly, although NO RFC specifies that a TCP connection's RTT average &
*                               deviation should be reset following a TCP transmit idle timeout; it seems
*                               reasonable to reset a TCP connection's RTT average & deviation controls
*                               whenever a TCP connection's transmit is idle for a period exceeding the
*                               re-transmit timeout.
*
*                               See also 'NetTCP_TxConnTxQ_TimeoutIdle()  Note #2a'.
*
*                       (5) RFC #2988, Section 3 states that "TCP MUST use Karn's algorithm ... for
*                           taking RTT samples.  That is, RTT samples MUST NOT be made using segments
*                           that were retransmitted (and thus for which it is ambiguous whether the reply
*                           was for the first instance of the packet or a later instance)".
*
*                   (b) (1) (A) (1) RFC #2988, Section 2.4 states that "whenever RTO is computed, if it
*                                   is less than 1 second then the RTO SHOULD be rounded up to 1 second".
*
*                                   (a) This amends RFC #1122, Section 4.2.3.1 which previously stated
*                                       that "the recommended ... RTO ... lower bound ... SHOULD be
*                                       measured in fractions of a second".
*
*                               (2) RFC #2988, Section 4 states that "there is no requirement for the
*                                   clock granularity G used for computing RTT measurements ... However,
*                                   if the K*RTTVAR term in the RTO calculation equals zero, the variance
*                                   term MUST be rounded to G seconds".
*
*                                   See also Notes #2a1A3 & #2a1B3.
*
*                           (B) (1) RFC #2988, Section 2.4 adds that "a maximum value MAY be placed on
*                                   RTO provided it is at least 60 seconds".
*
*                               (2) RFC #1122, Section 4.2.3.1 states that "the recommended ... RTO ...
*                                   upper bound should be 2*MSL".
*
*                               (3) Stevens, TCP/IP Illustrated, Volume 1, 8th Printing, Section 21.2,
*                                   Page 299 states that "the timeout value ... [has] an upper limit of 
*                                   64 seconds".
*
*                               See also 'net_tcp.c  NetTCP_TxConnRTO_CfgMaxTimeout()  Note #1'.
*
*                       (2) RFC #1122, Section 4.2.3.1 reiterates that an "implementation MUST also
*                           include 'exponential backoff' for successive RTO values for the same
*                           segment".
*
*                           (a) RFC #2988, Section 5.5 states that "when the retransmission timer
*                               expires ... the host MUST set RTO <- RTO * 2 ('back off the timer')".
*
*                               Thus, the TCP retransmission timer exponential back-off scalar
*                               value is 2.
*
*                           (b) Stevens, TCP/IP Illustrated, Volume 1, 8th Printing, Section 21.2,
*                               Page 299 reiterates that "this doubling is called an 'exponential
*                               backoff'".
*
*                           See also 'NetTCP_TxConnRTO_CalcBackOff()  Note #1'.
*********************************************************************************************************
*/

static  void  NetTCP_TxConnRTT_RTO_Calc (NET_TCP_CONN          *pconn,
                                         NET_TCP_CALC_CODE      calc_code,
                                         NET_TCP_TX_RTT_TS_MS   rtt_ts_txd_ms,
                                         NET_TCP_TX_RTT_TS_MS   rtt_ts_rxd_ms)
{
    NET_TCP_TIMEOUT_MS        timeout_ms;
    NET_TMR_TICK              timeout_tick;
    NET_TCP_TX_RTT_MS         rtt_cur_ms;
    NET_TCP_TX_RTT_MS_SCALED  rtt_cur_ms_scaled;
    NET_TCP_TX_RTT_MS_SCALED  rtt_err_ms_scaled;
    NET_TCP_TX_RTT_MS_SCALED  rtt_err_ms_scaled_abs;
    NET_TCP_TX_RTT_MS_SCALED  rtt_avg_ms_scaled;
    NET_TCP_TX_RTT_MS_SCALED  rtt_dev_ms_scaled;
    NET_TCP_TX_RTT_MS_SCALED  rtt_dev_ms_scaled_gain;
    NET_TCP_TX_RTT_MS_SCALED  rtt_dev_ms_scaled_min;
    NET_TCP_TX_RTT_MS_SCALED  rto_ms_scaled;



/*$PAGE*/
                                                                    /* -------------- PERFORM CALC CODE --------------- */
    switch (calc_code) {
        case NET_TCP_CONN_TX_RTT_CALC:
             break;


        case NET_TCP_CONN_TX_RTT_BACKOFF:                           /* Back-off RTO (see Note #2b2).                    */
             timeout_ms            =  (NET_TCP_TIMEOUT_MS ) NetTCP_TxConnRTO_CalcBackOff(pconn, pconn->TxRTT_RTO_ms);
             timeout_tick          = ((NET_TMR_TICK       ) timeout_ms * NET_TMR_TIME_TICK_PER_SEC) / DEF_TIME_NBR_mS_PER_SEC;

             pconn->TxRTT_RTO_ms   =  (NET_TCP_TIMEOUT_MS ) timeout_ms;
             pconn->TxRTT_RTO_sec  =  (NET_TCP_TIMEOUT_SEC)(timeout_ms / DEF_TIME_NBR_mS_PER_SEC);
             pconn->TxRTT_RTO_tick =  (NET_TMR_TICK       ) timeout_tick;
                                                                    /* 'break' intentionally omitted; do NOT move from  */
                                                                    /* ... following case : 'NET_TCP_CONN_TX_RTT_RESET'.*/
        case NET_TCP_CONN_TX_RTT_RESET:                             /* See Note #2a4.                                   */
             NetTCP_TxConnRTT_Reset(pconn);
             return;                                                /* Prevent 'break NOT reachable' compiler warning.  */


        case NET_TCP_CONN_TX_RTT_INIT:
        default:
             NetTCP_TxConnRTT_RTO_Init(pconn);
             return;                                                /* Prevent 'break NOT reachable' compiler warning.  */
    }



                                                                    /* -------------- PREPARE RTT CALCS --------------- */
    switch (pconn->TxRTT_RTO_State) {
        case NET_TCP_TX_RTT_RTO_STATE_INIT:
        case NET_TCP_TX_RTT_RTO_STATE_RESET:
        case NET_TCP_TX_RTT_RTO_STATE_CALC:
             rtt_cur_ms        = (NET_TCP_TX_RTT_MS       )(rtt_ts_rxd_ms - rtt_ts_txd_ms);
             rtt_cur_ms_scaled = (NET_TCP_TX_RTT_MS_SCALED)(rtt_cur_ms    * NET_TCP_TX_RTT_SCALE);
             break;


        case NET_TCP_TX_RTT_RTO_STATE_NONE:
        case NET_TCP_TX_RTT_RTO_STATE_RE_TX:                        /* See Note #2a5.                                   */
        default:
             return;                                                /* Prevent 'break NOT reachable' compiler warning.  */
    }

                                                                    /* -------------- PERFORM RTT CALCS --------------- */
    switch (pconn->TxRTT_RTO_State) {
        case NET_TCP_TX_RTT_RTO_STATE_INIT:                         /* Init   RTT calcs (see Notes #2a1A1 & #2a1A2).    */
        case NET_TCP_TX_RTT_RTO_STATE_RESET:
             rtt_avg_ms_scaled      = (rtt_cur_ms_scaled * NET_TCP_TX_RTT_GAIN_AVG_INIT_NUMER)
                                                         / NET_TCP_TX_RTT_GAIN_AVG_INIT_DENOM;

             rtt_dev_ms_scaled      = (rtt_cur_ms_scaled * NET_TCP_TX_RTT_GAIN_DEV_INIT_NUMER)
                                                         / NET_TCP_TX_RTT_GAIN_DEV_INIT_DENOM;

             pconn->TxRTT_RTO_State =  NET_TCP_TX_RTT_RTO_STATE_CALC;
             break;


        case NET_TCP_TX_RTT_RTO_STATE_CALC:                         /* Update RTT calcs (see Notes #2a1Bb1D & #2a1Bb2C).*/
             rtt_err_ms_scaled     =         rtt_cur_ms_scaled  - pconn->TxRTT_Avg_ms_scaled;
             rtt_err_ms_scaled_abs = DEF_ABS(rtt_err_ms_scaled);

             rtt_dev_ms_scaled     = pconn->TxRTT_Dev_ms_scaled + (((rtt_err_ms_scaled_abs - pconn->TxRTT_Dev_ms_scaled) * NET_TCP_TX_RTT_GAIN_DEV_NUMER)
                                                                                                                         / NET_TCP_TX_RTT_GAIN_DEV_DENOM);

             rtt_avg_ms_scaled     = pconn->TxRTT_Avg_ms_scaled +  ((rtt_err_ms_scaled                                   * NET_TCP_TX_RTT_GAIN_AVG_NUMER)
                                                                                                                         / NET_TCP_TX_RTT_GAIN_AVG_DENOM);
             break;


        case NET_TCP_TX_RTT_RTO_STATE_NONE:
        case NET_TCP_TX_RTT_RTO_STATE_RE_TX:                        /* See Note #2a5.                                   */
        default:
             return;                                                /* Prevent 'break NOT reachable' compiler warning.  */
    }

                                                                    /* ------------------ UPDATE RTT ------------------ */
    pconn->TxRTT_Avg_ms_scaled = rtt_avg_ms_scaled;
    pconn->TxRTT_Dev_ms_scaled = rtt_dev_ms_scaled;

    NetTCP_TxConnRTT_CalcUpdate(pconn);


/*$PAGE*/
                                                                    /* ------------------- CALC RTO ------------------- */
                                                                    /* Calc  RTO     (see Note #2a1B3).                 */
    rtt_dev_ms_scaled_gain = (pconn->TxRTT_Dev_ms_scaled * NET_TCP_TX_RTT_GAIN_RTO_NUMER)
                                                         / NET_TCP_TX_RTT_GAIN_RTO_DENOM;
                                                                    /* Limit RTT dev (see Note #2b1A2).                 */
    rtt_dev_ms_scaled_min  =  DEF_MAX(NET_TCP_TX_RTT_TS_CLK_MS_SCALED,
                                      rtt_dev_ms_scaled_gain);

    rto_ms_scaled          =  pconn->TxRTT_Avg_ms_scaled + rtt_dev_ms_scaled_min;

                                                                    /* Limit RTO (see Note #2b1).                       */
    if (rto_ms_scaled < NET_TCP_TX_RTO_MIN_TIMEOUT_MS_SCALED) {
        rto_ms_scaled = NET_TCP_TX_RTO_MIN_TIMEOUT_MS_SCALED;
    }
    if (rto_ms_scaled > pconn->TxRTT_RTO_Max_ms_scaled) {
        rto_ms_scaled = pconn->TxRTT_RTO_Max_ms_scaled;
    }

                                                                    /* ------------------ UPDATE RTO ------------------ */
    pconn->TxRTT_RTO_ms_scaled = rto_ms_scaled;

    NetTCP_TxConnRTO_CalcUpdate(pconn);
}


/*$PAGE*/
/*
*********************************************************************************************************
*                                        NetTCP_TxPktHandler()
*
* Description : (1) Prepare & transmit TCP packets :
*
*                   (a) Validate transmit packet
*                   (b) Transmit TCP packet
*                   (c) Free   transmit packet buffer(s)
*                   (d) Update transmit statistics
*
*
* Argument(s) : pbuf        Pointer to network buffer to transmit TCP packet.
*
*               src_addr    Source      IP  address.
*
*               src_port    Source      TCP port.
*
*               dest_addr   Destination IP  address.
*
*               dest_port   Destination TCP port.
*
*               seq_nbr     TCP segment                 sequence number.
*
*               ack_nbr     TCP segment acknowledgement sequence number.
*
*               win_size    TCP receive window advertisement size.
*
*               TOS         Specific TOS to transmit TCP/IP packet
*                               (see 'net_ip.h  IP HEADER TYPE OF SERVICE (TOS) DEFINES').
*
*               TTL         Specific TTL to transmit TCP/IP packet (see RFC #1122, Section 3.2.1.7) :
*
*                               NET_IP_HDR_TTL_MIN        1     minimum TTL transmit value
*                               NET_IP_HDR_TTL_MAX      255     maximum TTL transmit value
*                               NET_IP_HDR_TTL_DFLT             default TTL transmit value
*                               NET_IP_HDR_TTL_NONE       0     replace with default TTL
*
*               flags_tcp   Flags to select TCP transmit options; bit-field flags logically OR'd :
*
*                               NET_TCP_FLAG_NONE               No  TCP transmit flags selected.
*                               NET_TCP_FLAG_TX_FIN             Set TCP 'FIN'    flag.
*                               NET_TCP_FLAG_TX_SYNC            Set TCP 'SYN'    flag.
*                               NET_TCP_FLAG_TX_RESET           Set TCP 'RESET'  flag.
*                               NET_TCP_FLAG_TX_PUSH            Set TCP 'PUSH'   flag.
*                               NET_TCP_FLAG_TX_ACK             Set TCP 'ACK'    flag.
*                               NET_TCP_FLAG_TX_URGENT          Set TCP 'URGENT' flag.
*
*               flags_ip    Flags to select IP  transmit options; bit-field flags logically OR'd :
*
*                               NET_IP_FLAG_NONE                No  IP transmit flags selected.
*                               NET_IP_FLAG_TX_DONT_FRAG        Set IP 'Don't Frag' flag.
*
*               popts_tcp   Pointer to one or more TCP options configuration data structures :
*
*                               NULL                            NO  TCP transmit         options configuration.
*                               NET_TCP_OPT_CFG_MAX_SEG_SIZE    TCP Maximum Segment Size options configuration.
*
*               popts_ip    Pointer to one or more IP  options configuration data structures :
*
*                               NULL                            NO IP transmit options configuration.
*                               NET_IP_OPT_CFG_ROUTE_TS         Route &/or Internet Timestamp options configuration.
*                               NET_IP_OPT_CFG_SECURITY         Security options configuration
*                                                                   (see 'net_ip.c  Note #1f').
*
*               perr        Pointer to variable that will receive the return error code from this function :
*
*                               NET_TCP_ERR_NONE                TCP segments(s) successfully prepared & transmitted
*                                                                   to IP layer.
*                               NET_TCP_ERR_TX                  TCP transmit error; TCP segment buffer(s) discarded.
*
*                                                               ----------- RETURNED BY NetTCP_TxPkt() : -----------
*                               NET_ERR_INIT_INCOMPLETE         Network initialization NOT complete.
*                               NET_ERR_TX                      Transmit error.
*
* Return(s)   : none.
*
* Caller(s)   : NetTCP_TxConnSync(),
*               NetTCP_TxConnAck(),
*               NetTCP_TxConnReset(),
*               NetTCP_TxConnProbe(),
*               NetTCP_TxConnTxQ(),
*               NetTCP_TxConnReTxQ_Timeout().
*
* Note(s)     : (2) Network buffer already freed by lower layer; only increment error counter.
*********************************************************************************************************
*/
/*$PAGE*/
static  void  NetTCP_TxPktHandler (NET_BUF           *pbuf,
                                   NET_IP_ADDR        src_addr,
                                   NET_TCP_PORT_NBR   src_port,
                                   NET_IP_ADDR        dest_addr,
                                   NET_TCP_PORT_NBR   dest_port,
                                   NET_TCP_SEQ_NBR    seq_nbr,
                                   NET_TCP_SEQ_NBR    ack_nbr,
                                   NET_TCP_WIN_SIZE   win_size,
                                   NET_IP_TOS         TOS,
                                   NET_IP_TTL         TTL,
                                   CPU_INT16U         flags_tcp,
                                   CPU_INT16U         flags_ip,
                                   void              *popts_tcp,
                                   void              *popts_ip,
                                   NET_ERR           *perr)
{
#if (((NET_CTR_CFG_STAT_EN     == DEF_ENABLED)                    || \
      (NET_CTR_CFG_ERR_EN      == DEF_ENABLED))                   && \
      (CPU_CFG_CRITICAL_METHOD == CPU_CRITICAL_METHOD_STATUS_LOCAL))
    CPU_SR        cpu_sr;
#endif
    NET_BUF_HDR  *pbuf_hdr;
    NET_ERR       err;



#if (NET_ERR_CFG_ARG_CHK_DBG_EN == DEF_ENABLED)                 /* ------------------- VALIDATE PTR ------------------- */
    if (pbuf == (NET_BUF *)0) {
        NetTCP_TxPktDiscard(pbuf, perr);
        NET_CTR_ERR_INC(NetTCP_ErrNullPtrCtr);
        return;
    }
#endif


                                                                /* --------------- VALIDATE TX TCP PKT ---------------- */
    pbuf_hdr = &pbuf->Hdr;
#if (NET_ERR_CFG_ARG_CHK_DBG_EN == DEF_ENABLED)
    NetTCP_TxPktValidate(pbuf,
                         pbuf_hdr,
                         src_port,
                         dest_port,
                         seq_nbr,
                         ack_nbr,
                         win_size,
                         flags_tcp,
                         popts_tcp,
                         perr);
    switch (*perr) {
        case NET_TCP_ERR_NONE:
             break;


        case NET_ERR_INVALID_PROTOCOL:
        case NET_BUF_ERR_INVALID_IX:
        case NET_TCP_ERR_INVALID_LEN_DATA:
        case NET_TCP_ERR_INVALID_PORT_NBR:
        case NET_TCP_ERR_INVALID_FLAG:
        case NET_TCP_ERR_INVALID_OPT_TYPE:
        case NET_TCP_ERR_INVALID_OPT_CFG:
        default:
             NetTCP_TxPktDiscard(pbuf, &err);
            *perr = NET_TCP_ERR_TX;
             return;                                            /* Prevent 'break NOT reachable' compiler warning.      */
    }
#endif


/*$PAGE*/
                                                                /* -------------------- TX TCP PKT -------------------- */
    NetTCP_TxPkt(pbuf,
                 pbuf_hdr,
                 src_addr,
                 src_port,
                 dest_addr,
                 dest_port,
                 seq_nbr,
                 ack_nbr,
                 win_size,
                 TOS,
                 TTL,
                 flags_tcp,
                 flags_ip,
                 popts_tcp,
                 popts_ip,
                 perr);


                                                                /* ---------- FREE TX PKT / UPDATE TX STATS ----------- */
    switch (*perr) {
        case NET_IP_ERR_NONE:
             NET_CTR_STAT_INC(NetTCP_StatTxSegCtr);
            *perr = NET_TCP_ERR_NONE;
             break;


        case NET_ERR_TX:
             NET_CTR_ERR_INC(NetTCP_ErrTxPktDiscardedCtr);      /* See Note #2.                                         */
             return;                                            /* Prevent 'break NOT reachable' compiler warning.      */


        case NET_ERR_INIT_INCOMPLETE:
        case NET_TCP_ERR_INVALID_LEN_HDR:
        case NET_TCP_ERR_INVALID_OPT_TYPE:
        case NET_TCP_ERR_INVALID_OPT_LEN:
        case NET_BUF_ERR_INVALID_IX:
        case NET_BUF_ERR_INVALID_LEN:
        case NET_UTIL_ERR_NULL_PTR:
        case NET_UTIL_ERR_NULL_SIZE:
        case NET_UTIL_ERR_INVALID_PROTOCOL:
        default:
             NetTCP_TxPktDiscard(pbuf, &err);
            *perr = NET_TCP_ERR_TX;
             return;                                            /* Prevent 'break NOT reachable' compiler warning.      */
    }
}


/*$PAGE*/
/*
*********************************************************************************************************
*                                       NetTCP_TxPktValidate()
*
* Description : (1) Validate TCP transmit packet parameters & options :
*
*                   (a) Packets with the following invalid parameters will be "silently discarded" :
*
*                       (1) Protocols other than supported protocols :
*                           (A) BSD Sockets
*                           (B) TCP                                         See Note #2
*
*                       (2) Data Length
*                       (3) Source      Port
*                       (4) Destination Port
*                       (5) Flags
*
*                   (b) The following parameters are inherently assumed to be valid :
*
*                       (1) Sequence        Number
*                       (2) Acknowledgement Number
*                       (3) Receive Window Size
*
*
* Argument(s) : pbuf        Pointer to network buffer to transmit TCP packet.
*               ----        Argument checked   in NetTCP_TxPktHandler().
*
*               pbuf_hdr    Pointer to network buffer header.
*               --------    Argument validated in NetTCP_TxPktHandler().
*
*               src_port    Source      TCP port.
*
*               dest_port   Destination TCP port.
*
*               seq_nbr     TCP segment                 sequence number.
*
*               ack_nbr     TCP segment acknowledgement sequence number.
*
*               win_size    TCP receive window advertisement size.
*
*               flags_tcp   Flags to select TCP transmit options; bit-field flags logically OR'd :
*
*                               NET_TCP_FLAG_NONE               No  TCP transmit flags selected.
*                               NET_TCP_FLAG_TX_FIN             Set TCP 'FIN'    flag.
*                               NET_TCP_FLAG_TX_SYNC            Set TCP 'SYN'    flag.
*                               NET_TCP_FLAG_TX_RESET           Set TCP 'RESET'  flag.
*                               NET_TCP_FLAG_TX_PUSH            Set TCP 'PUSH'   flag.
*                               NET_TCP_FLAG_TX_ACK             Set TCP 'ACK'    flag.
*                               NET_TCP_FLAG_TX_URGENT          Set TCP 'URGENT' flag.
*
*               popts_tcp   Pointer to one or more TCP options configuration data structures :
*
*                               NULL                            NO  TCP transmit         options configuration.
*                               NET_TCP_OPT_CFG_MAX_SEG_SIZE    TCP Maximum Segment Size options configuration.
*
*               perr        Pointer to variable that will receive the return error code from this function :
*
*                               NET_TCP_ERR_NONE                Transmit packet validated.
*                               NET_ERR_INVALID_PROTOCOL        Invalid/unknown protocol type.
*                               NET_BUF_ERR_INVALID_IX          Invalid or insufficient buffer index.
*                               NET_TCP_ERR_INVALID_LEN_DATA    Invalid protocol/data length.
*                               NET_TCP_ERR_INVALID_PORT_NBR    Invalid TCP port number.
*                               NET_TCP_ERR_INVALID_FLAG        Invalid TCP flag(s).
*
*                                                               - RETURNED BY NetTCP_TxPktValidateOpt() : -
*                               NET_TCP_ERR_INVALID_OPT_TYPE    Invalid TCP option type.
*                               NET_TCP_ERR_INVALID_OPT_CFG     Invalid TCP option configuration.
*
* Return(s)   : none.
*
* Caller(s)   : NetTCP_TxPktHandler().
*
* Note(s)     : none.
*********************************************************************************************************
*/
/*$PAGE*/
#if (NET_ERR_CFG_ARG_CHK_DBG_EN == DEF_ENABLED)
static  void  NetTCP_TxPktValidate (NET_BUF           *pbuf,
                                    NET_BUF_HDR       *pbuf_hdr,
                                    NET_TCP_PORT_NBR   src_port,
                                    NET_TCP_PORT_NBR   dest_port,
                                    NET_TCP_SEQ_NBR    seq_nbr,
                                    NET_TCP_SEQ_NBR    ack_nbr,
                                    NET_TCP_WIN_SIZE   win_size,
                                    CPU_INT16U         flags_tcp,
                                    void              *popts_tcp,
                                    NET_ERR           *perr)
{
#if ((NET_CTR_CFG_ERR_EN      == DEF_ENABLED)                    && \
     (CPU_CFG_CRITICAL_METHOD == CPU_CRITICAL_METHOD_STATUS_LOCAL))
    CPU_SR       cpu_sr;
#endif
    CPU_INT16U   ix;
    CPU_INT16U   len;
    CPU_INT16U   flag_mask;
    CPU_BOOLEAN  flags_tcp_fin_syn;


                                                                /* ----------------- VALIDATE PROTOCOL ---------------- */
    switch (pbuf_hdr->ProtocolHdrType) {
        case NET_PROTOCOL_TYPE_APP:
        case NET_PROTOCOL_TYPE_SOCK:
        case NET_PROTOCOL_TYPE_TCP:
             ix  = (CPU_INT16U)pbuf_hdr->DataIx;
             len = (CPU_INT16U)pbuf_hdr->DataLen;
             break;


        case NET_PROTOCOL_TYPE_NONE:
        default:
             NET_CTR_ERR_INC(NetTCP_ErrTxInvalidProtocolCtr);
            *perr = NET_ERR_INVALID_PROTOCOL;
             return;                                            /* Prevent 'break NOT reachable' compiler warning.      */
    }

    if (ix == NET_BUF_IX_NONE) {
        NET_CTR_ERR_INC(NetTCP_ErrTxInvalidBufIxCtr);
       *perr = NET_BUF_ERR_INVALID_IX;
        return;
    }

    if (ix < NET_TCP_HDR_SIZE_MAX) {
        NET_CTR_ERR_INC(NetTCP_ErrTxInvalidBufIxCtr);
       *perr = NET_BUF_ERR_INVALID_IX;
        return;
    }



                                                                /* -------------- VALIDATE TOT DATA LEN --------------- */
    if (len != pbuf_hdr->TotLen) {
        NET_CTR_ERR_INC(NetTCP_ErrTxHdrDataLenCtr);
       *perr = NET_TCP_ERR_INVALID_LEN_DATA;
        return;
    }



                                                                /* ---------------- VALIDATE TCP PORTS ---------------- */
    if (src_port  == NET_TCP_PORT_NBR_RESERVED) {
        NET_CTR_ERR_INC(NetTCP_ErrTxHdrPortSrcCtr);
       *perr = NET_TCP_ERR_INVALID_PORT_NBR;
        return;
    }

    if (dest_port == NET_TCP_PORT_NBR_RESERVED) {
        NET_CTR_ERR_INC(NetTCP_ErrTxHdrPortDestCtr);
       *perr = NET_TCP_ERR_INVALID_PORT_NBR;
        return;
    }



/*$PAGE*/
                                                                /* ---------------- VALIDATE TCP FLAGS ---------------- */
    flag_mask = NET_TCP_FLAG_NONE     |
                NET_TCP_FLAG_TX_CLOSE |
                NET_TCP_FLAG_TX_SYNC  |
                NET_TCP_FLAG_TX_RESET |
                NET_TCP_FLAG_TX_PUSH  |
                NET_TCP_FLAG_TX_ACK   |
                NET_TCP_FLAG_TX_URGENT;

    if ((flags_tcp & ~flag_mask) != NET_TCP_FLAG_NONE) {        /* If any invalid flags req'd, rtn err.                 */
        NET_CTR_ERR_INC(NetTCP_ErrTxHdrFlagsCtr);
       *perr = NET_TCP_ERR_INVALID_FLAG;
        return;
    }

#if 1                                                           /* ???? Allow invalid 'SYN'/'FIN' flag combo?           */
    flag_mask         = NET_TCP_FLAG_TX_SYNC |
                        NET_TCP_FLAG_TX_FIN;
    flags_tcp_fin_syn = DEF_BIT_IS_SET(flags_tcp, flag_mask);
    if (flags_tcp_fin_syn != DEF_NO) {                          /* If invalid 'SYN'/'FIN' flag combo req'd, rtn err.    */
        NET_CTR_ERR_INC(NetTCP_ErrTxHdrFlagsCtr);
       *perr = NET_TCP_ERR_INVALID_FLAG;
        return;
    }
#endif



                                                                /* ---------------- VALIDATE TCP OPTS ----------------- */
    if (popts_tcp != (void *)0) {
        NetTCP_TxPktValidateOpt(popts_tcp, flags_tcp, perr);
        if (*perr != NET_TCP_ERR_NONE) {
             return;
        }
    }



                                                                /* ------------- IGNORE VALID TCP FIELDS -------------- */
   (void)&seq_nbr;                                              /* Prevent compiler warnings.                           */
   (void)&ack_nbr;
   (void)&win_size;


   *perr = NET_TCP_ERR_NONE;
}
#endif


/*$PAGE*/
/*
*********************************************************************************************************
*                                      NetTCP_TxPktValidateOpt()
*
* Description : Validate TCP transmit option configurations.
*
*               (1) TCP transmit options MUST be configured by appropriate transmit options configuration
*                   data structure(s) passed via 'popts_tcp'; see 'net_tcp.h  TCP HEADER OPTION CONFIGURATION
*                   DATA TYPES' for TCP options configuration.
*
*               (2) TCP header allows for a maximum option size of 40 octets (see 'net_tcp.h  TCP HEADER
*                   OPTIONS DEFINES  Note #3').
*
*
* Argument(s) : popts_tcp   Pointer to one or more TCP options configuration data structures (see Note #1) :
*
*                               NULL                            NO  TCP transmit         options configuration.
*                               NET_TCP_OPT_CFG_MAX_SEG_SIZE    TCP Maximum Segment Size options configuration.
*
*               flags_tcp   Flags to select TCP transmit options; bit-field flags logically OR'd :
*
*                               NET_TCP_FLAG_NONE               No  TCP transmit flags selected.
*                               NET_TCP_FLAG_TX_FIN             Set TCP 'FIN'    flag.
*                               NET_TCP_FLAG_TX_SYNC            Set TCP 'SYN'    flag.
*                               NET_TCP_FLAG_TX_RESET           Set TCP 'RESET'  flag.
*                               NET_TCP_FLAG_TX_PUSH            Set TCP 'PUSH'   flag.
*                               NET_TCP_FLAG_TX_ACK             Set TCP 'ACK'    flag.
*                               NET_TCP_FLAG_TX_URGENT          Set TCP 'URGENT' flag.
*
*               perr        Pointer to variable that will receive the return error code from this function :
*
*                               NET_TCP_ERR_NONE                TCP transmit option configurations validated.
*                               NET_TCP_ERR_INVALID_OPT_TYPE    Invalid TCP option type.
*                               NET_TCP_ERR_INVALID_OPT_CFG     Invalid TCP option configuration.
*
* Return(s)   : none.
*
* Caller(s)   : NetTCP_TxPktValidate().
*
* Note(s)     : (3) (a) See 'net_tcp.h  TCP HEADER OPTIONS DEFINES' for   supported TCP options' summary.
*
*                   (b) See 'net_tcp.c  Note #1c'                   for unsupported TCP options.
*
*               (4) The following TCP transmit options MUST be configured exclusively--i.e. only a single
*                   of each of the following TCP options may be configured for any one TCP segment :
*
*                   (a) NET_TCP_OPT_CFG_TYPE_MAX_SEG_SIZE
*********************************************************************************************************
*/
/*$PAGE*/
#if (NET_ERR_CFG_ARG_CHK_DBG_EN == DEF_ENABLED)
static  void  NetTCP_TxPktValidateOpt (void        *popts_tcp,
                                       CPU_INT16U   flags_tcp,
                                       NET_ERR     *perr)
{
#if ((NET_CTR_CFG_ERR_EN      == DEF_ENABLED)                    && \
     (CPU_CFG_CRITICAL_METHOD == CPU_CRITICAL_METHOD_STATUS_LOCAL))
    CPU_SR       cpu_sr;
#endif
    CPU_INT08U   opt_len_size;
    CPU_INT08U   opt_len;
    CPU_INT08U   opt_nbr_max_seg_size;
    NET_TYPE    *popt_cfg_type;
    void        *popt_cfg;
    void        *popt_next;


    opt_len_size         = 0;
    opt_nbr_max_seg_size = 0;
    popt_cfg             = popts_tcp;

    while (popt_cfg  != (void *)0) {
        popt_cfg_type = (NET_TYPE *)popt_cfg;
        switch (*popt_cfg_type) {
            case NET_TCP_OPT_CFG_TYPE_MAX_SEG_SIZE:             /* ----------------- MAX SEG SIZE OPT ----------------- */
                 if (opt_nbr_max_seg_size > 0) {                /* If > 1 max seg size opt, rtn err.                    */
                     NET_CTR_ERR_INC(NetTCP_ErrTxHdrOptCfgCtr);
                    *perr = NET_TCP_ERR_INVALID_OPT_CFG;
                     return;
                 }
                 opt_nbr_max_seg_size++;

                 NetTCP_TxPktValidateOptMaxSegSize(popt_cfg, &opt_len, &popt_next, flags_tcp, perr);
                 break;

#if 0                                                           /* --------------- UNSUPPORTED TCP OPTS --------------- */
                                                                /* See Note #3b.                                        */
            case NET_TCP_OPT_CFG_TYPE_WIN_SCALE:
            case NET_TCP_OPT_CFG_TYPE_SACK_PERMIT:
            case NET_TCP_OPT_CFG_TYPE_SACK:
            case NET_TCP_OPT_CFG_TYPE_ECHO_REQ:
            case NET_TCP_OPT_CFG_TYPE_ECHO_REPLY:
            case NET_TCP_OPT_CFG_TYPE_TS:
                                                                /* 'break' intentionally omitted; do NOT move from the  */
                                                                /* ... following case : 'NET_TCP_OPT_CFG_TYPE_NONE'.    */
#endif

            case NET_TCP_OPT_CFG_TYPE_NONE:                     /* ----------------- INVALID TCP OPTS ----------------- */
            default:
                 NET_CTR_ERR_INC(NetTCP_ErrTxOptTypeCtr);
                *perr = NET_TCP_ERR_INVALID_OPT_TYPE;
                 return;                                        /* Prevent 'break NOT reachable' compiler warning.      */
        }

        if (*perr != NET_TCP_ERR_NONE) {
             return;
        }

        opt_len_size += opt_len;
        if (opt_len_size > NET_TCP_HDR_OPT_SIZE_MAX) {          /* If tot opt len exceeds max opt len, rtn err.         */
            NET_CTR_ERR_INC(NetTCP_ErrTxHdrOptLenCtr);
           *perr = NET_TCP_ERR_INVALID_OPT_LEN;
            return;
        }

        popt_cfg = popt_next;                                   /* Validate next cfg opt.                               */
    }

   *perr = NET_TCP_ERR_NONE;
}
#endif


/*$PAGE*/
/*
*********************************************************************************************************
*                                 NetTCP_TxPktValidateOptMaxSegSize()
*
* Description : Validate TCP Maximum Segment Size option configuration.
*
*               (1) See 'net_tcp.h  TCP MAXIMUM SEGMENT SIZE OPTION CONFIGURATION DATA TYPE' for valid
*                   TCP Maximum Segment Size option configuration.
*
*               (2) Return option values.
*
*
* Argument(s) : popt_tcp    Pointer to TCP Maximum Segment Size option configuration data structure.
*               --------    Argument checked   in NetTCP_TxPktValidateOpt().
*
*               popt_len    Pointer to variable that will receive the TCP Maximum Segment Size option length
*               --------        (in octets).
*
*                           Argument validated in NetTCP_TxPktValidateOpt().
*
*               popt_next   Pointer to variable that will receive the pointer to the next TCP transmit option.
*               ---------   Argument validated in NetTCP_TxPktValidateOpt().
*
*               flags_tcp   Flags to select TCP transmit options; bit-field flags logically OR'd :
*
*                               NET_TCP_FLAG_NONE               No  TCP transmit flags selected.
*                               NET_TCP_FLAG_TX_FIN             Set TCP 'FIN'    flag.
*                               NET_TCP_FLAG_TX_SYNC            Set TCP 'SYN'    flag.
*                               NET_TCP_FLAG_TX_RESET           Set TCP 'RESET'  flag.
*                               NET_TCP_FLAG_TX_PUSH            Set TCP 'PUSH'   flag.
*                               NET_TCP_FLAG_TX_ACK             Set TCP 'ACK'    flag.
*                               NET_TCP_FLAG_TX_URGENT          Set TCP 'URGENT' flag.
*
*               perr        Pointer to variable that will receive the return error code from this function :
*
*                               NET_TCP_ERR_NONE                TCP Maximum Segment Size option
*                                                                   configuration validated.
*                               NET_TCP_ERR_INVALID_OPT_TYPE    Invalid TCP option type.
*                               NET_TCP_ERR_INVALID_OPT_CFG     Invalid TCP option configuration.
*
* Return(s)   : none.
*
* Caller(s)   : NetTCP_TxPktValidateOpt().
*
* Note(s)     : (3) RFC #793, Section 3.1 'Header Format : Options : Maximum Segment Size' states that a
*                   TCP Maximum Segment Size option "must only be sent in the initial connection request
*                   (i.e., in segments with the SYN control bit set)".
*********************************************************************************************************
*/
/*$PAGE*/
#if (NET_ERR_CFG_ARG_CHK_DBG_EN == DEF_ENABLED)
static  void  NetTCP_TxPktValidateOptMaxSegSize (void         *popt_tcp,
                                                 CPU_INT08U   *popt_len,
                                                 void        **popt_next,
                                                 CPU_INT16U    flags_tcp,
                                                 NET_ERR      *perr)
{
#if ((NET_CTR_CFG_ERR_EN      == DEF_ENABLED)                    && \
     (CPU_CFG_CRITICAL_METHOD == CPU_CRITICAL_METHOD_STATUS_LOCAL))
    CPU_SR                         cpu_sr;
#endif
    NET_TCP_OPT_CFG_MAX_SEG_SIZE  *popt_cfg_max_seg_size;
    CPU_BOOLEAN                    flags_tcp_syn;


    popt_cfg_max_seg_size = (NET_TCP_OPT_CFG_MAX_SEG_SIZE *)popt_tcp;

                                                                /* ------------------ VALIDATE TYPE ------------------- */
    if (popt_cfg_max_seg_size->Type != NET_TCP_OPT_CFG_TYPE_MAX_SEG_SIZE) {
        NET_CTR_ERR_INC(NetTCP_ErrTxOptTypeCtr);
       *perr = NET_TCP_ERR_INVALID_OPT_TYPE;
        return;
    }
                                                                /* -------------- VALIDATE MAX SEG SIZE --------------- */
                                                                /* If max seg size > max, rtn err.                      */
    if (popt_cfg_max_seg_size->MaxSegSize > NET_TCP_MAX_SEG_SIZE_MAX) {
        NET_CTR_ERR_INC(NetTCP_ErrTxHdrOptCfgCtr);
       *perr = NET_TCP_ERR_INVALID_OPT_CFG;
        return;
    }

                                                                /* -------------- VALIDATE OPT CFG/CTRL --------------- */
    flags_tcp_syn = DEF_BIT_IS_SET(flags_tcp, NET_TCP_HDR_FLAG_SYNC);
    if (flags_tcp_syn != DEF_YES) {                             /* If 'SYN' bit NOT set, rtn err (see Note #3).         */
        NET_CTR_ERR_INC(NetTCP_ErrTxHdrOptCfgCtr);
       *perr = NET_TCP_ERR_INVALID_OPT_CFG;
        return;
    }


                                                                /* ------------------- RTN OPT VALS ------------------- */
   *popt_len  = NET_TCP_HDR_OPT_LEN_MAX_SEG_SIZE;
   *popt_next = popt_cfg_max_seg_size->NextOptPtr;
   *perr      = NET_TCP_ERR_NONE;
}
#endif


/*$PAGE*/
/*
*********************************************************************************************************
*                                           NetTCP_TxPkt()
*
* Description : (1) Prepare TCP header & transmit TCP packet to IP layer :
*
*                   (a) Prepare   TCP options (if any)
*                   (b) Calculate TCP header buffer controls
*                   (c) Prepare   TCP header
*                   (d) Transmit  TCP packet
*
*
* Argument(s) : pbuf        Pointer to network buffer to transmit TCP packet.
*               ----        Argument checked   in NetTCP_TxPktHandler().
*
*               pbuf_hdr    Pointer to network buffer header.
*               --------    Argument validated in NetTCP_TxPktHandler().
*
*               src_addr    Source      IP  address.
*
*               src_port    Source      TCP port.
*               --------    Argument checked   in NetTCP_TxPktValidate().
*
*               dest_addr   Destination IP  address.
*
*               dest_port   Destination TCP port.
*               ---------   Argument checked   in NetTCP_TxPktValidate().
*
*               seq_nbr     TCP segment                 sequence number.
*               -------     Argument validated in NetTCP_TxPktValidate().
*
*               ack_nbr     TCP segment acknowledgement sequence number.
*               -------     Argument validated in NetTCP_TxPktValidate().
*
*               win_size    TCP receive window advertisement size.
*               --------    Argument validated in NetTCP_TxPktValidate().
*
*               TOS         Specific TOS to transmit TCP/IP packet
*                               (see 'net_ip.h  IP HEADER TYPE OF SERVICE (TOS) DEFINES').
*
*               TTL         Specific TTL to transmit TCP/IP packet (see RFC #1122, Section 3.2.1.7) :
*
*                               NET_IP_HDR_TTL_MIN        1     minimum TTL transmit value
*                               NET_IP_HDR_TTL_MAX      255     maximum TTL transmit value
*                               NET_IP_HDR_TTL_DFLT             default TTL transmit value
*                               NET_IP_HDR_TTL_NONE       0     replace with default TTL
*
*               flags_tcp   Flags to select TCP transmit options; bit-field flags logically OR'd :
*               ---------
*                               NET_TCP_FLAG_NONE               No  TCP transmit flags selected.
*                               NET_TCP_FLAG_TX_FIN             Set TCP 'FIN'    flag.
*                               NET_TCP_FLAG_TX_SYNC            Set TCP 'SYN'    flag.
*                               NET_TCP_FLAG_TX_RESET           Set TCP 'RESET'  flag.
*                               NET_TCP_FLAG_TX_PUSH            Set TCP 'PUSH'   flag.
*                               NET_TCP_FLAG_TX_ACK             Set TCP 'ACK'    flag.
*                               NET_TCP_FLAG_TX_URGENT          Set TCP 'URGENT' flag.
*
*                           Argument checked   in NetTCP_TxPktValidate().
*
*               flags_ip    Flags to select IP  transmit options; bit-field flags logically OR'd :
*
*                               NET_IP_FLAG_NONE                No  IP transmit flags selected.
*                               NET_IP_FLAG_TX_DONT_FRAG        Set IP 'Don't Frag' flag.
*
*               popts_tcp   Pointer to one or more TCP options configuration data structures :
*               ---------
*                               NULL                            NO  TCP transmit         options configuration.
*                               NET_TCP_OPT_CFG_MAX_SEG_SIZE    TCP Maximum Segment Size options configuration.
*
*                           Argument checked   in NetTCP_TxPktValidate().
*$PAGE*
*               perr        Pointer to variable that will receive the return error code from this function :
*
*                               NET_TCP_ERR_INVALID_LEN_HDR     Invalid TCP header length.
*
*                                                               - RETURNED BY NetTCP_TxPktPrepareOpt() : -
*                               NET_TCP_ERR_INVALID_OPT_TYPE    Invalid TCP option type.
*                               NET_TCP_ERR_INVALID_OPT_LEN     Invalid TCP option length.
*
*                                                               - RETURNED BY NetTCP_TxPktPrepareHdr() : -
*                               NET_BUF_ERR_INVALID_IX          Invalid/insufficient buffer index.
*                               NET_BUF_ERR_INVALID_LEN         Invalid buffer length.
*                               NET_UTIL_ERR_NULL_PTR           Check-sum passed a NULL pointer.
*                               NET_UTIL_ERR_NULL_SIZE          Check-sum passed a zero size.
*                               NET_UTIL_ERR_INVALID_PROTOCOL   Invalid data packet protocol.
*
*                                                               -------- RETURNED BY NetIP_Tx() : --------
*                               NET_IP_ERR_NONE                 TCP/IP packet successfully transmitted.
*                               NET_ERR_INIT_INCOMPLETE         Network initialization NOT complete.
*                               NET_ERR_TX                      Transmit error.
*
* Return(s)   : none.
*
* Caller(s)   : NetTCP_TxPktHandler().
*
* Note(s)     : none.
*********************************************************************************************************
*/
/*$PAGE*/
static  void  NetTCP_TxPkt (NET_BUF           *pbuf,
                            NET_BUF_HDR       *pbuf_hdr,
                            NET_IP_ADDR        src_addr,
                            NET_TCP_PORT_NBR   src_port,
                            NET_IP_ADDR        dest_addr,
                            NET_TCP_PORT_NBR   dest_port,
                            NET_TCP_SEQ_NBR    seq_nbr,
                            NET_TCP_SEQ_NBR    ack_nbr,
                            NET_TCP_WIN_SIZE   win_size,
                            NET_IP_TOS         TOS,
                            NET_IP_TTL         TTL,
                            CPU_INT16U         flags_tcp,
                            CPU_INT16U         flags_ip,
                            void              *popts_tcp,
                            void              *popts_ip,
                            NET_ERR           *perr)
{
    CPU_INT08U        tcp_opt_len_size;
    CPU_INT16U        tcp_hdr_len_size;
    NET_TCP_OPT_SIZE  tcp_hdr_opts[NET_TCP_HDR_OPT_NBR_MAX];


                                                                /* ----------------- PREPARE TCP OPTS ----------------- */
    if (popts_tcp != (void *)0) {
        tcp_opt_len_size = NetTCP_TxPktPrepareOpt((void       *) popts_tcp,
                                                  (CPU_INT08U *)&tcp_hdr_opts[0],
                                                  (NET_ERR    *) perr);
        if (*perr != NET_TCP_ERR_NONE) {
             return;
        }
    } else {
        tcp_opt_len_size = 0;
    }

                                                                /* ---------------- CALC TCP HDR CTRLS ---------------- */
                                                                /* Calc tot TCP hdr len (in octets).                    */
    tcp_hdr_len_size = (CPU_INT16U)(NET_TCP_HDR_SIZE_MIN + tcp_opt_len_size);
#if (NET_ERR_CFG_ARG_CHK_DBG_EN == DEF_ENABLED)
    if (tcp_hdr_len_size > NET_TCP_HDR_SIZE_MAX) {
       *perr = NET_TCP_ERR_INVALID_LEN_HDR;
        return;
    }
#endif


                                                                /* ----------------- PREPARE TCP HDR ------------------ */
    NetTCP_TxPktPrepareHdr(pbuf,
                           pbuf_hdr,
                           tcp_hdr_len_size,
                           tcp_opt_len_size,
                           src_addr,
                           src_port,
                           dest_addr,
                           dest_port,
                           seq_nbr,
                           ack_nbr,
                           win_size,
                           flags_tcp,
                          &tcp_hdr_opts[0],
                           perr);

    if (*perr != NET_TCP_ERR_NONE) {
         return;
    }


                                                                /* -------------------- TX TCP PKT -------------------- */
    NetIP_Tx(pbuf,
             src_addr,
             dest_addr,
             TOS,
             TTL,
             flags_ip,
             popts_ip,
             perr);
}


/*$PAGE*/
/*
*********************************************************************************************************
*                                      NetTCP_TxPktPrepareOpt()
*
* Description : (1) Prepare TCP header with TCP transmit options :
*
*                   (a) Prepare ALL TCP options from configuration
*                           data structure(s)
*                   (b) Pad remaining TCP header octets                     See RFC #793, Section 3.1
*                                                                               'Header Format : Padding'
*
*               (2) TCP transmit options MUST be configured by appropriate options configuration data
*                   structure(s) passed via 'popts_tcp'; see 'net_tcp.h  TCP HEADER OPTION CONFIGURATION
*                   DATA TYPES' for TCP options configuration.
*
*
* Argument(s) : popts_tcp   Pointer to one or more TCP options configuration data structures :
*               ---------
*                               NULL                            NO  TCP transmit         options configuration.
*                               NET_TCP_OPT_CFG_MAX_SEG_SIZE    TCP Maximum Segment Size options configuration.
*
*                           Argument checked   in NetTCP_TxPkt().
*
*               popt_hdr    Pointer to TCP transmit option buffer to prepare TCP options.
*               --------    Argument validated in NetTCP_TxPkt().
*
*               perr        Pointer to variable that will receive the return error code from this function :
*
*                               NET_TCP_ERR_NONE                TCP header options successfully prepared.
*                               NET_TCP_ERR_INVALID_OPT_TYPE    Invalid TCP option type.
*                               NET_TCP_ERR_INVALID_OPT_LEN     Invalid TCP option length.
*
* Return(s)   : Total TCP option length (in octets), if NO errors.
*
*               0,                                   otherwise.
*
* Caller(s)   : NetTCP_TxPkt().
*
* Note(s)     : (3) Transmit arguments & options validated in NetTCP_TxPktValidate()/NetTCP_TxPktValidateOpt() :
*                   (a) Assumes ALL   transmit arguments & options are valid.
*                   (b) Assumes total transmit options' lengths    are valid.
*
*               (4) TCP header allows for a maximum option size of 40 octets (see 'net_tcp.h  TCP HEADER
*                   OPTIONS DEFINES  Note #3').
*
*               (5) (a) RFC # 793, Section 3.1 'Options' states that each option is "a multiple of 8 bits
*                       in length" and "may begin on any octet boundary".
*
*                   (b) Since TCP options are NOT required or guaranteed to align multi-octet words on
*                       appropriate word boundaries, ALL TCP options are prepared a single octet at a time.
*
*               (6) Default case already invalidated in NetTCP_TxPktValidateOpt().  However, the default
*                   case is included as an extra precaution in case any of the TCP transmit options types
*                   are incorrectly modified.
*********************************************************************************************************
*/
/*$PAGE*/
static  CPU_INT08U  NetTCP_TxPktPrepareOpt (void        *popts_tcp,
                                            CPU_INT08U  *popt_hdr,
                                            NET_ERR     *perr)
{
#if ((NET_CTR_CFG_ERR_EN      == DEF_ENABLED)                    && \
     (CPU_CFG_CRITICAL_METHOD == CPU_CRITICAL_METHOD_STATUS_LOCAL))
    CPU_SR       cpu_sr;
#endif
    CPU_INT08U   tcp_opt_len_tot;
    CPU_INT08U   tcp_opt_len;
    CPU_INT08U  *popt_cfg_hdr;
    NET_TYPE    *popt_cfg_type;
    void        *popt_next;
    void        *popt_cfg;


    tcp_opt_len_tot = 0;
    popt_cfg        = popts_tcp;
    popt_cfg_hdr    = popt_hdr;
                                                                /* ----------------- PREPARE TCP OPTS ----------------- */
    while (popt_cfg  != (void *)0) {                            /* Prepare ALL cfg'd TCP opts (see Note #1a).           */
        popt_cfg_type = (NET_TYPE *)popt_cfg;
        switch (*popt_cfg_type) {
            case NET_TCP_OPT_CFG_TYPE_MAX_SEG_SIZE:
                 NetTCP_TxPktPrepareOptMaxSegSize(popt_cfg, popt_cfg_hdr, &tcp_opt_len, &popt_next, perr);
                 break;

#if 0                                                           /* --------------- UNSUPPORTED TCP OPTS --------------- */
            case NET_TCP_OPT_CFG_TYPE_WIN_SCALE:
            case NET_TCP_OPT_CFG_TYPE_SACK_PERMIT:
            case NET_TCP_OPT_CFG_TYPE_SACK:
            case NET_TCP_OPT_CFG_TYPE_ECHO_REQ:
            case NET_TCP_OPT_CFG_TYPE_ECHO_REPLY:
            case NET_TCP_OPT_CFG_TYPE_TS:
                                                                /* 'break' intentionally omitted; do NOT move from the  */
                                                                /* ... following case : 'NET_TCP_OPT_CFG_TYPE_NONE'.    */
#endif

            case NET_TCP_OPT_CFG_TYPE_NONE:                     /* ----------------- INVALID TCP OPTS ----------------- */
            default:                                            /* See Note #6.                                         */
                 NET_CTR_ERR_INC(NetTCP_ErrTxOptTypeCtr);
                *perr =  NET_TCP_ERR_INVALID_OPT_TYPE;
                 return (0);                                    /* Prevent 'break NOT reachable' compiler warning.      */
        }
#if (NET_ERR_CFG_ARG_CHK_DBG_EN == DEF_ENABLED)
        if (*perr != NET_TCP_ERR_NONE) {                        /* See Note #3a.                                        */
             return (0);
        }
        if (tcp_opt_len_tot > NET_TCP_HDR_OPT_SIZE_MAX) {       /* See Note #3b.                                        */
            NET_CTR_ERR_INC(NetTCP_ErrTxHdrOptLenCtr);
           *perr =  NET_TCP_ERR_INVALID_OPT_LEN;
            return (0);
        }
#endif

        tcp_opt_len_tot += tcp_opt_len;
        popt_cfg_hdr    += tcp_opt_len;

        popt_cfg         = popt_next;                           /* Prepare next cfg opt.                                */
    }


                                                                /* ------------------- PAD TCP HDR -------------------- */
    if (tcp_opt_len_tot > 0) {
                                                                /* Pad rem'ing TCP hdr octets (see Note #1b).           */
        while ((tcp_opt_len_tot  % NET_TCP_HDR_OPT_SIZE_WORD) &&
               (tcp_opt_len_tot <= NET_TCP_HDR_OPT_SIZE_MAX )) {
           *popt_cfg_hdr = NET_TCP_HDR_OPT_PAD;
            popt_cfg_hdr++;
            tcp_opt_len_tot++;
        }
#if (NET_ERR_CFG_ARG_CHK_DBG_EN == DEF_ENABLED)
        if (tcp_opt_len_tot > NET_TCP_HDR_OPT_SIZE_MAX) {       /* See Note #3b.                                        */
            NET_CTR_ERR_INC(NetTCP_ErrTxHdrOptLenCtr);
           *perr =  NET_TCP_ERR_INVALID_OPT_LEN;
            return (0);
        }
#endif
    }


   *perr =  NET_TCP_ERR_NONE;

    return (tcp_opt_len_tot);
}


/*$PAGE*/
/*
*********************************************************************************************************
*                                 NetTCP_TxPktPrepareOptMaxSegSize()
*
* Description : (1) Prepare TCP header with TCP Maximum Segment Size option :
*
*                   (a) Prepare TCP Maximum Segment Size option
*                   (b) Return option values
*
*
* Argument(s) : popts_tcp   Pointer to TCP Maximum Segment Size option configuration data structure.
*               ---------   Argument checked   in NetTCP_TxPkt().
*
*               popt_hdr    Pointer to TCP transmit option buffer to prepare TCP Maximum Segment Size option.
*               --------    Argument validated in NetTCP_TxPkt().
*
*               popt_len    Pointer to variable that will receive the returned TCP option length (in octets).
*               --------    Argument validated in NetTCP_TxPktPrepareOpt().
*
*               popt_next   Pointer to variable that will receive the pointer to the next TCP transmit option.
*               --------    Argument validated in NetTCP_TxPktPrepareOpt().
*
*               perr        Pointer to variable that will receive the return error code from this function :
*
*                               NET_TCP_ERR_NONE                TCP Maximum Segment Size option successfully
*                                                                   prepared.
*
* Return(s)   : none.
*
* Caller(s)   : NetTCP_TxPktPrepareOpt().
*
* Note(s)     : (2) See 'net_tcp.h  TCP HEADER OPTIONS DEFINES  Note #2b1' for TCP Maximum Segment Size
*                   option summary.
*
*               (3) Transmit arguments & options validated in NetTCP_TxPktValidate()/NetTCP_TxPktValidateOpt() :
*                   (a) Assumes ALL   transmit arguments & options are valid.
*                   (b) Assumes total transmit options' lengths    are valid.
*
*               (4) (a) RFC # 793, Section 3.1 'Options' states that each option is "a multiple of 8 bits
*                       in length" and "may begin on any octet boundary".
*
*                   (b) Since TCP options are NOT required or guaranteed to align multi-octet words on
*                       appropriate word boundaries, ALL TCP options are prepared a single octet at a time.
*
*               (5) #### 'perr' may NOT be necessary (remove if unnecessary).
*********************************************************************************************************
*/

static  void  NetTCP_TxPktPrepareOptMaxSegSize (void         *popts_tcp,
                                                CPU_INT08U   *popt_hdr,
                                                CPU_INT08U   *popt_len,
                                                void        **popt_next,
                                                NET_ERR      *perr)
{
    NET_TCP_OPT_CFG_MAX_SEG_SIZE  *popt_cfg_max_seg_size;
    CPU_INT08U                    *popt_cfg_hdr;
    CPU_INT08U                     opt_len;
    CPU_INT08U                     max_seg_size_hi;
    CPU_INT08U                     max_seg_size_lo;


                                                                /* ------------- PREPARE MAX SEG SIZE OPT ------------- */
    popt_cfg_max_seg_size = (NET_TCP_OPT_CFG_MAX_SEG_SIZE *)popts_tcp;
    popt_cfg_hdr          =  popt_hdr;

    opt_len               =  NET_TCP_HDR_OPT_LEN_MAX_SEG_SIZE;
    max_seg_size_hi       = (CPU_INT08U)(popt_cfg_max_seg_size->MaxSegSize >> DEF_OCTET_NBR_BITS);
    max_seg_size_lo       = (CPU_INT08U) popt_cfg_max_seg_size->MaxSegSize;


   *popt_cfg_hdr = NET_TCP_HDR_OPT_MAX_SEG_SIZE;                /* Prepare opt type.                                    */
    popt_cfg_hdr++;

   *popt_cfg_hdr = opt_len;                                     /* Prepare opt len.                                     */
    popt_cfg_hdr++;

   *popt_cfg_hdr = max_seg_size_hi;                             /* Prepare max seg size val.                            */
    popt_cfg_hdr++;

   *popt_cfg_hdr = max_seg_size_lo;


                                                                /* ------------------- RTN OPT VALS ------------------- */
   *popt_len  = opt_len;
   *popt_next = popt_cfg_max_seg_size->NextOptPtr;

   *perr      = NET_TCP_ERR_NONE;
}


/*$PAGE*/
/*
*********************************************************************************************************
*                                      NetTCP_TxPktPrepareHdr()
*
* Description : (1) Prepare TCP header :
*
*                   (a) Update network buffer's protocol index & length controls.
*
*                   (b) Prepare the transmit packet's following TCP header fields :
*
*                       (1) Source      Port
*                       (2) Destination Port
*                       (3) Sequence        Number
*                       (4) Acknowledgement Number
*                       (5) Header Length/Flags
*                       (6) Window Advertisement
*                       (7) Check-Sum                                       See Note #3
*                       (8) Urgent Pointer                                  See Note #2
*                       (9) Options
*
*                   (c) Convert the following TCP header fields from host-order to network-order :
*
*                       (1) Source      Port
*                       (2) Destination Port
*                       (3) Sequence        Number
*                       (4) Acknowledgement Number
*                       (5) Header Length/Flags
*                       (6) Window Advertisement
*                       (7) Check-Sum                                       See Note #3e
*                       (8) Urgent Pointer                                  See Note #2
*
*                   (d) Get TCP packet RTT timestamp transmitted.           See 'NetTCP_TxConnRTT_RTO_Calc()
*                                                                                   Note #2a2A1'
*
*$PAGE*
* Argument(s) : pbuf                Pointer to network buffer to transmit TCP packet.
*               ----                Argument checked   in NetTCP_TxPktHandler().
*
*               pbuf_hdr            Pointer to network buffer header.
*               --------            Argument validated in NetTCP_TxPktHandler().
*
*               tcp_hdr_len_tot     Total TCP header length.
*               ---------------     Argument checked   in NetTCP_TxPkt().
*
*               tcp_opt_len_tot     Total TCP header options' length.
*               ---------------     Argument checked   in NetTCP_TxPktPrepareOpt().
*
*               src_addr            Source      IP  address.
*
*               src_port            Source      TCP port.
*               --------            Argument checked   in NetTCP_TxPktValidate().
*
*               dest_addr           Destination IP  address.
*
*               dest_port           Destination TCP port.
*               ---------           Argument checked   in NetTCP_TxPktValidate().
*
*               seq_nbr             TCP segment                 sequence number.
*               -------             Argument validated in NetTCP_TxPktValidate().
*
*               ack_nbr             TCP segment acknowledgement sequence number.
*               -------             Argument validated in NetTCP_TxPktValidate().
*
*               win_size            TCP receive window advertisement size.
*               --------            Argument validated in NetTCP_TxPktValidate().
*
*               flags_tcp           Flags to select TCP transmit options; bit-field flags logically OR'd :
*               ---------
*                                       NET_TCP_FLAG_NONE               No  TCP transmit flags selected.
*                                       NET_TCP_FLAG_TX_FIN             Set TCP 'FIN'    flag.
*                                       NET_TCP_FLAG_TX_SYNC            Set TCP 'SYN'    flag.
*                                       NET_TCP_FLAG_TX_RESET           Set TCP 'RESET'  flag.
*                                       NET_TCP_FLAG_TX_PUSH            Set TCP 'PUSH'   flag.
*                                       NET_TCP_FLAG_TX_ACK             Set TCP 'ACK'    flag.
*                                       NET_TCP_FLAG_TX_URGENT          Set TCP 'URGENT' flag.
*
*                                   Argument checked   in NetTCP_TxPktValidate().
*
*               ptcp_hdr_opts       Pointer to TCP options buffer.
*               -------------       Argument checked   in NetTCP_TxPktPrepareOpt().
*
*               perr        Pointer to variable that will receive the return error code from this function :
*
*                               NET_TCP_ERR_NONE                TCP header successfully prepared.
*
*                                                               ----------- RETURNED BY NetBuf_DataWr() : ------------
*                               NET_BUF_ERR_INVALID_IX          Invalid buffer index  for transmit options.
*                               NET_BUF_ERR_INVALID_LEN         Invalid buffer length for transmit options.
*
*                                                               - RETURNED BY NetUtil_16BitOnesCplChkSumDataCalc() : -
*                               NET_UTIL_ERR_NULL_PTR           Check-sum passed a NULL pointer.
*                               NET_UTIL_ERR_NULL_SIZE          Check-sum passed a zero size.
*                               NET_UTIL_ERR_INVALID_PROTOCOL   Invalid data packet protocol.
*                               NET_BUF_ERR_INVALID_IX          Invalid buffer index.
*
* Return(s)   : none.
*
* Caller(s)   : NetTCP_TxPkt().
*$PAGE*
* Note(s)     : (2) Urgent pointer & data NOT supported (see 'net_tcp.c  Note #1b').
*
*               (3) (a) TCP header Check-Sum MUST be calculated AFTER the entire TCP header has been prepared.
*                       In addition, ALL multi-octet words are converted from host-order to network-order
*                       since "the sum of 16-bit integers can be computed in either byte order" [RFC #1071,
*                       Section 2.(B)].
*
*                   (b) TCP header Check-Sum field MUST be cleared to '0' BEFORE the TCP header Check-Sum is
*                       calculated (see RFC #793, Section 3.1 'Header Format : Checksum').
*
*                   (c) (1) In addition to the TCP segment header & data, the TCP Check-Sum calculation
*                           includes "a 96-bit pseudo header conceptually prefixed to the TCP header ...
*                           [which] contains the Source Address, the Destination Address, the Protocol,
*                           and TCP length" (see RFC #793, Section 3.1 'Header Format : Checksum').
*
*                       (2) Since network check-sum functions REQUIRE that 16-bit one's-complement check-
*                           sum calculations be performed on headers & data arranged in network-order (see
*                           'net_util.c  NetUtil_16BitOnesCplChkSumDataCalc()  Note #3'), TCP pseudo-header
*                           values MUST be set or converted to network-order.
*
*                   (d) RFC #793, Section 3.1 'Header Format : Checksum' specifies that "if a segment contains
*                       an odd number of header and text octets ... the last octet is padded ... with zeros to
*                       form a 16-bit word for checksum purposes".
*
*                       See also 'net_util.c  NetUtil_16BitSumDataCalc()  Note #8'.
*
*                   (e) The TCP header Check-Sum field is returned in network-order & MUST NOT be re-
*                       converted back to host-order (see 'net_util.c  NetUtil_16BitOnesCplChkSumDataCalc()
*                       Note #4').
*********************************************************************************************************
*/
/*$PAGE*/
static  void  NetTCP_TxPktPrepareHdr (NET_BUF           *pbuf,
                                      NET_BUF_HDR       *pbuf_hdr,
                                      CPU_INT16U         tcp_hdr_len_tot,
                                      CPU_INT08U         tcp_opt_len_tot,
                                      NET_IP_ADDR        src_addr,
                                      NET_TCP_PORT_NBR   src_port,
                                      NET_IP_ADDR        dest_addr,
                                      NET_TCP_PORT_NBR   dest_port,
                                      NET_TCP_SEQ_NBR    seq_nbr,
                                      NET_TCP_SEQ_NBR    ack_nbr,
                                      NET_TCP_WIN_SIZE   win_size,
                                      CPU_INT16U         flags_tcp,
                                      CPU_INT32U        *ptcp_hdr_opts,
                                      NET_ERR           *perr)
{
    NET_TCP_HDR         *ptcp_hdr;
    NET_TCP_PSEUDO_HDR   tcp_pseudo_hdr;
    CPU_INT16U           tcp_hdr_len;
    CPU_INT16U           tcp_flags;
    CPU_INT16U           tcp_hdr_len_flags;
    CPU_INT16U           tcp_opt_ix;
    NET_CHK_SUM          tcp_chk_sum;


                                                                /* ----------------- UPDATE BUF CTRLS ----------------- */
    pbuf_hdr->TCP_UDP_HdrLen     =  tcp_hdr_len_tot;
    pbuf_hdr->TCP_UDP_HdrDataIx  =  pbuf_hdr->DataIx - pbuf_hdr->TCP_UDP_HdrLen;

    pbuf_hdr->TotLen            += (NET_BUF_SIZE)pbuf_hdr->TCP_UDP_HdrLen;
    pbuf_hdr->TCP_UDP_TotLen     = (CPU_INT16U  )pbuf_hdr->TotLen;
    pbuf_hdr->TCP_UDP_DataLen    = (CPU_INT16U  )pbuf_hdr->DataLen;

    pbuf_hdr->ProtocolHdrType    =  NET_PROTOCOL_TYPE_TCP;



                                                                /* ----------------- PREPARE TCP HDR ------------------ */
    ptcp_hdr = (NET_TCP_HDR *)&pbuf->Data[pbuf_hdr->TCP_UDP_HdrDataIx];



                                                                /* ---------------- PREPARE TCP PORTS ----------------- */
    NET_UTIL_VAL_COPY_SET_NET_16(&ptcp_hdr->PortSrc,  &src_port);
    NET_UTIL_VAL_COPY_SET_NET_16(&ptcp_hdr->PortDest, &dest_port);



                                                                /* --------------- PREPARE TCP SEQ NBRS --------------- */
    NET_UTIL_VAL_COPY_SET_NET_32(&ptcp_hdr->SeqNbr, &seq_nbr);
    NET_UTIL_VAL_COPY_SET_NET_32(&ptcp_hdr->AckNbr, &ack_nbr);



                                                                /* ------------ PREPARE TCP HDR LEN/FLAGS ------------- */
    tcp_hdr_len        = pbuf_hdr->TCP_UDP_HdrLen / NET_TCP_HDR_LEN_WORD_SIZE;
    tcp_hdr_len      <<= NET_TCP_HDR_LEN_SHIFT;

    tcp_flags          = NET_TCP_HDR_FLAG_NONE;
    tcp_flags         |= flags_tcp;

#if (NET_ERR_CFG_ARG_CHK_DBG_EN == DEF_ENABLED)
    tcp_hdr_len       &= NET_TCP_HDR_LEN_MASK;
    tcp_flags         &= NET_TCP_HDR_FLAG_MASK;
#endif

    tcp_hdr_len_flags  = tcp_hdr_len | tcp_flags;
    NET_UTIL_VAL_COPY_SET_NET_16(&ptcp_hdr->HdrLen_Flags, &tcp_hdr_len_flags);



                                                                /* ----------------- PREPARE TCP WIN ------------------ */
    NET_UTIL_VAL_COPY_SET_NET_16(&ptcp_hdr->WinSize, &win_size);


                                                                /* -------------- PREPARE TCP URGENT PTR -------------- */
                                                                /* See Note #2.                                         */
    NET_UTIL_VAL_SET_NET_16(&ptcp_hdr->UrgentPtr, NET_TCP_HDR_URG_PTR_NONE);



/*$PAGE*/
                                                                /* ----------------- PREPARE TCP OPTS ----------------- */
    if (tcp_opt_len_tot > 0) {
        tcp_opt_ix = pbuf_hdr->TCP_UDP_HdrDataIx + NET_TCP_HDR_OPT_IX;
        NetBuf_DataWr((NET_BUF    *)pbuf,
                      (NET_BUF_SIZE)tcp_opt_ix,
                      (NET_BUF_SIZE)tcp_opt_len_tot,
                      (CPU_INT08U *)ptcp_hdr_opts,
                      (NET_ERR    *)perr);
#if (NET_ERR_CFG_ARG_CHK_DBG_EN == DEF_ENABLED)
        if (*perr != NET_BUF_ERR_NONE) {
             return;
        }
#endif
    }



                                                                /* --------------- PREPARE TCP CHK SUM ---------------- */
    NET_UTIL_VAL_SET_NET_16(&ptcp_hdr->ChkSum, 0x0000);         /* Clr TCP chk sum            (see Note #3b).           */
                                                                /* Cfg TCP chk sum pseudo-hdr (see Note #3c).           */
    tcp_pseudo_hdr.AddrSrc  = (NET_IP_ADDR)NET_UTIL_HOST_TO_NET_32(src_addr);
    tcp_pseudo_hdr.AddrDest = (NET_IP_ADDR)NET_UTIL_HOST_TO_NET_32(dest_addr);
    tcp_pseudo_hdr.Zero     = (CPU_INT08U )0x00;
    tcp_pseudo_hdr.Protocol = (CPU_INT08U )NET_IP_HDR_PROTOCOL_TCP;
    tcp_pseudo_hdr.TotLen   = (CPU_INT16U )NET_UTIL_HOST_TO_NET_16(pbuf_hdr->TCP_UDP_TotLen);
                                                                /* Calc TCP chk sum.                                    */
    tcp_chk_sum             =  NetUtil_16BitOnesCplChkSumDataCalc((void     *) pbuf,
                                                                  (void     *)&tcp_pseudo_hdr,
                                                                  (CPU_INT16U) NET_TCP_PSEUDO_HDR_SIZE,
                                                                  (NET_ERR  *) perr);
    if (*perr != NET_UTIL_ERR_NONE) {
         return;
    }

    NET_UTIL_VAL_COPY_16(&ptcp_hdr->ChkSum, &tcp_chk_sum);      /* Copy TCP chk sum in net order (see Note #3e).        */



                                                                /* ---------------- GET TCP RTT TX TS ----------------- */
    pbuf_hdr->TCP_RTT_TS_Txd_ms = (CPU_INT32U)NetTCP_TxConnRTT_GetTS_ms();



   *perr = NET_TCP_ERR_NONE;
}


/*$PAGE*/
/*
*********************************************************************************************************
*                                         NetTCP_TxPktFree()
*
* Description : Free network buffer(s).
*
* Argument(s) : pbuf_q      Pointer to network buffer queue.
*
* Return(s)   : none.
*
* Caller(s)   : NetTCP_RxPktConnHandlerReTxQ(),
*               NetTCP_TxConnAck(),
*               NetTCP_TxConnReset().
*
* Note(s)     : (1) (a) Although TCP Transmit initially requests the network buffer for transmit, the
*                       TCP layer maintains a reference to the buffer for possible retransmission.
*
*                   (b) Therefore, even though the network interface layer frees ALL unreferenced
*                       buffers after successful transmission [see 'net_if_pkt.c  NetIF_Pkt_TxPktFree()'
*                       or 'net_if_char.c  NetIF_Char_TxPktFree()'], the TCP layer MUST free transmit
*                       buffers which are still referenced.
*********************************************************************************************************
*/

static  void  NetTCP_TxPktFree (NET_BUF  *pbuf_q)
{
    NetBuf_FreeBufQ_PrimList((NET_BUF *)pbuf_q,
                             (NET_CTR *)0);
}


/*
*********************************************************************************************************
*                                        NetTCP_TxPktDiscard()
*
* Description : On any Transmit packet errors, discard TCP packet(s) & buffer(s).
*
* Argument(s) : pbuf        Pointer to network buffer.
*
*               perr        Pointer to variable that will receive the return error code from this function :
*
*                               NET_ERR_TX                      Transmit error.
*
* Return(s)   : none.
*
* Caller(s)   : NetTCP_TxConnAppData(),
*               NetTCP_TxPktHandler().
*
* Note(s)     : (1) Since some TCP Transmit packets are passed the network buffer from other TCP functions,
*                   they may NOT be the buffers' only references & MUST therefore check buffers' reference
*                   counter before freeing buffers.
*********************************************************************************************************
*/

static  void  NetTCP_TxPktDiscard (NET_BUF  *pbuf,
                                   NET_ERR  *perr)
{
    NET_CTR  *pctr;


#if (NET_CTR_CFG_ERR_EN == DEF_ENABLED)
    pctr = (NET_CTR *)&NetTCP_ErrTxPktDiscardedCtr;
#else
    pctr = (NET_CTR *) 0;
#endif
    NetBuf_FreeBufQ_PrimList((NET_BUF *)pbuf,
                             (NET_CTR *)pctr);

   *perr = NET_ERR_TX;
}


/*$PAGE*/
/*
*********************************************************************************************************
*                                          NetTCP_ConnCfg()
*
* Description : (1) Configure TCP connection's controls :
*
*                   (a) Configure  TCP connection's connection maximum segment size         See Note #2
*                   (b) Configure  TCP connection's receive  window controls                See Note #3
*                   (c) Configure  TCP connection's transmit window controls                See Note #4
*                   (d) Initialize TCP connection's transmit round-trip time &
*                                                re-transmit timeout controls
*
*
* Argument(s) : pconn       Pointer to a TCP connection.
*               -----       Argument validated in NetTCP_RxPktConnHandlerListen(),
*                                                 NetTCP_RxPktConnHandlerSyncTxd(),
*                                                 NetTCP_ConnClr().
*
*               cfg_code    Select which close action(s) to perform; bit-field flags logically OR'd :
*
*                               NET_TCP_CONN_CFG_NONE                   Perform NO  configuration actions.
*                               NET_TCP_CONN_CFG_ALL                    Perform ALL configuration actions.
*
*                               NET_TCP_CONN_CFG_MAX_SEG_SIZE_LOCAL     Configure local      maximum segment size.
*                               NET_TCP_CONN_CFG_MAX_SEG_SIZE_REMOTE    Configure remote     maximum segment size.
*                               NET_TCP_CONN_CFG_MAX_SEG_SIZE_CONN      Configure connection maximum segment size.
*                               NET_TCP_CONN_CFG_MAX_SEG_SIZE_ALL       Configure ALL        maximum segment sizes.
*
*                               NET_TCP_CONN_CFG_WIN_SIZE_RX            Configure receive    window size(s).
*                               NET_TCP_CONN_CFG_WIN_SIZE_TX            Configure transmit   window size(s).
*                               NET_TCP_CONN_CFG_WIN_SIZE_CONN          Configure connection window size(s).
*                               NET_TCP_CONN_CFG_WIN_SIZE_ALL           Configure ALL        window sizes.
*
*                               NET_TCP_CONN_CFG_TX_RTT_RTO             Configure transmit round-trip time (RTT)
*                                                                           & re-transmit timeout (RTO) control(s).
*
*                           See also 'TCP CONNECTION CONFIGURATION CODE DEFINES'.
*
* Return(s)   : none.
*
* Caller(s)   : NetTCP_RxPktConnHandlerListen(),
*               NetTCP_RxPktConnHandlerSyncTxd(),
*               NetTCP_ConnClr().
*
* Note(s)     : (2) A TCP connection's connection maximum segment size should NOT be updated until
*                   after certain other TCP connection control(s) have been configured.
*
*                   See also 'NetTCP_ConnCfgMaxSegSize()   Note #3'.
*
*               (3) A TCP connection's receive  window controls should NOT be updated until after
*                   certain other TCP connection control(s) have been configured.
*
*                   See also 'NetTCP_RxConnWinSizeCfg()    Note #2'.
*
*               (4) A TCP connection's transmit window controls should NOT be updated until after
*                   certain other TCP connection control(s) have been configured.
*
*                   See also 'NetTCP_TxConnWinSizeCfg()    Note #2'.
*
*               (5) A TCP connection's transmit round-trip time & re-transmit timeout controls
*                   should NOT be updated until after certain other TCP connection control(s)
*                   have been configured.
*
*                   See also 'NetTCP_TxConnRTT_RTO_Init()  Note #1'.
*********************************************************************************************************
*/

static  void  NetTCP_ConnCfg (NET_TCP_CONN      *pconn,
                              NET_TCP_CFG_CODE   cfg_code)
{
    CPU_BOOLEAN  cfg_conn_max_seg_size;
    CPU_BOOLEAN  cfg_conn_win_size;
    CPU_BOOLEAN  cfg_conn_tx_rtt_rto;


    cfg_conn_max_seg_size = DEF_BIT_IS_SET(cfg_code, NET_TCP_CONN_CFG_MAX_SEG_SIZE_CONN);
    if (cfg_conn_max_seg_size == DEF_YES) {
        NetTCP_ConnCfgMaxSegSize(pconn);                                /* Cfg  conn max seg size  (see Note #2).       */
    }

    cfg_conn_win_size     = DEF_BIT_IS_SET(cfg_code, NET_TCP_CONN_CFG_WIN_SIZE_ALL);
    if (cfg_conn_win_size     == DEF_YES) {
        NetTCP_RxConnWinSizeCfg(pconn);                                 /* Cfg  rx win ctrls       (see Note #3).       */
        NetTCP_TxConnWinSizeCfg(pconn);                                 /* Cfg  tx win ctrls       (see Note #4).       */
    }

    cfg_conn_tx_rtt_rto   = DEF_BIT_IS_SET(cfg_code, NET_TCP_CONN_CFG_TX_RTT_RTO);
    if (cfg_conn_tx_rtt_rto   == DEF_YES) {
        NetTCP_TxConnRTT_RTO_Init(pconn);                               /* Init tx RTT / RTO ctrls (see Note #5).       */
    }
}


/*$PAGE*/
/*
*********************************************************************************************************
*                                     NetTCP_ConnCfgMaxSegSize()
*
* Description : Configure TCP connection's maximum segment size.
*
* Argument(s) : pconn       Pointer to a TCP connection.
*               -----       Argument validated in NetTCP_ConnCfg().
*
* Return(s)   : none.
*
* Caller(s)   : NetTCP_ConnCfg().
*
* Note(s)     : (1) RFC #1122, Section 4.2.2.6 states that "the maximum size of a segment that TCP really
*                   sends, the 'effective send MSS', MUST be the smaller of the send MSS ... and ... less
*                   than or equal to ... the maximum size ... that can be received".
*
*               (2) In order to avoid transmit window deadlock with a remote host's receive window, the
*                   TCP connection's connection maximum segment size MUST be configured to ensure that
*                   full, maximum-segment-sized segments will transmit even for receive windows less than
*                   the default maximum segment size.
*
*                   (a) RFC #1122, Section 4.2.3.4.(3) states to "send data ... if at least a fraction Fs
*                       of the maximum window can be sent ... Fs is a fraction whose recommended value is
*                       1/2".
*
*                       Thus, it seems reasonable to calculate & limit the remote host's maximum window
*                       size by a similar fraction.
*
*               (3) A TCP connection's connection maximum segment size should NOT be updated until after
*                   the following TCP connection control(s) have been configured :
*
*                       (a) TCP connection's local  maximum segment size ('MaxSegSizeLocal')
*                               [see 'NetTCP_ConnClr()  Note #3a']
*
*                       (b) TCP connection's remote maximum segment size ('MaxSegSizeRemote')
*                               [see 'NetTCP_RxPktConnHandlerListen()   Note #7'
*                                  & 'NetTCP_RxPktConnHandlerSyncTxd()  Note #3']
*
*                       (c) TCP connection's maximum transmit remote window size ('TxWinSizeRemoteMax')
*                               [see 'NetTCP_RxPktConnHandlerTxWinRemote()   Note  #1a2A'
*                                  & 'NetTCP_TxConnWinSizeHandlerCongCtrl()  Notes #3a2A & #3b']
*********************************************************************************************************
*/

static  void  NetTCP_ConnCfgMaxSegSize (NET_TCP_CONN  *pconn)
{
    NET_TCP_WIN_SIZE  remote_win_size_th;
    NET_TCP_SEG_SIZE  remote_max_seg_size;

                                                                /* Calc remote max seg size (see Note #2).              */
    remote_win_size_th    = (NET_TCP_WIN_SIZE)(((CPU_INT32U)pconn->TxWinSizeRemoteMax * NET_TCP_TX_SILLY_WIN_NUMER)
                                                                                      / NET_TCP_TX_SILLY_WIN_DENOM);
    remote_max_seg_size   = (NET_TCP_SEG_SIZE)DEF_MIN(pconn->MaxSegSizeRemote,
                                                      remote_win_size_th);

                                                                /* Cfg conn max seg size    (see Note #1).              */
    pconn->MaxSegSizeConn = (NET_TCP_SEG_SIZE)DEF_MIN(pconn->MaxSegSizeLocal,
                                                      remote_max_seg_size);
}


/*$PAGE*/
/*
*********************************************************************************************************
*                                         NetTCP_ConnClose()
*
* Description : (1) Close a TCP connection due to TCP connection fault(s) :
*
*                   (a) Update   TCP connection close statistic(s)
*                   (b) Transmit TCP connection reset to remote host                    See Note #4
*                   (c) Close    TCP connection 
*
*
*               (2) TCP connection closed internally by TCP layer when certain TCP connection parameters
*                   are corrupted or when certain valid TCP connection operations fail.
*
*               (3) Since the mechanisms of TCP connection close are independent of the application layer
*                   close; TCP connection MAY need to close application layer connection(s).
*
*                   See also 'NetTCP_ConnCloseHandler()  Note #2b'.
*
*
* Argument(s) : pconn               Pointer to a TCP connection.
*               -----               Argument validated in various.
*
*               pbuf_hdr            Pointer to network buffer header that received TCP packet.
*
*               close_conn_app      Indicate whether to close application connection (see Note #3):
*
*                                       DEF_YES                        Close application connection.
*                                       DEF_NO                  Do NOT close application connection.
*
*               close_code      Select which close action(s) to perform; bit-field flags logically OR'd :
*
*                                   NET_TCP_CONN_CLOSE_NONE                 Perform NO  close actions.
*                                   NET_TCP_CONN_CLOSE_ALL                  Perform ALL close actions.
*
*                                   NET_TCP_CONN_CLOSE_CONN_TX_RESET        Perform close connection transmit reset.
*                                   NET_TCP_CONN_CLOSE_CONN_ALL             Perform ALL   connection close    actions.
*
*                                   NET_TCP_CONN_CLOSE_TMR_TX_IDLE          Close    transmit idle                  timer.
*                                   NET_TCP_CONN_CLOSE_TMR_TX_SILLY_WIN     Close    transmit silly window persist  timer.
*                                   NET_TCP_CONN_CLOSE_TMR_TX_ZERO_WIN      Close    transmit zero  window persist  timer.
*                                   NET_TCP_CONN_CLOSE_TMR_TX_ACK_DLY       Close    transmit acknowledgement delay timer.
*                                   NET_TCP_CONN_CLOSE_TMR_RE_TX            Close re-transmit                       timer.
*                                   NET_TCP_CONN_CLOSE_TMR_KEEP_ALIVE       Close connection keep-alive             timer.
*                                   NET_TCP_CONN_CLOSE_TMR_TIMEOUT          Close connection                        timer.
*                                   NET_TCP_CONN_CLOSE_TMR_ALL              Close ALL                               timers.
*
*                               See also 'TCP CONNECTION CLOSE/FREE CODE DEFINES'.
*
* Return(s)   : none.
*
* Caller(s)   : various.
*
* Note(s)     : (4) Although NO RFC directly states to transmit a TCP reset segment when a TCP connection
*                   fault-closes, it is inferred & seems reasonable that a TCP reset segment SHOULD be
*                   transmitted whenever a TCP connection closes abnormally from any of the following 
*                   synchronization/connected/closing states :
*
*                   (a) SYN-RECEIVED
*                   (b) SYN-SENT
*                   (c) ESTABLISHED
*                   (d) FIN-WAIT-1
*                   (e) FIN-WAIT-2
*                   (f) CLOSING
*                   (g) TIME_WAIT
*                   (h) CLOSE-WAIT
*                   (i) LAST-ACK
*
*                   See also 'NetTCP_TxConnReset()  Note #3b'.
*
*               (5) On any TCP connection handler function fault(s), TCP connection MUST NEVER be re-closed.
*
*                   See also 'NetTCP_ConnCloseHandler()  Note #4'.
*********************************************************************************************************
*/
/*$PAGE*/
static  void  NetTCP_ConnClose (NET_TCP_CONN        *pconn,
                                NET_BUF_HDR         *pbuf_hdr,
                                CPU_BOOLEAN          close_conn_app,
                                NET_TCP_CLOSE_CODE   close_code)
{
#if ((NET_CTR_CFG_ERR_EN      == DEF_ENABLED)                    && \
     (CPU_CFG_CRITICAL_METHOD == CPU_CRITICAL_METHOD_STATUS_LOCAL))
    CPU_SR       cpu_sr;
#endif
    CPU_BOOLEAN  tx_reset;
    NET_ERR      err;

                                                                            /* ---------- UPDATE CLOSE STATS ---------- */
    NET_CTR_ERR_INC(NetTCP_ErrConnCloseCtr);

                                                                            /* ---------- TX TCP CONN RESET ----------- */
    tx_reset = DEF_BIT_IS_SET(close_code, NET_TCP_CONN_CLOSE_CONN_TX_RESET);
    if (tx_reset == DEF_YES) {                                              /* Tx TCP conn reset (see Note #4).         */
        NetTCP_TxConnReset((NET_TCP_CONN     *) pconn,
                           (NET_BUF_HDR      *) pbuf_hdr,
                           (NET_TCP_RESET_CODE) NET_TCP_CONN_TX_RESET_FAULT,
                           (NET_TCP_CLOSE_CODE) NET_TCP_CONN_CLOSE_NONE,    /* MUST NOT re-close TCP conn (see Note #5).*/
                           (NET_ERR          *)&err);
    }

                                                                            /* ------------ CLOSE TCP CONN ------------ */
    NetTCP_ConnCloseHandler(pconn, close_conn_app, close_code);
}


/*$PAGE*/
/*
*********************************************************************************************************
*                                      NetTCP_ConnCloseHandler()
*
* Description : (1) Close a TCP connection :
*
*                   (a) Close network connection(s)                                 See Note #2
*                   (b) Free  TCP     connection 
*
*
*               (2) (a) TCP connection's network     connection(s) MUST be closed BEFORE the TCP connection
*                       is closed/freed.
*
*                   (b) TCP connection's application connection(s) :
*
*                       (1) MAY be CLOSED &/or reset :
*
*                           (A) For the following TCP connection condition(s), the TCP connection MUST
*                               close the application connection(s) :
*
*                               (1) (a) Invalid TCP connection parameters :
*                                       (1) Invalid TCP connection state(s)
*                                       (2) Invalid/corrupted TCP data queue(s) :
*                                           (A) Invalid sequence numbers
*                                           (B) Invalid segment  lengths
*
*                                   (b) Fatal TCP transmit     fault(s)
*                                   (c) TCP connection closing fault(s)
*
*                               (2) Invalid network connection configuration
*
*                           (B) For the following TCP connection condition(s), the TCP connection SHOULD
*                               close the application connection(s) based on its application close flag
*                               ('ConnCloseAppFlag') :
*
*                               (1) Valid TCP connection closing states/timeouts
*
*                           (C) For the following TCP connection condition(s), the TCP connection MAY --
*                               but is NOT required to -- close the application connection(s) :
*
*                               (1) Initial TCP connection configuration/preparation
*
*                       (2) But possibly NOT freed, since some application connections have NO mechanism
*                           or API to close an application's reference to the connection.
*
*                       See also specific application connection close function(s) for additional notes.
*
*
* Argument(s) : pconn               Pointer to a TCP connection.
*               -----               Argument validated in NetTCP_ConnClose(),
*                                                         NetTCP_ConnCloseTimeout(),
*                                                         various.
*
*               close_conn_app      Indicate whether to close application connection (see Note #2b):
*
*                                       DEF_YES                        Close application connection.
*                                       DEF_NO                  Do NOT close application connection.
*
*               close_code      Select which close action(s) to perform; bit-field flags logically OR'd :
*
*                                   NET_TCP_CONN_CLOSE_NONE                 Perform NO  close actions.
*                                   NET_TCP_CONN_CLOSE_ALL                  Perform ALL close actions.
*
*                                   NET_TCP_CONN_CLOSE_CONN_TX_RESET        Perform close connection transmit reset.
*                                   NET_TCP_CONN_CLOSE_CONN_ALL             Perform ALL   connection close    actions.
*
*                                   NET_TCP_CONN_CLOSE_TMR_TX_IDLE          Close    transmit idle                  timer.
*                                   NET_TCP_CONN_CLOSE_TMR_TX_SILLY_WIN     Close    transmit silly window persist  timer.
*                                   NET_TCP_CONN_CLOSE_TMR_TX_ZERO_WIN      Close    transmit zero  window persist  timer.
*                                   NET_TCP_CONN_CLOSE_TMR_TX_ACK_DLY       Close    transmit acknowledgement delay timer.
*                                   NET_TCP_CONN_CLOSE_TMR_RE_TX            Close re-transmit                       timer.
*                                   NET_TCP_CONN_CLOSE_TMR_KEEP_ALIVE       Close connection keep-alive             timer.
*                                   NET_TCP_CONN_CLOSE_TMR_TIMEOUT          Close connection                        timer.
*                                   NET_TCP_CONN_CLOSE_TMR_ALL              Close ALL                               timers.
*
*                               See also 'TCP CONNECTION CLOSE/FREE CODE DEFINES'.
*
* Return(s)   : none.
*
* Caller(s)   : NetTCP_ConnClose(),
*               NetTCP_ConnCloseTimeout(),
*               various.
*
* Note(s)     : (3) TCP connection free codes are identical to TCP connection close codes.
*
*                   See also 'TCP CONNECTION CLOSE/FREE CODE DEFINES  Note #2'.
*
*               (4) On any TCP connection close, TCP connection MUST NEVER be re-closed.
*********************************************************************************************************
*/
/*$PAGE*/
static  void  NetTCP_ConnCloseHandler (NET_TCP_CONN        *pconn,
                                       CPU_BOOLEAN          close_conn_app,
                                       NET_TCP_CLOSE_CODE   close_code)
{
#if ((NET_ERR_CFG_ARG_CHK_DBG_EN == DEF_ENABLED)                    && \
     (NET_CTR_CFG_ERR_EN         == DEF_ENABLED)                    && \
     (CPU_CFG_CRITICAL_METHOD    == CPU_CRITICAL_METHOD_STATUS_LOCAL))
    CPU_SR             cpu_sr;
#endif
#if  (NET_ERR_CFG_ARG_CHK_DBG_EN == DEF_ENABLED)
    CPU_BOOLEAN        used;
#endif
    NET_TCP_FREE_CODE  free_code;

                                                                    /* ------------ VALIDATE TCP CONN CLOSE ----------- */
#if (NET_ERR_CFG_ARG_CHK_DBG_EN == DEF_ENABLED)
    used = DEF_BIT_IS_SET(pconn->Flags, NET_TCP_FLAG_USED);
    if (used != DEF_YES) {
        NET_CTR_ERR_INC(NetTCP_ErrNotUsedCtr);
        return;
    }
#endif

    switch (pconn->ConnState) {
        case NET_TCP_CONN_STATE_LISTEN:
        case NET_TCP_CONN_STATE_SYNC_RXD:
        case NET_TCP_CONN_STATE_SYNC_RXD_PASSIVE:
        case NET_TCP_CONN_STATE_SYNC_RXD_ACTIVE:
        case NET_TCP_CONN_STATE_SYNC_TXD:
        case NET_TCP_CONN_STATE_CONN:
        case NET_TCP_CONN_STATE_FIN_WAIT_1:
        case NET_TCP_CONN_STATE_FIN_WAIT_2:
        case NET_TCP_CONN_STATE_CLOSING:
        case NET_TCP_CONN_STATE_TIME_WAIT:
        case NET_TCP_CONN_STATE_CLOSE_WAIT:
        case NET_TCP_CONN_STATE_LAST_ACK:
        case NET_TCP_CONN_STATE_CLOSING_DATA_AVAIL:
             break;


        case NET_TCP_CONN_STATE_NONE:
        case NET_TCP_CONN_STATE_FREE:                               /* MUST NOT re-close TCP conn if already ..         */
        case NET_TCP_CONN_STATE_CLOSED:                             /* .. free/closed (see Note #4).                    */
        default:
             return;                                                /* Prevent 'break NOT reachable' warning.           */
    }


                                                                    /* ---------------- CLOSE CONN(S) ----------------- */
    NetConn_CloseFromTransport(pconn->ID_Conn, close_conn_app);
    pconn->ID_Conn = NET_CONN_ID_NONE;                              /* Clr TCP conn's net conn id.                      */

                                                                    /* ---------------- FREE TCP CONN ----------------- */
    free_code = (NET_TCP_FREE_CODE)close_code;                      /* See Note #3.                                     */
    NetTCP_ConnFreeHandler(pconn, free_code);
}


/*$PAGE*/
/*
*********************************************************************************************************
*                                      NetTCP_ConnCloseTimeout()
*
* Description : Close a TCP connection on timeout.
*
* Argument(s) : pconn_timeout       Pointer to a TCP connection (see Note #1b).
*
* Return(s)   : none.
*
* Caller(s)   : Referenced in NetTCP_ConnReqClose(),
*                     various NetTCP_RxPktConnHandler() functions.
*
* Note(s)     : (1) Ideally, network timer expiration functions could be defined as '[(void) (OBJECT *)]' 
*                   type functions -- even though network timer API functions cast expiration functions 
*                   to generic 'CPU_FNCT_PTR' type (i.e. '[(void) (void *)]').
*
*                   (a) (1) Unfortunately, ISO-IEC 9899-1999 ANSI-C, Section 6.3.2.3.7 states that "a 
*                           pointer to an object ... may be converted to a pointer to a different object 
*                           ... [but] if the resulting pointer is not correctly aligned ... the behavior
*                           is undefined".
*
*                           And since compilers may NOT correctly convert 'void' pointers to non-'void' 
*                           pointer arguments, network timer expiration functions MUST avoid incorrect
*                           pointer conversion behavior between 'void' pointer parameters & non-'void' 
*                           pointer arguments & therefore CANNOT be defined as '[(void) (OBJECT *)]'.
*
*                       (2) However, Section 6.3.2.3.1 states that "a pointer to void may be converted 
*                           to or from a pointer to any ... object ... A pointer to any ... object ... 
*                           may be converted to a pointer to void and back again; the result shall 
*                           compare equal to the original pointer".
*                   
*                   (b) Therefore, to correctly convert 'void' pointer objects back to appropriate
*                       network object pointer objects, network timer expiration functions MUST :
*
*                       (1) Be defined as 'CPU_FNCT_PTR' type (i.e. '[(void) (void *)]'); &       ...
*                       (2) Explicitly cast 'void' pointer arguments to specific object pointers; ...
*                           (A) ... in this case, a 'NET_TCP_CONN' pointer.
*
*                   See also 'net_tmr.c  NetTmr_Get()  Note #3'.
*
*               (2) This function is a network timer expiration function :
*
*                   (a) (1) For the following connection timer(s) ... :
*
*                           (A) TCP connection timeout timer ('TimeoutTmr')
*
*                       (2) (A) Clear the timer pointer; ...
*                               (1) Cleared in NetTCP_ConnFreeTmr() via NetTCP_ConnClose(),
*                                                                       NetTCP_ConnCloseHandler().
*
*                           (B) but do NOT re-free the timer.
*
*                   (b) Do NOT set the following close timer flag(s) :
*
*                       (1) NET_TCP_CONN_CLOSE_TMR_TIMEOUT
*********************************************************************************************************
*/
/*$PAGE*/
static  void  NetTCP_ConnCloseTimeout (void  *pconn_timeout)
{
#if ((NET_ERR_CFG_ARG_CHK_DBG_EN == DEF_ENABLED)                    && \
     (NET_CTR_CFG_ERR_EN         == DEF_ENABLED)                    && \
     (CPU_CFG_CRITICAL_METHOD    == CPU_CRITICAL_METHOD_STATUS_LOCAL))
    CPU_SR               cpu_sr;
#endif
    NET_TCP_CONN        *pconn;
    NET_TCP_CLOSE_CODE   close_code;


    pconn = (NET_TCP_CONN *)pconn_timeout;                          /* See Note #1b2A.                                  */

#if (NET_ERR_CFG_ARG_CHK_DBG_EN == DEF_ENABLED)
                                                                    /* ---------------- VALIDATE PTR ------------------ */
    if (pconn == (NET_TCP_CONN *)0) {
        NET_CTR_ERR_INC(NetTCP_ErrNullPtrCtr);
        return;
    }
                                                                    /* ---------------- VALIDATE TYPE ----------------- */
    if (pconn->Type != NET_TCP_TYPE_CONN) {
        NET_CTR_ERR_INC(NetTCP_ErrConnInvalidTypeCtr);
        return;
    }
#endif

                                                                    /* ---------------- CLOSE TCP CONN ---------------- */
    close_code = NET_TCP_CONN_CLOSE_ALL;
    DEF_BIT_CLR(close_code, NET_TCP_CONN_CLOSE_TMR_TIMEOUT);        /* See Note #2b1.                                   */

    if (pconn->ConnCloseTimeoutFaultFlag != DEF_NO) {               /* If TCP conn timeout fault, ...                   */
                                                                    /* ... fault-close TCP conn.                        */
        NetTCP_ConnClose((NET_TCP_CONN     *)pconn,
                         (NET_BUF_HDR      *)0,
                         (CPU_BOOLEAN       )pconn->ConnCloseAppFlag,
                         (NET_TCP_CLOSE_CODE)close_code);

    } else {                                                        /* Else      close TCP conn.                        */
        NetTCP_ConnCloseHandler((NET_TCP_CONN     *)pconn,
                                (CPU_BOOLEAN       )pconn->ConnCloseAppFlag,
                                (NET_TCP_CLOSE_CODE)close_code);
    }
}


/*$PAGE*/
/*
*********************************************************************************************************
*                                NetTCP_ConnClosingTimeoutDataAvail()
*
* Description : (1) Handle closing TCP connection with available application data :
*
*                   (a) If TCP connection's application receive queue is       now empty,
*                           close the TCP connection
*                   (b) If TCP connection's application receive queue is still NOT empty
*                           after the time-wait timeout, set the user connection timeout
*
*                   See also 'NetTCP_RxPktConnHandlerFinWait1()  Note #2f5A2b',
*                            'NetTCP_RxPktConnHandlerFinWait2()  Note #2f5B2',
*                          & 'NetTCP_RxPktConnHandlerClosing()   Note #2d2B2a1B2'.
*
*
* Argument(s) : pconn_timeout       Pointer to a TCP connection (see Note #2b).
*
* Return(s)   : none.
*
* Caller(s)   : Referenced in NetTCP_RxPktConnHandlerFinWait1(),
*                             NetTCP_RxPktConnHandlerFinWait2(),
*                             NetTCP_RxPktConnHandlerClosing().
*
* Note(s)     : (2) Ideally, network timer expiration functions could be defined as '[(void) (OBJECT *)]' 
*                   type functions -- even though network timer API functions cast expiration functions 
*                   to generic 'CPU_FNCT_PTR' type (i.e. '[(void) (void *)]').
*
*                   (a) (1) Unfortunately, ISO-IEC 9899-1999 ANSI-C, Section 6.3.2.3.7 states that "a 
*                           pointer to an object ... may be converted to a pointer to a different object 
*                           ... [but] if the resulting pointer is not correctly aligned ... the behavior
*                           is undefined".
*
*                           And since compilers may NOT correctly convert 'void' pointers to non-'void' 
*                           pointer arguments, network timer expiration functions MUST avoid incorrect
*                           pointer conversion behavior between 'void' pointer parameters & non-'void' 
*                           pointer arguments & therefore CANNOT be defined as '[(void) (OBJECT *)]'.
*
*                       (2) However, Section 6.3.2.3.1 states that "a pointer to void may be converted 
*                           to or from a pointer to any ... object ... A pointer to any ... object ... 
*                           may be converted to a pointer to void and back again; the result shall 
*                           compare equal to the original pointer".
*                   
*                   (b) Therefore, to correctly convert 'void' pointer objects back to appropriate
*                       network object pointer objects, network timer expiration functions MUST :
*
*                       (1) Be defined as 'CPU_FNCT_PTR' type (i.e. '[(void) (void *)]'); &       ...
*                       (2) Explicitly cast 'void' pointer arguments to specific object pointers; ...
*                           (A) ... in this case, a 'NET_TCP_CONN' pointer.
*
*                   See also 'net_tmr.c  NetTmr_Get()  Note #3'.
*
*               (3) This function is a network timer expiration function :
*
*                   (a) (1) For the following connection timer(s) ... :
*
*                           (A) TCP connection timeout timer ('TimeoutTmr')
*
*                       (2) (A) Clear the timer pointer; ...
*                               (1) Cleared in NetTCP_ConnFreeTmr() via NetTCP_ConnCloseHandler(),
*                                                                       NetTCP_ConnClose(); or
*                               (2) Reset   by NetTmr_Get().
*
*                           (B) but do NOT re-free the timer.
*
*                   (b) Do NOT set the following close timer flag(s) :
*
*                       (1) NET_TCP_CONN_CLOSE_TMR_TIMEOUT
*
*               (4) RFC #793, Section 3.9 'Event Processing : USER TIMEOUT : USER TIMEOUT' states that
*                   "for any state if the user timeout expires, flush all queues, signal the user
*                   'error : connection aborted due to user timeout' ... [and] enter the CLOSED state".
*********************************************************************************************************
*/
/*$PAGE*/
static  void  NetTCP_ConnClosingTimeoutDataAvail (void  *pconn_timeout)
{
#if ((NET_ERR_CFG_ARG_CHK_DBG_EN == DEF_ENABLED)                    && \
     (NET_CTR_CFG_ERR_EN         == DEF_ENABLED)                    && \
     (CPU_CFG_CRITICAL_METHOD    == CPU_CRITICAL_METHOD_STATUS_LOCAL))
    CPU_SR                cpu_sr;
#endif
    NET_TCP_CONN         *pconn;
    NET_TCP_CLOSE_CODE    close_code;
    CPU_BOOLEAN           data_avail;
    NET_TCP_TIMEOUT_SEC   timeout_sec;
    NET_TMR_TICK          timeout_tick;
    NET_ERR               err;


    pconn      = (NET_TCP_CONN *)pconn_timeout;                     /* See Note #2b2A.                                  */

    close_code =  NET_TCP_CONN_CLOSE_ALL;
    DEF_BIT_CLR(close_code, NET_TCP_CONN_CLOSE_TMR_TIMEOUT);        /* See Note #3b1.                                   */

#if (NET_ERR_CFG_ARG_CHK_DBG_EN == DEF_ENABLED)
                                                                    /* ---------------- VALIDATE PTR ------------------ */
    if (pconn == (NET_TCP_CONN *)0) {
        NET_CTR_ERR_INC(NetTCP_ErrNullPtrCtr);
        return;
    }
                                                                    /* ---------------- VALIDATE TYPE ----------------- */
    if (pconn->Type != NET_TCP_TYPE_CONN) {
        NET_CTR_ERR_INC(NetTCP_ErrConnInvalidTypeCtr);
        return;
    }
#endif

                                                                    /* Closing data avail for half-closed conns ONLY.   */
    data_avail = ((pconn->ConnCloseCode !=  NET_CONN_CLOSE_HALF           ) ||
                 ((pconn->RxQ_State     ==  NET_TCP_RX_Q_STATE_CONN_CLOSED) &&
                  (pconn->RxQ_App_Head  == (NET_BUF *)0))) ? DEF_NO : DEF_YES;

    if (data_avail != DEF_YES) {                                    /* If NO app data avail, ...                        */
                                                                    /* ... close TCP conn  (see Note  #1a).             */
        NetTCP_ConnCloseHandler((NET_TCP_CONN     *)pconn,
                                (CPU_BOOLEAN       )pconn->ConnCloseAppFlag,
                                (NET_TCP_CLOSE_CODE)close_code);

    } else {                                                        /* Else reset user tmr (see Notes #1b & #4).        */
        timeout_sec       =  pconn->TimeoutUser_sec;
        timeout_tick      = (NET_TMR_TICK)timeout_sec * NET_TMR_TIME_TICK_PER_SEC;
        pconn->TimeoutTmr =  NetTmr_Get((void       *) pconn,
                                        (CPU_FNCT_PTR) NetTCP_ConnCloseTimeout,
                                        (NET_TMR_TICK) timeout_tick,
                                        (CPU_INT16U  ) NET_TMR_FLAG_NONE,
                                        (NET_ERR    *)&err);

        if (err != NET_TMR_ERR_NONE) {
            NetTCP_ConnClose((NET_TCP_CONN     *)pconn,
                             (NET_BUF_HDR      *)0,
                             (CPU_BOOLEAN       )pconn->ConnCloseAppFlag,
                             (NET_TCP_CLOSE_CODE)close_code);
            return;
        }

        pconn->ConnCloseAppFlag = DEF_YES;
    }
}


/*$PAGE*/
/*
*********************************************************************************************************
*                                      NetTCP_ConnFreeHandler()
*
* Description : (1) Free a TCP connection :
*
*                   (a) Free   TCP connection timers
*                   (b) Free   TCP connection packet buffer queues
*                   (c) Clear  TCP connection controls
*                   (d) Free   TCP connection back to TCP connection pool
*                   (e) Update TCP connection pool statistics
*
*
* Argument(s) : pconn           Pointer to a TCP connection.
*               -----           Argument validated in NetTCP_ConnFree(),
*                                                     NetTCP_ConnClose().
*
*               free_code       Select which free action(s) to perform; bit-field flags logically OR'd :
*
*                                   NET_TCP_CONN_FREE_TMR_NONE              Free NO                                timers.
*                                   NET_TCP_CONN_FREE_TMR_ALL               Free ALL                               timers.
*
*                                   NET_TCP_CONN_FREE_TMR_TX_IDLE           Free    transmit idle                  timer.
*                                   NET_TCP_CONN_FREE_TMR_TX_SILLY_WIN      Free    transmit silly window persist  timer.
*                                   NET_TCP_CONN_FREE_TMR_TX_ZERO_WIN       Free    transmit zero  window persist  timer.
*                                   NET_TCP_CONN_FREE_TMR_TX_ACK_DLY        Free    transmit acknowledgement delay timer.
*                                   NET_TCP_CONN_FREE_TMR_RE_TX             Free re-transmit                       timer.
*                                   NET_TCP_CONN_FREE_TMR_KEEP_ALIVE        Free connection keep-alive             timer.
*                                   NET_TCP_CONN_FREE_TMR_TIMEOUT           Free connection                        timer.
*
*                               See also 'TCP CONNECTION CLOSE/FREE CODE DEFINES'.
*
* Return(s)   : none.
*
* Caller(s)   : NetTCP_ConnFree(),
*               NetTCP_ConnClose().
*
* Note(s)     : (2) ALL network resources linked to the TCP connection MUST be freed PRIOR to TCP connection
*                   free or discard so that no network resources are lost.
*********************************************************************************************************
*/
/*$PAGE*/
static  void  NetTCP_ConnFreeHandler (NET_TCP_CONN       *pconn,
                                      NET_TCP_FREE_CODE   free_code)
{
#if ((NET_ERR_CFG_ARG_CHK_DBG_EN == DEF_ENABLED)                    && \
     (NET_CTR_CFG_ERR_EN         == DEF_ENABLED)                    && \
     (CPU_CFG_CRITICAL_METHOD    == CPU_CRITICAL_METHOD_STATUS_LOCAL))
    CPU_SR       cpu_sr;
#endif
    CPU_BOOLEAN  discard;
    NET_ERR      err;


#if (NET_ERR_CFG_ARG_CHK_DBG_EN == DEF_ENABLED)                     /* ---------------- VALIDATE TYPE ----------------- */
    if (pconn->Type != NET_TCP_TYPE_CONN) {
        NetTCP_ConnDiscard(pconn);
        NET_CTR_ERR_INC(NetTCP_ErrConnInvalidTypeCtr);
        return;
    }
#endif


                                                                    /* -------------- FREE TCP CONN TMRs -------------- */
    NetTCP_ConnFreeTmr(pconn, free_code);


                                                                    /* -------------- FREE TCP CONN Q's --------------- */
    NetTCP_ConnFreeBufQ(&pconn->RxQ_Transport_Head, &pconn->RxQ_Transport_Tail);
    NetTCP_ConnFreeBufQ(&pconn->RxQ_App_Head      , &pconn->RxQ_App_Tail      );
    NetTCP_ConnFreeBufQ(&pconn->TxQ_Head          , &pconn->TxQ_Tail          );
    NetTCP_ConnFreeBufQ(&pconn->ReTxQ_Head        , &pconn->ReTxQ_Tail        );


    discard = DEF_NO;

    NetOS_TCP_RxQ_Clr(pconn->ID, &err);                             /* Clr TCP conn rx Q.                               */
    if (err != NET_TCP_ERR_NONE) {                                  /* If  TCP conn rx Q NOT clr'd, ...                 */
        discard = DEF_YES;                                          /* ... discard TCP conn (see Note #2b).             */
    }

    NetOS_TCP_RxQ_Abort(pconn->ID, &err);                           /* Abort wait on TCP conn rx Q.                     */


    NetOS_TCP_TxQ_Clr(pconn->ID, &err);                             /* Clr TCP conn tx Q.                               */
    if (err != NET_TCP_ERR_NONE) {                                  /* If  TCP conn tx Q NOT clr'd, ...                 */
        discard = DEF_YES;                                          /* ... discard TCP conn (see Note #2b).             */
    }

    NetOS_TCP_TxQ_Abort(pconn->ID, &err);                           /* Abort wait on TCP conn tx Q.                     */


                                                                    /* ---------- DISCARD TCP CONN ON ERR(S) ---------- */
    if (discard != DEF_NO) {                                        /* On TCP conn free err(s), ...                     */
        NetTCP_ConnDiscard(pconn);                                  /* ... discard TCP conn (see Note #2a).             */
        return;
    }


                                                                    /* ----------------- CLR TCP CONN ----------------- */
    pconn->ConnState = NET_TCP_CONN_STATE_FREE;                     /* Set TCP conn as freed/NOT used.                  */
    DEF_BIT_CLR(pconn->Flags, NET_TCP_FLAG_USED);

#if (NET_DBG_CFG_MEM_CLR_EN == DEF_ENABLED)
    NetTCP_ConnClr(pconn);
#endif


                                                                    /* ---------------- FREE TCP CONN ----------------- */
    pconn->NextPtr     = (void         *)NetTCP_ConnPoolPtr;
    NetTCP_ConnPoolPtr = (NET_TCP_CONN *)pconn;


                                                                    /* ---------- UPDATE TCP CONN POOL STATS ---------- */
    NetStat_PoolEntryUsedDec(&NetTCP_ConnPoolStat, &err);
}


/*$PAGE*/
/*
*********************************************************************************************************
*                                        NetTCP_ConnFreeTmr()
*
* Description : Clear TCP connection's timers.
*
* Argument(s) : pconn           Pointer to a TCP connection.
*               -----           Argument validated in NetTCP_ConnFreeHandler(),
*                                                     various NetTCP_ConnHandler() functions.
*
*               free_code       Select which free action(s) to perform; bit-field flags logically OR'd :
*
*                                   NET_TCP_CONN_FREE_TMR_NONE              Free NO                                timers.
*                                   NET_TCP_CONN_FREE_TMR_ALL               Free ALL                               timers.
*
*                                   NET_TCP_CONN_FREE_TMR_TX_IDLE           Free    transmit idle                  timer.
*                                   NET_TCP_CONN_FREE_TMR_TX_SILLY_WIN      Free    transmit silly window persist  timer.
*                                   NET_TCP_CONN_FREE_TMR_TX_ZERO_WIN       Free    transmit zero  window persist  timer.
*                                   NET_TCP_CONN_FREE_TMR_TX_ACK_DLY        Free    transmit acknowledgement delay timer.
*                                   NET_TCP_CONN_FREE_TMR_RE_TX             Free re-transmit                       timer.
*                                   NET_TCP_CONN_FREE_TMR_KEEP_ALIVE        Free connection keep-alive             timer.
*                                   NET_TCP_CONN_FREE_TMR_TIMEOUT           Free connection                        timer.
*
*                               See also 'TCP CONNECTION CLOSE/FREE CODE DEFINES'.
*
* Return(s)   : none.
*
* Caller(s)   : NetTCP_ConnFreeHandler(),
*               various NetTCP_ConnHandler() functions.
*
* Note(s)     : none.
*********************************************************************************************************
*/
/*$PAGE*/
static  void  NetTCP_ConnFreeTmr (NET_TCP_CONN       *pconn,
                                  NET_TCP_FREE_CODE   free_code)
{
    CPU_BOOLEAN  free_tmr;


    free_tmr = DEF_BIT_IS_SET(free_code, NET_TCP_CONN_FREE_TMR_TX_IDLE);
    if (free_tmr == DEF_YES) {
        if (pconn->TxQ_IdleTmr != (NET_TMR *)0) {
            NetTmr_Free(pconn->TxQ_IdleTmr);
            pconn->TxQ_IdleTmr  = (NET_TMR *)0;
        }
    }

    free_tmr = DEF_BIT_IS_SET(free_code, NET_TCP_CONN_FREE_TMR_TX_SILLY_WIN);
    if (free_tmr == DEF_YES) {
        if (pconn->TxQ_SillyWinTmr != (NET_TMR *)0) {
            NetTmr_Free(pconn->TxQ_SillyWinTmr);
            pconn->TxQ_SillyWinTmr  = (NET_TMR *)0;
        }
    }

    free_tmr = DEF_BIT_IS_SET(free_code, NET_TCP_CONN_FREE_TMR_TX_ZERO_WIN);
    if (free_tmr == DEF_YES) {
        if (pconn->TxQ_ZeroWinTmr != (NET_TMR *)0) {
            NetTmr_Free(pconn->TxQ_ZeroWinTmr);
            pconn->TxQ_ZeroWinTmr  = (NET_TMR *)0;
        }
    }

    free_tmr = DEF_BIT_IS_SET(free_code, NET_TCP_CONN_FREE_TMR_TX_ACK_DLY);
    if (free_tmr == DEF_YES) {
        if (pconn->TxAckDlyTmr != (NET_TMR *)0) {
            NetTmr_Free(pconn->TxAckDlyTmr);
            pconn->TxAckDlyTmr  = (NET_TMR *)0;
        }
    }

    free_tmr = DEF_BIT_IS_SET(free_code, NET_TCP_CONN_FREE_TMR_RE_TX);
    if (free_tmr == DEF_YES) {
        if (pconn->ReTxQ_Tmr != (NET_TMR *)0) {
            NetTmr_Free(pconn->ReTxQ_Tmr);
            pconn->ReTxQ_Tmr  = (NET_TMR *)0;
        }
    }

    free_tmr = DEF_BIT_IS_SET(free_code, NET_TCP_CONN_FREE_TMR_KEEP_ALIVE);
    if (free_tmr == DEF_YES) {
        if (pconn->KeepAliveTmr != (NET_TMR *)0) {
            NetTmr_Free(pconn->KeepAliveTmr);
            pconn->KeepAliveTmr  = (NET_TMR *)0;
        }
    }

    free_tmr = DEF_BIT_IS_SET(free_code, NET_TCP_CONN_FREE_TMR_TIMEOUT);
    if (free_tmr == DEF_YES) {
        if (pconn->TimeoutTmr != (NET_TMR *)0) {
            NetTmr_Free(pconn->TimeoutTmr);
            pconn->TimeoutTmr  = (NET_TMR *)0;
        }
    }
}


/*$PAGE*/
/*
*********************************************************************************************************
*                                        NetTCP_ConnFreeBufQ()
*
* Description : Free a TCP connection's buffer queue.
*
* Argument(s) : pbuf_q_head     Pointer to a TCP connection buffer queue's head pointer.
*
*               pbuf_q_tail     Pointer to a TCP connection buffer queue's tail pointer.
*
* Return(s)   : none.
*
* Caller(s)   : NetTCP_RxPktConnHandlerRxQ_Sync(),
*               NetTCP_TxConnSync(),
*               NetTCP_ConnFreeHandler().
*
* Note(s)     : none.
*********************************************************************************************************
*/

static  void  NetTCP_ConnFreeBufQ (NET_BUF  **pbuf_q_head,
                                   NET_BUF  **pbuf_q_tail)
{
    NET_BUF  *pbuf_q;

                                                                /* Free buf Q.                                          */
    pbuf_q = *pbuf_q_head;
    NetBuf_FreeBufQ_PrimList((NET_BUF *)pbuf_q,
                             (NET_CTR *)0);
                                                                /* Clr  buf Q ptrs to NULL.                             */
   *pbuf_q_head = (NET_BUF *)0;
   *pbuf_q_tail = (NET_BUF *)0;
}


/*$PAGE*/
/*
*********************************************************************************************************
*                                          NetTCP_ConnClr()
*
* Description : Clear TCP connection controls.
*
* Argument(s) : pconn       Pointer to a TCP connection.
*               -----       Argument validated in NetTCP_Init(),
*                                                 NetTCP_ConnGet(),
*                                                 NetTCP_ConnFreeHandler().
*
* Return(s)   : none.
*
* Caller(s)   : NetTCP_Init(),
*               NetTCP_ConnGet(),
*               NetTCP_ConnFreeHandler().
*
* Note(s)     : (1) Configured in NetTCP_ConnCfg() :
*
*                   (a) Configured  in NetTCP_ConnCfgMaxSegSize().
*
*                   (b) Configured  in NetTCP_RxConnWinSizeCfg() :
*                       (1) Configured in NetTCP_RxConnWinSizeCfgUpdateTh().
*
*                   (c) Configured  in NetTCP_TxConnWinSizeCfg() :
*                       (1) Configured in NetTCP_TxConnWinSizeCfgCongCtrl().
*                       (2) Configured in NetTCP_TxConnWinSizeCfgMinTh().
*
*                   (d) Initialized in NetTCP_TxConnRTT_RTO_Init().
*                       (1) Configured in NetTCP_TxConnRTO_CfgMaxTimeout().
*
*               (2) See 'NetTCP_RxPktConnHandler()  Note #3c'.
*
*               (3) (a) See 'net_tcp.h  TCP SEGMENT SIZE DEFINES  Note #1b1'.
*                   (b) See 'net_tcp.h  TCP SEGMENT SIZE DEFINES  Note #1b2'.
*
*               (4) See 'net_cfg.h  TRANSMISSION CONTROL PROTOCOL LAYER CONFIGURATION  Note #2'.
*
*               (5) See 'NetTCP_TxConnTxQ()  Note #6b2B2'.
*
*               (6) See 'net_tcp.h  TCP CONGESTION CONTROL DEFINES  Note #5b4'.
*
*               (7) See 'NetTCP_TxConnWinSizeZeroWinHandler()  Note #1b2'.
*
*               (8) See 'net_tcp.h  TCP CONGESTION CONTROL DEFINES  Note #7'.
*
*               (9) See 'net_tcp.h  TCP CONGESTION CONTROL DEFINES  Note #6b'.
*
*              (10) See 'NetTCP_TxConnAck()  Note #4a4A1'.
*
*              (11) See 'NetTCP_ConnCfgReTxMaxTimeout()  Note #1'.
*
*              (12) See ####
*
*              (13) See 'NetTCP_RxPktConnHandlerConn()  Note #3a'.
*
*              (14) See 'net_tcp.h  TCP CONNECTION TIMEOUT DEFINES  Note #1b'.
*********************************************************************************************************
*/
/*$PAGE*/
static  void  NetTCP_ConnClr (NET_TCP_CONN  *pconn)
{
    NET_TCP_CONN_ID  conn_id_tcp;
    NET_ERR          err;



    pconn->NextPtr                      = (void *)0;

    pconn->ID_Conn                      =  NET_CONN_ID_NONE;

    pconn->ConnState                    =  NET_TCP_CONN_STATE_FREE;

    pconn->ConnCloseCode                =  NET_CONN_CLOSE_FULL;                         /* See Note #2.                 */
    pconn->ConnCloseAppFlag             =  DEF_YES;
    pconn->ConnCloseTimeoutFaultFlag    =  DEF_YES;



    pconn->MaxSegSizeLocal              =  NET_TCP_MAX_SEG_SIZE_DFLT_RX;                /* See Note #3a.                */
    pconn->MaxSegSizeRemote             =  NET_TCP_MAX_SEG_SIZE_DFLT_TX;                /* See Note #3b.                */
#if 0                                                                                   /* See Note #1a.                */
    pconn->MaxSegSizeConn               =  NET_TCP_MAX_SEG_SIZE_NONE;
#endif



    pconn->RxSeqNbrSync                 =  NET_TCP_SEQ_NBR_NONE;
    pconn->RxSeqNbrNext                 =  NET_TCP_SEQ_NBR_NONE;
    pconn->RxSeqNbrLast                 =  NET_TCP_SEQ_NBR_NONE;
    pconn->RxSeqNbrClose                =  NET_TCP_SEQ_NBR_NONE;
    pconn->RxWinSizeCfgd                =  NET_TCP_CFG_RX_WIN_SIZE_OCTET;               /* See Note #4.                 */
    pconn->RxWinSizeCfgdActualUpdateRem =  NET_TCP_WIN_SIZE_NONE;
    pconn->RxWinSizeCfgdActual          =  pconn->RxWinSizeCfgd;
    pconn->RxWinSizeCalcd               =  pconn->RxWinSizeCfgd;
    pconn->RxWinSizeActual              =  pconn->RxWinSizeCfgd;
#if 0                                                                                   /* See Note #1b1.               */
    pconn->RxWinSizeUpdateTh            =  NET_TCP_WIN_SIZE_NONE;
#endif

    pconn->RxQ_State                    =  NET_TCP_RX_Q_STATE_CONN_CLOSED;
    pconn->RxQ_Transport_Head           = (NET_BUF *)0;
    pconn->RxQ_Transport_Tail           = (NET_BUF *)0;
    pconn->RxQ_App_Head                 = (NET_BUF *)0;
    pconn->RxQ_App_Tail                 = (NET_BUF *)0;



    pconn->TxSeqNbrSync                 =  NET_TCP_SEQ_NBR_NONE;
    pconn->TxSeqNbrNext                 =  NET_TCP_SEQ_NBR_NONE;
    pconn->TxSeqNbrNextQ                =  NET_TCP_SEQ_NBR_NONE;
    pconn->TxSeqNbrUnReTxd              =  NET_TCP_SEQ_NBR_NONE;
    pconn->TxSeqNbrUnAckd               =  NET_TCP_SEQ_NBR_NONE;
    pconn->TxSeqNbrUnAckdPrev           =  NET_TCP_SEQ_NBR_NONE;
    pconn->TxSeqNbrUnAckdAlignDelta     =  0;
    pconn->TxSeqNbrLast                 =  NET_TCP_SEQ_NBR_NONE;
    pconn->TxSeqNbrClose                =  NET_TCP_SEQ_NBR_NONE;

    pconn->TxWinUpdateSeqNbr            =  NET_TCP_SEQ_NBR_NONE;
    pconn->TxWinUpdateAckNbr            =  NET_TCP_ACK_NBR_NONE;
    pconn->TxWinUpdateWinSize           =  NET_TCP_WIN_SIZE_NONE;
    pconn->TxWinSizeCfgd                =  NET_TCP_CFG_TX_WIN_SIZE_OCTET;               /* See Note #4.                 */
    pconn->TxWinSizeCfgdRem             =  pconn->TxWinSizeCfgd;
    pconn->TxWinSizeRemote              =  NET_TCP_WIN_SIZE_NONE;
    pconn->TxWinSizeRemoteMax           =  pconn->TxWinSizeRemote;
    pconn->TxWinSizeRemoteActual        =  pconn->TxWinSizeRemote;
    pconn->TxWinSizeRemoteRem           =  pconn->TxWinSizeRemote;
    pconn->TxWinSizeNagleEn             =  DEF_ENABLED;                                 /* See Note #5.                 */
    pconn->TxWinSillyWinTimeout_ms      =  NET_TCP_TX_SILLY_WIN_TIMEOUT_DFLT_MS;        /* See Note #6.                 */
    pconn->TxWinZeroWinTimeout_ms       =  0;                                           /* See Note #7.                 */
#if 0                                                                                   /* See Note #1c.                */
    pconn->TxWinRxdAckDupCtr            =  0;
    pconn->TxWinRxdLastSeqNbr           =  NET_TCP_SEQ_NBR_NONE;
    pconn->TxWinRxdLastAckNbr           =  NET_TCP_ACK_NBR_NONE;
    pconn->TxWinRxdLastWinSize          =  NET_TCP_WIN_SIZE_NONE;
    pconn->TxWinSizeSlowStartTh         =  NET_TCP_WIN_SIZE_NONE;
    pconn->TxWinSizeSlowStartThInit     =  NET_TCP_WIN_SIZE_NONE;
    pconn->TxWinSizeCongInit            =  NET_TCP_WIN_SIZE_NONE;
    pconn->TxWinSizeCongCalcdActual     =  NET_TCP_WIN_SIZE_NONE;
    pconn->TxWinSizeCongCalcdCur        =  NET_TCP_WIN_SIZE_NONE;
    pconn->TxWinSizeCongRem             =  NET_TCP_WIN_SIZE_NONE;
    pconn->TxWinSizeAvail               =  NET_TCP_WIN_SIZE_NONE;
    pconn->TxWinSizeMinTh               =  NET_TCP_WIN_SIZE_NONE;
#endif


/*$PAGE*/
    pconn->TxSegReTxTh                  =  NET_TCP_RE_TX_TH_DFLT;                       /* See Note #8.                 */

    pconn->TxAckDlyTimeout_ms           =  NET_TCP_CFG_TIMEOUT_CONN_ACK_DLY_MS;         /* See Note #9.                 */
    pconn->TxAckDlyTmr                  = (NET_TMR *)0;
    pconn->TxAckDlyCnt                  =  0;

    pconn->TxAckImmedRxdPushEn          =  DEF_ENABLED;                                 /* See Note #10.                */



    pconn->TxRTT_RTO_Max_sec            =  NET_TCP_TX_RTO_MAX_TIMEOUT_DFLT_SEC;         /* See Note #11.                */
#if 0                                                                                   /* See Note #1d.                */
    pconn->TxRTT_Avg_ms_scaled          =  NET_TCP_TX_RTT_NONE;
    pconn->TxRTT_Dev_ms_scaled          =  NET_TCP_TX_RTT_NONE;
    pconn->TxRTT_RTO_ms_scaled          =  NET_TCP_TX_RTO_NONE;
    pconn->TxRTT_RTO_Max_ms_scaled      =  NET_TCP_TX_RTO_NONE;                         /* See Note #1d1.               */
    pconn->TxRTT_Avg_ms                 =  NET_TCP_TX_RTT_NONE;
    pconn->TxRTT_Dev_ms                 =  NET_TCP_TX_RTT_NONE;
    pconn->TxRTT_RTO_ms                 =  NET_TCP_TX_RTO_NONE;
    pconn->TxRTT_RTO_Max_ms             =  NET_TCP_TX_RTO_NONE;                         /* See Note #1d1.               */
    pconn->TxRTT_RTO_sec                =  NET_TCP_TX_RTO_NONE;
    pconn->TxRTT_RTO_tick               =  NET_TMR_TIME_0S;
    pconn->TxRTT_RTO_State              =  NET_TCP_TX_RTT_RTO_STATE_NONE;
#endif


    pconn->TxIP_TOS                     =  NET_IP_TOS_DFLT;
    pconn->TxIP_TTL                     =  NET_IP_TTL_DFLT;
    pconn->TxIP_Flags                   =  NET_IP_FLAG_NONE;


    pconn->TxQ_State                    =  NET_TCP_TX_Q_STATE_CONN_CLOSED;
    pconn->TxQ_Head                     = (NET_BUF *)0;
    pconn->TxQ_Tail                     = (NET_BUF *)0;
    pconn->TxQ_IdleTmr                  = (NET_TMR *)0;
    pconn->TxQ_SillyWinTmr              = (NET_TMR *)0;
    pconn->TxQ_ZeroWinTmr               = (NET_TMR *)0;
    pconn->ReTxQ_Head                   = (NET_BUF *)0;
    pconn->ReTxQ_Tail                   = (NET_BUF *)0;
    pconn->ReTxQ_Tmr                    = (NET_TMR *)0;



    pconn->KeepAliveTmr                 = (NET_TMR *)0;
    pconn->TimeoutTmr                   = (NET_TMR *)0;
    pconn->TimeoutConn_sec              =  NET_TCP_CONN_TIMEOUT_CONN_DFLT_SEC;          /* See Note #12.                */
    pconn->TimeoutUser_sec              =  NET_TCP_CONN_TIMEOUT_USER_DFLT_SEC;          /* See Note #13.                */
    pconn->TimeoutMaxSeg_sec            =  NET_TCP_CFG_TIMEOUT_CONN_MAX_SEG_SEC;        /* See Note #14.                */



    pconn->Flags                        =  NET_TCP_FLAG_NONE;


    NetTCP_ConnCfg(pconn, NET_TCP_CONN_CFG_ALL);                                        /* See Note #1.                 */


                                                                                        /* -- CFG DFLT TIMEOUT VALS --- */
    conn_id_tcp = pconn->ID;
    NetOS_TCP_RxQ_TimeoutDflt(conn_id_tcp, &err);
    NetOS_TCP_TxQ_TimeoutDflt(conn_id_tcp, &err);
}


/*$PAGE*/
/*
*********************************************************************************************************
*                                          NetTCP_ConnCopy()
*
* Description : (1) Copy/clone a TCP connection :
*
*                   (a) TCP connection state
*
*                   (b) Receive  parameters :
*                       (1)    Receive  window size
*
*                   (c) Transmit parameters :
*                       (1)    Transmit window size
*
*                       (2) Re-transmit parameters :
*                           (A) Threshold
*                           (B) Maximum timeout
*
*                       (3) IP transmit parameters :
*                           (A) TOS
*                           (B) TTL
*                           (C) IP flags
*
*                   (d) TCP connection timeout values
*
*
* Argument(s) : pconn_dest      Pointer to TCP connection to receive TCP connection copy.
*               ----------      Argument validated in NetTCP_RxPktConnHandlerListen().
*
*               pconn_src       Pointer to TCP connection to copy.
*               ---------       Argument validated in NetTCP_RxPktConnHandlerListen().
*
* Return(s)   : none.
*
* Caller(s)   : NetTCP_RxPktConnHandlerListen().
*
* Note(s)     : none.
*********************************************************************************************************
*/

static  void  NetTCP_ConnCopy (NET_TCP_CONN  *pconn_dest,
                               NET_TCP_CONN  *pconn_src)
{
    pconn_dest->ConnState           = pconn_src->ConnState;

    pconn_dest->RxWinSizeCfgd       = pconn_src->RxWinSizeCfgd;

    pconn_dest->TxWinSizeCfgd       = pconn_src->TxWinSizeCfgd;
    pconn_dest->TxWinSizeNagleEn    = pconn_src->TxWinSizeNagleEn;
    pconn_dest->TxSegReTxTh         = pconn_src->TxSegReTxTh;
    pconn_dest->TxAckDlyTimeout_ms  = pconn_src->TxAckDlyTimeout_ms;
    pconn_dest->TxAckImmedRxdPushEn = pconn_src->TxAckImmedRxdPushEn;
    pconn_dest->TxRTT_RTO_Max_sec   = pconn_src->TxRTT_RTO_Max_sec;

    pconn_dest->TxIP_TOS            = pconn_src->TxIP_TOS;
    pconn_dest->TxIP_TTL            = pconn_src->TxIP_TTL;
    pconn_dest->TxIP_Flags          = pconn_src->TxIP_Flags;

    pconn_dest->TimeoutConn_sec     = pconn_src->TimeoutConn_sec;
    pconn_dest->TimeoutUser_sec     = pconn_src->TimeoutUser_sec;
    pconn_dest->TimeoutMaxSeg_sec   = pconn_src->TimeoutMaxSeg_sec;
}


/*$PAGE*/
/*
*********************************************************************************************************
*                                        NetTCP_ConnDiscard()
*
* Description : (1) Discard an invalid/corrupted TCP connection :
*
*                   (a) Discard TCP connection from available TCP connection pool           See Note #2
*                   (b) Update  TCP connection pool statistics
*
*               (2) Assumes TCP connection is invalid/corrupt & MUST be removed.  TCP connection removed
*                   simply by NOT returning the TCP connection back to the TCP connection pool.
*
*
* Argument(s) : pconn       Pointer to an invalid/corrupted TCP connection.
*
* Return(s)   : none.
*
* Caller(s)   : NetTCP_ConnGet(),
*               NetTCP_ConnFree().
*
* Note(s)     : none.
*********************************************************************************************************
*/

static  void  NetTCP_ConnDiscard (NET_TCP_CONN  *pconn)
{
    NET_ERR  stat_err;

                                                                /* ----------------- DISCARD TCP CONN ----------------- */
   (void)&pconn;                                                /* Prevent compiler warning (see Note #2).              */

                                                                /* --------------- UPDATE DISCARD STATS --------------- */
    NetStat_PoolEntryLostInc(&NetTCP_ConnPoolStat, &stat_err);
}


/*$PAGE*/
/*
*********************************************************************************************************
*                                             MODULE END
*
* Note(s) : (1) See 'MODULE  Note #1' & 'net_tcp.h  MODULE  Note #1'.
*********************************************************************************************************
*/

#endif                                                          /* End of TCP module include (see Note #1).             */

