Pong

June 9th 2014, SSL Server /w QTcpServer

June 8th 2014 QSslSocket | | June 9th 2014 SSL Client with QSslSocket

The key component of the QTcpServer class is the incomingConnection() method. The default implementation creates a new QTcpSocket, attaches the socket to the actual incoming connection and puts it into a queue, where it is waiting to be handled by the nextConnection() call.

The default implementation obviously cannot be reused for secure connections, since it is hardwired to standard unencrypted sockets.

In order to use SSL encryption we overwrite the standard implementation of incomingConnection(), so that the standard socket queue is just not used. Instead we create and attach a new SSL socket for each incoming connection like so:

class SSLServer: public QTcpServer
{
   Q_OBJECT

public:

   SSLServer(QObject *parent = NULL) : QTcpServer(parent) {}
   virtual ~SSLServer() {}

   // start listening
   void start(QString certPath, QString keyPath, quint16 port = 0);
   {
      certPath_ = certPath;
      keyPath_ = keyPath;

      listen(QHostAddress::Any, port);
   }

protected:

   // handle new incoming connection
   virtual void incomingConnection(int socketDescriptor)
   {
      // create new ssl server connection for each incoming connection
      SSLServerConnection *connection =
         new SSLServerConnection(socketDescriptor, certPath_, keyPath_, this);

      // initiate handshake
      connection->handshake();
   }

   QString certPath_;
   QString keyPath_;
};

class SSLServerConnection: public QObject
{
   Q_OBJECT

public:

   SSLServerConnection(int socketDescriptor,
                       QString certPath, QString keyPath,
                       QObject *parent = NULL)
      : QObject(parent)
   {
      // create new ssl socket for each incoming connection
      socket_ = new QSslSocket(this);
      socket_->setSocketDescriptor(socketDescriptor);

      // configure ssl socket
      socket_->setProtocol(QSsl::TlsV1);
      socket_->setLocalCertificate(certPath);
      socket_->setPrivateKey(keyPath);

      // start reading from an established connection
      connect(socket_, SIGNAL(readyRead()),
              this, SLOT(startReading()));

      // self-termination after socket has disconnected
      connect(socket_, SIGNAL(disconnected()),
              this, SLOT(deleteLater()));
   }

   virtual ~SSLServerConnection()
   {
      delete socket_;
   }

   // start ssl handshake
   void handshake()
   {
      socket_->startServerEncryption();
   }

protected:

   QSslSocket *socket_;

protected slots:

   // start reading after connection is established
   void startReading()
   {
      // read data from the ssl socket
      QByteArray data = socket_->readAll();

      // test output
      std::cout << QString(data).toStdString() << std::endl;
   }

};

The server requires an event loop to be running. Each new SSL connection automatically destroys itself after being disconnected. This is achieved by connecting the disconnect() signal of the socket to the deleteLater() signal of the connection.

Thinking about a threaded server, the answer is simply that threads won’t speed things up, as long as the server is just busy waiting for connections and copying data chunks around. It might be worthwhile, if the server had a higher work load, but even compression is not adding to the work load, since the server does not have to compress data, only the client. For a threaded version of the client read below.

June 8th 2014 QSslSocket | | June 9th 2014 SSL Client with QSslSocket

Options: