#define TCP_MAX_PORT    65535

#define TCP_SRTT_ALPHA  0.9

#define TCP_RTO_BETA    2
#define TCP_RTO_MIN             0.2
#define TCP_RTO_MAX             10

#define TCP_WINDOW_SIZE 8192

#define TCP_MSS                 536 // Max Segment Size default

#define TCP_TIMEOUT             5000

#define TCP_STATE_CLOSED                0
#define TCP_STATE_LISTEN                1
#define TCP_STATE_SYN_SENT              2
#define TCP_STATE_SYN_RECEIVED  3
#define TCP_STATE_ESTABLISHED   4
#define TCP_STATE_FIN_WAIT1             5
#define TCP_STATE_FIN_WAIT2             6
#define TCP_STATE_CLOSE_WAIT    7
#define TCP_STATE_CLOSING               8
#define TCP_STATE_LAST_ACK              9
#define TCP_STATE_TIME_WAIT             10

// TCP header flags. Test with Bt(), e.g. Bt(&flags, TCPf_RST)
#define TCPf_FIN        0
#define TCPf_SYN        1
#define TCPf_RST        2
//#define TCPf_PSH      3 // most stacks don't implement PUSH.
#define TCPf_ACK        4
//#define TCPf_URG      5 // most stacks don't implement URGENT.

#define TCPF_FIN        (1 << TCPf_FIN)
#define TCPF_SYN        (1 << TCPf_SYN)
#define TCPF_RST        (1 << TCPf_RST)
//#define TCPF_PSH      (1 << TCPf_PSH) // most stacks don't implement PUSH.
#define TCPF_ACK        (1 << TCPf_ACK)
//#define TCPF_URG      (1 << TCPf_URG) // most stacks don't implement URGENT.


class CTCPAckQueue:CQueue
{
        F64 time_sent;
        U32 retries;
        U32 start_seq_num;
        U32 end_seq_num;

        U32 tcp_packet_size;    // Size of memory allocation of U8* tcp_packet.
        U8 *tcp_packet;                 // Memory location of entire TCP Header + Data Payload.
};

// stores packet data of incoming connect() requests,
// local accept() will search queue for pending connections,
// and use this data to send out notification connection was accepted.
class CTCPAcceptQueue:CQueue
{
        U32 segment_seq_num;
        U32 ipv4_address;
        U16 port;
};

class CTCPSocket
{
        CSocket                                 *socket;
        U8                                               state;
        U64                                              timeout; // timeout for socket calls. Initialized 0: non-blocking.

        CSocketAddressStorage    source_address;        // based on ->family, cast or assign to a var as IPV4/IPV6 CSocketAddress
        CSocketAddressStorage    destination_address;

        CTCPAckQueue                    *ack_queue; // Sent TCP packets awaiting an ACK collect here to be retransmitted. CQueue head.

        U64                                              accept_queue_limit;
        CTCPAcceptQueue                 *accept_queue;

        U32                                              max_segment_size;

        U32                                              first_unacked_seq; // SEQ number of first unacknowledged octet
        U32                                              next_send_seq_num;
        U32                                              next_recv_seq_num;
        F64                                              srtt; // Smoothed Round-Trip Time
        F64                                              connection_time;

        U32                                              receive_window;// allowed # of unacknowledged incoming octets
        U32                                              send_window;   // allowed # of unacknowledged outgoing octets

        I64                                              write_position; // position in RX buffer to write incoming octets
        I64                                              read_position;  // position in RX buffer Socket calls have read up to
        I64                                              receive_buffer_size;
        U8                                              *receive_buffer;
};


class CTCPTreeQueue:CQueue
{
        CTCPSocket              *socket;
};

class CTCPTreeNode:CBST
{
        CTCPTreeQueue   *queue;
};

class CTCPRepEntry:CQueue
{
        CTCPTreeNode *node;
};


class CTCPHeader
{
        U16     source_port;
        U16     destination_port;
        U32 seq_num;
        U32     ack_num;
        U8      data_offset;
        U8      flags;
        U16     window_size;
        U16     checksum;
        U16     urgent_pointer;
};

class CTCPPseudoHeader
{
        U32 source_address;
        U32 destination_address;
        U8      zeros;
        U8      protocol;
        U16     tcp_length; // length of TCP headers & payload
};

class CTCPGlobals
{

        CTCPTreeNode    *bound_socket_tree;
        U16                              next_source_port;

} tcp_globals;