ArnLib  4.0.x
Active Registry Network
ArnServerRemote.cpp
Go to the documentation of this file.
1 // Copyright (C) 2010-2022 Michael Wiklund.
2 // All rights reserved.
3 // Contact: arnlib@wiklunden.se
4 //
5 // This file is part of the ArnLib - Active Registry Network.
6 // Parts of ArnLib depend on Qt and/or other libraries that have their own
7 // licenses. Usage of these other libraries is subject to their respective
8 // license agreements.
9 //
10 // GNU Lesser General Public License Usage
11 // This file may be used under the terms of the GNU Lesser General Public
12 // License version 2.1 as published by the Free Software Foundation and
13 // appearing in the file LICENSE_LGPL.txt included in the packaging of this
14 // file. In addition, as a special exception, you may use the rights described
15 // in the Nokia Qt LGPL Exception version 1.1, included in the file
16 // LGPL_EXCEPTION.txt in this package.
17 //
18 // GNU General Public License Usage
19 // Alternatively, this file may be used under the terms of the GNU General Public
20 // License version 3.0 as published by the Free Software Foundation and appearing
21 // in the file LICENSE_GPL.txt included in the packaging of this file.
22 //
23 // Other Usage
24 // Alternatively, this file may be used in accordance with the terms and conditions
25 // contained in a signed written agreement between you and Michael Wiklund.
26 //
27 // This program is distributed in the hope that it will be useful, but WITHOUT ANY
28 // WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
29 // PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
30 //
31 
33 #include "private/ArnServerRemote_p.hpp"
34 #include "ArnInc/ArnServer.hpp"
35 #include "ArnSync.hpp"
36 #include "ArnInc/ArnM.hpp"
37 #include "ArnInc/Arn.hpp"
38 #include <QTcpSocket>
39 #include <QHostInfo>
40 #include <QTimer>
41 #include <QDateTime>
42 
43 
45  ArnServerRemote* arnServerRemote)
46  : QObject( arnServerRemote)
47 {
48  _arnServerSession = arnServerSession;
49  _arnServerRemote = arnServerRemote;
50  _killCountdown = 0;
51  _pollCount = 0;
52 
53  QTcpSocket* socket = _arnServerSession->socket();
54  QHostAddress remAddr = socket->peerAddress();
55  quint32 remAddrV4 = remAddr.toIPv4Address();
56  if (remAddrV4) // MW: TODO Check if this is ok for IPV6
57  remAddr = QHostAddress( remAddrV4);
58 
59  QString remIp = remAddr.toString();
60  QString remIpPort = remIp + ":" + QString::number( socket->peerPort());
61  _sessionPath = Arn::pathServerSessions +
62  remIpPort + "/";
63 
64  ArnM::setValue( _sessionPath + "HostIp/value", remIp);
65 
66  _clientHostName = remIpPort; // Preliminary name
67  updateSessionValue();
68 
69  connect( _arnServerSession, SIGNAL(infoReceived(int)), this, SLOT(onInfoReceived(int)));
70  connect( _arnServerSession, SIGNAL(loginCompleted()), this, SLOT(onLoginCompleted()));
71  connect( _arnServerSession, SIGNAL(destroyed(QObject*)), SLOT(shutdown()));
72 
73  int lookupId = QHostInfo::lookupHost( remIp, this, SLOT(onIpLookup(QHostInfo)));
74  Q_UNUSED(lookupId);
75 
76  _timerPoll = new QTimer( this);
77  _timerPoll->start( 1000);
78  connect( _timerPoll, SIGNAL(timeout()), this, SLOT(doPoll()));
79 
80  _arnTraffic.open( _sessionPath + "Traffic/value");
81  _arnTrafficIn.open( _sessionPath + "Traffic/In/value");
82  _arnTrafficOut.open( _sessionPath + "Traffic/Out/value");
83 
84  _arnKill.open( _sessionPath + "Kill/value");
85  _arnKill = KillMode::Off;
86  ArnM::setValue( _sessionPath + "Kill/set", KillMode::txt().getEnumSet());
87  connect( &_arnKill, SIGNAL(changed()), this, SLOT(doKillChanged()));
88 
89  _arnChatPv.setPipeMode();
90  _arnChatPv.open( _sessionPath + "Chat!");
91  connect( &_arnChatPv, SIGNAL(changed(QString)), this, SLOT(doChatAdd(QString)));
92 
93  _arnChatAllPv.setPipeMode();
94  _arnChatAllPv.open( Arn::pathServer + "ChatSessions!");
95  connect( &_arnChatAllPv, SIGNAL(changed(QString)), this, SLOT(doChatAdd(QString)));
96 
97  connect( _arnServerSession, SIGNAL(messageReceived(int,QByteArray)),
98  this, SLOT(onMessageReceived(int,QByteArray)));
99 
100  _startTime = QDateTime::currentDateTimeUtc();
101  _arnUpTime.open( _sessionPath + "UpTime/value");
102  ArnM::setValue( _sessionPath + "UpTime/property", "prec=2 unit=h");
103 }
104 
105 
106 void ArnServerRemoteSession::updateSessionValue()
107 {
108  if (_sessionPath.isNull()) return; // Retired
109 
110  _sessionValue = _clientUserName.isEmpty() ? _clientAgent : _clientUserName;
111  if (!_clientHostName.isEmpty()) {
112  if (!_sessionValue.isEmpty())
113  _sessionValue += " ";
114  _sessionValue += "@ " + _clientHostName;
115  }
116  ArnM::setValue( _sessionPath + "name", _sessionValue);
117 }
118 
119 
120 void ArnServerRemoteSession::onInfoReceived( int type)
121 {
122  if (_sessionPath.isNull()) return; // Retired
123 
124  switch (type) {
125  case ArnSync::InfoType::WhoIAm:
126  {
127  Arn::XStringMap wimXsm = _arnServerSession->remoteWhoIAm();
128  _clientAgent = wimXsm.valueString("Agent");
129  _clientUserName = wimXsm.valueString("UserName");
130  updateSessionValue();
131  for (int i = 0; i < wimXsm.size(); ++i) {
132  ArnM::setValue( _sessionPath + wimXsm.key(i) + "/value", wimXsm.value(i));
133  }
134  break;
135  }
136  default:;
137  }
138 }
139 
140 
141 void ArnServerRemoteSession::onLoginCompleted()
142 {
143  if (_sessionPath.isNull()) return; // Retired
144 
145  ArnM::setValue( _sessionPath + "LoginName/value", _arnServerSession->loginUserName());
146 }
147 
148 
149 void ArnServerRemoteSession::onIpLookup( const QHostInfo& host)
150 {
151  if (_sessionPath.isNull()) return; // Retired
152 
153  if (host.error() == QHostInfo::NoError) {
154  _clientHostName = host.hostName();
155  updateSessionValue();
156  ArnM::setValue( _sessionPath + "HostName/value", _clientHostName);
157  }
158  else {
159  qDebug() << "ServerRemoteSession Lookup failed:" << host.errorString();
160  }
161 }
162 
163 
164 void ArnServerRemoteSession::doKillChanged()
165 {
166  if (_sessionPath.isNull()) return; // Retired
167 
168  KillMode kMode = KillMode::fromInt( _arnKill.toInt());
169 
170  switch (kMode) {
171  case KillMode::Off:
172  _killCountdown = 0;
173  break;
175  _killCountdown = 10;
176  break;
178  _killCountdown = 60;
179  break;
180  default:
181  break;
182  }
183 
184  QString txt;
185  if (_killCountdown > 0) {
186  txt = QString("Arn Connection kill countdown started (%1 sec)").arg( _killCountdown);
187  }
188  else {
189  txt = "Arn Connection kill Aborted at server";
190  }
191  _arnChatPv = txt;
192  _arnChatAllPv = _sessionValue + ": " + txt;
193  _arnServerSession->sendMessage( ArnSync::MessageType::ChatPrio, txt.toUtf8());
194 }
195 
196 
197 void ArnServerRemoteSession::doPoll()
198 {
199  if (_sessionPath.isNull()) return; // Retired
200 
201  if (_killCountdown > 0) {
203  --_killCountdown;
204  QString txt;
205  if ((_killCountdown % 5 == 0) || (_killCountdown < 10)) {
206  txt = QString("Arn Connection kill in %1 sec.").arg( _killCountdown);
207  _arnChatPv = txt;
208  _arnServerSession->sendMessage( ArnSync::MessageType::ChatPrio, txt.toUtf8());
209  }
210  if (_killCountdown == 0) {
211  txt = "Arn Connection kill Request from server";
212  _arnChatPv = txt;
213  _arnChatAllPv = _sessionValue + ": " + txt;
214  _arnServerSession->sendMessage( ArnSync::MessageType::ChatPrio, txt.toUtf8());
215  _arnServerSession->sendMessage( ArnSync::MessageType::KillRequest);
216  }
217  }
218 
219  if (_pollCount % 5 == 0) {
221  ARNREAL upTime = ARNREAL( _startTime.secsTo( QDateTime::currentDateTimeUtc())) / 3600.;
222  _arnUpTime.setValue( upTime);
223 
225  quint64 trafficIn;
226  quint64 trafficOut;
227  bool isOk = _arnServerSession->getTraffic( trafficIn, trafficOut);
228  if (isOk) {
229  _arnTraffic.setValue( trafficIn + trafficOut);
230  _arnTrafficIn.setValue( trafficIn);
231  _arnTrafficOut.setValue( trafficOut);
232  }
233  }
234 
235  ++_pollCount;
236 }
237 
238 
239 void ArnServerRemoteSession::doChatAdd( const QString& txt)
240 {
241  if (_sessionPath.isNull()) return; // Retired
242 
243  _arnServerSession->sendMessage( ArnSync::MessageType::ChatNormal, txt.toUtf8());
244 }
245 
246 
247 void ArnServerRemoteSession::onMessageReceived( int type, const QByteArray& data)
248 {
249  if (_sessionPath.isNull()) return; // Retired
250 
251  // XStringMap xmIn( data);
252  Arn::Allow allow = _arnServerSession->getAllow();
253  QString txt;
254 
255  switch (type) {
257  case ArnSync::MessageType::KillRequest:
258  // Not valid for server
259  break;
260  case ArnSync::MessageType::AbortKillRequest:
261  if (allow.isAny( allow.ReadWrite) && (_arnKill.toInt() != KillMode::Off)) {
262  txt = "Arn Connection kill Abort request from client";
263  _arnChatPv = txt;
264  _arnChatAllPv = _sessionValue + ": " + txt;
265  _arnKill = KillMode::Off;
266  }
267  break;
268  case ArnSync::MessageType::ChatPrio:
269  // Fall throu
270  case ArnSync::MessageType::ChatNormal:
271  if (allow.isAny( allow.ReadWrite)) {
272  _arnChatPv = "Client ==>" + QString::fromUtf8( data.constData(), data.size());
273  _arnChatAllPv = _sessionValue + " ==>" + QString::fromUtf8( data.constData(), data.size());
274  }
275  break;
276  default:;
277  // Not supported message-type.
278  }
279 }
280 
281 
282 void ArnServerRemoteSession::shutdown()
283 {
284  ArnM::destroyLink( _sessionPath);
285  _sessionPath = QString(); // Mark retired
286  deleteLater();
287 }
288 
289 
290 
291 ArnServerRemotePrivate::ArnServerRemotePrivate()
292 {
293  _arnServer = arnNullptr;
294  _sessionCount = 0;
295  _sessionNum = 0;
296 }
297 
298 
299 ArnServerRemotePrivate::~ArnServerRemotePrivate()
300 {
301 }
302 
303 
304 
305 void ArnServerRemote::init()
306 {
307 }
308 
309 
311  : QObject( parent)
312  , d_ptr( new ArnServerRemotePrivate)
313 {
314  init();
315 }
316 
317 
318 ArnServerRemote::ArnServerRemote( ArnServerRemotePrivate& dd, QObject* parent)
319  : QObject( parent)
320  , d_ptr( &dd)
321 {
322  init();
323 }
324 
325 
327 {
328  delete d_ptr;
329 }
330 
331 
333 {
334  Q_D(ArnServerRemote);
335 
336  if (!arnServer) return;
337 
338  d->_arnServer = arnServer;
339  connect( arnServer, SIGNAL(newSession()), this, SLOT(onNewSession()));
340 
341  d->_timerPoll.start(5000);
342  connect( &d->_timerPoll, SIGNAL(timeout()), this, SLOT(doPoll()));
343 
344  d->_startTime = QDateTime::currentDateTimeUtc();
345  d->_arnUpTime.open( Arn::pathServer + "ServerUpTime/value");
346  d->_arnSessionCount.open( Arn::pathServer + "SessionCount/value");
347  d->_arnSessionNum.open( Arn::pathServer + "SessionNum/value");
348  ArnM::setValue( Arn::pathServer + "ServerUpTime/property", "prec=2 unit=h");
349 }
350 
351 
352 void ArnServerRemote::onNewSession()
353 {
354  Q_D(ArnServerRemote);
355 
356  ++d->_sessionCount;
357  d->_arnSessionCount = d->_sessionCount;
358  ++d->_sessionNum;
359  d->_arnSessionNum = d->_sessionNum;
360 
361  Q_ASSERT(d->_arnServer);
362  ArnServerSession* serverSession = d->_arnServer->getSession();
363  new ArnServerRemoteSession( serverSession, this);
364 
365  connect( serverSession, SIGNAL(destroyed(QObject*)), SLOT(onDelSession(QObject*)));
366 }
367 
368 
369 void ArnServerRemote::onDelSession( QObject* sessionObj)
370 {
371  Q_UNUSED(sessionObj)
372 
373  Q_D(ArnServerRemote);
374 
375  --d->_sessionNum;
376  d->_arnSessionNum = d->_sessionNum;
377 }
378 
379 
380 void ArnServerRemote::doPoll()
381 {
382  Q_D(ArnServerRemote);
383 
384  ARNREAL upTime = ARNREAL( d->_startTime.secsTo( QDateTime::currentDateTimeUtc())) / 3600.;
385  d->_arnUpTime.setValue( upTime);
386 }
void setValue(const ArnBasicItem &other, int ignoreSame=Arn::SameValue::DefaultAction)
static void setValue(const QString &path, int value)
Assign an integer to an Arn Data Object at path
Definition: ArnM.cpp:473
Arn::XStringMap remoteWhoIAm() const
Definition: ArnServer.cpp:137
QTcpSocket * socket() const
Definition: ArnServer.cpp:131
bool open(const QString &path)
Open a handle to an Arn Data Object
Class for making an Arn Server.
Definition: ArnServer.hpp:98
ArnItem & setPipeMode()
Set general mode as Pipe for this Arn Data Object
Definition: ArnItem.hpp:211
Container class with string representation for serialized data.
Definition: XStringMap.hpp:107
const QString pathServer
Definition: Arn.cpp:50
bool getTraffic(quint64 &in, quint64 &out) const
Definition: ArnServer.cpp:169
ArnServerRemoteSession(ArnServerSession *arnServerSession, ArnServerRemote *arnServerRemote)
QByteArray value(int i, const char *def=arnNullptr) const
bool open(const QString &path)
Open a handle to an Arn Data Object
Definition: ArnItemB.cpp:91
void startUseServer(ArnServer *arnServer)
Start making remote control objects for the ArnServer.
#define ARNREAL
Definition: Arn.hpp:44
ArnServerRemoteSessionKillMode KillMode
QString valueString(int i, const QString &def=QString()) const
QByteArray key(int i, const char *def=arnNullptr) const
Class for remote controlling an Arn Server.
const QString pathServerSessions
Definition: Arn.cpp:51
QString loginUserName() const
Definition: ArnServer.cpp:145
Convenience, allow read & write.
Definition: Arn.hpp:224
static void destroyLink(const QString &path, bool isGlobal=true)
Destroy the Arn Data Object at path
Definition: ArnM.cpp:853
int toInt(bool *isOk=arnNullptr) const
Definition: ArnItem.hpp:352
void sendMessage(int type, const QByteArray &data=QByteArray())
Definition: ArnServer.cpp:161
int size() const
Definition: XStringMap.hpp:121
ArnServerRemote(QObject *parent=arnNullptr)
Arn::Allow getAllow() const
Definition: ArnServer.cpp:153