/* 
 * chan_internal.h
 *
 * x-kernel v3.3
 *
 * Copyright (c) 1993,1991,1990,1996  Arizona Board of Regents
 *
 * $Revision: 1.3 $
 * $Date: 1996/01/29 22:11:44 $
 */
 
#ifndef chan_internal_h
#define chan_internal_h

#include "chan.h"

#define CHANHLEN  		sizeof(CHAN_HDR) 
#define CHANEXTIDLEN 		sizeof(EXT_ID);
/* 
 * START_SEQ must be > 0
 */
#define START_SEQ 		1
 

/* 
 * Flags
 */
#define	FROM_CLIENT	0x01
#define	USER_MSG	0x02	/* valid user data */
#define ACK_REQUESTED	0x04
#define NEGATIVE_ACK	0x08


/* 
 * Protocol down vector indices
 */
#define CHAN_BIDCTL_I	1


typedef enum {
    /*--- Server states */
    SVC_EXECUTE = 1,	/* Sent msg up, waiting for answer */
    SVC_WAIT,		/* Waiting for an ACK of the reply */
    SVC_IDLE,
    /*--- Client states */
    CLNT_WAIT,
    CLNT_FREE,
    /*--- Client or server */
    DISABLED
} FsmState;


/*--- Message sequence possible status */
typedef enum {
  	old, current, new
} SEQ_STAT;

typedef xk_u_int32	SeqNum;
typedef xk_u_int16	Channel;

/*--- Channel Header structure */ 
typedef struct  {
    Channel	chan;
    xk_u_int8	unused;
    xk_u_int8 	flags;
    xk_u_int32	prot_id;
    SeqNum	seq;
    xk_u_int32	len;
} CHAN_HDR;


typedef struct {
    Msg	m;
    char valid;
} ChanMsg;


/*--- Channel State structure */
typedef struct {
        FsmState 	cur_state;
        int 		wait;
	int		waitParam;	/* user configurable wait value */
	int		maxWait;	/* user configurable wait value */
        Event 		event;
	CHAN_HDR 	hdr;
	ChanMsg		saved_msg;
	/* 
	 * client only
	 */
	XkReturn	replyValue;
        Msg 		*answer;
        Semaphore 	reply_sem;
	chan_info_t	info;
	IPhost		peer;
} CHAN_STATE, SState;

#define CHAN_IDLE_CLIENT_MAP_SZ		31
#define	CHAN_IDLE_SERVER_MAP_SZ		31
#define CHAN_ACTIVE_CLIENT_MAP_SZ	101
#define CHAN_ACTIVE_SERVER_MAP_SZ	101
#define CHAN_HLP_MAP_SZ		1

#define FIRST_CHAN	1

/*--- Protocol state structure */
typedef struct {
    Map		actCliHostMap, actCliKeyMap, idleCliMap;
    Map 	actSvrHostMap, actSvrKeyMap, idleSvrMap;
    Map 	passiveMap;
    Map		newChanMap;
    Semaphore	newSessnLock;
} PSTATE, PState;

/*--- Ids used to demux to active sessions */
typedef struct {
    int		chan;
    Sessn	lls;
    u_int 	prot_id;
} ActiveID;

/*--- prot_id serves as passive key to demux to passive sessions */
typedef unsigned int PassiveID;


/*--- Delays are specified in microseconds! */
#define SERVER_WAIT_DEFAULT	8 * 1000 * 1000		/* 8 seconds */
#define SERVER_MAX_WAIT_DEFAULT	60 * 1000 * 1000	/* 60 seconds */
#define CLIENT_WAIT_DEFAULT	5 * 1000 * 1000		/* 5 seconds */
#define CLIENT_MAX_WAIT_DEFAULT	60 * 1000 * 1000	/* 60 seconds */


/*--- We still need to figure out a good delay, may need to query
      bottom protocol for hints. */
#define CHAN_CLNT_DELAY(m, p) 	(p)
#define CHAN_SVC_DELAY(m, p)  	(p)

#define msg_valid(M)	((M).valid = 1)
#define msg_clear(M)	((M).valid = 0)
#define msg_isnull(M)	((M).valid == 0)
#define msg_flush(M) 	{ if ((M).valid) {  msgDestroy(&(M).m);  \
			    	 	    (M).valid=0; } }

#define MAX(x,y) 		((x)>(y) ? (x) : (y))
#define MIN(x,y) 		((x)<(y) ? (x) : (y))


typedef		int	(* MapChainForEachFun)(
#ifdef __STDC__
					       VOID *, VOID *
#endif					       
					       );

#ifdef __STDC__

typedef		Sessn (ChanOpenFunc)( Protl, Protl, Protl, ActiveID *, int );

XkReturn	chanAddIdleSessn( Map, Map, Map, Sessn );
XkReturn	chanBidctlRegister( Protl, IPhost * );
int		chanCheckMsgLen( u_int, Msg * );
SEQ_STAT 	chanCheckSeq( u_int, u_int );
void		chanClientIdleRespond( CHAN_HDR	*, Sessn, u_int );
void		chanClientPeerRebooted( PSTATE *, IPhost * );
int		chanControlSessn( Sessn, int, char *, int );
Sessn 		chanCreateSessn( Protl, Protl, Protl, ActiveID *,
				 SessnInitFunc, Map, Map );
void		chanDestroy( Sessn );
void		chanDispKey( ActiveID * );
void		chanEventFlush( Sessn );
void		chanFreeResources( Sessn );
Map		chanGetChanMap( Protl, IPhost * );
Map 		chanGetMap( Map, Sessn, long );
long		chanGetProtNum( Protl, Protl );
int		chanMapRemove( VOID *, VOID * );
XkReturn 	chanOpenEnable( Protl, Protl, Protl, Part * );
XkReturn 	chanOpenDisable( Protl, Protl, Protl, Part * );
XkReturn 	chanOpenDisableAll( Protl, Protl );
void		chanRemoveActive( Sessn, Map keyMap, Map hostMap );
int		chanRemoveIdleSessns( Map, IPhost * );
XkHandle	chanReply( Sessn, CHAN_HDR *, int );
XkHandle	chanResend( Sessn, int, int );
void		chanServerPeerRebooted( PSTATE *, IPhost * );
char * 		chanStateStr( int );
void		chanTimeout( Event, VOID * );
ChanOpenFunc	chanSvcOpen;
void		chanHdrStore( void *, char *, long, void * );
Sessn		chanOpen( Protl, Protl, Protl, Part * );
char * 		chanStatusStr( SEQ_STAT );
void 		pChanHdr( CHAN_HDR * );

/* 
 * chan_mapchain.c
 */
void		chanMapChainAddObject( VOID *, Map, IPhost *, long, int );
int		chanMapChainApply( Map, IPhost *, MapChainForEachFun );
Map		chanMapChainFollow( Map, IPhost *, long );

#else

typedef		Sessn (ChanOpenFunc)();

XkReturn	chanAddIdleSessn();
XkReturn	chanBidctlRegister();
int		chanCheckMsgLen();
SEQ_STAT 	chanCheckSeq();
void		chanClientIdleRespond();
void		chanClientPeerRebooted();
int		chanControlSessn();
Sessn 		chanCreateSessn();
void		chanDestroy();
void		chanDispKey();
void		chanEventFlush();
void		chanFreeResources();
Map 		chanGetChanMap();
Map 		chanGetMap();
long		chanGetProtNum();
void		chanHdrStore();
void		chanInternalClose();
int		chanMapRemove();
XkReturn 	chanOpenEnable();
XkReturn 	chanOpenDisable();
XkReturn 	chanOpenDisableAll();
void		chanRemoveActive();
int		chanRemoveIdleSessns();
XkHandle	chanReply();
XkHandle	chanResend();
char * 		chanStateStr();
void		chanServerPeerRebooted();
Sessn		chanOpen();
char * 		chanStatusStr();
Sessn		chanSvcOpen();
void		chanTimeout();
void 		pChanHdr();

void		chanMapChainAddObject();
int		chanMapChainApply();
Map		chanMapChainFollow();

#endif


extern	int	tracechanp;

#endif
