/*
 * nasd_srpc.h
 *
 * Definitions and structures for SRPC
 *
 * Authors: Jim Zelenka, Nat Lanza
 */
/*
 * Copyright (c) of Carnegie Mellon University, 1999, 2000.
 *
 * Permission to reproduce, use, and prepare derivative works of
 * this software for internal use is granted provided the copyright
 * and "No Warranty" statements are included with all reproductions
 * and derivative works. This software may also be redistributed
 * without charge provided that the copyright and "No Warranty"
 * statements are included in all redistributions.
 *
 * NO WARRANTY. THIS SOFTWARE IS FURNISHED ON AN "AS IS" BASIS.
 * CARNEGIE MELLON UNIVERSITY MAKES NO WARRANTIES OF ANY KIND, EITHER
 * EXPRESSED OR IMPLIED AS TO THE MATTER INCLUDING, BUT NOT LIMITED
 * TO: WARRANTY OF FITNESS FOR PURPOSE OR MERCHANTABILITY, EXCLUSIVITY
 * OF RESULTS OR RESULTS OBTAINED FROM USE OF THIS SOFTWARE. CARNEGIE
 * MELLON UNIVERSITY DOES NOT MAKE ANY WARRANTY OF ANY KIND WITH RESPECT
 * TO FREEDOM FROM PATENT, TRADEMARK, OR COPYRIGHT INFRINGEMENT.
 */


#ifndef _NASD__NASD_SRPC_H_
#define _NASD__NASD_SRPC_H_

#include <nasd/nasd_options.h>
#include <nasd/nasd_rpcgen_c.h>
#include <nasd/nasd_base_types.h>
#include <nasd/nasd_types.h>
#include <nasd/nasd_threadstuff.h>
#include <nasd/nasd_srpc_types.h>
#include <nasd/nasd_rpcgen_glob_param.h>
#include <nasd/nasd_shutdown.h>
#include <nasd/nasd_mem.h>

#define NASD_SRPC_OTW_BASE_ARGS \
  ((NASD_SRPC_MAX_ARGSIZE/sizeof(nasd_otw_base_t))+1)

#define NASD_SRPC_OTW_BASE_RES \
  ((NASD_SRPC_MAX_RESSIZE/sizeof(nasd_otw_base_t))+1)

#ifdef SOLARIS
#include <sys/filio.h>

/* Rather than support 4.3/4.4 nonsense... */
#define NASD_SRPC_USE_RECVFROM 0
#endif /* SOLARIS */

#ifdef IRIX
#define NASD_SRPC_USE_RECVFROM 0
#endif /* IRIX */

#ifndef NASD_SRPC_TIMERS
#define NASD_SRPC_TIMERS    1
#endif /* !NASD_SRPC_TIMERS */

#ifndef NASD_SRPC_COUNTERS
#define NASD_SRPC_COUNTERS  1
#endif /* !NASD_SRPC_COUNTERS */

#if NASD_SRPC_TIMERS > 0
#include <nasd/nasd_timer.h>
#endif /* NASD_SRPC_TIMERS > 0 */

typedef struct nasd_srpc_call_s              nasd_srpc_call_t;
typedef struct nasd_srpc_conn_s              nasd_srpc_conn_t;
typedef struct nasd_srpc_listener_s          nasd_srpc_listener_t;
typedef struct nasd_srpc_listener_set_s      nasd_srpc_listener_set_t;
typedef struct nasd_srpc_memvec_s            nasd_srpc_memvec_t;
typedef struct nasd_srpc_client_pipestate_s  nasd_srpc_client_pipestate_t;
typedef struct nasd_srpc_client_pullcb_s     nasd_srpc_client_pullcb_t;
typedef struct nasd_srpc_client_pushcb_s     nasd_srpc_client_pushcb_t;
typedef struct nasd_srpc_req_header_s        nasd_srpc_req_header_t;
typedef struct nasd_srpc_server_pipestate_s  nasd_srpc_server_pipestate_t;
typedef struct nasd_srpc_server_call_s       nasd_srpc_server_call_t;
typedef struct nasd_srpc_sock_s              nasd_srpc_sock_t;
typedef struct nasd_srpc_sys_conn_s          nasd_srpc_sys_conn_t;
typedef struct nasd_srpc_sys_listener_s      nasd_srpc_sys_listener_t;
typedef struct nasd_srpc_sys_sock_s          nasd_srpc_sys_sock_t;
typedef struct nasd_srpc_sockbuf_opts_s      nasd_srpc_sockbuf_opts_t;
typedef struct nasd_srpc_stats_s             nasd_srpc_stats_t;

#ifndef KERNEL
#include <nasd/generic/nasd_generic_sock.h>
#include <nasd/generic/nasd_generic_srpc.h>
#endif /* !KERNEL */

#if defined(LINUX) && defined(KERNEL)
#include <nasd/linux/nasd_linux_sock.h>
#include <nasd/linux/nasd_linux_srpc.h>
#endif /* LINUX && KERNEL */

#define NASD_SRPC_PIPESTATE_PEND     0 /* not yet started */
#define NASD_SRPC_PIPESTATE_RUNNING  1 /* data moving */
#define NASD_SRPC_PIPESTATE_RTERM    2 /* data moving, receiver doesn't want */
#define NASD_SRPC_PIPESTATE_TERM     3 /* closed */

#define NASD_SRPC_MAXPIPES         16
#define NASD_SRPC_PIPENUM_DONE     NASD_SRPC_MAXPIPES
#define NASD_SRPC_PIPENUM_NOPIPES  (NASD_SRPC_MAXPIPES+1)

#define NASD_SRPC_MAX_ARG_OTW_BASES \
  (NASD_SRPC_MAX_NARGS*NASD_SRPC_OTW_BASE_ARGS)
#define NASD_SRPC_MAX_RES_OTW_BASES \
  (NASD_SRPC_MAX_NRES*NASD_SRPC_OTW_BASE_RES)

#define NASD_SRPC_MAX_ARG_BYTES \
  (NASD_SRPC_MAX_ARG_OTW_BASES*sizeof(nasd_otw_base_t))
#define NASD_SRPC_MAX_RES_BYTES \
  (NASD_SRPC_MAX_RES_OTW_BASES*sizeof(nasd_otw_base_t))

/*
 * "kinds" of handles
 */
#define NASD_SRPC_CONN_CLIH  1 /* client handle */
#define NASD_SRPC_CONN_SERV  2 /* server handle to client */

/*
 * Connection states
 */
#define NASD_SRPC_STATE_CONN   0x0001 /* connected */
#define NASD_SRPC_STATE_IDLE   0x0002 /* idle */
#define NASD_SRPC_STATE_DISC   0x0004 /* disconnecting (unbind) */
#define NASD_SRPC_STATE_OP_S   0x0008 /* outgoing op call in progress */
#define NASD_SRPC_STATE_OP_R   0x0010 /* incoming op call in progress */
#define NASD_SRPC_STATE_ODAM   0x0020 /* outgoing state damaged */
#define NASD_SRPC_STATE_IDAM   0x0040 /* incoming state damaged */
#define NASD_SRPC_STATE_REIDLE 0x0080 /* reidle (server) */
#define NASD_SRPC_STATE_DEAD   0x0100 /* on dead list (server) */
#define NASD_SRPC_STATE_AR     0x0200 /* active ring (server) */

/*
 * sock_recv flags
 */
#define NASD_SRPC_RECV_FILL   0x0001 /* must fill buf */
#define NASD_SRPC_RECV_NOWAIT 0x0002 /* don't read if no data pending */

#define NASD_SRPC_CALLHASH_BUCKETS 3
#define NASD_SRPC_CALL_HASH(_callid_) ((_callid_) % NASD_SRPC_CALLHASH_BUCKETS)

#define NASD_SRPC_EXTRABUF_SIZE 256

struct nasd_srpc_stats_s {
#if NASD_SRPC_COUNTERS > 0
  nasd_uint64      sock_send_calls;
  nasd_uint64      sock_write_calls;
  nasd_uint64      sock_writev_calls;
  nasd_uint64      sock_send_chgblock;
  nasd_uint64      sock_send_errs;

  nasd_uint64      sock_recv_calls;
  nasd_uint64      sock_read_calls;
  nasd_uint64      sock_recv_chgblock;
  nasd_uint64      sock_recv_errs;
#endif /* NASD_SRPC_COUNTERS > 0 */

#if NASD_SRPC_TIMERS > 0
  nasd_timespec_t  pipe_push_wait_ts;
  nasd_timespec_t  pipe_push_send_ts;

  nasd_timespec_t  pipe_pull_recv_ts;
#endif /* NASD_SRPC_TIMERS > 0 */

#if (NASD_SRPC_COUNTERS == 0) && (NASD_SRPC_TIMERS == 0)
  int  placeholder;
#endif /* (NASD_SRPC_COUNTERS == 0) && (NASD_SRPC_TIMERS == 0) */
};

struct nasd_srpc_req_header_s {
  nasd_srpc_header_otw_t  opheader;
  nasd_srpc_req_otw_t     reqheader;
};

struct nasd_srpc_listener_set_s {
  nasd_srpc_listener_t      *listener;
  nasd_uint64                serial_num;
  nasd_srpc_listener_set_t  *next;
};

struct nasd_srpc_memvec_s {
  void                *buf;
  int                  len;
  nasd_srpc_memvec_t  *next;
};

struct nasd_srpc_client_pushcb_s {
  void   *state;
  void  (*alloc_cb)(void          *state,
                    nasd_uint32    bsize,
                    nasd_byte_t  **bufp,
                    nasd_uint32   *bcount);
  void  (*push_cb) (void          *state,
                    void          *buf,
                    nasd_uint32    in_count);
};

struct nasd_srpc_client_pullcb_s {
  void   *state;
  void  (*alloc_cb)(void          *state,
                    nasd_uint32    bsize,
                    nasd_byte_t  **bufp,
                    nasd_uint32   *bcount);
  void  (*pull_cb) (void          *state,
                    void          *buf,
                    nasd_uint32    in_count,
                    nasd_uint32   *out_count);
};

struct nasd_srpc_server_pipestate_s {
  nasd_srpc_pipenum_t       pipenum;
  nasd_srpc_listener_t     *listener;
  nasd_srpc_conn_t         *conn;
  nasd_srpc_server_call_t  *call;
  int                       state;
  int                       dir;
};

struct nasd_srpc_client_pipestate_s {
  nasd_srpc_pipenum_t       pipenum;
  int                       state;
};

typedef nasd_status_t (*nasd_srpc_demux_proc_t)(
  nasd_srpc_listener_t     *listener,
  nasd_srpc_conn_t         *conn,
  nasd_srpc_server_call_t  *call);

struct nasd_srpc_call_s {
  nasd_srpc_callid_t     callid;
  nasd_srpc_header_t     header;
  nasd_srpc_header_t     pipe_header;
  nasd_srpc_status_t     local_stat;
  int                    state;
  int                    ishashed;
  nasd_srpc_call_t      *next;
  nasd_srpc_call_t      *prev;

  int                    pipe_expected;
  nasd_srpc_pipenum_t    last_pipe_finished;

  int                    pipe_enabled;
  nasd_otw_base_t        resmem[NASD_SRPC_MAX_RES_OTW_BASES];

  NASD_DECLARE_COND(data_ready)
};

struct nasd_srpc_server_call_s {
  nasd_otw_base_t                argmem[NASD_SRPC_MAX_ARG_OTW_BASES];
  nasd_otw_base_t                resmem[NASD_SRPC_MAX_RES_OTW_BASES];

  nasd_srpc_callid_t             callid;
  nasd_srpc_header_t             call_header;
  nasd_srpc_header_t             pipe_header;
  nasd_srpc_req_t                req;
  nasd_srpc_server_call_t       *next;
  nasd_srpc_server_call_t       *prev;
  nasd_srpc_server_call_t       *pend_next;
  int                            ishashed;

  int                            handle_count_held;     /* for pipe */
  int                            handle_count_held_opt; /* for pipe */

  int                            arglen;
  int                            reslen;
  nasd_srpc_status_t             result;

  nasd_srpc_pipenum_t            cur_pipenum;

  nasd_srpc_server_pipestate_t   pipes[NASD_SRPC_MAXPIPES];
  int                            npipes;
  int                            pull_remain;
  nasd_srpc_server_pipestate_t  *cur_pipe;


  NASD_DECLARE_COND(data_ready)
};

struct nasd_srpc_sock_s {
  nasd_srpc_sys_sock_t   sock;
  nasd_srpc_sock_t      *next;
};

struct nasd_srpc_conn_s {
  nasd_srpc_sock_t              *sock;
  int                            kind;
  int                            state;
  int                            use_count; /* RPCs in flight */

  int                            bytes_outstanding;
  nasd_srpc_header_t             cur_header;

  nasd_uint32                    ipaddr;
  nasd_uint16                    ipport;
  nasd_srpc_callid_t             next_callid;

  nasd_srpc_call_t               c_call_buckets[NASD_SRPC_CALLHASH_BUCKETS];
  nasd_srpc_server_call_t        s_call_buckets[NASD_SRPC_CALLHASH_BUCKETS];

  nasd_srpc_conn_t              *next;

  nasd_srpc_conn_t              *active_next;
  nasd_srpc_conn_t              *active_prev;
  int                            handle_count;

  nasd_srpc_conn_t              *idle_next;
  nasd_srpc_conn_t              *idle_prev;

  nasd_srpc_server_call_t       *pend_calls;
  nasd_srpc_server_call_t       *pend_calls_tail;

  nasd_shutdown_list_t          *shutdown_list;

  nasd_srpc_sys_conn_t           sys_conn;

  nasd_uint64                    conn_number;

  NASD_DECLARE_MUTEX(lock)
  NASD_DECLARE_COND(use_cond)
  NASD_DECLARE_COND(state_cond)
};

struct nasd_srpc_listener_s {
  nasd_shutdown_list_t      *shutdown_list;

  nasd_thread_t             *threads;
  nasd_threadgroup_t         listener_group;
  int                        nthreads;
  nasd_srpc_demux_proc_t     demux_proc;
  nasd_uint16                ipport;

  nasd_thread_t              dead_thread;
  nasd_threadgroup_t         dead_group;

  nasd_uint64                conn_number;

  /*
   * The "active/idle" here refer to whether or not data
   * is pending for reading.
   */

  nasd_srpc_conn_t            conn_active_ring;
  nasd_srpc_conn_t            conn_idle_ring;

  nasd_srpc_conn_t           *dead_list;

  nasd_uint64                 serial_num;

  nasd_srpc_sys_listener_t    sys_listener;
};

struct nasd_srpc_sockbuf_opts_s {
  int  sndbuf;
  int  rcvbuf;
#ifndef __linux__
  int  sndlowat;
  int  rcvlowat;
#endif /* !__linux__ */
  int  nodelay;
  int  nodelay_thresh;
  int  keepalive;
  int  reuseaddr;
#ifndef __linux__
  int  loopback;
#endif /* !__linux__ */
};

#define NASD_SRPC_LOCK_CONN(_conn_) \
  NASD_LOCK_MUTEX((_conn_)->lock)

#define NASD_SRPC_TRY_LOCK_CONN(_conn_)  /* nonzero = lock taken */ \
  NASD_TRY_LOCK_MUTEX((_conn_)->lock)

#define NASD_SRPC_UNLOCK_CONN(_conn_) \
  NASD_UNLOCK_MUTEX((_conn_)->lock)

#define NASD_SRPC_CONN_LOCK_OWNED(_conn_) \
  NASD_MUTEX_OWNED((_conn_)->lock)

#define NASD_SRPC_CONN_LOCK_NOT_OWNED(_conn_) \
  NASD_MUTEX_NOT_OWNED((_conn_)->lock)

#define NASD_SRPC_CONN_WAIT_USE(_conn_) \
  NASD_WAIT_COND((_conn_)->use_cond, (_conn_)->lock)

#define NASD_SRPC_CONN_WAIT_STATE(_conn_) \
  NASD_WAIT_COND((_conn_)->state_cond, (_conn_)->lock)

#define NASD_SRPC_CONN_INC_USE(_conn_) { \
  (_conn_)->use_count++; \
  if ((_conn_)->use_count == 1) { \
    if ((_conn_)->kind == NASD_SRPC_CONN_CLIH) { \
      NASD_ASSERT((_conn_)->state&NASD_SRPC_STATE_IDLE); \
      (_conn_)->state &= ~NASD_SRPC_STATE_IDLE; \
    } \
    NASD_BROADCAST_COND((_conn_)->state_cond); /* ??? necessary ? */ \
  } \
}

/* 
 * Caller holds conn lock
 */
#define NASD_SRPC_CONN_DEC_USE(_conn_) { \
  NASD_ASSERT((_conn_)->use_count > 0); \
  if ((_conn_)->kind == NASD_SRPC_CONN_CLIH) { \
    NASD_ASSERT(!((_conn_)->state&NASD_SRPC_STATE_IDLE)); \
  } \
  (_conn_)->use_count--; \
  if ((_conn_)->use_count == 0) { \
    if ((_conn_)->kind == NASD_SRPC_CONN_CLIH) { \
      (_conn_)->state |= NASD_SRPC_STATE_IDLE; \
      NASD_BROADCAST_COND((_conn_)->state_cond); \
    } \
    NASD_BROADCAST_COND((_conn_)->use_cond); \
  } \
}

/*
 * Caller holds listener lock
 * Caller holds conn lock
 */
#define NASD_SRPC_CONN_INC_HANDLE(_listener_,_conn_) { \
  NASD_ASSERT((_conn_)->handle_count >= 0); \
  NASD_ASSERT((_conn_)->kind == NASD_SRPC_CONN_SERV); \
  (_conn_)->handle_count++; \
  if ((_conn_)->handle_count == 1) { \
    nasd_status_t _rc; \
    _rc = nasd_srpc_sys_mark_conn_active(_listener_,_conn_); \
    if (_rc) { \
      NASD_PANIC(); \
    } \
  } \
  NASD_ASSERT(!((_conn_)->state&\
    (NASD_SRPC_STATE_REIDLE|NASD_SRPC_STATE_IDLE))); \
  NASD_ASSERT((_conn_)->handle_count >= 0); \
}

/*
 * Caller holds listener lock
 * Caller holds conn lock
 */
#define NASD_SRPC_CONN_DEC_HANDLE(_listener_,_conn_) { \
  nasd_status_t _rc; \
  NASD_ASSERT((_conn_)->handle_count > 0); \
  NASD_ASSERT((_conn_)->kind == NASD_SRPC_CONN_SERV); \
  NASD_ASSERT(!((_conn_)->state&\
    (NASD_SRPC_STATE_REIDLE|NASD_SRPC_STATE_IDLE))); \
  (_conn_)->handle_count--; \
  if ((_conn_)->handle_count == 0) { \
    NASD_ASSERT(!((_conn_)->state&\
      (NASD_SRPC_STATE_OP_R|NASD_SRPC_STATE_AR))); \
    _rc = nasd_srpc_sys_mark_conn_idle(_listener_,_conn_); \
    if (_rc) { \
      NASD_PANIC(); \
    } \
    /* \
     * NOTE: \
     * We do not assert that the connection is idle here, \
     * because the nasd_srpc_sys_mark_conn_idle() is allowed \
     * to decide that the connection has readable data, and \
     * should therefore be marked active instead of idle. \
     */ \
  } \
}

/*
 * Caller holds listener lock
 * Caller holds conn lock
 */
#define NASD_SRPC_CONN_MARK_DEAD(_listener_,_conn_) { \
  NASD_ASSERT(!((_conn_)->state&NASD_SRPC_STATE_DEAD)); \
  (_conn_)->next = (_listener_)->dead_list; \
  (_listener_)->dead_list = (_conn_); \
  (_conn_)->state |= NASD_SRPC_STATE_DEAD; \
}

#define NASD_SRPC_LOCK_LISTENER(_lis_)      NASD_SRPC_SYS_LOCK_LISTENER(_lis_)
#define NASD_SRPC_TRY_LOCK_LISTENER(_lis_)  NASD_SRPC_SYS_TRY_LOCK_LISTENER(_lis_)
#define NASD_SRPC_UNLOCK_LISTENER(_lis_)    NASD_SRPC_SYS_UNLOCK_LISTENER(_lis_)

#define NASD_SRPC_CONN_CONNECTED(_conn_) \
  ((_conn_)->state&NASD_SRPC_STATE_CONN)

#if NASD_SRPC_TIMERS > 0
#define NASD_SRPC_START_TIMER(_tm_,_ts_) { \
  NASD_TM_START(_tm_); \
}
#define NASD_SRPC_FINISH_TIMER(_tm_,_ts_,_accum_ts_) { \
  NASD_TM_STOP(_tm_); \
  NASD_TM_ELAPSED_TS(_tm_,_ts_); \
  NASD_TIMESPEC_ADD(*(_accum_ts_),*(_ts_)); \
}
#else /* NASD_SRPC_TIMERS > 0 */
#define NASD_SRPC_START_TIMER(_tm_,_ts_) { /* noop */ }
#define NASD_SRPC_FINISH_TIMER(_tm_,_ts_,_accum_ts_) { /* noop */ }
#endif /* NASD_SRPC_TIMERS > 0 */

#if NASD_SRPC_COUNTERS > 0
#define NASD_SRPC_INC_COUNTER(_counter_) NASD_ATOMIC_INC64(_counter_)
#else /* NASD_SRPC_COUNTERS > 0 */
#define NASD_SRPC_INC_COUNTER(_counter_) { /* noop */ }
#endif /* NASD_SRPC_COUNTERS > 0 */

typedef nasd_status_t (*nasd_srpc_client_push_func_t)(
  nasd_srpc_conn_t     *conn,
  nasd_srpc_call_t     *call,
  void                 *rock,
  nasd_srpc_pipenum_t   pipenum,
  int                  *bytes_pushed,
  int                   final_state,
  nasd_srpc_status_t   *status);

typedef nasd_status_t (*nasd_srpc_client_pull_func_t)(
  nasd_srpc_conn_t     *conn,
  nasd_srpc_call_t     *call,
  void                 *rock,
  nasd_srpc_pipenum_t   pipenum,
  nasd_srpc_status_t   *status);

/* init/teardown */
nasd_status_t nasd_srpc_real_init(void);
void nasd_srpc_real_shutdown(void);
void nasd_srpcsys_init(void);
nasd_status_t nasd_srpc_init(void);
void nasd_srpc_shutdown(void);

/* shared */
extern nasd_srpc_sockbuf_opts_t nasd_srpc_cli_sockbuf_opts;
extern nasd_srpc_sockbuf_opts_t nasd_srpc_srv_sockbuf_opts;
extern nasd_srpc_stats_t nasd_srpc_stats;
void nasd_srpc_reset_stats(void);
void nasd_srpc_dump_stats(void);
nasd_status_t nasd_srpc_conn_init(nasd_srpc_conn_t *conn);
void nasd_srpc_conn_clean(nasd_srpc_conn_t *conn);
nasd_status_t nasd_srpc_call_init(nasd_srpc_call_t *call);
void nasd_srpc_call_clean(nasd_srpc_call_t *call);
nasd_status_t nasd_srpc_server_call_init(nasd_srpc_server_call_t *server_call);
void nasd_srpc_server_call_clean(nasd_srpc_server_call_t *server_call);
nasd_status_t nasd_srpc_sys_init(nasd_shutdown_list_t *sl);
nasd_status_t nasd_srpc_sys_sock_set_options(
  nasd_srpc_sock_t *sock, nasd_srpc_sockbuf_opts_t *opts);
nasd_status_t nasd_srpc_allocate_mem(void **bufp, int len);
void nasd_srpc_free_mem(void *buf, int len);
nasd_status_t nasd_srpc_conn_get(nasd_srpc_conn_t **connp);
void nasd_srpc_conn_free(nasd_srpc_conn_t *conn);
nasd_status_t nasd_srpc_sock_get(nasd_srpc_sock_t **sockp);
void nasd_srpc_sock_free(nasd_srpc_sock_t *sock);
nasd_status_t nasd_srpc_call_get(nasd_srpc_call_t **callp);
void nasd_srpc_call_free(nasd_srpc_call_t *call);
nasd_status_t nasd_srpc_server_call_get(nasd_srpc_server_call_t **callp);
void nasd_srpc_server_call_free(nasd_srpc_server_call_t *call);
nasd_status_t nasd_srpc_slurp_extra(nasd_srpc_conn_t *conn, int extra);
void nasd_srpc_conn_reinit(nasd_srpc_conn_t *conn);
void nasd_srpc_call_reinit(nasd_srpc_call_t *call);
void nasd_srpc_server_call_reinit(nasd_srpc_server_call_t *call);
char *nasd_srpc_error_string(nasd_srpc_status_t status,
  char *str, int len, char *file, int line);

/* client */
nasd_status_t nasd_srpc_call_complete(nasd_srpc_conn_t *conn,
  nasd_srpc_call_t *call, int final_state, int reslen,
  nasd_srpc_status_t *status);
nasd_status_t nasd_srpc_conn_disc(nasd_srpc_conn_t *conn);
nasd_status_t nasd_srpc_initiate_call(nasd_srpc_conn_t *conn,
  nasd_srpc_call_t **callp);
nasd_status_t nasd_srpc_place_call(nasd_srpc_conn_t *conn,
  nasd_srpc_call_t *call, nasd_srpc_memvec_t *memvec,
  int nmemvecs, int total_len, nasd_uint32 pipeword);
nasd_status_t nasd_srpc_conn_conn(nasd_srpc_conn_t *conn);
void nasd_srpc_conn_shutdown_conn(void *conn_arg);
nasd_status_t nasd_srpc_bind_to_server(char *servername,
  char *portnum, nasd_srpc_handle_t *handlep);
nasd_status_t nasd_srpc_unbind_server(nasd_srpc_handle_t *handlep);
nasd_status_t nasd_srpc_client_handle(nasd_srpc_conn_t *conn,
  nasd_srpc_call_t *until_call);
nasd_status_t nasd_srpc_client_run_serverpush(nasd_srpc_conn_t *conn,
  nasd_srpc_call_t *call, void *rock, nasd_srpc_pipenum_t pipenum,
  int *bytes_pushed, int final_state, nasd_srpc_status_t *status);
nasd_status_t nasd_srpc_client_run_serverpull(nasd_srpc_conn_t *conn,
  nasd_srpc_call_t *call, void *rock, nasd_srpc_pipenum_t pipenum,
  nasd_srpc_status_t *status);
nasd_status_t nasd_srpc_client_run_serverpush_cb(nasd_srpc_conn_t *conn,
  nasd_srpc_call_t *call, void *rock, nasd_srpc_pipenum_t pipenum,
  int *bytes_pushed, int final_state, nasd_srpc_status_t *status);
nasd_status_t nasd_srpc_client_run_serverpull_cb(nasd_srpc_conn_t *conn,
  nasd_srpc_call_t *call, void *rock, nasd_srpc_pipenum_t pipenum,
  nasd_srpc_status_t *status);
nasd_status_t nasd_srpc_client_wait_pipeenab(
  nasd_srpc_conn_t *conn, nasd_srpc_call_t *call,
  int final_state, nasd_srpc_status_t *status);

/* server */
int nasd_srpc_listener_in_set(nasd_srpc_listener_t *listener,
  nasd_uint64 serial_num);
nasd_status_t nasd_srpc_listener_wait(nasd_srpc_listener_t *listener);
nasd_status_t nasd_srpc_server_init(nasd_shutdown_list_t *sl);
nasd_status_t nasd_srpc_send_reply_header(nasd_srpc_listener_t *listener,
  nasd_srpc_conn_t *conn, nasd_srpc_header_t *header);
nasd_status_t nasd_srpc_call_enable_pipes(nasd_srpc_listener_t *listener,
  nasd_srpc_conn_t *conn, nasd_srpc_server_call_t *call);
void nasd_srpc_listener_proc(void *listener_arg);
void nasd_srpc_listener_proc_shutdown(void *listener_arg);
nasd_status_t nasd_srpc_listener_start(nasd_srpc_listener_t **listener,
  int service_threads, nasd_uint16 ipport,
  nasd_srpc_demux_proc_t demux_proc);
void nasd_srpc_listener_dead_proc(void *listener_arg);
nasd_status_t nasd_srpc_listener_handle_conn(nasd_srpc_listener_t *listener,
  nasd_srpc_conn_t *conn, nasd_srpc_server_call_t **callp,
  nasd_srpc_server_call_t *call_active);
nasd_status_t nasd_srpc_listener_destroy(nasd_srpc_listener_t *listener);
void nasd_srpc_listener_do_shutdown(void *listener_arg);
nasd_status_t nasd_srpc_server_pipe_push(void *pipe_arg, void *buf,
  nasd_len_t len);
nasd_status_t nasd_srpc_server_procpipe_push(void *pipe_arg, void *buf,
  nasd_len_t len, nasd_byte_t *ign1, nasd_byte_t *ign2, int *ign3);
nasd_status_t nasd_srpc_server_pipe_pull(void *pipe_arg, void *buf,
  nasd_len_t len, nasd_len_t *bytes_pulled);

/* platform-specific sock */
nasd_status_t nasd_srpc_sys_sock_init(nasd_srpc_sock_t *sock);
nasd_status_t nasd_srpc_sys_sock_conn(nasd_srpc_sock_t *sock,
  nasd_uint32 ipaddr, nasd_uint16 ipport);
nasd_status_t nasd_srpc_sys_sock_send(nasd_srpc_sock_t *sock,
  nasd_srpc_memvec_t *memvec, int total_len, int *bytes_sent);
nasd_status_t nasd_srpc_sys_sock_recv(nasd_srpc_sock_t *sock,
  void *buf, int len, int *bytes_received, int flags);
nasd_status_t nasd_srpc_sys_sock_destroy(nasd_srpc_sock_t *sock);

/* platform-specific listener */
nasd_status_t nasd_srpc_sys_listener_init(nasd_srpc_listener_t *listener);
nasd_status_t nasd_srpc_sys_listener_start(nasd_srpc_listener_t *listener);
void nasd_srpc_sys_listener_stop(nasd_srpc_listener_t *listener);
nasd_status_t nasd_srpc_sys_mark_conn_idle(nasd_srpc_listener_t *listener,
  nasd_srpc_conn_t *conn);
nasd_status_t nasd_srpc_sys_mark_conn_active(nasd_srpc_listener_t *listener,
  nasd_srpc_conn_t *conn);
nasd_status_t nasd_srpc_sys_listener_conn_dead(nasd_srpc_listener_t *listener,
  nasd_srpc_conn_t *conn);

/* platform-specific client */
nasd_status_t nasd_srpc_client_sys_conn_init(nasd_srpc_conn_t *conn);
void nasd_srpc_sys_client_proc(void *conn_arg);

#endif /* !_NASD__NASD_SRPC_H_ */

/* Local Variables:  */
/* indent-tabs-mode: nil */
/* tab-width: 2 */
/* End: */
