Add --bus-name option to use different D-Bus bus name

This commit is contained in:
AsamK 2024-02-09 17:45:41 +01:00
parent a48fdaf8b7
commit 1bf703b012
8 changed files with 98 additions and 53 deletions

View file

@ -13,6 +13,7 @@
Sending to the self number (+XXXX) now behaves the same as the `--note-to-self` parameter. To get the previous Sending to the self number (+XXXX) now behaves the same as the `--note-to-self` parameter. To get the previous
behavior, the `--notify-self` parameter can be added behavior, the `--notify-self` parameter can be added
- New `--unrestricted-unidentified-sender` parameter for `updateAccount command` - New `--unrestricted-unidentified-sender` parameter for `updateAccount command`
- New `--bus-name` parameter for `daemon` command to use another D-Bus bus name
### Improved ### Improved
@ -23,6 +24,7 @@
## [0.12.8] - 2024-02-06 ## [0.12.8] - 2024-02-06
### Fixes ### Fixes
- Update user agent - Update user agent
## [0.12.7] - 2023-12-15 ## [0.12.7] - 2023-12-15

View file

@ -71,6 +71,9 @@ Make request via user dbus.
*--dbus-system*:: *--dbus-system*::
Make request via system dbus. Make request via system dbus.
*--bus-name*::
Connect to another D-Bus bus name than the default.
*-o* OUTPUT-MODE, *--output* OUTPUT-MODE:: *-o* OUTPUT-MODE, *--output* OUTPUT-MODE::
Specify if you want commands to output in either "plain-text" mode or in "json". Specify if you want commands to output in either "plain-text" mode or in "json".
Defaults to "plain-text" Defaults to "plain-text"
@ -746,6 +749,9 @@ See **signal-cli-dbus**(5) for info on the dbus interface.
Export DBus interface on system bus. + Export DBus interface on system bus. +
See **signal-cli-dbus**(5) for info on the dbus interface. See **signal-cli-dbus**(5) for info on the dbus interface.
*--bus-name*::
Claim another D-Bus bus name than the default.
*--ignore-attachments*:: *--ignore-attachments*::
Dont download attachments of received messages. Dont download attachments of received messages.

View file

@ -76,6 +76,10 @@ public class App {
.dest("global-dbus-system") .dest("global-dbus-system")
.help("Make request via system dbus.") .help("Make request via system dbus.")
.action(Arguments.storeTrue()); .action(Arguments.storeTrue());
parser.addArgument("--bus-name")
.dest("global-bus-name")
.setDefault(DbusConfig.getBusname())
.help("Specify the D-Bus bus name to connect to.");
parser.addArgument("-o", "--output") parser.addArgument("-o", "--output")
.help("Choose to output in plain text or JSON") .help("Choose to output in plain text or JSON")
@ -125,8 +129,9 @@ public class App {
final var useDbus = Boolean.TRUE.equals(ns.getBoolean("global-dbus")); final var useDbus = Boolean.TRUE.equals(ns.getBoolean("global-dbus"));
final var useDbusSystem = Boolean.TRUE.equals(ns.getBoolean("global-dbus-system")); final var useDbusSystem = Boolean.TRUE.equals(ns.getBoolean("global-dbus-system"));
if (useDbus || useDbusSystem) { if (useDbus || useDbusSystem) {
final var busName = ns.getString("global-bus-name");
// If account is null, it will connect to the default object path // If account is null, it will connect to the default object path
initDbusClient(command, account, useDbusSystem, commandHandler); initDbusClient(command, account, useDbusSystem, busName, commandHandler);
return; return;
} }

View file

@ -4,6 +4,7 @@ import net.sourceforge.argparse4j.impl.Arguments;
import net.sourceforge.argparse4j.inf.Namespace; import net.sourceforge.argparse4j.inf.Namespace;
import net.sourceforge.argparse4j.inf.Subparser; import net.sourceforge.argparse4j.inf.Subparser;
import org.asamk.signal.DbusConfig;
import org.asamk.signal.OutputType; import org.asamk.signal.OutputType;
import org.asamk.signal.ReceiveMessageHandler; import org.asamk.signal.ReceiveMessageHandler;
import org.asamk.signal.Shutdown; import org.asamk.signal.Shutdown;
@ -50,6 +51,9 @@ public class DaemonCommand implements MultiLocalCommand, LocalCommand {
subparser.addArgument("--dbus-system", "--system") subparser.addArgument("--dbus-system", "--system")
.action(Arguments.storeTrue()) .action(Arguments.storeTrue())
.help("Expose a DBus interface on the system bus."); .help("Expose a DBus interface on the system bus.");
subparser.addArgument("--bus-name")
.setDefault(DbusConfig.getBusname())
.help("Specify the D-Bus bus name to connect to.");
subparser.addArgument("--socket") subparser.addArgument("--socket")
.nargs("?") .nargs("?")
.type(File.class) .type(File.class)
@ -177,20 +181,25 @@ public class DaemonCommand implements MultiLocalCommand, LocalCommand {
final var isDbusSystem = Boolean.TRUE.equals(ns.getBoolean("dbus-system")); final var isDbusSystem = Boolean.TRUE.equals(ns.getBoolean("dbus-system"));
if (isDbusSystem) { if (isDbusSystem) {
daemonHandler.runDbus(true); final var busName = ns.getString("bus-name");
daemonHandler.runDbus(true, busName);
} }
final var isDbusSession = Boolean.TRUE.equals(ns.getBoolean("dbus")); final var isDbusSession = Boolean.TRUE.equals(ns.getBoolean("dbus"));
if (isDbusSession || ( if (isDbusSession) {
!isDbusSystem final var busName = ns.getString("bus-name");
daemonHandler.runDbus(false, busName);
}
if (!isDbusSystem
&& !isDbusSession
&& socketFile == null && socketFile == null
&& tcpAddress == null && tcpAddress == null
&& httpAddress == null && httpAddress == null
&& inheritedChannel == null && inheritedChannel == null) {
)) {
logger.warn( logger.warn(
"Running daemon command without explicit mode is deprecated. Use --dbus to use the dbus interface."); "Running daemon command without explicit mode is deprecated. Use --dbus to use the dbus interface.");
daemonHandler.runDbus(false); daemonHandler.runDbus(false, DbusConfig.getBusname());
} }
} }
@ -214,7 +223,7 @@ public class DaemonCommand implements MultiLocalCommand, LocalCommand {
public abstract void runSocket(ServerSocketChannel serverChannel) throws CommandException; public abstract void runSocket(ServerSocketChannel serverChannel) throws CommandException;
public abstract void runDbus(boolean isDbusSystem) throws CommandException; public abstract void runDbus(boolean isDbusSystem, final String busname) throws CommandException;
public abstract void runHttp(InetSocketAddress address) throws CommandException; public abstract void runHttp(InetSocketAddress address) throws CommandException;
@ -267,8 +276,8 @@ public class DaemonCommand implements MultiLocalCommand, LocalCommand {
} }
@Override @Override
public void runDbus(final boolean isDbusSystem) throws CommandException { public void runDbus(final boolean isDbusSystem, final String busname) throws CommandException {
runDbus(new DbusHandler(isDbusSystem, m, receiveMode != ReceiveMode.ON_START)); runDbus(new DbusHandler(isDbusSystem, busname, m, receiveMode != ReceiveMode.ON_START));
} }
@Override @Override
@ -292,8 +301,8 @@ public class DaemonCommand implements MultiLocalCommand, LocalCommand {
} }
@Override @Override
public void runDbus(final boolean isDbusSystem) throws CommandException { public void runDbus(final boolean isDbusSystem, final String busname) throws CommandException {
runDbus(new DbusHandler(isDbusSystem, c, receiveMode != ReceiveMode.ON_START)); runDbus(new DbusHandler(isDbusSystem, busname, c, receiveMode != ReceiveMode.ON_START));
} }
@Override @Override

View file

@ -24,12 +24,16 @@ import java.io.IOException;
public class DbusCommandHandler { public class DbusCommandHandler {
public static void initDbusClient( public static void initDbusClient(
final Command command, final String account, final boolean systemBus, final CommandHandler commandHandler final Command command,
final String account,
final boolean systemBus,
final String busname,
final CommandHandler commandHandler
) throws CommandException { ) throws CommandException {
try { try {
final var busType = systemBus ? DBusConnection.DBusBusType.SYSTEM : DBusConnection.DBusBusType.SESSION; final var busType = systemBus ? DBusConnection.DBusBusType.SYSTEM : DBusConnection.DBusBusType.SESSION;
try (var dBusConn = DBusConnectionBuilder.forType(busType).build()) { try (var dBusConn = DBusConnectionBuilder.forType(busType).build()) {
handleCommand(command, account, dBusConn, commandHandler); handleCommand(command, account, dBusConn, busname, commandHandler);
} }
} catch (ServiceUnknown e) { } catch (ServiceUnknown e) {
throw new UserErrorException("signal-cli DBus daemon not running on " throw new UserErrorException("signal-cli DBus daemon not running on "
@ -45,6 +49,7 @@ public class DbusCommandHandler {
final Command command, final Command command,
final String account, final String account,
final DBusConnection dBusConn, final DBusConnection dBusConn,
final String busname,
final CommandHandler commandHandler final CommandHandler commandHandler
) throws CommandException, DBusException { ) throws CommandException, DBusException {
try { try {
@ -53,27 +58,27 @@ public class DbusCommandHandler {
throw new UserErrorException("You cannot specify a account (phone number) when linking"); throw new UserErrorException("You cannot specify a account (phone number) when linking");
} }
handleProvisioningCommand(c, dBusConn, commandHandler); handleProvisioningCommand(c, dBusConn, busname, commandHandler);
return; return;
} }
if (account == null && command instanceof MultiLocalCommand c) { if (account == null && command instanceof MultiLocalCommand c) {
handleMultiLocalCommand(c, dBusConn, commandHandler); handleMultiLocalCommand(c, dBusConn, busname, commandHandler);
return; return;
} }
if (account != null && command instanceof RegistrationCommand c) { if (account != null && command instanceof RegistrationCommand c) {
handleRegistrationCommand(c, account, dBusConn, commandHandler); handleRegistrationCommand(c, account, dBusConn, busname, commandHandler);
return; return;
} }
if (!(command instanceof LocalCommand localCommand)) { if (!(command instanceof LocalCommand localCommand)) {
throw new UserErrorException("Command only works in multi-account mode"); throw new UserErrorException("Command only works in multi-account mode");
} }
var accountObjectPath = account == null ? tryGetSingleAccountObjectPath(dBusConn) : null; var accountObjectPath = account == null ? tryGetSingleAccountObjectPath(dBusConn, busname) : null;
if (accountObjectPath == null) { if (accountObjectPath == null) {
accountObjectPath = DbusConfig.getObjectPath(account); accountObjectPath = DbusConfig.getObjectPath(account);
} }
handleLocalCommand(localCommand, accountObjectPath, dBusConn, commandHandler); handleLocalCommand(localCommand, accountObjectPath, dBusConn, busname, commandHandler);
} catch (UnsupportedOperationException e) { } catch (UnsupportedOperationException e) {
throw new UserErrorException("Command is not yet implemented via dbus", e); throw new UserErrorException("Command is not yet implemented via dbus", e);
} catch (DBusExecutionException e) { } catch (DBusExecutionException e) {
@ -81,10 +86,10 @@ public class DbusCommandHandler {
} }
} }
private static String tryGetSingleAccountObjectPath(final DBusConnection dBusConn) throws DBusException, CommandException { private static String tryGetSingleAccountObjectPath(
var control = dBusConn.getRemoteObject(DbusConfig.getBusname(), final DBusConnection dBusConn, final String busname
DbusConfig.getObjectPath(), ) throws DBusException, CommandException {
SignalControl.class); var control = dBusConn.getRemoteObject(busname, DbusConfig.getObjectPath(), SignalControl.class);
try { try {
final var accounts = control.listAccounts(); final var accounts = control.listAccounts();
if (accounts.isEmpty()) { if (accounts.isEmpty()) {
@ -102,12 +107,13 @@ public class DbusCommandHandler {
} }
private static void handleMultiLocalCommand( private static void handleMultiLocalCommand(
final MultiLocalCommand c, final DBusConnection dBusConn, final CommandHandler commandHandler final MultiLocalCommand c,
final DBusConnection dBusConn,
final String busname,
final CommandHandler commandHandler
) throws CommandException, DBusException { ) throws CommandException, DBusException {
final var signalControl = dBusConn.getRemoteObject(DbusConfig.getBusname(), final var signalControl = dBusConn.getRemoteObject(busname, DbusConfig.getObjectPath(), SignalControl.class);
DbusConfig.getObjectPath(), try (final var multiAccountManager = new DbusMultiAccountManagerImpl(signalControl, dBusConn, busname)) {
SignalControl.class);
try (final var multiAccountManager = new DbusMultiAccountManagerImpl(signalControl, dBusConn)) {
commandHandler.handleMultiLocalCommand(c, multiAccountManager); commandHandler.handleMultiLocalCommand(c, multiAccountManager);
} }
} }
@ -116,10 +122,11 @@ public class DbusCommandHandler {
final LocalCommand c, final LocalCommand c,
String accountObjectPath, String accountObjectPath,
final DBusConnection dBusConn, final DBusConnection dBusConn,
final String busname,
final CommandHandler commandHandler final CommandHandler commandHandler
) throws CommandException, DBusException { ) throws CommandException, DBusException {
var signal = dBusConn.getRemoteObject(DbusConfig.getBusname(), accountObjectPath, Signal.class); var signal = dBusConn.getRemoteObject(busname, accountObjectPath, Signal.class);
try (final var manager = new DbusManagerImpl(signal, dBusConn)) { try (final var manager = new DbusManagerImpl(signal, dBusConn, busname)) {
commandHandler.handleLocalCommand(c, manager); commandHandler.handleLocalCommand(c, manager);
} }
} }
@ -128,24 +135,24 @@ public class DbusCommandHandler {
final RegistrationCommand c, final RegistrationCommand c,
String account, String account,
final DBusConnection dBusConn, final DBusConnection dBusConn,
final String busname,
final CommandHandler commandHandler final CommandHandler commandHandler
) throws CommandException, DBusException { ) throws CommandException, DBusException {
final var signalControl = dBusConn.getRemoteObject(DbusConfig.getBusname(), final var signalControl = dBusConn.getRemoteObject(busname, DbusConfig.getObjectPath(), SignalControl.class);
DbusConfig.getObjectPath(),
SignalControl.class);
try (final var registrationManager = new DbusRegistrationManagerImpl(account, signalControl, dBusConn)) { try (final var registrationManager = new DbusRegistrationManagerImpl(account, signalControl, dBusConn)) {
commandHandler.handleRegistrationCommand(c, registrationManager); commandHandler.handleRegistrationCommand(c, registrationManager);
} }
} }
private static void handleProvisioningCommand( private static void handleProvisioningCommand(
final ProvisioningCommand c, final DBusConnection dBusConn, final CommandHandler commandHandler final ProvisioningCommand c,
final DBusConnection dBusConn,
final String busname,
final CommandHandler commandHandler
) throws CommandException, DBusException { ) throws CommandException, DBusException {
final var signalControl = dBusConn.getRemoteObject(DbusConfig.getBusname(), final var signalControl = dBusConn.getRemoteObject(busname, DbusConfig.getObjectPath(), SignalControl.class);
DbusConfig.getObjectPath(),
SignalControl.class);
final var provisioningManager = new DbusProvisioningManagerImpl(signalControl, dBusConn); final var provisioningManager = new DbusProvisioningManagerImpl(signalControl, dBusConn);
commandHandler.handleProvisioningCommand(c, provisioningManager); commandHandler.handleProvisioningCommand(c, provisioningManager);
} }

View file

@ -21,12 +21,15 @@ public class DbusHandler implements AutoCloseable {
private final boolean isDbusSystem; private final boolean isDbusSystem;
private DBusConnection dBusConnection; private DBusConnection dBusConnection;
private final String busname;
private final List<AutoCloseable> closeables = new ArrayList<>(); private final List<AutoCloseable> closeables = new ArrayList<>();
private final DbusRunner dbusRunner; private final DbusRunner dbusRunner;
private final boolean noReceiveOnStart; private final boolean noReceiveOnStart;
public DbusHandler(final boolean isDbusSystem, final Manager m, final boolean noReceiveOnStart) { public DbusHandler(
final boolean isDbusSystem, final String busname, final Manager m, final boolean noReceiveOnStart
) {
this.isDbusSystem = isDbusSystem; this.isDbusSystem = isDbusSystem;
this.dbusRunner = (connection) -> { this.dbusRunner = (connection) -> {
try { try {
@ -35,9 +38,15 @@ public class DbusHandler implements AutoCloseable {
} }
}; };
this.noReceiveOnStart = noReceiveOnStart; this.noReceiveOnStart = noReceiveOnStart;
this.busname = busname;
} }
public DbusHandler(final boolean isDbusSystem, final MultiAccountManager c, final boolean noReceiveOnStart) { public DbusHandler(
final boolean isDbusSystem,
final String busname,
final MultiAccountManager c,
final boolean noReceiveOnStart
) {
this.isDbusSystem = isDbusSystem; this.isDbusSystem = isDbusSystem;
this.dbusRunner = (connection) -> { this.dbusRunner = (connection) -> {
final var signalControl = new DbusSignalControlImpl(c, DbusConfig.getObjectPath()); final var signalControl = new DbusSignalControlImpl(c, DbusConfig.getObjectPath());
@ -72,6 +81,7 @@ public class DbusHandler implements AutoCloseable {
} }
}; };
this.noReceiveOnStart = noReceiveOnStart; this.noReceiveOnStart = noReceiveOnStart;
this.busname = busname;
} }
public void init() throws CommandException { public void init() throws CommandException {
@ -79,7 +89,7 @@ public class DbusHandler implements AutoCloseable {
throw new AssertionError("DbusHandler already initialized"); throw new AssertionError("DbusHandler already initialized");
} }
final var busType = isDbusSystem ? DBusConnection.DBusBusType.SYSTEM : DBusConnection.DBusBusType.SESSION; final var busType = isDbusSystem ? DBusConnection.DBusBusType.SYSTEM : DBusConnection.DBusBusType.SESSION;
logger.debug("Starting DBus server on {} bus: {}", busType, DbusConfig.getBusname()); logger.debug("Starting DBus server on {} bus: {}", busType, busname);
try { try {
dBusConnection = DBusConnectionBuilder.forType(busType).build(); dBusConnection = DBusConnectionBuilder.forType(busType).build();
dbusRunner.run(dBusConnection); dbusRunner.run(dBusConnection);
@ -90,13 +100,13 @@ public class DbusHandler implements AutoCloseable {
} }
try { try {
dBusConnection.requestBusName(DbusConfig.getBusname()); dBusConnection.requestBusName(busname);
} catch (DBusException e) { } catch (DBusException e) {
throw new UnexpectedErrorException("Dbus command failed, maybe signal-cli dbus daemon is already running: " throw new UnexpectedErrorException("Dbus command failed, maybe signal-cli dbus daemon is already running: "
+ e.getMessage(), e); + e.getMessage(), e);
} }
logger.info("Started DBus server on {} bus: {}", busType, DbusConfig.getBusname()); logger.info("Started DBus server on {} bus: {}", busType, busname);
} }
@Override @Override

View file

@ -1,7 +1,6 @@
package org.asamk.signal.dbus; package org.asamk.signal.dbus;
import org.asamk.Signal; import org.asamk.Signal;
import org.asamk.signal.DbusConfig;
import org.asamk.signal.manager.Manager; import org.asamk.signal.manager.Manager;
import org.asamk.signal.manager.api.AlreadyReceivingException; import org.asamk.signal.manager.api.AlreadyReceivingException;
import org.asamk.signal.manager.api.AttachmentInvalidException; import org.asamk.signal.manager.api.AttachmentInvalidException;
@ -90,14 +89,16 @@ public class DbusManagerImpl implements Manager {
private final Set<ReceiveMessageHandler> weakHandlers = new HashSet<>(); private final Set<ReceiveMessageHandler> weakHandlers = new HashSet<>();
private final Set<ReceiveMessageHandler> messageHandlers = new HashSet<>(); private final Set<ReceiveMessageHandler> messageHandlers = new HashSet<>();
private final List<Runnable> closedListeners = new ArrayList<>(); private final List<Runnable> closedListeners = new ArrayList<>();
private final String busname;
private DBusSigHandler<Signal.MessageReceivedV2> dbusMsgHandler; private DBusSigHandler<Signal.MessageReceivedV2> dbusMsgHandler;
private DBusSigHandler<Signal.EditMessageReceived> dbusEditMsgHandler; private DBusSigHandler<Signal.EditMessageReceived> dbusEditMsgHandler;
private DBusSigHandler<Signal.ReceiptReceivedV2> dbusRcptHandler; private DBusSigHandler<Signal.ReceiptReceivedV2> dbusRcptHandler;
private DBusSigHandler<Signal.SyncMessageReceivedV2> dbusSyncHandler; private DBusSigHandler<Signal.SyncMessageReceivedV2> dbusSyncHandler;
public DbusManagerImpl(final Signal signal, DBusConnection connection) { public DbusManagerImpl(final Signal signal, DBusConnection connection, final String busname) {
this.signal = signal; this.signal = signal;
this.connection = connection; this.connection = connection;
this.busname = busname;
} }
@Override @Override
@ -820,7 +821,7 @@ public class DbusManagerImpl implements Manager {
private <T extends DBusInterface> T getRemoteObject(final DBusPath path, final Class<T> type) { private <T extends DBusInterface> T getRemoteObject(final DBusPath path, final Class<T> type) {
try { try {
return connection.getRemoteObject(DbusConfig.getBusname(), path.getPath(), type); return connection.getRemoteObject(busname, path.getPath(), type);
} catch (DBusException e) { } catch (DBusException e) {
throw new AssertionError(e); throw new AssertionError(e);
} }

View file

@ -2,7 +2,6 @@ package org.asamk.signal.dbus;
import org.asamk.Signal; import org.asamk.Signal;
import org.asamk.SignalControl; import org.asamk.SignalControl;
import org.asamk.signal.DbusConfig;
import org.asamk.signal.manager.Manager; import org.asamk.signal.manager.Manager;
import org.asamk.signal.manager.MultiAccountManager; import org.asamk.signal.manager.MultiAccountManager;
import org.asamk.signal.manager.ProvisioningManager; import org.asamk.signal.manager.ProvisioningManager;
@ -32,10 +31,14 @@ public class DbusMultiAccountManagerImpl implements MultiAccountManager {
// TODO add listeners for added/removed accounts // TODO add listeners for added/removed accounts
private final Set<Consumer<Manager>> onManagerAddedHandlers = new HashSet<>(); private final Set<Consumer<Manager>> onManagerAddedHandlers = new HashSet<>();
private final Set<Consumer<Manager>> onManagerRemovedHandlers = new HashSet<>(); private final Set<Consumer<Manager>> onManagerRemovedHandlers = new HashSet<>();
private final String busname;
public DbusMultiAccountManagerImpl(final SignalControl signalControl, DBusConnection connection) { public DbusMultiAccountManagerImpl(
final SignalControl signalControl, DBusConnection connection, final String busname
) {
this.signalControl = signalControl; this.signalControl = signalControl;
this.connection = connection; this.connection = connection;
this.busname = busname;
} }
@Override @Override
@ -50,7 +53,7 @@ public class DbusMultiAccountManagerImpl implements MultiAccountManager {
public List<Manager> getManagers() { public List<Manager> getManagers() {
return signalControl.listAccounts() return signalControl.listAccounts()
.stream() .stream()
.map(a -> (Manager) new DbusManagerImpl(getRemoteObject(a, Signal.class), connection)) .map(a -> (Manager) new DbusManagerImpl(getRemoteObject(a, Signal.class), connection, busname))
.toList(); .toList();
} }
@ -70,7 +73,9 @@ public class DbusMultiAccountManagerImpl implements MultiAccountManager {
@Override @Override
public Manager getManager(final String phoneNumber) { public Manager getManager(final String phoneNumber) {
return new DbusManagerImpl(getRemoteObject(signalControl.getAccount(phoneNumber), Signal.class), connection); return new DbusManagerImpl(getRemoteObject(signalControl.getAccount(phoneNumber), Signal.class),
connection,
busname);
} }
@Override @Override
@ -98,7 +103,7 @@ public class DbusMultiAccountManagerImpl implements MultiAccountManager {
private <T extends DBusInterface> T getRemoteObject(final DBusPath path, final Class<T> type) { private <T extends DBusInterface> T getRemoteObject(final DBusPath path, final Class<T> type) {
try { try {
return connection.getRemoteObject(DbusConfig.getBusname(), path.getPath(), type); return connection.getRemoteObject(busname, path.getPath(), type);
} catch (DBusException e) { } catch (DBusException e) {
throw new AssertionError(e); throw new AssertionError(e);
} }