diff --git a/index.js b/index.js index 2348654..c55d6a6 100644 --- a/index.js +++ b/index.js @@ -41,6 +41,16 @@ module.exports.sessionBus = function(opts) { return createClient(opts); }; +/** + * Create a new {@link MessageBus} client to communicate peer-to-peer. + * + * @param {object} [stream] - Duplex stream for communication. + * @param {object} [options] - Options for `MessageBus` creation. + */ +module.exports.peerBus = function(stream, opts) { + return createClient(Object.assign({}, opts, { stream })); +}; + /** * Use JSBI as a polyfill for long integer types ('x' and 't') in the client * and the service. This is required for Node verisons that do not support the diff --git a/lib/bus.js b/lib/bus.js index 5d679eb..32d90bf 100644 --- a/lib/bus.js +++ b/lib/bus.js @@ -74,7 +74,7 @@ class MessageBus extends EventEmitter { /** * The unique name of the bus connection. This will be `null` until the - * `MessageBus` is connected. + * `MessageBus` is connected, unless we're operating in peer-to-peer mode. * @memberof MessageBus# * @member {string} name */ @@ -159,22 +159,28 @@ class MessageBus extends EventEmitter { this.emit('error', err); }); - const helloMessage = new Message({ - path: '/org/freedesktop/DBus', - destination: 'org.freedesktop.DBus', - interface: 'org.freedesktop.DBus', - member: 'Hello' - }); - - this.call(helloMessage) - .then((msg) => { - this.name = msg.body[0]; + if (conn.mode === 'p2p') { + process.nextTick(() => { this.emit('connect'); - }) - .catch((err) => { - this.emit('error', err); - throw new Error(err); }); + } else { + const helloMessage = new Message({ + path: '/org/freedesktop/DBus', + destination: 'org.freedesktop.DBus', + interface: 'org.freedesktop.DBus', + member: 'Hello' + }); + + this.call(helloMessage) + .then((msg) => { + this.name = msg.body[0]; + this.emit('connect'); + }) + .catch((err) => { + this.emit('error', err); + throw new Error(err); + }); + } } /** @@ -468,6 +474,10 @@ class MessageBus extends EventEmitter { this._matchRules[match] = 1; + if (this._connection.mode === 'p2p') { + return Promise.resolve(); + } + // TODO catch error and update refcount const msg = new Message({ path: '/org/freedesktop/DBus', @@ -496,6 +506,10 @@ class MessageBus extends EventEmitter { delete this._matchRules[match]; + if (this._connection.mode === 'p2p') { + return Promise.resolve(); + } + // TODO catch error and update refcount const msg = new Message({ path: '/org/freedesktop/DBus', diff --git a/lib/connection.js b/lib/connection.js index a1ee121..00c37f3 100644 --- a/lib/connection.js +++ b/lib/connection.js @@ -90,8 +90,15 @@ function createStream (opts) { function createConnection (opts) { const self = new EventEmitter(); opts = opts || {}; - const stream = (self.stream = createStream(opts)); - stream.setNoDelay && stream.setNoDelay(); + let { stream } = opts; + if (stream) { + self.mode = 'p2p'; + } else { + self.mode = 'bus'; + stream = createStream(opts); + stream.setNoDelay && stream.setNoDelay(); + } + self.stream = stream; stream.on('error', function (err) { // forward network and stream errors diff --git a/types.d.ts b/types.d.ts index 8dc3399..eb9195d 100644 --- a/types.d.ts +++ b/types.d.ts @@ -1,6 +1,7 @@ declare module 'dbus-next' { import { EventEmitter } from "events"; + import { Duplex } from "stream"; export type ObjectPath = string; export type PropertyAccess = "read" | "write" | "readwrite"; @@ -142,4 +143,5 @@ declare module 'dbus-next' { export function setBigIntCompat(state: boolean): void; export function systemBus(): MessageBus; export function sessionBus(options?: BusOptions): MessageBus; + export function peerBus(stream: Duplex, options?: BusOptions): MessageBus; }