GCC Code Coverage Report


Directory: ./
File: qtpdcom/QtPdCom1/Process.h
Date: 2025-02-23 04:08:29
Exec Total Coverage
Lines: 0 4 0.0%
Branches: 0 2 0.0%

Line Branch Exec Source
1 /*****************************************************************************
2 *
3 * Copyright (C) 2009-2022 Florian Pose <fp@igh.de>
4 *
5 * This file is part of the QtPdCom library.
6 *
7 * The QtPdCom library is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU Lesser General Public License as published by
9 * the Free Software Foundation, either version 3 of the License, or (at your
10 * option) any later version.
11 *
12 * The QtPdCom library is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
14 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
15 * License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public License
18 * along with the QtPdCom Library. If not, see <http://www.gnu.org/licenses/>.
19 *
20 ****************************************************************************/
21
22 #ifndef QTPDCOM_PROCESS_H
23 #define QTPDCOM_PROCESS_H
24
25 #include <QObject>
26 #include <QString>
27 #include <QList>
28 #include <QSslCertificate>
29 #include <QUrl>
30
31 #include <pdcom5.h>
32 #include <pdcom5/ClientStatistics.h>
33 #include <pdcom5/Process.h>
34 #include <QFuture>
35
36 #ifndef PDCOM_VERSION_CODE
37 # error "No PDCOM_VERSION_CODE found."
38 #elif \
39 !PDCOM_DEVEL \
40 && (PDCOM_VERSION_CODE < PDCOM_VERSION(5, 0, 0) \
41 || PDCOM_VERSION_CODE >= PDCOM_VERSION(6, 0, 0))
42 # error "Invalid PdCom version."
43 #endif
44
45 #include "QtPdCom1.h"
46 #include "Export.h"
47 #include "FutureWatchers.h"
48 #include "VariableList.h"
49
50 class QTranslator;
51 class QSslKey;
52
53
54 #ifdef QTPDCOM_HAS_LOGIN_MANAGER
55 #include "LoginManager.h"
56 #else
57 namespace QtPdCom {
58 class LoginManager;
59 }
60
61 Q_DECLARE_OPAQUE_POINTER(QtPdCom::LoginManager*);
62 #endif
63
64 namespace QtPdCom {
65
66 /****************************************************************************/
67
68 /** PdCom::Process implementation for Qt.
69 */
70 class QTPDCOM_PUBLIC Process:
71 public QObject, public PdCom::Process
72 {
73 Q_OBJECT
74 Q_PROPERTY(bool connected READ isConnected NOTIFY connectionStatusChanged)
75 Q_PROPERTY(ConnectionState connectionState READ getConnectionState NOTIFY connectionStatusChanged)
76 Q_PROPERTY(SslCaMode sslCaMode READ getCaMode WRITE setCaMode NOTIFY sslCaModeChanged)
77 Q_PROPERTY(int port READ getPort NOTIFY connectionStatusChanged)
78 Q_PROPERTY(QString host READ getHost NOTIFY connectionStatusChanged)
79 Q_PROPERTY(QUrl url READ getUrl NOTIFY connectionStatusChanged)
80 Q_PROPERTY(QString applicationName READ getApplicationName WRITE setApplicationName)
81 Q_PROPERTY(QtPdCom::LoginManager * loginManager READ getLoginManager WRITE setLoginManager)
82 Q_PROPERTY(QVariant name READ nameQt NOTIFY connectionStatusChanged)
83 Q_PROPERTY(QVariant version READ versionQt NOTIFY connectionStatusChanged)
84
85 public:
86 enum class SslCaMode {
87 NoTLS, /**< Disable TLS, unencrypted traffic only. */
88 DefaultCAs /**< Use system-default Certificate Authories. */,
89 CustomCAs /**< Use provided CAs only. */,
90 IgnoreCertificate /**< Accept any server certificate. */,
91 };
92 Q_ENUM(SslCaMode)
93
94 Process(QObject *parent = nullptr);
95 virtual ~Process();
96
97 void setApplicationName(const QString &);
98 QString getApplicationName() const;
99 Q_INVOKABLE void connectToHost(const QString &, quint16 = 2345);
100 Q_INVOKABLE void disconnectFromHost();
101
102 /** State of the process connection.
103 */
104 enum ConnectionState {
105 Disconnected, /**< Process disconnected. */
106 Connecting, /**< Currently connecting. */
107 Connected, /**< Process connection established. */
108 ConnectError, /**< An error happened while connecting. */
109 ConnectedError /**< An error happened, after the connection was
110 established. */
111 };
112 Q_ENUM(ConnectionState);
113
114 ConnectionState getConnectionState() const;
115 bool isConnected() const;
116 const QString &getErrorString() const;
117 QString getPeerName() const;
118 QUrl getUrl() const;
119 int getPort() const;
120 QString getHost() const;
121
122 Q_INVOKABLE void sendBroadcast(const QString &, const QString &attr = "text");
123 quint64 getRxBytes() const;
124 quint64 getTxBytes() const;
125
126 /** Remote process name string */
127 QVariant nameQt() const;
128 /** Remote process version string */
129 QVariant versionQt() const;
130
131 /** Find a Variable.
132 *
133 * Finding a variable is asynchronous in general. If you need to write
134 * to a variable, a variable object is needed. To write a variable
135 * with a single call you can use futures and a lambda function. See
136 * the example in the overloaded method
137 * find(const QString&, Class *, Function&&).
138 *
139 * @return A Future. You can use VariableWatcher to monitor it.
140 */
141 QFuture<PdCom::Variable> find(const QString&);
142 QFuture<VariableList> list(const QString& = "");
143 QFuture<void> pingQt();
144 QFuture<std::vector<PdCom::ClientStatistics>> getClientStatisticsQt();
145
146 /** Also find a Variable.
147 *
148 * Here, a FutureWatcher is created on your behalf.
149 * Callback can be one of
150 * - a member Function of obj which takes a PdCom::Variable
151 * - a lambda which takes a reference to obj and a PdCom::Variable
152 * - a lambda which takes only a PdCom::Variable
153 *
154 * The obj reference is needed to use it as a parent for the watcher
155 * and to make the connections disconnect automatically when the Process
156 * or the object itself goes away.
157 *
158 * Below is an example of how to make use of a lambda function to find
159 * a variable and write to it once it is found:
160 *
161 * \code{.cpp}
162 * const double val = 30.0;
163 * const QString path = "/osc/amplitude/Setpoint";
164 *
165 * process->find(path, this, [val](const PdCom::Variable& var) {
166 * if (var.empty()) {
167 * std::cerr << "Variable not found." << std::endl;
168 * }
169 * else {
170 * var.setValue(val);
171 * std::cerr << "Set " << var.getPath()
172 * << " to " << val << std::endl;
173 * }
174 * });
175 * \endcode
176 *
177 * \param path Variable to find.
178 * \param obj QObject-derived class.
179 * \param callback Callback which receives the result.
180 * \return A freshly created FutureWatcher instance with all signals connected.
181 */
182 template<class Class, class Function>
183 QFutureWatcher<PdCom::Variable>& find(const QString& path, Class *obj, Function&& callback);
184 template<class Class, class Function>
185 QFutureWatcher<VariableList>& list(const QString& path, Class *obj, Function&& callback);
186 template<class Class, class Function>
187 QFutureWatcher<void>& ping(Class *obj, Function&& callback);
188 template<class Class, class Function>
189 QFutureWatcher<std::vector<PdCom::ClientStatistics>>&
190 getClientStatistics(Class *obj, Function&& callback);
191
192 /**
193 * Set Traffic Encryption mode.
194 *
195 * See the SslCaMode enum for details.
196 *
197 * \param mode Mode.
198 */
199 void setCaMode(SslCaMode mode);
200 /**
201 * Get Traffic Encryption mode.
202 *
203 * \return Traffic Encryption mode.
204 */
205 SslCaMode getCaMode() const;
206
207 /**
208 * Provide a client certificate.
209 *
210 * \param cert Public certificate.
211 * \param key Private key.
212 */
213 void setClientCertificate(const QSslCertificate& cert,const QSslKey& key);
214 /**
215 * Set list of trusted Certificate Authorities.
216 *
217 * For \c SslCaMode::CustomCAs mode.
218 *
219 * \param cas List of trusted CAs.
220 */
221 void setCustomCAs(QList<QSslCertificate> cas);
222
223 static QtPdCom::Process *getDefaultProcess();
224 static void setDefaultProcess(QtPdCom::Process *);
225
226 PdCom::MessageManagerBase *getMessageManager() const;
227
228 /**
229 * Set the Login Manager.
230 * \param lm The Login manager. May be \c NULL.
231 */
232 void setLoginManager(LoginManager* lm);
233 LoginManager *getLoginManager() const;
234 private:
235 struct Q_DECL_HIDDEN Impl;
236 std::unique_ptr<Impl> impl;
237
238 /** Virtual from PdCom::Process. */
239 std::string applicationName() const override;
240 std::string hostname() const override;
241 int read(char *, int) override;
242 void write(const char *, size_t) override;
243 void flush() override;
244 void connected() override;
245 void broadcastReply(
246 const std::string &message,
247 const std::string &attr,
248 std::chrono::nanoseconds time_ns,
249 const std::string &user) override;
250 void pingReply() override;
251 void findReply(PdCom::Variable const& var) override;
252 void listReply(std::vector<PdCom::Variable> vars, std::vector<std::string> dirs) override;
253 void clientStatisticsReply(std::vector<PdCom::ClientStatistics> statistics) override;
254 void reset();
255
256 /** Disconnect method inherited from QObject.
257 *
258 * This is made private, to avoid confusion.
259 */
260 bool disconnect(
261 const char *signal = 0, /**< Signal. */
262 const QObject *receiver = 0, /**< Receiver. */
263 const char *method = 0 /**< Method. */
264 );
265
266 // make setMessageManager() private
267 using PdCom::Process::setMessageManager;
268
269 signals:
270 /** Connection established.
271 *
272 * This is emitted after the connection is established.
273 */
274 void processConnected();
275
276 /** Disconnected gracefully.
277 *
278 * This is only emitted, after the user called disconnectFromHost().
279 */
280 void disconnected();
281
282 /** Connection error.
283 *
284 * This is emitted after a connection error or when the connection was
285 * closed due to a parser error.
286 */
287 void error();
288
289 void broadcastReceived(
290 const QString &message,
291 const QString &attr,
292 std::uint64_t time_ns,
293 const QString &user);
294
295 void connectionStatusChanged();
296
297 void sslCaModeChanged();
298
299
300 private slots:
301 void socketConnected();
302 void socketDisconnected();
303 void socketError();
304 void socketRead();
305 };
306
307 /****************************************************************************/
308
309 template<class Class, class Function>
310 inline QFutureWatcher<PdCom::Variable>& Process::find(
311 const QString& path, Class *obj, Function&& callback)
312 {
313 auto& ans = createWatcher<PdCom::Variable>(obj, callback);
314 ans.setFuture(find(path));
315 return ans;
316 }
317
318 /****************************************************************************/
319
320 template<class Class, class Function>
321 inline QFutureWatcher<VariableList>& Process::list(const QString& path, Class *obj, Function&& callback)
322 {
323 auto& ans = createWatcher<VariableList>(obj, callback);
324 ans.setFuture(list(path));
325 return ans;
326 }
327
328 /****************************************************************************/
329
330 template<class Class, class Function>
331 inline QFutureWatcher<void>& Process::ping(Class *obj, Function&& callback)
332 {
333 auto& ans = createWatcher<void>(obj, callback);
334 ans.setFuture(pingQt());
335 return ans;
336 }
337
338 /****************************************************************************/
339
340 template<class Class, class Function>
341 inline QFutureWatcher<std::vector<PdCom::ClientStatistics>>&
342 Process::getClientStatistics(Class *obj, Function&& callback)
343 {
344 auto& ans = createWatcher<std::vector<PdCom::ClientStatistics>>(
345 obj, callback
346 );
347 ans.setFuture(getClientStatisticsQt());
348 return ans;
349 }
350
351 /****************************************************************************/
352
353 } // namespace
354
355 #endif // QTPDCOM_PROCESS_H
356