// -*-c++-*- /* $Id: aclnt.h,v 1.18 2001/03/25 09:01:55 dm Exp $ */ /* * * Copyright (C) 1998 David Mazieres (dm@uun.org) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2, or (at * your option) any later version. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * USA * */ #include "backoff.h" class aclnt; class xhinfo; typedef callback::ref aclnt_cb; typedef callback::ref aclntraw_cb; typedef callback, clnt_stat>::ref aclntalloc_cb; typedef callback, int>::ref axprtalloc_fn; extern aclnt_cb aclnt_cb_null; class callbase { friend class aclnt; bool checksrc (const sockaddr *) const; virtual clnt_stat decodemsg (const char *, size_t) = 0; void expire () { tmo = NULL; finish (RPC_TIMEDOUT); } protected: const ref c; const sockaddr *const dest; timecb_t *tmo; virtual ~callbase (); callbase (ref, u_int32_t, const sockaddr *); public: const u_int32_t xid; list_entry clink; // Per-client list of calls ihash_entry hlink; // Link in XID hash table void timeout (time_t duration); void cancel () { delete this; } virtual void finish (clnt_stat) = 0; }; class rpccb : public callbase { protected: rpccb (ref, u_int32_t, aclnt_cb, void *, xdrproc_t, const sockaddr *); virtual ~rpccb () {} u_int32_t getxid (xdrsuio &x); u_int32_t getxid (char *, size_t); public: aclnt_cb cb; void *outmem; xdrproc_t outxdr; rpccb (ref, xdrsuio &, aclnt_cb, void *, xdrproc_t, const sockaddr *); clnt_stat decodemsg (const char *, size_t); void finish (clnt_stat); }; class rpccb_unreliable : public rpccb { rpccb_unreliable (); public: void *msgbuf; size_t msglen; tmoq_entry tlink; rpccb_unreliable (ref, xdrsuio &, aclnt_cb, void *out, xdrproc_t outproc, const sockaddr *); rpccb_unreliable (ref, char *, size_t, aclnt_cb, void *out, xdrproc_t outproc, const sockaddr *); ~rpccb_unreliable (); void xmit (int retry); void timeout () { finish (RPC_TIMEDOUT); } }; class aclnt : public virtual refcount { friend class callbase; list calls; const ref xi; public: const rpc_program &rp; private: cbv::ptr eofcb; sockaddr *dest; aclnt (const axprt &); const aclnt &operator= (const aclnt &); static void seteof (ref); protected: aclnt (const ref &x, const rpc_program &rp); ~aclnt (); public: list_entry xhlink; const ref &xprt () const; static bool marshal_call (xdrsuio &, AUTH *auth, u_int32_t progno, u_int32_t versno, u_int32_t procno, xdrproc_t inproc, const void *in); static void dispatch (ref, const char *, ssize_t, const sockaddr *); callbase *call (u_int32_t procno, const void *in, void *out, aclnt_cb, AUTH *auth = NULL, xdrproc_t inproc = NULL, xdrproc_t outproc = NULL, u_int32_t progno = 0, u_int32_t versno = 0, sockaddr *d = NULL); callbase *timedcall (time_t duration, u_int32_t procno, const void *in, void *out, aclnt_cb, AUTH *auth = NULL, xdrproc_t inproc = NULL, xdrproc_t outproc = NULL, u_int32_t progno = 0, u_int32_t versno = 0, sockaddr *d = NULL); clnt_stat scall (u_int32_t procno, const void *in, void *out, AUTH *auth = NULL, xdrproc_t inproc = NULL, xdrproc_t outproc = NULL, u_int32_t progno = 0, u_int32_t versno = 0, sockaddr *d = NULL, time_t duration = 0); callbase *rawcall (const char *msg, size_t len, aclntraw_cb, sockaddr *dest); void seteofcb (cbv::ptr); static ptr alloc (ref x, const rpc_program &pr, const sockaddr *d = NULL); }; void aclntudp_create (const char *host, int port, const rpc_program &rp, aclntalloc_cb cb); void aclntudp_create (const in_addr &addr, int port, const rpc_program &rp, aclntalloc_cb cb); extern const axprtalloc_fn axprt_stream_alloc_default; void aclnttcp_create (const char *host, int port, const rpc_program &rp, aclntalloc_cb cb, axprtalloc_fn xa = axprt_stream_alloc_default); void aclnttcp_create (const in_addr &addr, int port, const rpc_program &rp, axprtalloc_fn xa = axprt_stream_alloc_default); inline const strbuf & strbuf_cat (const strbuf &sb, clnt_stat stat) { return strbuf_cat (sb, clnt_sperrno (stat)); }