]> nmode's Git Repositories - signal-cli/blob - src/main/java/org/asamk/signal/commands/DaemonCommand.java
8d26e452c984658c3dbedbc383e9b1a69547f7ec
[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.OutputType;
11 import org.asamk.signal.commands.exceptions.CommandException;
12 import org.asamk.signal.commands.exceptions.UnexpectedErrorException;
13 import org.asamk.signal.dbus.DbusSignalImpl;
14 import org.asamk.signal.manager.Manager;
15 import org.freedesktop.dbus.connections.impl.DBusConnection;
16 import org.freedesktop.dbus.exceptions.DBusException;
17 import org.slf4j.Logger;
18 import org.slf4j.LoggerFactory;
19
20 import java.io.IOException;
21 import java.util.ArrayList;
22 import java.util.List;
23 import java.util.Set;
24 import java.util.concurrent.TimeUnit;
25
26 public class DaemonCommand implements MultiLocalCommand {
27
28 private final static Logger logger = LoggerFactory.getLogger(DaemonCommand.class);
29
30 @Override
31 public void attachToSubparser(final Subparser subparser) {
32 subparser.addArgument("--system")
33 .action(Arguments.storeTrue())
34 .help("Use DBus system bus instead of user bus.");
35 subparser.addArgument("--ignore-attachments")
36 .help("Don’t download attachments of received messages.")
37 .action(Arguments.storeTrue());
38 subparser.addArgument("--json")
39 .help("WARNING: This parameter is now deprecated! Please use the global \"--output=json\" option instead.\n\nOutput received messages in json format, one json object per line.")
40 .action(Arguments.storeTrue());
41 }
42
43 @Override
44 public Set<OutputType> getSupportedOutputTypes() {
45 return Set.of(OutputType.PLAIN_TEXT, OutputType.JSON);
46 }
47
48 @Override
49 public void handleCommand(final Namespace ns, final Manager m) throws CommandException {
50 var inJson = ns.get("output") == OutputType.JSON || ns.getBoolean("json");
51
52 // TODO delete later when "json" variable is removed
53 if (ns.getBoolean("json")) {
54 logger.warn("\"--json\" option has been deprecated, please use the global \"--output=json\" instead.");
55 }
56
57 boolean ignoreAttachments = ns.getBoolean("ignore_attachments");
58
59 DBusConnection.DBusBusType busType;
60 if (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, ignoreAttachments, inJson);
69
70 conn.requestBusName(DbusConfig.getBusname());
71
72 try {
73 t.join();
74 } catch (InterruptedException ignored) {
75 }
76 } catch (DBusException | IOException e) {
77 logger.error("Dbus command failed", e);
78 throw new UnexpectedErrorException("Dbus command failed");
79 }
80 }
81
82 @Override
83 public void handleCommand(final Namespace ns, final List<Manager> managers) throws CommandException {
84 var inJson = ns.get("output") == OutputType.JSON || ns.getBoolean("json");
85
86 // TODO delete later when "json" variable is removed
87 if (ns.getBoolean("json")) {
88 logger.warn("\"--json\" option has been deprecated, please use the global \"--output=json\" instead.");
89 }
90
91 boolean ignoreAttachments = ns.getBoolean("ignore_attachments");
92
93 DBusConnection.DBusBusType busType;
94 if (ns.getBoolean("system")) {
95 busType = DBusConnection.DBusBusType.SYSTEM;
96 } else {
97 busType = DBusConnection.DBusBusType.SESSION;
98 }
99
100 try (var conn = DBusConnection.getConnection(busType)) {
101 var receiveThreads = new ArrayList<Thread>();
102 for (var m : managers) {
103 var objectPath = DbusConfig.getObjectPath(m.getUsername());
104 var thread = run(conn, objectPath, m, ignoreAttachments, inJson);
105 receiveThreads.add(thread);
106 }
107
108 conn.requestBusName(DbusConfig.getBusname());
109
110 for (var t : receiveThreads) {
111 try {
112 t.join();
113 } catch (InterruptedException ignored) {
114 }
115 }
116 } catch (DBusException | IOException e) {
117 logger.error("Dbus command failed", e);
118 throw new UnexpectedErrorException("Dbus command failed");
119 }
120 }
121
122 private Thread run(
123 DBusConnection conn, String objectPath, Manager m, boolean ignoreAttachments, boolean inJson
124 ) throws DBusException {
125 conn.exportObject(objectPath, new DbusSignalImpl(m));
126
127 final var thread = new Thread(() -> {
128 while (true) {
129 try {
130 m.receiveMessages(1,
131 TimeUnit.HOURS,
132 false,
133 ignoreAttachments,
134 inJson
135 ? new JsonDbusReceiveMessageHandler(m, conn, objectPath)
136 : new DbusReceiveMessageHandler(m, conn, objectPath));
137 } catch (IOException e) {
138 logger.warn("Receiving messages failed, retrying", e);
139 }
140 }
141 });
142
143 logger.info("Exported dbus object: " + objectPath);
144
145 thread.start();
146
147 return thread;
148 }
149 }