/*
 * 5799-WZQ (C) COPYRIGHT IBM CORPORATION 1988
 * LICENSED MATERIALS - PROPERTY OF IBM
 * REFER TO COPYRIGHT INSTRUCTIONS FORM NUMBER G120-2083
 */
/* $Header:r.h 12.0$ */
/* $ACIS:r.h 12.0$ */
/* $Source: /ibm/acis/usr/sys/afs/RCS/r.h,v $ */

#if !defined(lint) && !defined(LOCORE) && defined(RCS_HDRS)
static char *rcsidr = "$Header:r.h 12.0$";
#endif

/* r.h -- definitions for r remote procedure call package
Mike Kazar
July, 1986 */

#ifdef R_INTERNALS

#define RPROTOVERSION	3

/* here are the opcode definitions */
#define OCall		1	/* a call */
#define OResponse	2	/* the reply */
#define OAckCall	3	/* not a response, but acks a call */
#define OAckResponse	4	/* not a call, but acks a reply */
#define OGetKeys	5	/* please send authenticator */
#define OKeys		6	/* here is authenticator */

/* Values for flags in header */
#define HError		1	/* response auto. generated in response to an error */
/* n.b. next two used to get encryption level from bits 2 and 4 */
#define HEncryptionLevel 3	/* mask for encryption level */
#define HELShift	1	/* encryption level shift */

/* values for conn.state for client */
#define CIDLE		0x69	/* 'i' idle */
#define CSENT		0x77	/* 'w' sent request */

/* value for conn.state for server */
#define SIDLE		0x49	/* 'I' idle */
#define SBUSY		0x42	/* 'B' doing request */
#define SAUTHWAIT	0x41	/* 'A' waiting for OKeys pkt */
#endif R_INTERNALS

/* Connection flags */
#define CFGOTBUSY	1	/* connection got an OAckCall packet */
#define CFINQUEUE	2	/* connection is in the lastAckConns queue */
#define CFKEYVALID	4	/* the auth.key field is valid */
#define CFDODELETE	8	/* delete this dude when next idle */
#define CFNOLWP		0x20		/* busy due to no free lwp's */

/* define r_errno values */
#define R_ERROR		1	/* random decoding error */
#define R_TIMEOUT	2	/* actual timeout */

#define RKEYSIZE	8
/* an encryption key for r */
struct r_encryptionKey {
    char data[RKEYSIZE];
};

struct q {
    struct q *next;
    struct q *prev;
    long data, data2;
};

extern struct q *QNew();

/* The stuff in a packet header.  This struct does not define the format, though. */
/* don't change this without changing r.c's xdr_rheader function */
struct r_header {
    long sid;		/* the source subsys id */
    unsigned long seqno;		/* sequence number */
    long who;		/* auth info */
    unsigned long epoch;		/* when the rpc pkg started */
    short length;	/* in bytes, counting header; ignored on input */
    char opcode;	/* operation code */
    char flags;		/* flags like SYN */
    char headerSize;	/* the size of the header in words (in xdr representation) */
    char clearSize;	/* the amount of the header in the clear (in words, in xdr rep.) */
};

/* A packet buffer. */
struct r_packet {
    struct r_packet *next;	/* next guy in the free list */
    XDR xdrs;			/* xdr structure for packing/unpacking */
    struct r_header header;	/* the unpacked header */
    struct mbuf *mbuf;		/* mbuf handle, or null */
    char *data;			/* pointer to data */
};

/* structure representing a single R server.  Consists of a udp socket where packets
 * arrive, along with enough info for us to use them.
 */
struct r_server {
    struct q requestWaiters;		/* users waiting for incoming requests */
    struct q lastAckConns;		/* conns waiting for last ack */
    struct r_server *next;		/* next server in list */
    struct osi_socket *socket;		/* associated server socket */
    short states;			/* always have those states */
    u_short port;
};

/* A connection. */
struct r_connection {
    struct r_connection *hnext;	/* next in hash table */
    u_long host;		/* other guys' host */
    u_short portal;		/* other guys' udp port */
    long sid;			/* client's subport (always the client!) */
    struct authInfo {
	long who;		/* who we're authenticated as */
	struct r_encryptionKey key;	/* pointer to the handshake/session encryption key */
	long authLevel;		/* authentication level (further qualifies who field) */
	long expirationTime;	/* when the token expires */
    } auth;
    unsigned long seqno;			/* sequence number */
    long timeResponseSent;	/* guess */
    struct r_packet *callp;	/* call packet stored here while getting keys */
    struct r_packet *reply;	/* reply packet stored here until acked */
    struct osi_WaitHandle handler;	/* the lwp process handling this call */
    struct r_server *server;	/* associated server */
    char *rock;			/* a rock for the client to use in any way desired */
    unsigned long epoch;			/* the other dude's epoch value on the last call */
    short replyRetries;		/* number of times we're retried the reply */
    unsigned char nWaiters;	/* number of lwp's waiting for this connection */
    char state;			/* status */
    char flags;			/* flags */
    char isClient;		/* client or server connection? */
    char encryptionLevel;	/* the level we are using for encryption */
    char retryCount;		/* max retries for this conn */
};

/* values for encryptionLevel (fits in two bits par HEncryptionLevel) */
#define RAUTHONLY	0	/* must be zero, or init'd in r_New{Server}Conn */
#define RHEADERSONLY	1
#define RSECURE		2

/* Variables that the client can set before calling r_Init. */
extern int r_nPackets;		/* number of packets to allocate */
extern int r_encryptionLevel;	/* RAuthOnly, RHeadersOnly, RSecure */
extern int (*r_GetKeys)();	/* client's get keys routine / called on SL stack */
extern int (*r_WhoIsThisReally)();	/* server's decode routine / called on SL stack */
extern int r_packetSize;	/* the size of them */
extern int r_nRetries;		/* number of timeouts on a call */
extern int r_retryInterval;	/* in seconds */
extern int (*r_FreeConnProc)();	/* proc to call with aconn when freeing server conn */

#define R_NOAUTH	(-1L)	/* value for auth param of r_SendPacket */

#define r_GetAuth(ac)		(ac)->auth.who
#define r_GetEpoch(ac)		(ac)->epoch
#define r_PeerHost(ac)		(ac)->host
#define r_PeerPortal(ac)	(ac)->portal
#define r_SetLevel(ac,al)	(ac)->encryptionLevel=(al)
#define r_GetLevel(ac)		(ac)->encryptionLevel
#define	r_SetRetries(ac,val)	(ac)->retryCount = (val)
#define	r_GetRetries(ac,val)	((ac)->retryCount)
#define	r_ResetRetries(ac)	(ac)->retryCount = r_nRetries
#define	r_Busy(ac)		((ac)->state != CIDLE)

struct r_stat {
    long inCalls;		/* total incoming calls */
    long inBusies;		/* number of incoming busies */
    long inErrors;		/* number of response error packets */
    long inOldPackets;		/* out of seq packets */
    long outCalls;		/* total outgoing calls */
    long outCallsX;		/* output retransmissions */
    long outResps;		/* output send responses */
    long outRespsX;		/* and retransmissions of same */
    long outBusies;		/* busy packets we've sent */
    long callDeads;		/* number of dead calls */
    long replyDeads;		/* number of dead replies */
};

extern int r_Init();
extern struct r_packet *r_AllocSendPacket();
extern int r_FreePacket();
extern struct r_connection *r_NewConn();
extern struct r_server *r_NewServer();
extern struct r_packet *r_SendPacket();
extern int r_GetRequest();
extern int r_SendResponse();
