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);