11#include "wvdbusconn.h"
13#include "wvstrutils.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));
116 ++conncount),
WvLog::Debug5),
119 init(_auth, _client);
127 ++conncount),
WvLog::Debug5),
130 log(
"Connecting to '%s'\n", moniker);
131 init(_auth, _client);
135void 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.",
259const char *WvDBusConn::in()
268void 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);
290void 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)
323int 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;
357WvDBusClientAuth::WvDBusClientAuth()
359 sent_request =
false;
363wvuid_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);
399time_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());
417bool 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();
479void WvDBusConn::expire_pending(Pending *p)
483 WvDBusCallback xcb(p->cb);
486 "Timed out while waiting for reply");
492void WvDBusConn::cancel_pending(uint32_t serial)
494 Pending *p = pending[serial];
497 WvDBusCallback xcb(p->cb);
501 "Canceled while waiting for reply");
507void 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());
519bool WvDBusConn::_registered(
WvDBusMsg &msg)
522 _uniquename = i.getnext().get_str();
523 set_uniquename(_uniquename);
The basic interface which is included by all other XPLC interfaces and objects.
virtual bool authorize(WvDBusConn &c)=0
Main action callback.
size_t used() const
Returns the number of elements in the buffer currently available for reading.
virtual bool authorize(WvDBusConn &c)
Main action callback.
virtual void close()
Close the underlying stream.
virtual bool filter_func(WvDBusMsg &msg)
Called by for each received message.
virtual ~WvDBusConn()
Release this connection.
WvDBusConn(WvStringParm moniker, IWvDBusAuth *_auth=NULL, bool _client=true)
Creates a new dbus connection using the given WvStreams moniker.
CallbackPri
The priority level of a callback registration.
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.
void request_name(WvStringParm name, const WvDBusCallback &onreply=0, time_t msec_timeout=WVDBUS_DEFAULT_TIMEOUT)
Request the given service name on DBus.
bool isidle()
Returns true if there are no outstanding messages that have not received (or timed out) their reply.
uint32_t send(WvDBusMsg msg)
Send a message on the bus, not expecting any reply.
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...
void del_callback(void *cookie)
Delete all callbacks that have the given cookie.
WvString uniquename() const
Return this connection's unique name on the bus, assigned by the server at connect time.
WvDBusMsg & append(const char *s)
The following methods are designed to allow appending various arguments to the message.
static WvDBusMsg * demarshal(WvBuf &buf)
Demarshals a new WvDBusMsg from a buffer containing its binary DBus protocol representation.
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 marshal(WvBuf &buf)
Locks this message, encodes it in DBus binary protocol format, and adds it to the given buffer.
A WvFastString acts exactly like a WvString, but can take (const char *) strings without needing to a...
A WvLog stream accepts log messages from applications and forwards them to all registered WvLogRcv's.
A type-safe version of WvMonikerBase that lets you provide create functions for object types other th...
WvStreamClone simply forwards all requests to the "cloned" stream.
virtual void close()
Close this stream.
virtual bool isok() const
return true if the stream is actually usable right now
virtual bool post_select(SelectInfo &si)
post_select() is called after select(), and returns true if this object is now ready.
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.
void alarm(time_t msec_timeout)
set an alarm, ie.
virtual size_t write(const void *buf, size_t count)
Write data to the stream.
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 size_t read(void *buf, size_t count)
read a data block on the stream.
time_t alarm_remaining()
return the number of milliseconds remaining before the alarm will go off; -1 means no alarm is set (i...
virtual void seterr(int _errnum)
Override seterr() from WvError so that it auto-closes the stream.
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.
WvString is an implementation of a simple and efficient printable-string class.
Based on (and interchangeable with) struct timeval.
char * trim_string(char *string)
Trims whitespace from the beginning and end of the character string, including carriage return / line...