]> nmode's Git Repositories - signal-cli/blob - src/main/java/org/asamk/signal/commands/DaemonCommand.java
a121c7e93de4f31bc9dfb60b7fe480baf8299169
[signal-cli] / src / main / java / org / asamk / signal / commands / DaemonCommand.java
1 package org.asamk.signal.commands;
2
3 import net.sourceforge.argparse4j.impl.Arguments;
4 import net.sourceforge.argparse4j.inf.Namespace;
5 import net.sourceforge.argparse4j.inf.Subparser;
6
7 import org.asamk.signal.DbusConfig;
8 import org.asamk.signal.DbusReceiveMessageHandler;
9 import org.asamk.signal.JsonDbusReceiveMessageHandler;
10 import org.asamk.signal.JsonWriter;
11 import org.asamk.signal.OutputType;
12 import org.asamk.signal.OutputWriter;
13 import org.asamk.signal.PlainTextWriter;
14 import org.asamk.signal.commands.exceptions.CommandException;
15 import org.asamk.signal.commands.exceptions.UnexpectedErrorException;
16 import org.asamk.signal.dbus.DbusSignalControlImpl;
17 import org.asamk.signal.dbus.DbusSignalImpl;
18 import org.asamk.signal.manager.Manager;
19 import org.freedesktop.dbus.connections.impl.DBusConnection;
20 import org.freedesktop.dbus.exceptions.DBusException;
21 import org.slf4j.Logger;
22 import org.slf4j.LoggerFactory;
23
24 import java.io.IOException;
25 import java.util.List;
26
27 public class DaemonCommand implements MultiLocalCommand {
28
29 private final static Logger logger = LoggerFactory.getLogger(DaemonCommand.class);
30
31 @Override
32 public String getName() {
33 return "daemon";
34 }
35
36 @Override
37 public void attachToSubparser(final Subparser subparser) {
38 subparser.help("Run in daemon mode and provide an experimental dbus interface.");
39 subparser.addArgument("--system")
40 .action(Arguments.storeTrue())
41 .help("Use DBus system bus instead of user bus.");
42 subparser.addArgument("--ignore-attachments")
43 .help("Don’t download attachments of received messages.")
44 .action(Arguments.storeTrue());
45 }
46
47 @Override
48 public List<OutputType> getSupportedOutputTypes() {
49 return List.of(OutputType.PLAIN_TEXT, OutputType.JSON);
50 }
51
52 @Override
53 public void handleCommand(
54 final Namespace ns, final Manager m, final OutputWriter outputWriter
55 ) throws CommandException {
56 boolean ignoreAttachments = Boolean.TRUE.equals(ns.getBoolean("ignore-attachments"));
57 m.setIgnoreAttachments(ignoreAttachments);
58
59 DBusConnection.DBusBusType busType;
60 if (Boolean.TRUE.equals(ns.getBoolean("system"))) {
61 busType = DBusConnection.DBusBusType.SYSTEM;
62 } else {
63 busType = DBusConnection.DBusBusType.SESSION;
64 }
65
66 try (var conn = DBusConnection.getConnection(busType)) {
67 var objectPath = DbusConfig.getObjectPath();
68 var t = run(conn, objectPath, m, outputWriter);
69
70 conn.requestBusName(DbusConfig.getBusname());
71
72 try {
73 t.join();
74 synchronized (this) {
75 wait();
76 }
77 } catch (InterruptedException ignored) {
78 }
79 } catch (DBusException | IOException e) {
80 logger.error("Dbus command failed", e);
81 throw new UnexpectedErrorException("Dbus command failed", e);
82 }
83 }
84
85 @Override
86 public void handleCommand(
87 final Namespace ns, final List<Manager> managers, final SignalCreator c, final OutputWriter outputWriter
88 ) throws CommandException {
89 boolean ignoreAttachments = Boolean.TRUE.equals(ns.getBoolean("ignore-attachments"));
90
91 DBusConnection.DBusBusType busType;
92 if (Boolean.TRUE.equals(ns.getBoolean("system"))) {
93 busType = DBusConnection.DBusBusType.SYSTEM;
94 } else {
95 busType = DBusConnection.DBusBusType.SESSION;
96 }
97
98 try (var conn = DBusConnection.getConnection(busType)) {
99 final var signalControl = new DbusSignalControlImpl(c, m -> {
100 m.setIgnoreAttachments(ignoreAttachments);
101 try {
102 final var objectPath = DbusConfig.getObjectPath(m.getSelfNumber());
103 return run(conn, objectPath, m, outputWriter);
104 } catch (DBusException e) {
105 logger.error("Failed to export object", e);
106 return null;
107 }
108 }, DbusConfig.getObjectPath());
109 conn.exportObject(signalControl);
110
111 for (var m : managers) {
112 signalControl.addManager(m);
113 }
114
115 conn.requestBusName(DbusConfig.getBusname());
116
117 signalControl.run();
118 } catch (DBusException | IOException e) {
119 logger.error("Dbus command failed", e);
120 throw new UnexpectedErrorException("Dbus command failed", e);
121 }
122 }
123
124 private Thread run(
125 DBusConnection conn, String objectPath, Manager m, OutputWriter outputWriter
126 ) throws DBusException {
127 final var signal = new DbusSignalImpl(m, conn, objectPath);
128 conn.exportObject(signal);
129 final var initThread = new Thread(signal::initObjects);
130 initThread.start();
131
132 logger.info("Exported dbus object: " + objectPath);
133
134 final var receiveMessageHandler = outputWriter instanceof JsonWriter ? new JsonDbusReceiveMessageHandler(m,
135 (JsonWriter) outputWriter,
136 conn,
137 objectPath) : new DbusReceiveMessageHandler(m, (PlainTextWriter) outputWriter, conn, objectPath);
138 m.addReceiveHandler(receiveMessageHandler);
139 return initThread;
140 }
141 }