WvStreams
wvdbusconn.h
00001 /* -*- Mode: C++ -*-
00002  * Worldvisions Weaver Software:
00003  *   Copyright (C) 2004-2006 Net Integration Technologies, Inc.
00004  * 
00005  * Pathfinder Software:
00006  *   Copyright (C) 2007, Carillon Information Security Inc.
00007  *
00008  * This library is licensed under the LGPL, please read LICENSE for details.
00009  *
00010  * A WvDBusConn represents a connection to another application. Messages
00011  * can be sent and received via this connection. In most cases, the
00012  * other application is a message bus. 
00013  */ 
00014 #ifndef __WVDBUSCONN_H
00015 #define __WVDBUSCONN_H
00016 
00017 #include "wvstreamclone.h"
00018 #include "wvlog.h"
00019 #include "wvdbusmsg.h"
00020 #include "wvhashtable.h"
00021 #include "wvuid.h"
00022 
00023 #define WVDBUS_DEFAULT_TIMEOUT (300*1000)
00024 
00025 class WvDBusConn;
00026 
00032 typedef wv::function<bool(WvDBusMsg&)> WvDBusCallback;
00033 
00034 class IWvDBusAuth
00035 {
00036 public:
00037     virtual ~IWvDBusAuth() { };
00038     
00047     virtual bool authorize(WvDBusConn &c) = 0;
00048 
00049     // Returns the unix UID negotiated during authentication.  Boring on the
00050     // client side (generally just getuid()), more useful for the server.
00051     virtual wvuid_t get_uid() = 0;
00052 };
00053 
00054 
00055 class WvDBusClientAuth : public IWvDBusAuth
00056 {
00057     bool sent_request;
00058 public:
00059     WvDBusClientAuth();
00060     virtual bool authorize(WvDBusConn &c);
00061     virtual wvuid_t get_uid();
00062 };
00063 
00064 
00065 class WvDBusConn : public WvStreamClone
00066 {
00067     bool client, authorized, in_post_select;
00068     WvString _uniquename;
00069     IWvDBusAuth *auth;
00070     
00071 public:
00072     WvLog log;
00073     
00085     WvDBusConn(WvStringParm moniker, IWvDBusAuth *_auth = NULL,
00086                bool _client = true);
00087     
00092     WvDBusConn(IWvStream *_cloned, IWvDBusAuth *_auth = NULL,
00093                bool _client = true);
00094     
00095     void init(IWvDBusAuth *_auth, bool _client);
00096     
00101     virtual ~WvDBusConn();
00102     
00103     void set_uniquename(WvStringParm s);
00104     void try_auth();
00105     void send_hello();
00106     wvuid_t get_uid() { return auth ? auth->get_uid() : WVUID_INVALID; }
00107     
00108     void out(WvStringParm s);
00109     void out(WVSTRING_FORMAT_DECL)
00110         { return out(WvString(WVSTRING_FORMAT_CALL)); }
00111     const char *in();
00112 
00119     void request_name(WvStringParm name, const WvDBusCallback &onreply = 0,
00120                       time_t msec_timeout = WVDBUS_DEFAULT_TIMEOUT);
00121     
00126     WvString uniquename() const;
00127     
00132     virtual void close();
00133     
00138     uint32_t send(WvDBusMsg msg);
00139     
00144     void send(WvDBusMsg msg, const WvDBusCallback &onreply,
00145               time_t msec_timeout = WVDBUS_DEFAULT_TIMEOUT);
00146     
00162     WvDBusMsg send_and_wait(WvDBusMsg msg,
00163                             time_t msec_timeout = WVDBUS_DEFAULT_TIMEOUT,
00164                             wv::function<void(uint32_t)> serial_cb = 0);
00165 
00170     enum CallbackPri { 
00171         PriSystem    = 0,     // implemented by DBus or WvDBus.  Don't use.
00172         PriSpecific  = 5000,  // strictly limited by interface/method
00173         PriNormal    = 6000,  // a reasonably selective callback
00174         PriBridge    = 7000,  // proxy selectively to other listeners
00175         PriBroadcast = 8000,  // last-resort proxy to all listeners
00176         PriGaveUp    = 9900,  // run this if nothing else works
00177     };
00178     
00198     void add_callback(CallbackPri pri, WvDBusCallback cb, void *cookie = NULL);
00199     
00203     void del_callback(void *cookie);
00204 
00210     virtual bool filter_func(WvDBusMsg &msg);
00211     
00217     bool isidle();
00218     
00219 private:
00220     time_t mintimeout_msec();
00221     virtual bool post_select(SelectInfo &si);
00222     
00223     struct Pending
00224     {
00225         WvDBusMsg msg; // needed in case we need to generate timeout replies
00226         uint32_t serial;
00227         WvDBusCallback cb;
00228         WvTime valid_until;
00229         
00230         Pending(WvDBusMsg &_msg, const WvDBusCallback &_cb,
00231                 time_t msec_timeout)
00232             : msg(_msg), cb(_cb)
00233         {
00234             serial = msg.get_serial();
00235             if (msec_timeout < 0)
00236                 msec_timeout = 5*3600*1000; // "forever" is a few hours
00237             valid_until = msecadd(wvstime(), msec_timeout);
00238         }
00239     };
00240     DeclareWvDict(Pending, uint32_t, serial);
00241     
00242     PendingDict pending;
00243     WvDynBuf in_queue, out_queue;
00244     
00245     void expire_pending(Pending *p);
00246     void cancel_pending(uint32_t serial);
00247     void add_pending(WvDBusMsg &msg, WvDBusCallback cb,
00248                      time_t msec_timeout);
00249     bool _registered(WvDBusMsg &msg);
00250 
00251     struct CallbackInfo
00252     {
00253         CallbackPri pri;
00254         WvDBusCallback cb;
00255         void *cookie;
00256         
00257         CallbackInfo(CallbackPri _pri,
00258                      const WvDBusCallback &_cb, void *_cookie)
00259             : cb(_cb)
00260             { pri = _pri; cookie = _cookie; }
00261     };
00262     static int priority_order(const CallbackInfo *a, const CallbackInfo *b);
00263         
00264     DeclareWvList(CallbackInfo);
00265     CallbackInfoList callbacks;
00266     
00267 };
00268 
00269 #endif // __WVDBUSCONN_H