/* 
 * $Id: qcs.h,v 1.2 91/05/03 03:03:12 qjb Exp Locker: qjb $
 * $Source: /afs/athena.mit.edu/astaff/project/qcs/src/RCS/qcs.h,v $
 * $Author: qjb $
 *
 */

#ifndef __QCS_H__
#define __QCS_H__

#if !defined(lint) && !defined(SABER) || defined(RCS_HDRS)
static char *rcsid_qcs_h = "$Id: qcs.h,v 1.2 91/05/03 03:03:12 qjb Exp Locker: qjb $";
#endif /* !lint && !SABER || RCS_HDRS */

#include <krb.h>
#include <des.h>
#include <qrpc.h>

#include "qcs_err.h"

#define QCS_SUCCESS 0
#define QCS_FAILURE -1

#define QCS_NO_USERQRPC ((qrpc_t) 1)

/* Arbitrarily restrict the number of jobs per client to NOFILE */
#define MAXJOBS NOFILE

typedef char qcs_bool;
typedef int qcs_error_t;

typedef struct {
    int fd;
    unsigned int unique;
} qcs_client_id;

/* 
 * The function qcsi_get_command knows that qcs_cmd is really char ** .
 */
typedef char **qcs_cmd;

typedef struct {
    qcs_client_id id;		/* Unique client identifier */
    qrpc_t qrpc;
    unsigned long last_req;
    unsigned long last_notified;
    unsigned int cur_jobno;
    int nreq;
    AUTH_DAT auth_dat;
    des_cblock sess_key;
    des_key_schedule sched;
    qcs_bool shutdown;		/* True if this client issued shutdown */
    qcs_bool done;
} *qcs_client;

typedef unsigned long qcs_jobno;

typedef struct {
    qcs_client_id client_id;
    qcs_cmd cmd;
    qcs_jobno jobno;
} qcs_request;

#ifdef __STDC__
typedef void(*qcs_dispatcher)(qcs_client, qcs_request *);
typedef qcs_error_t(*qcs_print_handler)(struct qcs_t_rec *, char *, void *);
typedef qcs_error_t(*qcs_select_handler)(struct qcs_t_rec *, void *);
typedef qcs_error_t(*qcs_comp_handler)(struct qcs_t_rec *, qcs_jobno, void *);
#else
typedef void(*qcs_dispatcher)();
typedef qcs_error_t(*qcs_print_handler)();
typedef qcs_error_t(*qcs_select_handler)();
typedef qcs_error_t(*qcs_comp_handler)();
#endif

typedef struct {
    char *cmd_name;
    qcs_dispatcher dispatcher;
} qcs_cmd_desc;

typedef struct {
    char *aname;
    char *keyfile;
    int timeout;
    char *service;
    int port;
} qcs_server_params;

typedef struct {
    qrpc_client_info client_info;
    char aname[ANAME_SZ + 1];
    int ui_fd;			/* User input file descriptor */
    qcs_print_handler handle_error;
    qcs_print_handler handle_notify;
    qcs_print_handler handle_message;
    qcs_select_handler handle_periodic;
    qcs_select_handler handle_input;
    qcs_select_handler handle_userqrpc;
    qcs_comp_handler handle_completion;
} qcs_client_params;

/* Main client object */
typedef struct qcs_t_rec {
    char errmsg[QRPC_ERRMSGSIZE];
    qcs_bool done;
    qcs_client_params *params;
    qrpc_t qrpc;
    des_cblock sess_key;
    des_key_schedule sched;
    qrpc_t user_qrpc[MAXJOBS];	/* qrpcs for communicating with user server */
} qcs_t;

/* Function prototypes */

/* Server functions */
qcs_error_t qcs_server_mainloop(void);
void qcs_setup_server_params(qcs_server_params *, char *,
			     char *, int, char *,
			     int);
qcs_error_t qcs_server_setup(qcs_cmd_desc **,
			     qrpc_t *, qcs_server_params *,
			     char *);
qcs_error_t qcs_client_message(qcs_client, char *);
qcs_error_t qcs_create_comm(qcs_client, qcs_request *, qrpc_t *, 
			    qrpc_valid_opcode [], 
			    qrpc_version_t, qrpc_version_t);

/* Standard dispatchers */
void qcs_sd_status(qcs_client, qcs_request *);
void qcs_sd_shutdown(qcs_client, qcs_request *);

/* Client functions */
void qcs_setup_client_params(qcs_client_params *, char *,
			     char *, char *, int, int, 
			     qcs_print_handler, qcs_print_handler,
			     qcs_print_handler, qcs_select_handler,
			     qcs_select_handler, qcs_select_handler,
			     qcs_comp_handler);
qcs_error_t qcs_connect(qcs_t *, qcs_client_params *);
qcs_error_t qcs_client_mainloop(qcs_t *, void *);
qcs_error_t qcs_send_command(qcs_t *, char *, void *);
void qcs_disconnect(qcs_t *);

#endif /* __QCS_H__ */
