/*									rpc_ts.h
**
**	    TS layer internal types
**	    =======================
**
**  This file contains definitions common to the transport service support
**  for RPC. At the bottom are the definitions which the RPC layer needs
**  to see. If TS_INTERNALS is defined, then visibility is extended to the
**  things the TS layer needs to see.
*/

#ifdef TS_INTERNALS

/*
**
**    ETHERNET-specific types
*/
#ifdef ETHERNET
typedef rpc_byte rpc_ethernet_address[6]; 
typedef struct {unsigned char h, l;} eth_protocol_type;
#endif


/*    CATS-specific types internal to TS
*/
#ifdef CATS
#include "cats.h"
typedef enum {no_read, asynch_read, read_pending } read_pending_type;
typedef struct device_struct {    /* Variable length string for CATS TSUF */
	int	    length;
	rpc_name    body;
}	device_name_type;

#endif

/*	TCP-specific types internal to TS
*/
#ifdef TCP
#ifndef TCP_INCLUDES_DONE
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>	    /* Must be after netinet/in.h */
#include <netdb.h>
#include <errno.h>	    /* independent */
#include <sys/time.h>	    /* independent */
#endif

/*	Default macros for manipulating masks for select()
*/
#ifndef FD_SET
typedef unsigned int fd_set;
#define FD_SET(fd,pmask) (*(pmask)) |=  (1<<(fd))
#define FD_CLR(fd,pmask) (*(pmask)) &= ~(1<<(fd))
#define FD_ZERO(pmask)   (*(pmask))=0
#define FD_ISSET(fd,pmask) (*(pmask) & (1<<(fd)))
#endif

#endif

#endif	    /* TS_INTERNALS */

/*                                                                            
**	RPC message fields for TS private use:
**
**  The "protocol header" is information not part of the logical message at
**  layer 6.  It is available to the transport service if this helps it go
**  faster.
**  The fields in this part are RIGHT ADJUSTED -- this needs some care.
**  The total length for each case must be exactly 16 bytes.
**                                                                              
**  This field is only visible within the TS layer.
*/                                                                            
                             

#ifndef TS_INTERNALS
typedef rpc_byte protocol_header[16];	/* Dummy definition */

#else	/* TS_INTERNALS defined */
typedef union {
#ifdef V24                                                                              
                struct { rpc_byte dummy[12];                                   
                         unsigned char hb[4];
	        } v24;
#endif
#ifdef ETHERNET
                struct { rpc_byte		dummy[2];
                         rpc_ethernet_address	dest,
						source;
                         eth_protocol_type	ptype;
		} ether;
#endif
	        struct { rpc_byte dummy[12];	/* For internet, precede */
			 unsigned long length;	/* message with the length */
		} ip;

        } protocol_header;


/*    V24-specific types
*/ 
#ifdef V24
typedef int channel;			    /* Channel number */
typedef enum { seven_bit, seven_plus, eight_bit }       traffic_type;
typedef enum { checksum, crc_ccitt }    block_check_type;
typedef enum { got_marker,
	getting_length,
	got_length,
	got_link_number,
	getting_proc_number,
	getting_data,
	got_data,
	getting_block_check,
	idle,
	got_good_packet,
	C1_abort,
	got_garbled_packet }
    packet_reader_states;
typedef enum { cleared, got_escape_7d, got_escape_7e }
    byte_reader_states;

/*    This structure stores information about each V24 channel:
 */
typedef struct {
   packet_reader_states	    packet_reader_state;
   byte_reader_states	    byte_reader_state;
   traffic_type		    traffic;
   rpc_boolean		    rtscts_enabled;
   rpc_boolean		    block_check_enabled;
   block_check_type	    block_check_used;

   rpc_long		    speed;
   unsigned int             computed_block_check;
   unsigned int             received_block_check;
   int			    data_index;
   int			    message_size;	/* Incomming message size */
   int			    link_number;	/* Received link# */
   int			    v24_usage;
}   v24_chan_info_type;

typedef v24_chan_info_type	v24_chan_info_array[V24_CHANNELS];
typedef rpc_byte		v24_buffer[2*RPC_BUFFER_SIZE+1];
#endif

#endif	    /* TS_INTERNALS */

/*
**      Socket format
**      =============
** 
**  The socket is a structure which contains all the information
**  about one connection, or channel.  A socket number is allocated by TS_open,
**  and passed to each other routine to identify the connection which is to
**  be used.  The socket number being used for an rpc message is stored in its
**  m_socket field.
**
**  For ethernet, details (address and protocol type) of packets on this
**  channel are stored, and also a mask, so that a channel can have a wildcard
**  address. If the mask is ones (FFFF...) then the relevant address field is
**  used to filter packets, but if it is zeros, then any packet is let though
**  on reception, and on transmission, the details are copiedfrom the last
**  packet received.
**
*/

typedef enum {single, transient, slave, master, passive} socket_role;

typedef struct socket_struct {
    socket_type             soc_next;             /* Link if on a list of sockets */
    rpc_pointer		    soc_astadr;		  /* Address if service routine   */
    rpc_message_pointer     soc_astprm;           /* parameter for AST routine */

    rpc_message_pointer     soc_last_call_sent;   /* Messages stored    */
    rpc_message_pointer     soc_last_reply_sent;  /* for retransmission */
    short int		    soc_next_call_tid;    /* Next sequence no.  */
    unsigned long	    soc_efn;              /* Event flag number */
#ifdef AST
    void		    (*soc_user_ast)();    /* Address of user service procedure */
#endif

    struct rpc_protocol_struct * soc_protocol;	   /* Pointer to prot. object */

#ifdef TS_INTERNALS

/*      The format of the rest of the socket depends on the medium in use:
*/
    union {					    /* medium-dependent part */
#ifdef V24
        struct  {                                 /*  V24 */     
	    channel   soc_chan;
	    int       soc_link_number;
        } v24;
#endif
#ifdef ETHERNET
        struct  {				    /* Ethernet:    */
	    rpc_ethernet_address    soc_addr_filter;    /* The peer address if one is specified */
	    rpc_ethernet_address    soc_addr_mask;      /* A mask for comparing addresses on receipt */
	    courier_word	    soc_type_filter;    /* The protocol type being used */
	    unsigned short int      soc_type_mask;      /* Mask for comparing type fields */

	    rpc_ethernet_address    soc_rx_dest_addr;   /* Destination of last packet received */
	    rpc_ethernet_address    soc_rx_source_addr; /* Source of last packet received */
	    courier_word	    soc_rx_protocol_type;/* Protocol type of last packet received */

      } soc_ether;
#endif

#ifdef CATS
      struct  {				    /* CATS: */
	    socket_role		soc_role;
	    socket_type		soc_self;
	    socket_type		soc_master;
	    rpc_long		soc_conn_id;
	    socket_type		soc_slaves;
/*		read_pending_type   soc_reading; 
				It's defined in TSCATS_SPEC_VAR.H file */
	    rpc_message_pointer soc_message;
	    rpc_boolean		soc_async_read_queued;
	    rpc_boolean         soc_holding_message;
	    rpc_boolean         soc_connected;
	    int			soc_retlen;
	    TS_systat		soc_systat;
	    device_name_type    soc_tsuf;
      } soc_cats;

/*   VALIDITY:		Client or Fast	Master socket	Slave socket
**			--------------	--------------	----------------
**
** soc_master points to	    same socket	same socket	Master socket
**
** soc_slaves is	    NIL		list head	link on list
**
** soc_holding_message	    n/a		n/a		VALID
**
** soc_async_read_queued    VALID	VALID		n/a
**
** soc_efn		    VALID	VALID		n/a
**
** soc_conn_id		    VALID	n/a		VALID
**
*/

#endif
#ifdef TCP
      struct {				    /* TCP */
	    socket_role	    soc_role;
	    socket_type	    soc_master;	  /* Related master(for slave)*/
	    socket_type	    soc_slaves;   /* Slave (for master) */
	    rpc_message_pointer soc_message;  /* Message being read */
	    rpc_boolean	    soc_connected;
	    struct sockaddr_in  soc_address;  /* See netinet/in.h */
	    int		    soc_addrlen;
	    int		    soc_s;	  /* inet socket number */
      } soc_tcp; 
#endif
    } mdp;	/* Medium-Dependent Part */
#endif		/* TS_INTERNALS */
}       socket_descriptor;

/*	    Transport Protocol Object
**	    =========================
**
**  The transport object represents a transport service provider, often a
**  communications protocol. The operations available are message stream
**  operations.
**
**  These definitions assume a knowledge of the rpc_message_pointer type
**  and the socket_type (definied in rpcrts.h).
*/

struct rpc_protocol_struct {
    struct rpc_protocol_struct *next;   /* Link on list of valid protocols	  */
    char *	    name;	    /* Eg "tcp" or "ethernet"		  */
    int		    reliable;	    /* Is another protocol needed on top? */

/*  Methods applicable to this protocol:
*/

#ifdef __STDC__
    rpc_status (*open)(		    /* Open a socket			*/
        socket_type	psocket,    /*	    socket to be set up		*/
        char *          service);   /*	    communications address	*/

    rpc_status (*close)(	    /* Close a socket			*/
	socket_type socket);	    /*	    In Socket			*/

    rpc_status (*write)(	    /* Send a message			*/
	rpc_message_pointer *ppmes); /*	    IN	Ptr to ptr to message	*/

    rpc_status (*read)(		     /* Receive a message		*/
        rpc_message_pointer *ppmes, /*     OUT ptr to ptr to message	*/
        int		    timeout);/*	    IN	Maximum number of bytes	*/
    
    rpc_status (*aread)(	    /* Asynchronous receive		*/
	rpc_message_pointer pmessage,  /*		Pointer to buffer given */
	rpc_pointer	action,	    /*	    IN	Call this on completion	*/
	rpc_integer	user_1);    /*	    IN	Pass this to action	*/

    rpc_status (*my_address)(    /* Return comms address of socket	*/
        socket_type     socket,	    /*	    IN  Socket			*/
        char *          addrstr,    /*	    OUT address of this socket  */
	rpc_integer	addrlen);   /*	        size of buffer          */

    rpc_status (*peer_address)(  /* Return comms address of peer	*/
        socket_type     socket,	    /*	    IN  Socket			*/
        char *          addrstr,    /*	    OUT address of peer         */
	rpc_integer	addrlen);   /*	        size of buffer          */

#else
    rpc_status (*open)();	    /* Open a socket	*/
    rpc_status (*close)();	    /* Close a socket	*/
    rpc_status (*write)();	    /* Send a message down a socket	*/
    rpc_status (*read)();	    /* Receive a message from a socket	*/
    rpc_status (*aread)();	    /* Asynchronous receive of message	*/
    rpc_status (*my_address)();     /* Get my address	*/
    rpc_status (*peer_address)();   /* Get his address	*/
#endif

}; /* end rpc_protocol_struct */

typedef struct rpc_protocol_struct rpc_protocol;
/* typedef struct rpc_protocol_struct *rpc_protocol_id; */


/*	Access Routines (Methods):
*/
#define TS_OPEN ts_open
#define TS_CLOSE ts_close
#define TS_MY_ADDRESS ts_my_address
#define TS_PEER_ADDRESS ts_peer_address

#define TS_READ(pp,timeout) (*(*pp)->m_socket->soc_protocol->read)(pp,timeout)
#define TS_AREAD(pp) (*(*pp)->m_socket->soc_protocol->aread)(pp)
#define TS_WRITE(pp) (*(*pp)->m_socket->soc_protocol->write)(pp)

#ifdef __STDC__
 extern rpc_status
rpc_use(rpc_protocol * protocol);
#else
 extern rpc_status
rpc_use();
#endif
