11 #include "wvdbusconn.h"
12 #include "wvmoniker.h"
14 #undef interface // windows
15 #include <dbus/dbus.h>
21 WvStringList::Iter i(l);
23 if (!strncasecmp(dbus_moniker,
"unix:", 5))
26 l.
split(dbus_moniker+5,
",");
27 for (i.rewind(); i.next(); )
29 if (!strncasecmp(*i,
"path=", 5))
31 else if (!strncasecmp(*i,
"abstract=", 9))
33 else if (!strncasecmp(*i,
"tmpdir=", 7))
39 return WvString(
"unix:%s/dbus.sock", tmpdir);
41 else if (!strncasecmp(dbus_moniker,
"tcp:", 4))
44 l.
split(dbus_moniker+4,
",");
45 for (i.rewind(); i.next(); )
47 if (!strncasecmp(*i,
"family=", 7))
49 else if (!strncasecmp(*i,
"host=", 5))
51 else if (!strncasecmp(*i,
"port=", 5))
55 return WvString(
"tcp:%s:%s", host, port);
59 return WvString(
"tcp:0.0.0.0:%s", port);
70 if (!strcasecmp(s,
"starter"))
72 WvString startbus(getenv(
"DBUS_STARTER_ADDRESS"));
74 return IWvStream::create(translate(startbus));
77 WvString starttype(getenv(
"DBUS_STARTER_BUS_TYPE"));
78 if (!!starttype && !strcasecmp(starttype,
"system"))
80 else if (!!starttype && !strcasecmp(starttype,
"session"))
85 if (!strcasecmp(s,
"system"))
92 WvString bus(getenv(
"DBUS_SYSTEM_BUS_ADDRESS"));
94 return IWvStream::create(translate(bus));
97 if (!strcasecmp(s,
"session"))
99 WvString bus(getenv(
"DBUS_SESSION_BUS_ADDRESS"));
101 return IWvStream::create(translate(bus));
104 return IWvStream::create(translate(s));
110 static int conncount;
116 ++conncount),
WvLog::Debug5),
119 init(_auth, _client);
127 ++conncount),
WvLog::Debug5),
130 log(
"Connecting to '%s'\n", moniker);
131 init(_auth, _client);
135 void WvDBusConn::init(
IWvDBusAuth *_auth,
bool _client)
137 log(
"Initializing.\n");
140 authorized = in_post_select =
false;
141 if (!client) set_uniquename(
WvString(
":%s.0", conncount));
158 log(
"Shutting down.\n");
160 log(
"Error was: %s\n", errstr());
185 uint32_t flags = (DBUS_NAME_FLAG_ALLOW_REPLACEMENT |
186 DBUS_NAME_FLAG_REPLACE_EXISTING);
187 WvDBusMsg msg(
"org.freedesktop.DBus",
"/org/freedesktop/DBus",
188 "org.freedesktop.DBus",
"RequestName");
190 send(msg, onreply, msec_timeout);
199 log(
" >> %s\n", msg);
203 log(
" .> %s\n", msg);
204 return msg.get_serial();
213 add_pending(msg, onreply, msec_timeout);
227 { reply =
new WvDBusMsg(msg);
return true; }
232 wv::function<
void(uint32_t)> serial_cb)
236 send(msg, wv::bind(&xxReplyWaiter::reply_wait, &rw, _1),
239 serial_cb(msg.get_serial());
240 while (!rw.reply &&
isok())
245 "while waiting for reply.",
259 const char *WvDBusConn::in()
268 void WvDBusConn::send_hello()
270 WvDBusMsg msg(
"org.freedesktop.DBus",
"/org/freedesktop/DBus",
271 "org.freedesktop.DBus",
"Hello");
272 send(msg, wv::bind(&WvDBusConn::_registered,
this, _1));
273 WvDBusMsg msg2(
"org.freedesktop.DBus",
"/org/freedesktop/DBus",
274 "org.freedesktop.DBus",
"AddMatch");
275 msg2.append(
"type='signal'");
284 log(
"Assigned name '%s'\n", s);
290 void WvDBusConn::try_auth()
296 if (out_queue.
used())
298 log(
" >> (sending enqueued messages)\n");
309 callbacks.append(
new CallbackInfo(pri, cb, cookie),
true);
316 CallbackInfoList::Iter i(callbacks);
317 for (i.rewind(); i.next(); )
318 if (i->cookie == cookie)
323 int WvDBusConn::priority_order(
const CallbackInfo *a,
const CallbackInfo *b)
325 return a->pri - b->pri;
333 uint32_t rserial = msg.get_replyserial();
336 Pending *p = pending[rserial];
346 CallbackInfoList::Sorter i(callbacks, priority_order);
347 for (i.rewind(); i.next(); )
349 bool handled = i->cb(msg);
350 if (handled)
return true;
357 WvDBusClientAuth::WvDBusClientAuth()
359 sent_request =
false;
363 wvuid_t WvDBusClientAuth::get_uid()
375 c.out(
"AUTH EXTERNAL %s\r\n\0",
WvHexEncoder().strflushstr(uid));
380 const char *line = c.in();
383 if (!strncasecmp(line,
"OK ", 3))
388 else if (!strncasecmp(line,
"ERROR ", 6))
389 c.
seterr(
"Auth failed: %s", line);
391 c.
seterr(
"Unknown AUTH response: '%s'", line);
399 time_t WvDBusConn::mintimeout_msec()
402 PendingDict::Iter i(pending);
403 for (i.rewind(); i.next(); )
405 if (!when || when > i->valid_until)
406 when = i->valid_until;
410 else if (when <= wvstime())
413 return msecdiff(when, wvstime());
417 bool WvDBusConn::post_select(SelectInfo &si)
420 if (si.inherit_request)
return ready;
422 if (in_post_select)
return false;
423 in_post_select =
true;
425 if (!authorized && ready)
431 PendingDict::Iter i(pending);
432 for (i.rewind(); i.next(); )
434 if (now > i->valid_until)
436 log(
"Expiring %s\n", i->msg);
437 expire_pending(i.ptr());
443 if (authorized && ready)
453 size_t amt = needed - in_queue.
used();
467 alarm(mintimeout_msec());
468 in_post_select =
false;
475 return !out_queue.
used() && pending.isempty();
479 void WvDBusConn::expire_pending(Pending *p)
483 WvDBusCallback xcb(p->cb);
486 "Timed out while waiting for reply");
492 void WvDBusConn::cancel_pending(uint32_t serial)
494 Pending *p = pending[serial];
497 WvDBusCallback xcb(p->cb);
501 "Canceled while waiting for reply");
507 void WvDBusConn::add_pending(
WvDBusMsg &msg, WvDBusCallback cb,
510 uint32_t serial = msg.get_serial();
513 cancel_pending(serial);
514 pending.add(
new Pending(msg, cb, msec_timeout),
true);
515 alarm(mintimeout_msec());
519 bool WvDBusConn::_registered(
WvDBusMsg &msg)
522 _uniquename = i.getnext().get_str();
523 set_uniquename(_uniquename);
A WvFastString acts exactly like a WvString, but can take (const char *) strings without needing to a...
The basic interface which is included by all other XPLC interfaces and objects.
static size_t demarshal_bytes_needed(WvBuf &buf)
Given a buffer containing what might be the header of a DBus message, checks how many bytes need to b...
void runonce(time_t msec_timeout=-1)
Exactly the same as: if (select(timeout)) callback();.
char * getline(time_t wait_msec=0, char separator= '\n', int readahead=1024)
Read up to one line of data from the stream and return a pointer to the internal buffer containing th...
virtual bool isok() const
return true if the stream is actually usable right now
virtual void close()
Close the underlying stream.
bool isidle()
Returns true if there are no outstanding messages that have not received (or timed out) their reply...
Based on (and interchangeable with) struct timeval.
WvDBusMsg send_and_wait(WvDBusMsg msg, time_t msec_timeout=WVDBUS_DEFAULT_TIMEOUT, wv::function< void(uint32_t)> serial_cb=0)
Send a message on the bus and wait for a reply to come in, returning the message when it does...
virtual size_t write(const void *buf, size_t count)
Write data to the stream.
virtual ~WvDBusConn()
Release this connection.
WvDBusConn(WvStringParm moniker, IWvDBusAuth *_auth=NULL, bool _client=true)
Creates a new dbus connection using the given WvStreams moniker.
void marshal(WvBuf &buf)
Locks this message, encodes it in DBus binary protocol format, and adds it to the given buffer...
A type-safe version of WvMonikerBase that lets you provide create functions for object types other th...
void add_callback(CallbackPri pri, WvDBusCallback cb, void *cookie=NULL)
Adds a callback to the connection: all received messages will be sent to all callbacks to look at and...
virtual int geterr() const
If isok() is false, return the system error number corresponding to the error, -1 for a special error...
void delay_output(bool is_delayed)
force write() to always buffer output.
uint32_t send(WvDBusMsg msg)
Send a message on the bus, not expecting any reply.
virtual bool filter_func(WvDBusMsg &msg)
Called by for each received message.
WvDBusMsg & append(const char *s)
The following methods are designed to allow appending various arguments to the message.
WvString uniquename() const
Return this connection's unique name on the bus, assigned by the server at connect time...
virtual bool post_select(SelectInfo &si)
post_select() is called after ::select(), and returns true if this object is now ready.
virtual bool authorize(WvDBusConn &c)
Main action callback.
This is a WvList of WvStrings, and is a really handy way to parse strings.
void split(WvStringParm s, const char *splitchars=" \t\r\n", int limit=0)
split s and form a list ignoring splitchars (except at beginning and end) ie.
size_t used() const
Returns the number of elements in the buffer currently available for reading.
virtual void close()
Close this stream.
CallbackPri
The priority level of a callback registration.
virtual void seterr(int _errnum)
Override seterr() from WvError so that it auto-closes the stream.
Various little string functions.
static WvDBusMsg * demarshal(WvBuf &buf)
Demarshals a new WvDBusMsg from a buffer containing its binary DBus protocol representation.
char * trim_string(char *string)
Trims whitespace from the beginning and end of the character string, including carriage return / line...
void del_callback(void *cookie)
Delete all callbacks that have the given cookie.
virtual bool authorize(WvDBusConn &c)=0
Main action callback.
WvString is an implementation of a simple and efficient printable-string class.
time_t alarm_remaining()
return the number of milliseconds remaining before the alarm will go off; -1 means no alarm is set (i...
void alarm(time_t msec_timeout)
set an alarm, ie.
virtual size_t read(void *buf, size_t count)
read a data block on the stream.
A WvLog stream accepts log messages from applications and forwards them to all registered WvLogRcv's...
WvStreamClone simply forwards all requests to the "cloned" stream.
void request_name(WvStringParm name, const WvDBusCallback &onreply=0, time_t msec_timeout=WVDBUS_DEFAULT_TIMEOUT)
Request the given service name on DBus.