Remoto - VFS: VFS_tcp_client.cpp Source File
Remoto - VFS
VFS_tcp_client.cpp
Go to the documentation of this file.
1 
2 #include <arpa/inet.h>
3 
4 #include <QJsonDocument>
5 #include <QJsonObject>
6 #include <QFile>
7 
8 #include "VFS.h"
9 #include "VFS_tcp_client.h"
10 
27 VFS_tcp_client::VFS_tcp_client(QTcpSocket *socket, bool ssl, QString sslCertPath)
28 : VFS_node()
29 , _socket(socket)
30 , _messageSize(0)
31 , _initialized(false)
32 , _ssl(ssl)
33 , _sslCertPath(sslCertPath)
34 {
35  _address = _socket->peerAddress().toString();
36  _port = _socket->peerPort();
37 
38  //connect(VFS::root(),SIGNAL(initialized()),this,SLOT(init()));
39  connect(this,SIGNAL(mounted()),this,SLOT(init()));
40  connect(this,SIGNAL(unmounted(VFS_node*)),this,SLOT(close()));
41 
42  if (_ssl)
43  {
44  //printf("SSL socket!\n");
45  QSslSocket *_sslSocket = dynamic_cast<QSslSocket *> (_socket);
46 
47  //add certificates
48  QList<QSslCertificate> certs = QSslCertificate::fromPath(_sslCertPath, QSsl::Pem);
49  if (!certs.length())
50  VFS::WARN(QString("Failed to add '%1' as a cert. Is the format or path bad?").arg(_sslCertPath),0,className());
51  //else
52  // VFS::LOG( QString("Using cert file: '%1'").arg(_sslCertPath), 9, className() );
53 
54  QSslConfiguration sslConfiguration;
55  sslConfiguration.addCaCertificates(certs);
56  _sslSocket->setSslConfiguration(sslConfiguration);
57 
58  //peer verify
59  connect(_sslSocket, SIGNAL(peerVerifyError(QSslError)), this, SLOT(peerVerifyError(QSslError)));
60 
61  //sslErrors
62  connect(_sslSocket, SIGNAL(sslErrors(QList<QSslError>)), this, SLOT(sslErrors(QList<QSslError>)));
63 
64  //mode change
65  connect(_sslSocket, SIGNAL(modeChanged(QSslSocket::SslMode)), this, SLOT(modeChanged(QSslSocket::SslMode)));
66 
67  //encrypted
68  connect(_sslSocket, SIGNAL(encrypted()), this, SLOT(sslReady()));
69  }
70 }
71 
82 VFS_tcp_client::VFS_tcp_client(QString address, quint16 port, bool ssl, QString sslCertPath)
83 : VFS_node()
84 , _socket(nullptr)
85 , _messageSize(0)
86 , _initialized(false)
87 , _address(address)
88 , _port(port)
89 , _ssl(ssl)
90 , _sslCertPath(sslCertPath)
91 {
92  if (_ssl)
93  _socket = new QSslSocket(this);
94  else
95  _socket = new QTcpSocket(this);
96 
97  connect(VFS::root(),SIGNAL(initialized()),this,SLOT(init()));
98  connect(this,SIGNAL(mounted()),this,SLOT(init()));
99  connect(this,SIGNAL(unmounted(VFS_node*)),this,SLOT(close()));
100 
101  if (_ssl)
102  {
103  //printf("SSL socket!\n");
104  QSslSocket *_sslSocket = dynamic_cast<QSslSocket *> (_socket);
105 
106  //add certificates
107  QList<QSslCertificate> certs = QSslCertificate::fromPath(_sslCertPath, QSsl::Pem);
108  if (!certs.length())
109  VFS::WARN(QString("Failed to add '%1' as a cert. Is the format or path bad?").arg(_sslCertPath),0,className());
110  //else
111  // VFS::LOG( QString("Using cert file: '%1'").arg(_sslCertPath), 9, className() );
112 
113  QSslConfiguration sslConfiguration;
114  sslConfiguration.addCaCertificates(certs);
115  _sslSocket->setSslConfiguration(sslConfiguration);
116 
117  //peer verify
118  connect(_sslSocket, SIGNAL(peerVerifyError(QSslError)), this, SLOT(peerVerifyError(QSslError)));
119 
120  //sslErrors
121  connect(_sslSocket, SIGNAL(sslErrors(QList<QSslError>)), this, SLOT(sslErrors(QList<QSslError>)));
122 
123  //mode change
124  connect(_sslSocket, SIGNAL(modeChanged(QSslSocket::SslMode)), this, SLOT(modeChanged(QSslSocket::SslMode)));
125 
126  //encrypted
127  connect(_sslSocket, SIGNAL(encrypted()), this, SLOT(sslReady()));
128 
129  //check for encrypted
130  //connect(_sslSocket, SIGNAL(connected()), this, SLOT(initSSL()));
131  }
132 }
133 
134 
144 VFS_tcp_client::VFS_tcp_client(QTcpSocket *socket, bool ssl, QSslConfiguration sslConfiguration)
145 : VFS_node()
146 , _socket(socket)
147 , _messageSize(0)
148 , _initialized(false)
149 , _ssl(ssl)
150 {
151  _address = _socket->peerAddress().toString();
152  _port = _socket->peerPort();
153 
154  //connect(VFS::root(),SIGNAL(initialized()),this,SLOT(init()));
155  connect(this,SIGNAL(mounted()),this,SLOT(init()));
156  connect(this,SIGNAL(unmounted(VFS_node*)),this,SLOT(close()));
157 
158  if (_ssl)
159  {
160  //printf("SSL socket!\n");
161  QSslSocket *_sslSocket = dynamic_cast<QSslSocket *> (_socket);
162 
163  //add configuration
164  _sslSocket->setSslConfiguration(sslConfiguration);
165 
166  //peer verify
167  connect(_sslSocket, SIGNAL(peerVerifyError(QSslError)), this, SLOT(peerVerifyError(QSslError)));
168 
169  //sslErrors
170  connect(_sslSocket, SIGNAL(sslErrors(QList<QSslError>)), this, SLOT(sslErrors(QList<QSslError>)));
171 
172  //mode change
173  connect(_sslSocket, SIGNAL(modeChanged(QSslSocket::SslMode)), this, SLOT(modeChanged(QSslSocket::SslMode)));
174 
175  //encrypted
176  connect(_sslSocket, SIGNAL(encrypted()), this, SLOT(sslReady()));
177 
178  //check for encrypted
179  //connect(_sslSocket, SIGNAL(connected()), this, SLOT(initSSL()));
180  }
181 }
182 
183 
185 {
186  close();
187 
188  _socket->deleteLater();
189 }
190 
191 
197 {
198  if (_initialized)
199  return;
200 
201  //printf("TCP_CLIENT INIT\n");
202 
203  connect( _socket, SIGNAL( connected() ),
204  this, SLOT( initSSL() ) );
205 
206  //connect( _socket, SIGNAL( modeChanged(QSslSocket::SslMode)),
207  // this, SLOT( modeChanged(QSslSocket::SslMode)) );
208 
209  connect( _socket, SIGNAL( disconnected() ),
210  this, SIGNAL( disconnected() ) );
211 
212  connect( _socket, SIGNAL( readyRead() ),
213  this, SLOT( readyRead() ) );
214 
215  connect( this, SIGNAL( moreToRead() ),
216  this, SLOT( readyRead() ) );
217 
218  connect( _socket, SIGNAL( error(QAbstractSocket::SocketError) ),
219  this, SIGNAL( error(QAbstractSocket::SocketError) ) );
220 
221  //initSSL();
222 
223  _initialized = true;
224 }
225 
231 {
232  //printf("INIT SSL!\n");
233  //return;
234 
235  if (_ssl)
236  {
237  QSslSocket *_sslSocket = dynamic_cast<QSslSocket *> (_socket);
238  if (!_sslSocket->isEncrypted())
239  {
240  QString cn = className();
241 
242  if (!_sslSocket->waitForEncrypted(500))
243  {
244  //if the socket closes and the destructor is called, className() is no longer available, so we save it ahead of time.
245  VFS::WARN( QString("SSL socket is not in encrypted state. You may need to enable SSL on the remote side. Closing socket. (%1:%2)").arg(_address).arg(_port),0,cn);
246 
247  //sometimes sockets are closed twice, depending on destructor sequence.
248  if (!__isNode(this))
249  return;
250 
251  //this will also be invalid after the destructor
252  close();
253  //deleteLater();
254  //emit finished(false);
255 
256  return;
257  }
258  //else
259  // VFS::LOG("SSL socket is now in encrypted state.",9,className());
260  }
261  }
262 
263  emit connected();
264 }
265 
266 
272 {
273  _socket->close();
274 }
275 
276 
282 {
283  if (_messageSize == 0)
284  {
285  if ( _socket->bytesAvailable() >= (qint64) sizeof(MESSAGE_SIZE) )
286  {
287  MESSAGE_SIZE m;
288  _socket->read((char*)&m,sizeof(MESSAGE_SIZE));
289  _messageSize = ntohl(m);
290 
291  //printf("RECEIVE MESSAGE SIZE: %d\n",_messageSize);
292 
294  {
295  //FIXME
296  VFS::ERROR( QString("%1 message size of %2 was too big. Wierd stuff is going to happen.").arg(className()).arg(_messageSize) );
297  _messageSize = 0;
298  return;
299  }
300  }
301  else
302  return;
303  }
304 
305  if (_socket->bytesAvailable() >= _messageSize)
306  {
307  QByteArray message = _socket->read(_messageSize);
308 
309  if (message.length() == 0)
310  {
311  VFS::ERROR( QString("%1 message was empty. It should be %2. Check for errors.").arg(className()).arg(_messageSize) );
312  }
313 
314  _messageSize = 0;
315  emit readyMessage(message);
316  }
317  else
318  return;
319 
320  //allow multiple messages coming in together to process...
321  if (_socket->bytesAvailable() > 0)
322  emit moreToRead();
323 }
324 
325 
331 void VFS_tcp_client::writeMessage(QByteArray data)
332 {
333  MESSAGE_SIZE s = data.size();
334  MESSAGE_SIZE n = htonl(s);
335 
336  //printf("SEND MESSAGE SIZE: %d %d %d\n",data.length(),s,n);
337 
338  _socket->write((char*)&n,sizeof(MESSAGE_SIZE));
339  _socket->write(data);
340 }
341 
342 
349 {
350  Q_UNUSED(r);
351 
352  printf("about to write..\n");
353  printf("socket parent: %p\n",_socket->thread());
354 
355  printf("FIXME: VFS_tcp_client::write needs to be defined!");
356  //_socket->write(r->_data.toJson());
357 
358  printf("wrote...\n");
359 }
360 
361 
368 {
369  return false;
370 }
371 
372 
379 {
380  return QString("%1:%2 (%3)").arg(_address).arg(_port).arg(_ssl?"secure":"insecure");
381 }
382 
383 
390 {
391  Q_UNUSED(error)
392 
393  //A peer verify error is also an SSL error, so no need to print twice
394  //VFS::ERROR(QString("Peer verify error: %1").arg(error.errorString()),0,className());
395 }
396 
397 
403 void VFS_tcp_client::sslErrors(const QList<QSslError> &errors)
404 {
405  for (int i=0;i<errors.length();i++)
406  VFS::ERROR(QString("SSL error: %1").arg(errors[i].errorString()),0,className());
407 }
408 
416 void VFS_tcp_client::modeChanged(QSslSocket::SslMode mode)
417 {
418  Q_UNUSED(mode);
419 
420  //VFS::WARN( QString("SOCKET MODE IS NOW: %1").arg(mode), 0, this->metaObject()->className() );
421 }
422 
430 {
431  VFS::LOG( "SSL handshake complete.", 9, this->metaObject()->className() );
432 }
quint32 MESSAGE_SIZE
#define MAX_MESSAGE_SIZE
VFS_node is the base class from which all other VFS_node classes derive.
Definition: VFS_node.h:143
static bool __isNode(VFS_node *)
Check to see if a node is in the global registry.
Definition: VFS_node.cpp:588
void mounted()
Emitted when a node is mount()ed.
void unmounted(VFS_node *self)
Emitted when a node is unmount()ed.
QString className()
Return the class name of a node.
Definition: VFS_node.cpp:2039
The base class for all requests between nodes.
Definition: VFS_node.h:54
void error(QAbstractSocket::SocketError)
Emitted when a socket error occurs.
void connected()
Emitted when a connection has been made.
QString _address
The address resolved by peerAddress(), or the address to connect to.
MESSAGE_SIZE _messageSize
The message size received. Will wait for this many bytes before emitting messageReady.
void readyRead()
DOCME.
void sslErrors(const QList< QSslError > &errors)
VFS_tcp_client::sslErrors.
void initSSL()
DOCME.
void sslReady()
Signal that an SSL connnection has been established.
QTcpSocket * _socket
The socket connection.
VFS_tcp_client(QTcpSocket *socket, bool ssl=false, QSslConfiguration sslConfiguration=QSslConfiguration())
VFS_tcp_client constructor for client mode.
virtual QString reportDetails()
Report data about this client.
void readyMessage(QByteArray message)
Emitted when a message is ready for processing.
virtual bool isContainer()
DOCME.
bool _initialized
Has this node been initialized?
void peerVerifyError(const QSslError &error)
VFS_tcp_client::peerVerifyError.
virtual void init()
DOCME.
virtual void close()
DOCME.
quint16 _port
The port to connect to.
QString _sslCertPath
ssl cert file path.
virtual void write(VFS_request *r)
DOCME.
bool _ssl
Use ssl?
virtual void writeMessage(QByteArray data)
DOCME.
void modeChanged(QSslSocket::SslMode mode)
A slot for when the SSL mode has changed.
void disconnected()
Emitted when a connection has been lost.
void moreToRead()
Emitted when an incoming message has additional data.
virtual ~VFS_tcp_client()
static VFS * root()
Return the root node of the VFS filesystem.
Definition: VFS.cpp:399
static void LOG(QString message, int level=0, QString user="server")
Send a message to the VFS::_messages VFS_stream.
Definition: VFS.cpp:209
static void ERROR(QString message, int level=0, QString user="server")
Send a message to the VFS::_errors VFS_stream.
Definition: VFS.cpp:307
static void WARN(QString message, int level=0, QString user="server")
Send a message to the VFS::_warnings VFS_stream.
Definition: VFS.cpp:258
setter error
Set the error value of this widget.