diff --git a/lib/src/dbus_client.dart b/lib/src/dbus_client.dart index fe3ca35..421ba24 100644 --- a/lib/src/dbus_client.dart +++ b/lib/src/dbus_client.dart @@ -127,14 +127,18 @@ class DBusSignalStream extends Stream { void _onListen() { _client._signalStreams.add(this); - if (_rule.sender != null) { - _client._findUniqueName(_rule.sender!); + if (_client._messageBus) { + if (_rule.sender != null) { + _client._findUniqueName(_rule.sender!); + } + _client._addMatch(_rule.toDBusString()); } - _client._addMatch(_rule.toDBusString()); } Future _onCancel() async { - await _client._removeMatch(_rule.toDBusString()); + if (_client._messageBus) { + await _client._removeMatch(_rule.toDBusString()); + } _client._signalStreams.remove(this); } } @@ -226,6 +230,9 @@ class DBusClient { // Names owned by this client. e.g. [ 'com.example.Foo', 'com.example.Bar' ]. final _ownedNames = {}; + // True if this client is connecting to a message bus. + final bool _messageBus; + // Unique name of this client, e.g. ':42'. DBusBusName? _uniqueName; @@ -233,8 +240,12 @@ class DBusClient { final bool introspectable; /// Creates a new DBus client to connect on [address]. - DBusClient(DBusAddress address, {this.introspectable = true}) - : _address = address; + /// If [messageBus] is false, then the server is not running a message bus and + /// no adresses or client to client communication is suported. + DBusClient(DBusAddress address, + {this.introspectable = true, bool messageBus = true}) + : _address = address, + _messageBus = messageBus; /// Creates a new DBus client to communicate with the system bus. factory DBusClient.system({bool introspectable = true}) { @@ -794,6 +805,11 @@ class DBusClient { return; } + if (!_messageBus) { + _connectCompleter?.complete(); + return; + } + // The first message to the bus must be this call, note requireConnect is // false as the _connect call hasn't yet completed and would otherwise have // been called again. diff --git a/lib/src/dbus_server.dart b/lib/src/dbus_server.dart index 85a784d..2feed00 100644 --- a/lib/src/dbus_server.dart +++ b/lib/src/dbus_server.dart @@ -98,7 +98,9 @@ class _DBusRemoteClient { // If the subscription is for an owned name, check if that matches the unique name in the message. var sender = message.sender; if (rule.sender != null && - server._messageBusObject._getClientByName(rule.sender!)?.uniqueName == + server._messageBusObject + ?._getClientByName(rule.sender!) + ?.uniqueName == sender) { sender = rule.sender; } @@ -224,7 +226,7 @@ class _DBusServerSocket { /// Handle a client disconnecting. void _clientDisconnected(_DBusRemoteClient client) { _clients.remove(client); - server._messageBusObject._releaseAllNames(client); + server._messageBusObject?._releaseAllNames(client); } Future close() async { @@ -355,11 +357,13 @@ class DBusServer { final _interfaces = []; /// Message bus functionality. - late final _MessageBusObject _messageBusObject; + _MessageBusObject? _messageBusObject; /// Creates a new DBus server. - DBusServer() { - _messageBusObject = _MessageBusObject(this); + DBusServer({bool messageBus = true}) { + if (messageBus) { + _messageBusObject = _MessageBusObject(this); + } } /// Start a service that uses [name]. @@ -514,18 +518,21 @@ class DBusServer { Future _processMessage( _DBusRemoteClient? client, DBusMessage message) async { // Forward to any clients that are listening to this message. - var targetClient = message.destination != null - ? _messageBusObject._getClientByName(message.destination!) - : null; - for (var client in _clients) { - if (client == targetClient || client.matchMessage(message)) { - client.sendMessage(message); + if (_messageBusObject != null) { + var targetClient = message.destination != null + ? _messageBusObject!._getClientByName(message.destination!) + : null; + for (var client in _clients) { + if (client == targetClient || client.matchMessage(message)) { + client.sendMessage(message); + } } } // Process requests for the server. DBusMethodResponse? response; - if (client != null && + if (_messageBusObject != null && + client != null && !client.receivedHello && !(message.destination?.value == 'org.freedesktop.DBus' && message.interface?.value == 'org.freedesktop.DBus' && @@ -540,7 +547,7 @@ class DBusServer { } else { // No-one is going to handle this message. if (message.destination != null && - _messageBusObject._getClientByName(message.destination!) == null) { + _messageBusObject?._getClientByName(message.destination!) == null) { response = _DBusServerErrorResponse.serviceUnknown( 'The name ${message.destination} is not registered'); } @@ -568,8 +575,13 @@ class DBusServer { sender: DBusBusName('org.freedesktop.DBus'), values: values); _nextSerial++; - // ignore: unawaited_futures - _processMessage(null, responseMessage); + + if (_messageBusObject != null) { + // ignore: unawaited_futures + _processMessage(null, responseMessage); + } else { + client?.sendMessage(responseMessage); + } } } @@ -580,19 +592,26 @@ class DBusServer { return DBusMethodErrorResponse.failed(); } - var object = _messageBusObject; var methodCall = _ServerMethodCall(client, message); if (methodCall.interface == 'org.freedesktop.DBus.Peer') { return await handlePeerMethodCall(methodCall); } else if (methodCall.interface == 'org.freedesktop.DBus.Introspectable') { var objectTree = DBusObjectTree(); - var node = objectTree.add(message.path ?? DBusObjectPath('/'), object); - return handleIntrospectableMethodCall(node, methodCall); - } else if (methodCall.interface == 'org.freedesktop.DBus.Properties') { - return await handlePropertiesMethodCall(object, methodCall); + if (_messageBusObject != null) { + objectTree.add(message.path ?? DBusObjectPath('/'), _messageBusObject!); + } + return handleIntrospectableMethodCall( + message.path != null ? objectTree.lookup(message.path!) : null, + methodCall); + } else if (_messageBusObject != null) { + if (methodCall.interface == 'org.freedesktop.DBus.Properties') { + return await handlePropertiesMethodCall(_messageBusObject!, methodCall); + } else { + return await _messageBusObject!.handleMethodCall(methodCall); + } } else { - return await object.handleMethodCall(methodCall); + return DBusMethodErrorResponse.unknownObject(); } } diff --git a/test/dbus_test.dart b/test/dbus_test.dart index 0518a78..65dc440 100644 --- a/test/dbus_test.dart +++ b/test/dbus_test.dart @@ -5010,6 +5010,36 @@ void main() { throwsA(isA())); }); + test('no message bus', () async { + var server = DBusServer(messageBus: false); + var address = + await server.listenAddress(DBusAddress.unix(dir: Directory.systemTemp)); + var client = DBusClient(address, messageBus: false); + addTearDown(() async { + await client.close(); + await server.close(); + }); + + await client.ping(); + }); + + test('no message bus - introspect', () async { + var server = DBusServer(messageBus: false); + var address = + await server.listenAddress(DBusAddress.unix(dir: Directory.systemTemp)); + var client = DBusClient(address, messageBus: false); + addTearDown(() async { + await client.close(); + await server.close(); + }); + + // Read introspection data from the server. + var remoteObject = DBusRemoteObject(client, + name: 'org.freedesktop.DBus', path: DBusObjectPath('/')); + var node = await remoteObject.introspect(); + expect(node.toXml().toXmlString(), equals('')); + }); + test('introspect xml - empty', () { expect(() => parseDBusIntrospectXml(''), throwsFormatException); });