/*
    Copyright 2000 (c) by Reto Gaehler, Toni Kaufmann,
    Swiss Federal Institute of Technology,
    Computer Engineering and Networks Laboratory.
 
    TOPSY -- A Teachable Operating System.
             Implementation of a tiny and simple
             micro kernel for teaching purposes.
 
    For further information, please visit http://www.tik.ee.ethz.ch/~topsy
 
    This software is provided under the terms of the GNU General Public 
    Licence. A full copy of the GNU GPL is provided in the file COPYING 
    found in the development root of Topsy.
*/
/*
    File:                  $Source: /home/ruf/cvs_Topsy/cvs/Topsy/Net/old/TCP/nettcpTCP.h,v $
    Author(s):             
    Affiliation:           ETH Zuerich, TIK
    Version:               $Revision: 2922 $
    Creation Date:         
    Last Date of Change:   $Date: 2007-03-19 17:48:52 +0100 (Mon, 19 Mär 2007) $      by: $Author: baderma $
 
 
    $Log: nettcpTCP.h,v $
    Revision 1.3  2000/11/15 10:12:15  ruf
    Repository Reorganisation
 
    Revision 1.2  2000/04/03 17:45:31  gfa
    *** empty log message ***
 
    Revision 1.1  2000/03/31 17:50:39  gfa
    Merged with /Net from several term projects
 
*/

//	This file contains all tcp data types and definitions.

#ifndef __NETTCPTCP_H
#define __NETTCPTCP_H

#include "nettcpConfig.h"
#include "nettcpTCP.h"
#include "Ports.h"
#include "Semaphore.h"
#include "GPQueue.h"

#include <Topsy.h>
#include <Messages.h>
#include <Syscall.h>

#include <NetDebug.h>
#include <NetBuf.h>
#include <NetAttr.h>
#include <NetConfig.h>
#include <NetModules.h>

//**************************************************************************************************
//	defines
//**************************************************************************************************

// flags for tcp packet dump
#define TCP_DUMP_OFF					0x00000000
#define TCP_DUMP_SEND_RESET 			0x00000001
#define TCP_DUMP_SEND_DATA 				0x00000002
#define TCP_DUMP_SEND_ACK 				0x00000004
#define TCP_DUMP_RECEIVE 				0x00000008
#define TCP_DUMP_ALL	 				0xFFFFFFFF

#define TCP_DUMP_MASK  					TCP_DUMP_OFF


// TCP Options
#define	TCP_OPTION_EOL					0			// end Of Option List
#define	TCP_OPTION_NOOP					1			// no Operation
#define	TCP_OPTION_MAXSEGSIZE			2			// maximum Segment Size


#define	TCPINCR							904
#define	TCP_READERS						1
#define	TCP_WRITERS						2
#define	TCP_FRAGMENT_QUEUE_SIZE			10			// TCP fragment queue size
#define	TCP_QUEUE_LEN					20			// TCP process port queue length
#define	TCP_ACKDELAY	   				20			// 1/5 sec ACK delay

// timer events
#define	SEND							0x1
#define	PERSIST							0x2
#define	RETRANSMIT						0x3
#define	DELETE							0x4

#define	TCP_MINRXT	   					50			// 1/2 second min rexmt time
#define	TCP_MIN_HDR_LEN	  				20			// minimum TCP header length
#define	TCP_MAX_HDR_LEN	  				24			// maximum TCP header length in this impl
#define	TCP_HDR_OFFSET					0x50		// tcp_offset value for TCP_MIN_HDR_LEN
#define	TCP_TWOMSL						120			// (2 * Max Segment Lifetime)
#define	TCP_MAXPRS	 					6000		// 1 minute max persist time
#define	TCP_MAXRETRIES	   				12			// max retransmissions before giving up
#define	TCP_MAXRXT	 					2000		// 20 seconds max rexmt time


#define TCP_SND_BUF_SIZE				2024		// initial send buffer size
#define TCP_RCV_BUF_SIZE				2024		// initial receive buffer size

/* second argument to tcpsend(): */
#define	TCP_NEWDATA						0			// send all new data
#define	TCP_REXMT						1			// retransmit the first pending segment

// TCP control bits (RFC 793, p15)
#define TCP_CODE_URG					0x20		// urgent pointer is valid
#define TCP_CODE_ACK					0x10		// acknowledgment field is valid
#define TCP_CODE_PSH					0x08		// this segment requests a push
#define TCP_CODE_RST					0x04		// reset the connection
#define TCP_CODE_SYN					0x02		// synchronize sequence number
#define TCP_CODE_FIN					0x01		// sender has reached end of its stream

// result codes
#define	TCP_OK		 					1			// call ok
#define TCP_NO_ERR						0
#define	TCP_GENERAL_ERROR				-1			// cgeneral error occured
#define TCP_GENERAL_ERR					-2
#define TCP_HEADER_TOO_SHORT_ERR		-3
#define TCP_CHECKSUM_ERR				-4
#define TCP_NO_LISTENER_ERR				-5
#define	TCP_RESET						-6
#define	TCP_REFUSED						-7
#define	TCP_TOOBIG						-8
#define	TCP_TIMEDOUT					-9
#define	TCP_URGENTMODE					-10
#define	TCP_NORMALMODE					-11
#define	TCP_URGENT_ERR					-12

// TCB Flags
#define	TCP_TCB_NEED_OUTPUT				0x01		// we need output
#define	TCP_TCB_FIRST_SEND				0x02		// no data to ACK
#define	TCP_TCB_RCV_DONE				0x08		// no more receive data to process
#define	TCP_TCB_SND_DONE				0x10		// no more send data allowed
#define	TCP_TCB_DELACK					0x20		// do delayed ACK's
#define	TCP_TCB_BUFFER					0x40		// do TCP buffering (default no)
#define	TCP_TCB_PUSH					0x80		// got a push; deliver what we have
#define	TCP_TCB_SEND_FIN				0x100		// user process has closed; send a FIN
#define	TCP_TCB_RCV_URGENT_ISOK			0x200		// receive urgent pointer is valid
#define	TCP_TCB_SND_URGENT_ISOK			0x400		// send urgent pointer is valid

//**************************************************************************************************
//	macros
//**************************************************************************************************

#define NETBUF_SETLEN(buf,length) 		(buf->end = buf->start + length)

#define	MIN(a,b)						( (a) < (b) ? (a) : (b) )
#define	MAX(a,b)						( (a) > (b) ? (a) : (b) )

//**************************************************************************************************
//	Sequence space comparator: This handles sequence space wrap-around. Overflow/Underflow
//	makes the result below correct (-,0,+) for any a,b in the sequence space.
//	Results: 	result	implies
//				-		a < b
//				0		a = b
//				+		a > b
//**************************************************************************************************
#define COMPARE_SEQUENCE(a,b)			((a)-(b))

//**************************************************************************************************
//	Computes the length of the tcp header in bytes. The header length, measured in 32-bit words,
//	is stored in the high-order 4 bits of the 8 bit offset field. To compute the header length in
//	bytes, the macro must multiply the length in 32 bit words by 4. To do so, it references the
//	entire byte, computes a logical and to extract the length bits, and shifts them into position.
//**************************************************************************************************
#define TCP_HEADER_LEN(pTcpHeader)		(((pTcpHeader)->u8Offset & 0xF0)>>2)


//**************************************************************************************************
//	type definitions
//**************************************************************************************************

// tcp connection states
// don't change order. For example, TCP_STATE_ESTABLISHED must be greater than TCP_CODE_SYNRCVD
typedef enum
{
  TCP_STATE_CLOSED = 1,
  TCP_STATE_LISTEN = 2,
  TCP_STATE_SYNSENT = 3,
  TCP_STATE_SYNRCVD = 4,
  TCP_STATE_ESTABLISHED = 5,
  TCP_STATE_FINWAIT1 = 6,
  TCP_STATE_FINWAIT2 = 7,
  TCP_STATE_CLOSEWAIT = 8,
  TCP_STATE_LASTACK = 9,
  TCP_STATE_CLOSING = 10,
  TCP_STATE_TIMEWAIT = 11
} TCPStateSet;

// tcp connection types
typedef enum
{
  TCP_TYPE_CONNECTION = 1,
  TCP_TYPE_SERVER = 256
} TCPTypeSet;

// tcp output states
typedef enum
{
  TCP_OUT_STATE_IDLE = 0,
  TCP_OUT_STATE_PERSISTS = 1,
  TCP_OUT_STATE_TRANSMIT = 2,
  TCP_OUT_STATE_RETRANSMIT = 3
} TCPOutStateSet;

// IP Address, byte oriented
typedef struct
{
  unsigned char 	u8Addr0;
  unsigned char 	u8Addr1;
  unsigned char 	u8Addr2;
  unsigned char 	u8Addr3;
}
IPAddressRec;

// IP Address, byte and long word oriented
typedef union
{
  IPAddressRec	recAddr;
  unsigned long	u32Addr;
} IPAddressUon,*IPAddressPtr;

typedef enum
{
  TCP_IP_SRC_ADDR = 1,
  TCP_IP_DST_ADDR = 256
} IPAddrSet;

// TCB
typedef struct
{
  struct TCBRec	*pNext;					// next tcp in linked list or nil
  TCPStateSet		setState;				// tcp state
  TCPOutStateSet	setOutState;			// tcp output state
  TCPTypeSet		setType;				// tcp type
  SemaphoreRec	recMutex;				// protects tcb
  unsigned short	u16Flags;				// various tcb state flags
  unsigned char	u8NextPacketCode;		// TCP code for next packet
  int				nError;					// returns error for user side

  NetAttrs		netParams;				// network parameters, like ip nr

  long			n32SndUnacked;			// send unacked
  long			n32SndNext;				// send next
  unsigned long	u32SndWinSize;			// send window size
  long			n32SndLast;				// seq of FIN, if TCP_TCB_SEND_FIN
  long			n32SeqOfLastWinUpdt;	// sequence of last window update
  long			n32AckSeqOfLastWinUpdt;	// ack seq of last window update
  unsigned long	u32CongestionWinSize;	// congestion window size
  unsigned long	u32SlowStartThreshold;	// slow start threshold
  unsigned long	u32SndMaxSegSize;		// send max segment size
  long			n32InitSndSeq;			// initial send sequence

  int				nSmoothedRoundTripTime;	// smoothed round trip time
  int				nRoundTripDeviationEst;	// round trip deviation estimator
  int				nPersist;				// persist timeout value
  int				nRetransmitTimeout;		// retransmit timeout value
  int				nNumOfRetransmits;		// number of retransmits

  long			n32RcvNextSeq;			// receive next
  long			n32RcvUrgentSeq;		// receive urgent pointer
  long			n32SndUrgentSeq;		// send urgent pointer

  int				nListenQueueSize;		// listen queue size
  PortRec			recListenQueue;			// listen queue port (SERVERs)
  struct TCBRec	*pParentTCB;			// pointer to parent TCB (ACCEPT)
  SemaphoreRec	recOpenCloseSemaphore;	// open close semaphore
  void			*pDevice;				// socket ptr

  SemaphoreRec	recSndSemaphore;		// send semaphore
  unsigned char	*pu8sndBuf;				// send buffer
  unsigned long	u32SndBufStart;			// start of valid data
  unsigned long	u32SndBufCount;			// data character count
  unsigned long	u32SndBufSize;			// send buffer size in bytes

  SemaphoreRec	recRcvSemaphore;		// receive semaphore
  unsigned char	*pu8rcvBuf;				// receive buffer
  unsigned long	u32RcvBufStart;			// start of valid data
  unsigned long	u32RcvBufCount;			// data character count
  unsigned long	u32RcvBufSize;			// receive buffer size
  long			n32CurAdvWinSeq;		// seq of currently advertised win
  unsigned long	u32RcvMaxSegSize;		// receive max segment size
  int				nRcvSegFragQueue;		// segment fragment queue
  long			n32FINSeqNum;			// FIN sequence number or 0
  long			n32PUSHSeqNum;			// PUSH sequence number or 0
}
TCBRec, *TCBPtr;

// TCP protocol header (RFC 793, p15)
typedef struct
{
  unsigned short	u16SrcPort;
  unsigned short	u16DstPort;
  long			n32Seq;
  long			n32AckSeq;
  unsigned char	u8Offset;
  unsigned char	u8Code;
  unsigned short	u16Window;
  unsigned short	u16CheckSum;
  unsigned short	u16Urgent;
  unsigned char	aryData[0];
}
TCPSegRec,*TCPSegPtr;

// fragment
typedef struct
{
  long	n32Seq;
  int		nLen;
}
TCPFragmentRec,*TCPFragmentPtr;

// packet
typedef struct
{
  TCPSegPtr		pTCPSeg;				// pointer to first byte of tcp packet
  NetBuf 			segBuf;
  NetAttrs 		netAttrs;
}
PacketRec,*PacketPtr;


//**************************************************************************************************
//	module interface
//**************************************************************************************************

unsigned char *tcpAlloc(unsigned int nSize);
void tcpFree(unsigned char *pBuf);
int tcpGetIPAddr(NetAttrs attrs,IPAddrSet setType,IPAddressPtr pIpAddr);
int	tcpSetIPAddr(NetAttrs attrs,IPAddrSet setType,IPAddressPtr pIpAddr);
int tcpWakeup(TCBPtr pTCB,int nType);
void tcpInput(NetBuf buf,NetAttrs attrs);
int tcpSync(TCBPtr pTCB);
int tcpTCBAllocate(TCBPtr *ppTCB);
int tcpTCBDeallocate(TCBPtr pTCB);
int tcpKick(TCBPtr pTCB);
int tcpRcvWindow(TCBPtr pTCB);

#ifdef MacOS

pascal extern void *tcpOut(ThreadArg arg);
#else

extern void tcpOut(ThreadArg arg);
#endif

#endif
