GCC Code Coverage Report


./
File: src/XpertMass/MassDataClient.cpp
Date: 2024-08-24 11:26:06
Lines:
0/61
0.0%
Functions:
0/8
0.0%
Branches:
0/74
0.0%

Line Branch Exec Source
1 /* BEGIN software license
2 *
3 * MsXpertSuite - mass spectrometry software suite
4 * -----------------------------------------------
5 * Copyright (C) 2009--2020 Filippo Rusconi
6 *
7 * http://www.msxpertsuite.org
8 *
9 * This file is part of the MsXpertSuite project.
10 *
11 * The MsXpertSuite project is the successor of the massXpert project. This
12 * project now includes various independent modules:
13 *
14 * - massXpert, model polymer chemistries and simulate mass spectrometric data;
15 * - mineXpert, a powerful TIC chromatogram/mass spectrum viewer/miner;
16 *
17 * This program is free software: you can redistribute it and/or modify
18 * it under the terms of the GNU General Public License as published by
19 * the Free Software Foundation, either version 3 of the License, or
20 * (at your option) any later version.
21 *
22 * This program is distributed in the hope that it will be useful,
23 * but WITHOUT ANY WARRANTY; without even the implied warranty of
24 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
25 * GNU General Public License for more details.
26 *
27 * You should have received a copy of the GNU General Public License
28 * along with this program. If not, see <http://www.gnu.org/licenses/>.
29 *
30 * *****************************************************************************
31 * This specific code is a port to C++ of the Envemind Python code by Radzinski
32 * and colleagues of IsoSpec fame (Lacki, Startek and company :-)
33 *
34 * See https://github.com/PiotrRadzinski/envemind.
35 * *****************************************************************************
36 *
37 * END software license
38 */
39
40
41 #include <QDebug>
42 #include <QtNetwork>
43
44 #include "MassDataClient.hpp"
45
46 namespace MsXpS
47 {
48 namespace libXpertMass
49 {
50
51 /*!
52 \class MsXpS::libXpertMass::MassDataClient
53 \inmodule libXpertMass
54 \ingroup XpertMassUtilities
55 \inheaderfile MassDataClient.hpp
56
57 \brief The MassDataClient class provides a network client.
58 */
59
60 /*!
61 \variable MsXpS::libXpertMass::MassDataClient::m_inStream
62
63 \brief The data stream in input in this MassDataClient instance.
64 */
65
66 /*!
67 \variable MsXpS::libXpertMass::MassDataClient::m_data
68
69 \brief The data being transported.
70 */
71
72 /*!
73 \variable MsXpS::libXpertMass::MassDataClient::m_ipAddress
74
75 \brief The server IP address to which the connection must be made.
76 */
77
78 /*!
79 \variable MsXpS::libXpertMass::MassDataClient::m_portNumber
80
81 \brief The port number to which to attach during the connection..
82 */
83
84 /*!
85 \variable MsXpS::libXpertMass::MassDataClient::m_connectionFrequency
86
87 \brief The frequency at which the client connects to the server, in times per
88 second.
89
90 A frequency of 1 means that the connection will be tried once per second. This
91 is empirically correct.
92 */
93
94 /*!
95 \variable MsXpS::libXpertMass::MassDataClient::mpa_tcpSocket
96
97 \brief The socket that is used for the connection.
98 */
99
100 /*!
101 \brief Constructs a MassDataClient instance.
102
103 \list
104 \li \a ip_address: the server IP address at which the client needs to try a
105 connection.
106 \li \a port_number: the port number for the connection.
107 \li \a connection_frequency: the frequency at which the client tries a
108 connection to the server.
109 \li \a parent: the parent QObject.
110 \endlist
111 */
112 MassDataClient::MassDataClient(const QString &ip_address,
113 int port_number,
114 int connection_frequency,
115 QObject *parent)
116 : QObject(parent),
117 m_ipAddress(ip_address),
118 m_portNumber(port_number),
119 m_connectionFrequency(connection_frequency)
120 {
121 mpa_tcpSocket = new QTcpSocket(parent);
122 if(mpa_tcpSocket == nullptr)
123 qFatal("Failed to allocate a socket.");
124
125 // QString host_name = QHostInfo::localHostName();
126
127 // if(!host_name.isEmpty())
128 //{
129 // QString domain_name = QHostInfo::localDomainName();
130
131 // if(!domain_name.isEmpty())
132 // qDebug() << "address:" << host_name + "/" + domain_name;
133 //}
134
135 // if(host_name != QLatin1String("locahost"))
136 // qDebug() << "host_name is not localhost.";
137
138 // QList<QHostAddress> ip_addresses_list = QNetworkInterface::allAddresses();
139
140 // for(int iter = 0; iter < ip_addresses_list.size(); ++iter)
141 // qDebug() << "New ip address:" << ip_addresses_list.at(iter)
142 //<< "is loopback:" << ip_addresses_list.at(iter).isLoopback();
143
144 connect(mpa_tcpSocket, &QTcpSocket::hostFound, [this]() {
145 emit hostFoundSignal();
146 });
147
148 connect(mpa_tcpSocket, &QTcpSocket::connected, [this]() {
149 emit connectedSignal();
150 });
151
152 connect(mpa_tcpSocket,
153 &QAbstractSocket::errorOccurred,
154 this,
155 &MassDataClient::reportError);
156
157 m_inStream.setDevice(mpa_tcpSocket);
158 m_inStream.setVersion(QDataStream::Qt_5_0);
159 connect(
160 mpa_tcpSocket, &QIODevice::readyRead, this, &MassDataClient::readData);
161
162
163 // A time with a timeout of 0 will trigger as soon as all the other events
164 // have been processed. This is thus not intrusive.
165
166 QTimer *timer_p = new QTimer(this);
167 // This does not work, the interaval is too short and the server can't serve
168 // in time, it seems.
169 // timer_p->setInterval(0);
170 // 1 second is largely enough, which means a frequency of 1, which is the
171 // default for the connection frequency parameter!
172 timer_p->setInterval(1000 / m_connectionFrequency);
173 connect(timer_p, &QTimer::timeout, this, &MassDataClient::requestNewData);
174
175 timer_p->start();
176 }
177
178 /*!
179 \brief Destructs this MassDataClient instance.
180 */
181 MassDataClient::~MassDataClient()
182 {
183 if(mpa_tcpSocket != nullptr)
184 {
185 qDebug("Now deleting the socket.");
186 delete mpa_tcpSocket;
187 }
188 }
189
190 /*!
191 \brief Tries a connection to the server using the member QTcpSocket.
192 */
193 void
194 MassDataClient::requestNewData()
195 {
196 qDebug() << "Client requests data at" << QDateTime::currentDateTime();
197
198 QAbstractSocket::SocketState state = mpa_tcpSocket->state();
199 if(state != QAbstractSocket::UnconnectedState)
200 mpa_tcpSocket->abort();
201
202 mpa_tcpSocket->connectToHost(m_ipAddress, m_portNumber);
203 }
204
205 /*!
206 \brief Reads the data into the QByteArray m_data member using the QDataStream
207 m_inStream member.
208
209 Emits the newDataSignal() signal with m_data;.
210 */
211 void
212 MassDataClient::readData()
213 {
214 // qDebug() << "Reading data.";
215
216 // We need to have the same version, FIXME, this should go as a macro
217 // somewhere.
218
219 // qDebug() << "The number of bytes available in this readData call:"
220 //<< mp_tcpSocket->bytesAvailable() << "at"
221 //<< QDateTime::currentDateTime().toString();
222
223 // This version uses the readAll() function.
224
225 // QByteArray byte_array = mp_tcpSocket->readAll();
226
227 // QDataStream stream(byte_array);
228 // stream.setVersion(QDataStream::Qt_5_0);
229 // stream.startTransaction();
230 // stream >> m_data;
231
232 // if(!stream.commitTransaction())
233 //{
234 // qDebug() << "Failed to commit the data read transaction.";
235
236 // return ;
237 //}
238
239 // This version uses the stream operator.
240 // Seems to work equivalently to the version above.
241 // stream.setVersion(QDataStream::Qt_5_0);
242 m_inStream.startTransaction();
243
244 m_inStream >> m_data;
245
246 // qDebug() << "Atomically read" << m_data.size();
247
248 if(!m_inStream.commitTransaction())
249 {
250 qDebug() << "Could NOT commit the transaction fine.";
251 return;
252 }
253 // else
254 // qDebug() << "Could commit the transaction fine.";
255
256 emit newDataSignal(m_data);
257
258 // qDebug() << "Got these data:" << QString(m_data);
259 }
260
261 /*!
262 \brief Reports the error \a socket_error.
263 */
264 void
265 MassDataClient::reportError(QAbstractSocket::SocketError socket_error)
266 {
267 switch(socket_error)
268 {
269 case QAbstractSocket::RemoteHostClosedError:
270 // qDebug() << "Error: QAbstractSocket::RemoteHostClosedError.";
271 // emit reportErrorSignal("RemoteHostClosedError");
272 break;
273 case QAbstractSocket::HostNotFoundError:
274 // qDebug() << "Error: QAbstractSocket::HostNotFoundError.";
275 // emit reportErrorSignal("HostNotFoundError");
276 break;
277 case QAbstractSocket::ConnectionRefusedError:
278 qDebug() << "Error: QAbstractSocket::ConnectionRefusedError.";
279 emit reportErrorSignal("ConnectionRefusedError");
280 break;
281 default:
282 // qDebug() << "Error:" << mp_tcpSocket->errorString();
283 // emit reportErrorSignal(mp_tcpSocket->errorString());
284 break;
285 }
286 }
287
288 /*!
289 \brief Returns a string display the connection details.
290 */
291 QString
292 MassDataClient::getStatus()
293 {
294 return QString("Doing well, connection should be to IP address: %1, port %2.")
295 .arg(m_ipAddress)
296 .arg(m_portNumber);
297 }
298
299 } // namespace libXpertMass
300
301 } // namespace MsXpS
302