/*
**	#include file for C-stubs in DD/OC RPC scheme         RPCHEADER
**      ---------------------------------------------------------------
**      derived by Nici Schraudolph (Summer Student), CERN DD, Aug 1987
**	modified by Johannes Raab, Tim Berners-Lee, Roberto Bagnara and
**	probably others.
**
**
**  History:
**
**	 2 Aug 89   Cleaned up. (RB)
**	22 Sep 89   rpc_boolean
**	29 Nov 89   Illegal "unsigned rpc_long" removed for OS9.
**
**  Language:
**
**	Standard C, with the following preprocessor keywords:
**
**	vax (*)	    Compile for VAX*. This implies special treatment of reals.
**
**	VAXVMS	    For use with the VaxVMS Pascal version of the RPC run-time
**		    library.
**
**	OSK (*)	    Compiler for OS9 with M680x0.
**
**	__TURBOC__  IBM-PC with Turbo-C.
**
**	RPC_BUFFER_SIZE   The RPC buffer size. By default, 1500.  To increase,
**		    compile everything with it set to something bigger.
**
**	(*) means:  predefined preprocessor token (i.e. there is no need to
**		    specify it on a command line define directive).
**
**
**  Derived keywords are:
**
**	LSBFIRST    The byte order is Least Significant Byte First.
*/
 
#ifndef LSBFIRST
#ifdef vax
#define LSBFIRST
#endif
#ifdef __TURBOC__
#define LSBFIRST
#endif
#endif

 
/*
**	Constants.
**	----------
*/
 
#define RPC_DEFAULT_TIMEOUT (-1)	/* Infinite timeout. */
#define RPC_S_NORMAL    1               /* Happens to be VMS SS$_NORMAL. */
#define RPC_SEV_ERROR   2               /* VMS-style severity code. */
#define RPC_FACILITY    0x0852          /* VMS-style facility code. */
 
#define CALL_HEADER_LENGTH	12      /* Length of message headers in bytes. */
#define RETURN_HEADER_LENGTH	4
#define REJECT_HEADER_LENGTH	6
 
#define RPC_NAME_LENGTH         40      /* Length of service name. */
 
#define RPC_V24_RTS	'|'		/* ASCII 124 - V24 Request To Send. */
#define RPC_V24_CTS     '^'		/* ASCII  94 - V24 Clear To Send.   */
#define RPC_V24_STX     '_'		/* ASCII  95 - V24 Start of TeXt.   */
#define RPC_V24_STARTOFPACKET	1	/* V24 start of packet marker. */
#define RPC_V24_ESC_7D		125	/* V24 1st escape character. */
#define RPC_V24_ESC_7E		126	/* V24 2nd escape character. */
 
#ifndef RPC_BUFFER_SIZE
#define RPC_BUFFER_SIZE		1500    /* Max packet size in this version. */
#endif
 
/*
**	Courier definitions of message type constants.
**	----------------------------------------------
**
**  The first block are always the actual values: the second block are
**  (obsolete, and) are the values which will appear in a marshalled
**  message, if regarded as variables in the local datra format.
*/
 
#define RPC_CALL_MESSAGE	0
#define RPC_REJECT_MESSAGE	1
#define RPC_RETURN_MESSAGE	2
#define RPC_ABORT_MESSAGE	3
 
#define CALL_MESSAGE		0
#ifndef LSBFIRST
#define REJECT_MESSAGE		1
#define RETURN_MESSAGE		2
#define ABORT_MESSAGE		3
#else
#define REJECT_MESSAGE		256	/* The same definitions here, but    */
#define RETURN_MESSAGE		512	/* taking into account byte swapping */
#define ABORT_MESSAGE		768	/* implied by LSBFIRST.              */
#endif

 
/*
**	Error codes definitions.
**	------------------------
**
**  NOTE:   If you change this table, you must also change the following table
**	    so that the two are kept consistent ! You should also change the
**	    PASCAL version of this file, the VMS error message file, and the
**	    explicit error message decoding in the source.
**
**			    139591680	    Facility
**				    8	    Message number times 8
**				32768	    b15 = "Facility-wide message"
**				    2	    Severity = error
**			    ---------
**			    139624458
**
**					Code:           Blame:
*/
 
#define RPC_S_UNSUPPORTED_VERSION       139624458       /* Compatability */
#define RPC_S_BAD_PROCEDURE_NUMBER      139624466       /* Client Stub */
#define RPC_S_IVPARAM                   139624474       /* Caller */
#define RPC_S_BAD_MSG_TYPE              139624482       /* Other machne */
#define RPC_S_BAD_PROGRAM_NUMBER        139624490       /* Routing */
#define RPC_S_BAD_REJECT_CODE           139624498       /* Server */
#define RPC_S_BAD_ETHERNET_ADDRESS      139624506       /* Routing */
#define RPC_S_SYNTAX_1                  139624514       /* Name server */
#define RPC_S_SYNTAX_2                  139624522       /* Name server */
#define RPC_S_SYNTAX_3                  139624530       /* Name server */
#define RPC_S_SYNTAX_4                  139624538       /* Name server */
#define RPC_S_BAD_MESSAGE_HEADER        139624546       /* Other end */
#define RPC_S_TOO_MANYCLIENTS           139624554       /* MAX_UNIT */
#define RPC_S_TOO_MANYSERVERS           139624562       /* MAX_PROGRAM */
#define RPC_S_NO_RESULTS_RETURNED       139624570       /* Stub code */
#define RPC_S_NO_SUCH_PACKAGE           139624578       /* Config prog */
#define RPC_S_TOO_MANYSOCKETS           139624586       /* MAX_socket */
#define RPC_S_SYNTAX_5                  139624594       /* Name too long */
#define RPC_S_FRAMING                   139624602       /* V24 framing error (STX) */
#define RPC_S_BAD_HANDLE                139624610       /* Caller of RTS */
#define RPC_S_NOT_IMPLEMENTED           139624618       /* Not implemented - Tim */
#define RPC_S_CONVERSION_ERROR          139624626       /* Number/string too large */
#define RPC_S_NOSUCHSOCKET              139624634       /* Caller of TS */
#define RPC_S_TS_INTERNAL_ERROR         139624642       /* Internal TS error */
#define RPC_S_ALREADY_READING           139624650       /* Caller of TS */
#define RPC_S_TIMEOUT                   139624658       /* Peer node not responding */
#define RPC_S_NO_TRANSLATION            139624666       /* No translation */
#define RPC_S_BUFFER_OVERFLOW		139624674	/* buffer_overflow */
#define RPC_S_OPERATING_SYSTEM		139624682	/* OS error reported */
#define RPC_S_COMMUNICATIONS		139624690	/* Comms system error */
#define RPC_S_NOT_AUTHORIZED		139624698	/* Authorisation sys */

 
/*
**	Message numbers, without severity or facility.
**	----------------------------------------------
**
**					Code:	What to Blame:
*/
 
#define RPC_M_NORMAL                    0       /* No-one */
#define RPC_M_UNSUPPORTED_VERSION       1       /* Compatability */
#define RPC_M_BAD_PROCEDURE_NUMBER      2       /* Client Stub */
#define RPC_M_IVPARAM                   3       /* Caller */
#define RPC_M_BAD_MSG_TYPE              4       /* Other machne */
#define RPC_M_BAD_PROGRAM_NUMBER        5       /* Routing */
#define RPC_M_BAD_REJECT_CODE           6       /* Server */
#define RPC_M_BAD_ETHERNET_ADDRESS      7       /* Routing */
#define RPC_M_SYNTAX_1                  8       /* Name server */
#define RPC_M_SYNTAX_2                  9       /* Name server */
#define RPC_M_SYNTAX_3                  10      /* Name server */
#define RPC_M_SYNTAX_4                  11      /* Name server */
#define RPC_M_BAD_MESSAGE_HEADER        12      /* Other end */
#define RPC_M_TOO_MANYCLIENTS           13      /* MAX_UNIT (not in C)*/
#define RPC_M_TOO_MANYSERVERS           14      /* MAX_PROGRAM (not in C)*/
#define RPC_M_NO_RESULTS_RETURNED       15      /* Stub code */
#define RPC_M_NO_SUCH_PACKAGE           16      /* No local package found */
#define RPC_M_TOO_MANYSOCKETS           17      /* MAX_socket (not in C)*/
#define RPC_M_SYNTAX_5                  18      /* Name too long */
#define RPC_M_FRAMING                   19      /* V24 framing error (bad protocol) */
#define RPC_M_BAD_HANDLE                20      /* Caller of RTS */
#define RPC_M_NOT_IMPLEMENTED           21      /* Not implemented */
#define RPC_M_CONVERSION_ERROR          22      /* Number/string too large */
#define RPC_M_NOSUCHSOCKET              23      /* Caller of TS */
#define RPC_M_TS_INTERNAL_ERROR         24      /* Internal TS error */
#define RPC_M_ALREADY_READING           25      /* Caller of TS */
#define RPC_M_TIMEOUT                   26      /* Peer node not responding */
#define RPC_M_NO_TRANSLATION            27	/* No translation */
#define RPC_M_BUFFER_OVERFLOW		28  	/* buffer_overflow */
#define RPC_M_OPERATING_SYSTEM		29	/* OS error reported */
#define RPC_M_COMMUNICATIONS		30	/* Comms system error */

 
/*
**	RPC Data Types.
**	---------------
*/
 
typedef unsigned char   rpc_boolean;
typedef unsigned char   rpc_byte;
typedef char		rpc_char;
typedef short		rpc_short;
typedef long		rpc_long;
typedef int		rpc_integer;	    /* Generic 16 or 32 bit integer. */
typedef float		rpc_real32;
typedef double		rpc_real48;	    /* Not yet supported. */
typedef double		rpc_real64;	    /* Not yet supported. */
typedef double		rpc_real128;	    /* Not yet supported. */
 
typedef void		(*rpc_pointer)();   /* Stub entry point. */
typedef rpc_long	rpc_status;	    /* Returned status. */
 
/*
**	Allow space for the string null terminator, so
**	that RPC_NAME_LENGTH is the real string length.
*/
 
typedef char		rpc_name[RPC_NAME_LENGTH+1];
 
 
/*
**	Words stored in their Courier order WHATEVER the system.
**	--------------------------------------------------------
*/
 
typedef struct { rpc_byte     h, l; }   courier_word;
typedef struct { courier_word h, l; }   courier_long;
 
/*	Forward declaration of pointer used in rpc_ts.h
*/
typedef struct rpc_message_struct *rpc_message_pointer;
 
 
/*	Transport Layer:    Protocol header, Socket definition
**	---------------	    ----------------------------------
**
**	rpc_ts.h contains the real definition of these things. If we
**	do not need TS layer visibility, then we don't get it.
**	This is an implementation of private types, we do that in order
**	to obey the information hiding golden rule.
*/
 
typedef struct socket_struct *    socket_type;   /* Forward ref */
 
#ifndef TS
typedef rpc_long    protocol_header[4];	/* 16 byte header used by TS only */
/* typedef int	    *socket_type;	 Pointer to socket */
#else
#include "rpc_ts.h"
#endif
 

 
/*
**	RPC message format.
**	-------------------
**
**	The information kept in this block is in three parts:  there is
**	internal information about the state of the transaction kept by
**	the RPC Run-Time System; there is a space left for use by the
**	Transport Service ("protocol header") and there is the logical
**	RPC message itself, in Courier format.
**
*/
 
typedef rpc_short   message_type;	    /* Takes the message type values. */
 
typedef struct rpc_message_struct {
 
    /* Internal RPCRTS use: */
 
    rpc_message_pointer m_next;	    /* Next message in messages list. */
    rpc_status	    m_status;	    /* Status of this transaction. */
    socket_type	    m_socket;	    /* Socket used for this transaction. */
    rpc_long	    m_index;	    /* Byte index for (un)packing. */
 
    /* Transport layer use: */
 
    protocol_header	    header;
 
    /* Logical message at layer 6: */
 
    union {
	rpc_byte	    rpc_b[RPC_BUFFER_SIZE];	/* As a byte array. */
	rpc_char	    rpc_ch[RPC_BUFFER_SIZE];	/* As a char array. */
	message_type    which;
 
/*  A message has 1 of the following 4 formats, depending on its type.
**  Note that this use of a union type to "equivalence" two structures is
**  NOT PORTABLE (for example onto the cray), so is obsolete.  The marshalling
**  macros and the offsets below should always be used instead.
**  The "abort" format is courier, but not used by DD/OC's RPC.
*/
	struct {
	    message_type	call_which;
	    courier_word	call_transaction_id;
	    courier_long	program_number;
	    courier_word	version_number;
	    courier_word	procedure_number;
	 } cal;
 
	struct {
	    message_type	reject_which;
	    courier_word	reject_transaction_id;
	    courier_word	why;
	    courier_long	reject_status;
	} rej;
 
	struct {
	    message_type	return_which;
	    courier_word	return_transaction_id;
	} ret;
			
	struct {
	    message_type	abort_which;
	    courier_word	abort_transaction_id;
	    courier_word	abort_code;
	} abt;
    } body;
} rpc_message;
 
/*  Offsets in bytes to fields in the above structure:
*/
#define RPC_MESSAGE_TYPE_OFFSET	    0
#define RPC_TID_OFFSET		    2
 
#define RPC_PROGRAM_NUMBER_OFFSET   4
#define RPC_VERSION_NUMBER_OFFSET   8
#define RPC_PROCEDURE_NUMBER_OFFSET 10
#define RPC_CALL_PARAMETER_OFFSET   12
 
#define RPC_RETURN_PARAMETER_OFFSET 4
 
#define RPC_REJECT_REASON_OFFSET    4
 
typedef rpc_long    program_index;
typedef rpc_long    rpc_handle;

 
/*
**	In-line expansion macros for the marshalling routines.
**	------------------------------------------------------
*/
 
#define next_byte(p)	(p)->body.rpc_b[(p)->m_index++]
#define next_char(p)	(p)->body.rpc_ch[(p)->m_index++]
 
#define pck_char(p, x)	next_char(p) = (rpc_char)(x)
#define pck_byte(p, x)	next_byte(p) = (rpc_byte)((x) & 0xff)
 
#define pck_long(p, x) {		\
	register rpc_long fix_pckl = x;	\
	pck_byte(p, fix_pckl>>24);	\
        pck_byte(p, fix_pckl>>16);	\
	pck_byte(p, fix_pckl>>8);	\
        pck_byte(p, fix_pckl); }
 
#define pck_short(p ,x) {		\
	register rpc_short fix_pcks = x;\
	pck_byte(p, fix_pcks>>8);	\
	pck_byte(p, fix_pcks); }
 
#define pck_integer(p, x) pck_short(p, x)
 
#ifdef vax
#define pck_real32(p, x)		    \
	if ( x == 0.0 ) {pck_long(p, 0);}   \
	else {				    \
	    register rpc_long fix_pckl = (*(rpc_long *)&(x)); \
	    pck_byte(p, (fix_pckl>>8)-1);   \
	    pck_byte(p, fix_pckl>>0);	    \
	    pck_byte(p, fix_pckl>>24);	    \
	    pck_byte(p, fix_pckl>>16); }
#else
#define pck_real32(p, x) {	    \
	rpc_long fix_pckl;	    \
	*(float *)(&fix_pckl)=(x);  \
	pck_byte(p, fix_pckl>>24);  \
        pck_byte(p, fix_pckl>>16);  \
	pck_byte(p, fix_pckl>>8);   \
        pck_byte(p, fix_pckl); }
#endif
 
#define upk_char(p, x)	    (x) = next_char(p)
#define upk_byte(p, x)	    (x) = next_byte(p)
 
#define upk_short(p, x)     upk_byte(p, x);		    \
			    (x) = ((x)<<8) + next_byte(p)
#define upk_integer(p, x)   upk_short(p, x)
 
#define upk_long(p, x)	    upk_short(p, x);		    \
			    (x) = ((x)<<8) + next_byte(p);  \
			    (x) = ((x)<<8) + next_byte(p)
#ifdef vax
#define upk_real32(p, x) {				\
	unsigned int x1 = next_byte(p);			\
	unsigned int x2 = next_byte(p);			\
	if( !(x1 % 128) && (x2 < 128) ) {		\
	    (x) = 0.0;					\
	    next_byte(p);				\
	    next_byte(p);				\
	} else {					\
	    rpc_long fix_pckl = (x1+1)<<8;		\
	    fix_pckl = fix_pckl + (x2<<0);		\
	    fix_pckl = fix_pckl + (next_byte(p)<<24);	\
	    fix_pckl = fix_pckl + (next_byte(p)<<16);	\
	    (x) = *((float *)(&fix_pckl));		\
	} }
#else
#define upk_real32(p, x)  upk_long(p, *(unsigned long *)&(x))
#endif

 
/*
**	RTS call convention interface macros.
**	-------------------------------------
*/
 
#define c_open(a, b, c)		rpc_open(&(a), &(b), c)
#define c_early_return(a)	rpc_early_return(&(a))
 
/*
**	RTS call convention interface macros for VaxVMS Pascal.
**	-------------------------------------------------------
**
**	EVERYTHING is passed by reference.
*/
 
#ifdef VAXVMS
 
#define c_attach_stub(a, b, c, d) \
	{ int p_routine;		  \
	  p_routine = (int)&(b);	  \
	  rpc_attach_stub(&(a), &(p_routine), c, &(d));}
 
#define c_detach_stub(p)	rpc_detach_stub(&(p))
#define c_new(a, b)		rpc_new(&(a), &(b))
#define c_dispose(a)		rpc_dispose(&(a))
#define c_call(a,b,c)		rpc_call(&(a), &(b), &(c))
#define c_call_status(a, b, c)	rpc_call_status(&(a), &(b), &(c))
#define c_report_error(a)	rpc_report_error(&(a))
#define c_close(s, h)		rpc_close(&(s), &(h))
 
#else
 
#define c_attach_stub(a, b, c, d) rpc_attach_stub(&(a), b, c, &(d))
#define c_detach_stub(p)	rpc_detach_stub(p)
#define c_new(a, b)		rpc_new(&(a), b)
#define c_dispose(a)		rpc_dispose(a)
#define c_call(a,b,c)		rpc_call(&(a), &(b), c)
#define c_call_status(a, b, c)	rpc_call_status(&(a), &(b), c)
#define c_report_error(a)	rpc_report_error(&a)
#define c_close(s, h)		rpc_close(&(s), h)
 
#endif
