/* 
 * $Id: qrpc.h,v 1.19 90/10/05 15:02:42 qjb Exp $
 * $Source: /afs/athena.mit.edu/user/q/qjb/source/qrpc/src/RCS/qrpc.h,v $
 * $Author: qjb $
 *
 * This header files defines the QRPC object and some important 
 * global parameters.
 */

#ifndef __QRPC_H__
#define __QRPC_H__

#if !defined(lint) && !defined(SABER) && !defined(RCS_HDRS)
static char *rcsid_qrpc_h = "$Id: qrpc.h,v 1.19 90/10/05 15:02:42 qjb Exp $";
#endif /* lint || SABER || RCS_HDRS */

#include <sys/types.h>
#include <netinet/in.h>
#include <sys/time.h>
#include <sys/param.h>
#include <krb.h>

#include <qrpc_err.h>
#define QRPC_SUCCESS 0

#ifdef __STDC__
#define QRPC_PROTO(x) x
#else
#define QRPC_PROTO(x) ()
#endif /* __STDC__ */

#define QRPC_ERRMSGSIZE 512
#define QRPC_NOT_LISTENING -1

/* For compatibility with systems that don't have this in errno.h */
extern int      errno;
extern char     *sys_errlist[];
extern int      sys_nerr;

/* 
 * Types 
 */
#ifdef __STDC__
typedef void *qrpc_pointer;
#else
typedef char *qrpc_pointer;
#endif /* __STDC__ */

typedef int qrpc_error_t;
typedef u_short qrpc_opcode_t;
typedef u_short qrpc_version_t;
typedef u_long qrpc_length_t;
typedef u_char *qrpc_data_t;
typedef u_char qrpc_bool;
typedef u_char qrpc_byte;

typedef void (*qrpc_error_fn_t) QRPC_PROTO((char *));

typedef struct {
    qrpc_opcode_t opcode;
    char *name;
} qrpc_valid_opcode;

typedef struct {		/* Information needed for client-side setup */
    /* PRIVATE */
    char *host;			/* Server host */
    char *service;		/* Service name */
    int port;			/* Fallback port no. if service is unknown */
    int timeoutval;		/* Seconds to wait during network read/write */
    char fullhost[MAXHOSTNAMELEN + 1]; /* To be filled in by library */
} qrpc_client_info;

typedef enum {
    qst_unknown = 0, 
    qst_inetd, 
    qst_listen,
    qst_accept
} qrpc_server_type;

typedef struct {		/* Information needed for server-side setup */
    /* PRIVATE */
    qrpc_server_type server_type; 
    int timeoutval;		/* Seconds to wait during network read/write */
    char *service;		/* Service name for listen-based servers */
    int port;			/* Fallback port no. if service is unknown */
    int backlog;		/* Backlog for listen() */
} qrpc_server_info;

typedef struct {
    /* PUBLIC READONLY */
    struct sockaddr_in caddr;	/* Client socket address structure */
    struct sockaddr_in saddr;	/* Server socket address structure */
    qrpc_version_t version;	/* Protocol version being used */
    int in;			/* incoming socket */
    int out;			/* outgoing socket */
    struct _qrpci_listen_info *listen_info; /* Info for listeners only */
    /* PRIVATE */
    char errmsg[QRPC_ERRMSGSIZE]; /* Space for error messages */
    qrpc_error_fn_t default_error_fn; /* Default error function */
    qrpc_error_fn_t error_fn;	/* Function to print error messages */
    qrpc_valid_opcode *valid_opcodes; /* Valid opcodes and their names */
    int max_valid_opcode;	/* Maximum valid application-def'd opcode */
    qrpc_bool connected;	/* Are we connected? */
    qrpc_version_t save_minv;	/* Save minv for listen sockets */
    qrpc_version_t save_maxv;	/* Save maxv for listen sockets */
    qrpc_byte state;		/* Some value of QRPC_ST_*; what's expected */
    qrpc_length_t expected_length; /* Length of incoming data */
    qrpc_byte client_or_server;	/* Either QRPC_IS_CLIENT or QRPC_IS_SERVER */
    union {
	qrpc_client_info client;
	qrpc_server_info server;
    } setup;
} *qrpc_t;

/* Use a structure tag because of interdependency between this and qrpc_t */
typedef struct _qrpci_listen_info {
    int sock;			/* Socket for listen */
    qrpc_t accepted[NOFILE];	/* List of all accepted qrpc's */
} *qrpc_listen_info;

/*
 * Function prototypes 
 */

qrpc_error_t qrpc_recv_header 
    QRPC_PROTO((qrpc_t, qrpc_opcode_t *, qrpc_length_t *));
qrpc_error_t qrpc_recv_some_data
    QRPC_PROTO((qrpc_t, qrpc_data_t, qrpc_length_t));
qrpc_error_t qrpc_recv_data 
    QRPC_PROTO((qrpc_t, qrpc_data_t));
qrpc_error_t qrpc_send 
    QRPC_PROTO((qrpc_t, qrpc_opcode_t, qrpc_data_t, qrpc_length_t));
qrpc_error_t qrpc_recv 
    QRPC_PROTO((qrpc_t, qrpc_opcode_t, qrpc_data_t, qrpc_length_t *));
qrpc_error_t qrpc_init_tcp_client_info 
    QRPC_PROTO((qrpc_client_info *, char *, char *, int));
qrpc_error_t qrpc_init_inetd_server_info 
    QRPC_PROTO((qrpc_server_info *));
qrpc_error_t qrpc_init_listen_server_info 
    QRPC_PROTO((qrpc_server_info *, char *, int, int));
qrpc_error_t qrpc_create_client 
    QRPC_PROTO((qrpc_t *, qrpc_client_info *, qrpc_valid_opcode[],
		qrpc_version_t, qrpc_version_t));
qrpc_error_t qrpc_create_server 
    QRPC_PROTO((qrpc_t *, qrpc_server_info *, qrpc_valid_opcode[],
		qrpc_version_t, qrpc_version_t));
qrpc_error_t qrpc_accept
    QRPC_PROTO((qrpc_t, qrpc_t *));
void qrpc_destroy 
    QRPC_PROTO((qrpc_t *));
qrpc_error_t qrpc_sendauth 
    QRPC_PROTO((qrpc_t, KTEXT));
qrpc_error_t qrpc_recvauth 
    QRPC_PROTO((qrpc_t, KTEXT));
qrpc_error_t qrpc_auth_to_server 
    QRPC_PROTO((qrpc_t, char *, char *, des_cblock, des_key_schedule));
qrpc_error_t qrpc_auth_from_client 
    QRPC_PROTO((qrpc_t, char *, char *, AUTH_DAT *, des_cblock, 
		des_key_schedule));
qrpc_error_t qrpc_is_client 
    QRPC_PROTO((qrpc_t, qrpc_byte *));
qrpc_error_t qrpc_is_server 
    QRPC_PROTO((qrpc_t, qrpc_byte *));
char *qrpc_error_string 
    QRPC_PROTO((qrpc_t, qrpc_error_t));
void qrpc_drop 
    QRPC_PROTO((qrpc_t, char *));
void qrpc_print_error 
    QRPC_PROTO((qrpc_t, qrpc_error_t));
void qrpc_error_exit 
    QRPC_PROTO((qrpc_t, qrpc_error_t, qrpc_byte));
void qrpc_set_error_fn
    QRPC_PROTO((qrpc_t, qrpc_error_fn_t));


#endif /* __QRPC_H__ */
