/*--------------------------------------------------------------------------*/
/*	File name:	TCP.H							Revision date:	2000.08.14	*/
/*	Revised by:	Ulf Ronald Andersson			Revision start:	1999.01.14	*/
/*	Created by:	Peter Rottengatter				Creation date:	1997.02.19	*/
/*--------------------------------------------------------------------------*/
#ifndef	TCP_H
#define	TCP_H
/*--------------------------------------------------------------------------*/
/*	Macros to evaluate sequence numbers										*/
/*--------------------------------------------------------------------------*/
#define	SEQ_diff(x,y)	((int32)(x)-(int32)(y))
#define	SEQ_in(x,l,h)	(	(0<=((int32)(x)-(int32)(l)))\
						&&	(0<=((int32)(h)-(int32)(x)))\
						)
/*--------------------------------------------------------------------------*/
/*	Macro for safe use of _appl_yield										*/
/*--------------------------------------------------------------------------*/
#define	safe_appl_yield()\
	if	(!(protect_exec(NULL, pe_get_imask)&0x2000))\
		_appl_yield()

/*--------------------------------------------------------------------------*/
/*	Macros to handle DEFER state and semaphore switching					*/
/*--------------------------------------------------------------------------*/
#define	BEG_lock(x,y,z)		/* args: conn, int16_f, uint32_time */\
	if	(	(y = req_flag (& (x)->sema)) != 0\
		&&	(!((x)->flags & DEFER))\
		&&	(!(protect_exec(NULL, pe_get_imask)&0x2000))\
		)\
	{	uint32	temptime = TIMER_now();\
		while	(	((y = req_flag (& (x)->sema)) != 0)\
				&&	TIMER_elapsed(temptime) < (z)\
				)\
			_appl_yield();\
	}\
	if	(y)\
		return(E_LOCKED);
/*----------------------------------*/
#define	IF_lock(x,y,z)		/* args: conn, int16_f, uint32_time */\
	if	(	(y = req_flag (& (x)->sema)) != 0\
		&&	(!((x)->flags & DEFER))\
		&&	(!(protect_exec(NULL, pe_get_imask)&0x2000))\
		)\
	{	uint32	temptime = TIMER_now();\
		while	(	((y = req_flag (& (x)->sema)) != 0)\
				&&	TIMER_elapsed(temptime) < (z)\
				)\
			_appl_yield();\
	}\
	if	(y)\
/*----------------------------------*/
#define	TRY_lock(x)		req_flag (& (x)->sema)
#define	END_lock(x)		rel_flag (& (x)->sema)
/*--------------------------------------------------------------------------*/
/*	Macros to evaluate Precedence											*/
/*--------------------------------------------------------------------------*/
#define	PREC(x)			((x)>>5 & 7)	/* Calculate Precedence from IP tos	*/
#define	PREC_bits(x)	((x) & 0xE0)	/* Isolate precedence bits			*/
#define	un_PREC_bits(x)	((x) & 0x1F)	/* Eliminate precedence bits		*/
/*--------------------------------------------------------------------------*/
/* 	Diverse constants														*/
/*--------------------------------------------------------------------------*/
#define	MIN_MSS		536			/* lowest MSS which all TCPs must support	*/
#define	MAX_MSS		32768u		/* highest possible MSS, support optional	*/
#define	MAX_WIND	65535u		/* highest possible window size				*/
/*--------------------------------------------------------------------------*/
/*	State Categories														*/
/*--------------------------------------------------------------------------*/
#define	C_DEFAULT	0		/* Default for invalid states				*/
#define	C_LISTEN	1		/* We're listening for connections			*/
#define	C_READY		2		/* Ready to receive data					*/
#define	C_FIN		3		/* Nothing to send anyore (FIN sent)		*/
#define	C_END		4		/* Nothing to receive anyore (FIN rec'vd)	*/
#define	C_CLSD		5		/* We've closed. Nothing can be done.		*/
/*--------------------------------------------------------------------------*/
/*	TCP header and chain link structure.									*/
/*--------------------------------------------------------------------------*/
typedef  struct header
{	uint16		src_port;		/* Port number of sender					*/
	uint16		dest_port;		/* Port number of receiver					*/
	uint32		sequence;		/* Sequence number							*/
	uint32		acknowledge;	/* Acknowledgement number					*/
	unsigned	offset : 4;		/* Data offset (header length)				*/
	unsigned	resvd  : 6;		/* Reserved									*/
	unsigned	urgent : 1;		/* Flag for urgent data present				*/
	unsigned	ack    : 1;		/* Flag for acknowledgement segment			*/
	unsigned	push   : 1;		/* Flag for push function					*/
	unsigned	reset  : 1;		/* Flag for resetting connection			*/
	unsigned	sync   : 1;		/* Flag for synchronizing sequence numbers	*/
	unsigned	fin    : 1;		/* Flag for no more data from sender		*/
	uint16		window;			/* Receive window							*/
	uint16		chksum;			/* Checksum of all header, options and data	*/
	uint16		urg_ptr;		/* First byte following urgent data			*/
}	TCP_HDR;
/*--------------------------------------------------------------------------*/
/*	Values for flags in CONNEC.												*/
/*--------------------------------------------------------------------------*/
#define	FORCE		1			/* Flag forcing emission of a TCP segment	*/
#define	RETRAN		2			/* Flag indicating this is a retransmission	*/
#define	CLOSING		4			/* Flag indicating background close action	*/
#define	DISCARD		8			/* Flag forced discarding of receive data	*/
#define ACK_DELAYED	32			/* Flag set when delaying an ACK			*/
#define FIN_QUEUED	64			/* Flag set when FIN is added to send.count	*/
#define	DEFER		128			/* Flag indicating deferred call methods	*/
/*--------------------------------------------------------------------------*/
/*	TCP re-sequencing structure.											*/
/*--------------------------------------------------------------------------*/
typedef  struct resequ
{	struct resequ	*next;		/* Link to next segment in chain		*/
	uint8			tos;		/* TOS used by this segment to travel	*/
	TCP_HDR			*hdr;		/* Pointer to TCP header data			*/
	uint8			*data;		/* Pointer to data in this segment		*/
	uint16			data_len;	/* Amount of data in this segment		*/
}	RESEQU;
/*--------------------------------------------------------------------------*/
/*	TCP connection structure.												*/
/*--------------------------------------------------------------------------*/
typedef	struct	connec
{	uint32    remote_IP_address;	/* Foreign socket IP address			*/
	uint16    remote_port;			/* Foreign socket port number			*/
	uint32    local_IP_address;		/* Local socket IP address				*/
	uint16    local_port;			/* Local socket port number				*/
	uint8     state;				/* TCP state of the connection			*/
	uint8     flags;				/* Various flags (FORCE, RETRAN, etc.)	*/
	uint16    mss;					/* Maximum Segment Size					*/
	uint16    mtu;					/* Maximum Transmission Unit  (for IP)	*/
	int16     tos;					/* Type Of Service            (for IP)	*/
	int16     ttl;					/* Time To Live               (for IP)	*/
	CIB       *info;				/* Connection information link			*/
	int16     reason;				/* Reason for closing  (in TCLOSED)		*/
	int16     net_error;			/* Error to be reported with next call	*/
	struct						/* Structure containing SEND info		*/
	{	uint32	next;				/*   Next new sequence number to send	*/
		uint32	ptr;				/*   Sequence number in transmission	*/
		uint32	unack;				/*   First unacknowledged sequence		*/
		uint16	window;				/*   Actual size of send window			*/
		uint32	lwup_seq;			/*   Sequence of last window update		*/
		uint32	lwup_ack;			/*   Acknowledge of last window update	*/
		int16	total;				/*   Total real data in queue			*/
		int16	bufflen;			/*   Maximum amount of data in queue	*/
		int16	count;				/*   Data (with flags) in queue			*/
		uint32	ini_sequ;			/*   Initial sequence number			*/
		uint32	ACK_time;			/*   Time when sending last ACK			*/
		NDB		*queue;				/*   Send queue							*/
	}	send;					/* End of SEND info						*/
	struct						/* Structure containing RECEIVE info	*/
	{	uint32   next;				/*   Next acceptable sequence number	*/
		uint16   window;			/*   Actual size of receive window		*/
		uint32   lst_nxt;			/*   Seqnum of last window sent			*/
		uint16   lst_win;			/*   Last window size sent				*/
		RESEQU   *reseq;			/*   Segment queue for resequencing		*/
		int16    count;				/*   Real data in queue					*/
		NDB      *queue;			/*   Receive queue						*/
	}	recve;					/* End of RECEIVE info					*/
	struct						/* Struct. for retransmission timer		*/
	{	uint32   start;				/*   Starting time						*/
		uint32   timeout;			/*   Timeout (ms)						*/
		uint8    mode;				/*   Mode flag : Running / Stopped		*/
		uint8    backoff;			/*   Retransmission backoff counter		*/
	}	rtrn;					/* End of retransmission timer info		*/
	struct						/* Structure for round trip timer		*/
	{	uint32	start;				/*   Starting time						*/
		uint8	mode;				/*   Mode flag : Running / Stopped		*/
		uint32	sequ;				/*   Sequence number being timed		*/
		uint32	srtt;				/*   Smoothed round trip time			*/
		uint32	rto;				/*   standard Roundtrip TimeOut			*/
	}	rtrp;					/* End of round trip timer info			*/
	struct						/* Structure for closing timer			*/
	{	uint32	start;				/*   Starting time						*/
		uint32	timeout;			/*   Timeout time						*/
	}	close;					/* End of closing timer info			*/
	struct						/* Structure for initial TCP_open		*/
	{	int16	type;				/* data needed for ability to RESET		*/
		CAB		sock;
		int16	handle;				/* handle is used by destroy_conn		*/
	}	open;					/* End of initial TCP_open data			*/
	struct						/* Structure for congestion avoidance	*/
	{	uint16	cwnd;				/*	congestion window (init to mss)		*/
		uint16	sstresh;			/*	slow start treshold (init to 65535)	*/
		uint32	time;				/*  start of period for CA recovery		*/
		uint16	accu;				/*  accumulated 'ca' recovery in period	*/
	}	ca;						/* End of congestion avoidance struct	*/
	int16		sema;			/* Semaphore for locking structures		*/
	int16		*result;		/* Return deferred close results here	*/
	uint32		last_work;		/* Last time work has been done			*/
	IP_DGRAM	*pending;		/* Pending IP datagrams					*/
	struct	connec	*next;		/* Link to next connection in chain		*/
}	CONNEC;					/* End of connection struct	*/

/*--------------------------------------------------------------------------*/
/*	STX internal structure for all protocol relevant information.			*/
/*--------------------------------------------------------------------------*/
typedef	struct tcp_desc
{	LAYER	generic;		/* Standard layer structure				*/
	uint16	mss;			/* Maximum segment size					*/
	uint16	rcv_window;		/* TCP receive window					*/
	uint16	def_rtt;		/* Initial Round Trip Time in ms		*/
	int16	def_ttl;		/* Default value for IP TTL				*/
	int16	max_slt;		/* Estimated maximum segment lifetime	*/
	uint16	con_out;		/* Outgoing connection attempts			*/
	uint16	con_in;			/* Incoming connection attempts			*/
	uint16	resets;			/* Counting sent resets					*/
}	TCP_CONF;
/*--------------------------------------------------------------------------*/
/*	Subroutines of TCP_SUBS.S												*/
/*--------------------------------------------------------------------------*/
void	illegal(void);					/* AMON breakpoint function		*/
void	illegal_n(uint32 flag);			/* AMON d0-flagged breakpoint	*/
/*----*/
void	_appl_yield (void);
/*----*/
int16	req_flag (int16 *semaphore);
void	rel_flag (int16 *semaphore);
/*----*/
uint16	sm_get_imask(void);				/* supermode get imask		*/
void	sm_set_imask(uint16 imask);		/* supermode set imask		*/
uint16	sm_dis_imask(void);				/* supermode disable imask	*/
void	sm_pol_imask(uint16 imask);		/* supermode poll of imask	*/
/*----*/
int32	cdecl	pe_get_imask(void *dummy);	/* protect_exec get imask		*/
int32	cdecl	pe_set_imask(void *imask);	/* protect_exec set imask		*/
int32	cdecl	pe_dis_imask(void *dummy);	/* protect_exec disable imask	*/
int32	cdecl	pe_pol_imask(void *imask);	/* protect_exec poll of imask	*/
/*----*/
/* NB: The last four above need argument typecast to work properly	*/
/*----*/
int32	cdecl	pe_poll_work(void *conn);
IP_DGRAM *		get_pending (IP_DGRAM **pointer);
uint16			check_sum (uint32 src_ip, uint32 dest_ip, TCP_HDR *packet, uint16 length);
/*--------------------------------------------------------------------------*/
#endif /* TCP_H */
/*--------------------------------------------------------------------------*/
/* End of file:		TCP.H													*/
/*--------------------------------------------------------------------------*/
