GCC Code Coverage Report


Directory: ./
File: qtpdcom/QtPdCom1/Process.h
Date: 2024-11-17 04:08:36
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
83 public:
84 enum class SslCaMode {
85 NoTLS, /**< Disable TLS, unencrypted traffic only. */
86 DefaultCAs /**< Use system-default Certificate Authories. */,
87 CustomCAs /**< Use provided CAs only. */,
88 IgnoreCertificate /**< Accept any server certificate. */,
89 };
90 Q_ENUM(SslCaMode)
91
92 Process(QObject *parent = nullptr);
93 virtual ~Process();
94
95 void setApplicationName(const QString &);
96 QString getApplicationName() const;
97 Q_INVOKABLE void connectToHost(const QString &, quint16 = 2345);
98 Q_INVOKABLE void disconnectFromHost();
99
100 /** State of the process connection.
101 */
102 enum ConnectionState {
103 Disconnected, /**< Process disconnected. */
104 Connecting, /**< Currently connecting. */
105 Connected, /**< Process connection established. */
106 ConnectError, /**< An error happened while connecting. */
107 ConnectedError /**< An error happened, after the connection was
108 established. */
109 };
110 Q_ENUM(ConnectionState);
111
112 ConnectionState getConnectionState() const;
113 bool isConnected() const;
114 const QString &getErrorString() const;
115 QString getPeerName() const;
116 QUrl getUrl() const;
117 int getPort() const;
118 QString getHost() const;
119
120 Q_INVOKABLE void sendBroadcast(const QString &, const QString &attr = "text");
121 quint64 getRxBytes() const;
122 quint64 getTxBytes() const;
123
124 /** Find a Variable.
125 *
126 * Finding a variable is asynchronous in general. If you need to write
127 * to a variable, a variable object is needed. To write a variable
128 * with a single call you can use futures and a lambda function. See
129 * the example in the overloaded method
130 * find(const QString&, Class *, Function&&).
131 *
132 * @return A Future. You can use VariableWatcher to monitor it.
133 */
134 QFuture<PdCom::Variable> find(const QString&);
135 QFuture<VariableList> list(const QString& = "");
136 QFuture<void> pingQt();
137 QFuture<std::vector<PdCom::ClientStatistics>> getClientStatisticsQt();
138
139 /** Also find a Variable.
140 *
141 * Here, a FutureWatcher is created on your behalf.
142 * Callback can be one of
143 * - a member Function of obj which takes a PdCom::Variable
144 * - a lambda which takes a reference to obj and a PdCom::Variable
145 * - a lambda which takes only a PdCom::Variable
146 *
147 * The obj reference is needed to use it as a parent for the watcher
148 * and to make the connections disconnect automatically when the Process
149 * or the object itself goes away.
150 *
151 * Below is an example of how to make use of a lambda function to find
152 * a variable and write to it once it is found:
153 *
154 * \code{.cpp}
155 * const double val = 30.0;
156 * const QString path = "/osc/amplitude/Setpoint";
157 *
158 * process->find(path, this, [val](const PdCom::Variable& var) {
159 * if (var.empty()) {
160 * std::cerr << "Variable not found." << std::endl;
161 * }
162 * else {
163 * var.setValue(val);
164 * std::cerr << "Set " << var.getPath()
165 * << " to " << val << std::endl;
166 * }
167 * });
168 * \endcode
169 *
170 * \param path Variable to find.
171 * \param obj QObject-derived class.
172 * \param callback Callback which receives the result.
173 * \return A freshly created FutureWatcher instance with all signals connected.
174 */
175 template<class Class, class Function>
176 QFutureWatcher<PdCom::Variable>& find(const QString& path, Class *obj, Function&& callback);
177 template<class Class, class Function>
178 QFutureWatcher<VariableList>& list(const QString& path, Class *obj, Function&& callback);
179 template<class Class, class Function>
180 QFutureWatcher<void>& ping(Class *obj, Function&& callback);
181 template<class Class, class Function>
182 QFutureWatcher<std::vector<PdCom::ClientStatistics>>&
183 getClientStatistics(Class *obj, Function&& callback);
184
185 /**
186 * Set Traffic Encryption mode.
187 *
188 * See the SslCaMode enum for details.
189 *
190 * \param mode Mode.
191 */
192 void setCaMode(SslCaMode mode);
193 /**
194 * Get Traffic Encryption mode.
195 *
196 * \return Traffic Encryption mode.
197 */
198 SslCaMode getCaMode() const;
199
200 /**
201 * Provide a client certificate.
202 *
203 * \param cert Public certificate.
204 * \param key Private key.
205 */
206 void setClientCertificate(const QSslCertificate& cert,const QSslKey& key);
207 /**
208 * Set list of trusted Certificate Authorities.
209 *
210 * For \c SslCaMode::CustomCAs mode.
211 *
212 * \param cas List of trusted CAs.
213 */
214 void setCustomCAs(QList<QSslCertificate> cas);
215
216 static QtPdCom::Process *getDefaultProcess();
217 static void setDefaultProcess(QtPdCom::Process *);
218
219 PdCom::MessageManagerBase *getMessageManager() const;
220
221 /**
222 * Set the Login Manager.
223 * \param lm The Login manager. May be \c NULL.
224 */
225 void setLoginManager(LoginManager* lm);
226 LoginManager *getLoginManager() const;
227 private:
228 struct Q_DECL_HIDDEN Impl;
229 std::unique_ptr<Impl> impl;
230
231 /** Virtual from PdCom::Process. */
232 std::string applicationName() const override;
233 std::string hostname() const override;
234 int read(char *, int) override;
235 void write(const char *, size_t) override;
236 void flush() override;
237 void connected() override;
238 void broadcastReply(
239 const std::string &message,
240 const std::string &attr,
241 std::chrono::nanoseconds time_ns,
242 const std::string &user) override;
243 void pingReply() override;
244 void findReply(PdCom::Variable const& var) override;
245 void listReply(std::vector<PdCom::Variable> vars, std::vector<std::string> dirs) override;
246 void clientStatisticsReply(std::vector<PdCom::ClientStatistics> statistics) override;
247 void reset();
248
249 /** Disconnect method inherited from QObject.
250 *
251 * This is made private, to avoid confusion.
252 */
253 bool disconnect(
254 const char *signal = 0, /**< Signal. */
255 const QObject *receiver = 0, /**< Receiver. */
256 const char *method = 0 /**< Method. */
257 );
258
259 // make setMessageManager() private
260 using PdCom::Process::setMessageManager;
261
262 signals:
263 /** Connection established.
264 *
265 * This is emitted after the connection is established.
266 */
267 void processConnected();
268
269 /** Disconnected gracefully.
270 *
271 * This is only emitted, after the user called disconnectFromHost().
272 */
273 void disconnected();
274
275 /** Connection error.
276 *
277 * This is emitted after a connection error or when the connection was
278 * closed due to a parser error.
279 */
280 void error();
281
282 void broadcastReceived(
283 const QString &message,
284 const QString &attr,
285 std::uint64_t time_ns,
286 const QString &user);
287
288 void connectionStatusChanged();
289
290 void sslCaModeChanged();
291
292
293 private slots:
294 void socketConnected();
295 void socketDisconnected();
296 void socketError();
297 void socketRead();
298 };
299
300 /****************************************************************************/
301
302 template<class Class, class Function>
303 inline QFutureWatcher<PdCom::Variable>& Process::find(
304 const QString& path, Class *obj, Function&& callback)
305 {
306 auto& ans = createWatcher<PdCom::Variable>(obj, callback);
307 ans.setFuture(find(path));
308 return ans;
309 }
310
311 /****************************************************************************/
312
313 template<class Class, class Function>
314 inline QFutureWatcher<VariableList>& Process::list(const QString& path, Class *obj, Function&& callback)
315 {
316 auto& ans = createWatcher<VariableList>(obj, callback);
317 ans.setFuture(list(path));
318 return ans;
319 }
320
321 /****************************************************************************/
322
323 template<class Class, class Function>
324 inline QFutureWatcher<void>& Process::ping(Class *obj, Function&& callback)
325 {
326 auto& ans = createWatcher<void>(obj, callback);
327 ans.setFuture(pingQt());
328 return ans;
329 }
330
331 /****************************************************************************/
332
333 template<class Class, class Function>
334 inline QFutureWatcher<std::vector<PdCom::ClientStatistics>>&
335 Process::getClientStatistics(Class *obj, Function&& callback)
336 {
337 auto& ans = createWatcher<std::vector<PdCom::ClientStatistics>>(
338 obj, callback
339 );
340 ans.setFuture(getClientStatisticsQt());
341 return ans;
342 }
343
344 /****************************************************************************/
345
346 } // namespace
347
348 #endif // QTPDCOM_PROCESS_H
349