/* $Id: rex.h,v 1.40 2001/12/13 05:03:03 kaminsky Exp $ */ /* * * Copyright (C) 2000-2001 Eric Peterson (ericp@lcs.mit.edu) * Copyright (C) 2001 Michael Kaminsky (kaminsky@lcs.mit.edu) * * 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 * */ #ifndef _SFSMISC_REX_H_ #define _SFSMISC_REX_H_ 1 #include "sfsmisc.h" #include "sfsconnect.h" #include "qhash.h" #include "crypt.h" #include "aios.h" #include "rex_prot.h" #include "agentconn.h" class rexchannel; class rexfd : public virtual refcount { protected: rexchannel *pch; ptr proxy; u_int32_t channo; int fd; public: // these implement null fd behavior, so you'll probably want to override them virtual void abort (); virtual void data (svccb *sbp); virtual void newfd (svccb *sbp) { sbp->replyref (false); } virtual void exited () {}; /* called when remote module exits */ rexfd (rexchannel *pch, int fd); virtual ~rexfd (); }; class unixfd : public rexfd { protected: int localfd; ptr paios; private: bool weof; bool reof; bool shutrdonexit; cbv closecb; void update_connstate (int how, int error = 0); void datacb (ref okp, clnt_stat) { if (!*okp) update_connstate (SHUT_RDWR); } public: virtual void rcb (const str data, int err); virtual void newfd (svccb *sbp); virtual void data (svccb *sbp); virtual void abort () { update_connstate (SHUT_RDWR); } void exited () { if (shutrdonexit) update_connstate (SHUT_RD); } unixfd (rexchannel *pch, int fd, int localfd, bool noclose = false, bool shutrdonexit = false, cbv closecb = cbv_null); virtual ~unixfd () { if (paios) paios->flush (); closecb (); } }; class rexsession; class rexchannel { vec > vfds; int fdc; protected: rexsession *sess; ptr proxy; u_int32_t channo; bool got_exit_cb; int initnfds; vec command; friend class rexsession; virtual void quit (); virtual void abort (); virtual void madechannel (int error) {}; void channelinit (u_int32_t chnumber, ref proxyaclnt, int error); virtual void data(svccb *sbp); virtual void newfd (svccb *sbp); virtual void exited (int status); public: void insert_fd (int fdn, ref rfd); void remove_fd (int fdn); int get_initnfds () { return initnfds; } vec get_cmd () { return command; } u_int32_t get_channo () { return channo; } ptr get_proxy () { return proxy; } rexchannel (rexsession *sess, int initialfdcount, vec command) : fdc (0), sess (sess), got_exit_cb (false), initnfds (initialfdcount), command(command) { /* warn << "--reached rexchannel: fdc = " << fdc << "\n"; */ } virtual ~rexchannel () { /* warn << "--reached ~rexchannel\n"; */ } }; class rexsession { bool verbose; ptr proxyxprt; ptr rexserv; //todo : make this non-refcounted pointer qhash > channels; qhash > channels_pending_exit; int cchan; callback::ptr endcb; public: str schost; ptr proxy; private: void rexcb_dispatch (svccb *sbp); void madechannel (ref resp, ref newchan, clnt_stat err); void seq2sessinfo (u_int64_t seqno, sfs_hash *sidp, sfs_sessinfo *sip, rex_sesskeydat *kcsdat, rex_sesskeydat *kscdat); void attached (rexd_attach_res *resp, ptr sessxprt, sfs_sessinfo *sessinfo, cbv sessioncreatedcb, clnt_stat err); void connected (rex_sesskeydat *kcsdat, rex_sesskeydat *kscdat, sfs_seqno *rexseqno, cbv sessioncreatedcb, ptr sc, str err); void quitcaller (const u_int32_t &chno, ptr pchan) { pchan->quit (); } void abortcaller (const u_int32_t &chno, ptr pchan) { pchan->abort (); } public: // get's called when all channels close or we get EOF from proxy void setendcb (cbv endcb) { rexsession::endcb = endcb; } void set_verbose (bool status) { verbose = status; } void makechannel (ref newchan, rex_env env = rex_env ()); void remove_chan (int channo); void remove_chan_pending_exit (int channo); // informs all channels that client wants to quit. default // behavior is to kill remote module. void quit () { channels.traverse (wrap (this, &rexsession::quitcaller)); } // calls the abort member function of every channel, which should blow // all the channels away void abort () { endcb = NULL; channels.traverse (wrap (this, &rexsession::abortcaller)); } //use this one if you already have an encrypted transport connected to proxy rexsession (str schostname, ptr proxyxprt); rexsession (cbv sessioncreatedcb, str schostname, bool forwardagent); ~rexsession () { /* warn << "--reached ~rexsession\n"; */ } }; #endif /* _SFSMISC_REX_H_ */