// -*-c++-*- /* $Id: axprt.h,v 1.28 2001/11/09 16:56:26 kaminsky 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 * */ class axprt : public virtual refcount { friend class xhinfo; axprt (const axprt &); axprt &operator= (const axprt &); protected: xhinfo *xhip; axprt (bool r, bool c, size_t ss = 0) : xhip (NULL), reliable (r), connected (c), socksize (ss) {} public: enum { defps = 0x10400 }; const bool reliable; const bool connected; const size_t socksize; typedef callback::ptr recvcb_t; virtual void sendv (const iovec *, int, const sockaddr *) = 0; virtual void setwcb (cbv cb) { (*cb) (); } virtual void setrcb (recvcb_t) = 0; virtual bool ateof () { return false; } void send (const void *data, size_t len, const sockaddr *dest) { iovec iov = {(char *) data, len}; sendv (&iov, 1, dest); } }; class axprt_dgram : public axprt { const size_t pktsize; int fd; recvcb_t cb; sockaddr *sabuf; char *pktbuf; static bool isconnected (int fd); void input (); protected: axprt_dgram (int, bool, size_t, size_t); virtual ~axprt_dgram (); public: void sendv (const iovec *, int, const sockaddr *); void setrcb (recvcb_t); static ref alloc (int f, size_t ss = sizeof (sockaddr), size_t ps = defps) { return New refcounted (f, isconnected (f), ss, ps); } }; class axprt_stream : public axprt { bool destroyed; bool ingetpkt; vec syncpts; protected: const size_t pktsize; const size_t bufsize; int fd; recvcb_t cb; u_int32_t pktlen; char *pktbuf; struct suio *out; bool wcbset; void wrsync (); void sendbreak (cbv::ptr); bool checklen (int32_t *len); virtual ssize_t doread (void *buf, size_t maxlen); virtual int dowritev (int iovcnt) { return out->output (fd, iovcnt); } virtual void recvbreak (); virtual bool getpkt (char **, char *); void fail (); void input (); void callgetpkt (); void output (); axprt_stream (int fd, size_t ps, size_t bufsize = 0); virtual ~axprt_stream (); public: void ungetpkt (const void *pkt, size_t len); int reclaim (); bool ateof () { return fd < 0; } virtual void sendv (const iovec *, int, const sockaddr * = NULL); void setrcb (recvcb_t); void setwcb (cbv); static ref alloc (int f, size_t ps = defps) { return New refcounted (f, ps); } unsigned long bytes_sent; unsigned long bytes_recv; }; /* Clonesrv reads only one packet at a time from the kernel. Its file * descriptor can therefore be passed off to another process without * fear of loosing buffered data in the sender. */ class axprt_clone : public axprt_stream { friend class axprt_unix; int takefd (); protected: axprt_clone (int f, size_t ps) : axprt_stream (f, ps) {} virtual ssize_t doread (void *buf, size_t maxsz); public: static ref alloc (int f, size_t ps = defps) { return New refcounted (f, ps); } }; class axprt_unix : public axprt_stream { struct fdtosend { const int fd; mutable bool closeit; fdtosend (int f, bool c) : fd (f), closeit (c) {} ~fdtosend () { if (closeit) close (fd); } fdtosend (const fdtosend &f) : fd (f.fd), closeit (f.closeit) { f.closeit = false; } }; vec fdsendq; vec fdrecvq; //void sendit (int, bool); protected: axprt_unix (int f, size_t ps, size_t bs = 0) : axprt_stream (f, ps, bs), allow_recvfd (true) {} virtual ~axprt_unix (); virtual void recvbreak (); virtual ssize_t doread (void *buf, size_t maxsz); virtual int dowritev (int iovcnt); public: bool allow_recvfd; static ref alloc (int, size_t = axprt_stream::defps); void sendfd (int fd, bool closeit = true); void sendfd (ref x) { sendfd (x->fd, false); } void clone (ref x); int recvfd (); }; extern pid_t axprt_unix_spawn_pid; #ifdef MAINTAINER extern bool axprt_unix_spawn_connected; #else /* !MAINTAINER */ enum { axprt_unix_spawn_connected = 0 }; #endif /* !MAINTAINER */ ptr axprt_unix_spawnv (str path, const vec &av, size_t = 0, cbv::ptr postforkcb = NULL, char *const *env = NULL); ptr axprt_unix_aspawnv (str path, const vec &av, size_t = 0, cbv::ptr postforkcb = NULL, char *const *env = NULL); ptr axprt_unix_spawn (str path, size_t = 0, char *arg0 = NULL, ...); ptr axprt_unix_connect (const char *path, size_t ps = axprt_stream::defps); ptr axprt_unix_stdin (size_t ps = axprt_stream::defps); typedef callback, int>::ref cloneserv_cb; bool cloneserv (int fd, cloneserv_cb cb, size_t ps = axprt_stream::defps); #if 0 template<> struct hashfn > { hashfn () {} hash_t operator () (axprt *p) const { return (u_int) p; } }; #endif