Implement basic SSL client and server sockets

This commit is contained in:
Janek Bevendorff 2017-02-15 21:48:13 +01:00
parent 5274826e5c
commit 9d5d3081dc
9 changed files with 76 additions and 13 deletions

View File

@ -78,6 +78,9 @@ public:
if ( isocket.ibackendType == ETcpSocket ) { if ( isocket.ibackendType == ETcpSocket ) {
initTcpSocket(); initTcpSocket();
} else if ( isocket.ibackendType == ESslSocket ) {
initSslSocket();
} else if ( isocket.ibackendType == ELocalSocket ) { } else if ( isocket.ibackendType == ELocalSocket ) {
initLocalSocket(); initLocalSocket();
} }
@ -86,7 +89,7 @@ public:
public: public:
int messageBegin(http_parser* parser); int messageBegin(http_parser* parser);
int url(http_parser*, const char*, size_t) { int url(http_parser*, const char*, size_t) {
return 0; // not used in parsing incoming respone. return 0; // not used in parsing incoming response.
} }
int status(http_parser* parser, const char* at, size_t length) ; int status(http_parser* parser, const char* at, size_t length) ;
int headerField(http_parser* parser, const char* at, size_t length); int headerField(http_parser* parser, const char* at, size_t length);
@ -152,6 +155,31 @@ private:
); );
} }
void initSslSocket() {
QSslSocket* sok = new QSslSocket(q_func());
isocket.itcpSocket = sok;
QObject::connect(
sok, &QSslSocket::encrypted,
[this](){ onConnected(); }
);
QObject::connect(
sok, &QSslSocket::readyRead,
[this](){ onReadyRead(); }
);
QObject::connect(
sok, &QSslSocket::bytesWritten,
[this](qint64){
const auto& ts = isocket.itcpSocket;
if ( ts->bytesToWrite() == 0 && ilastRequest )
emit ilastRequest->allBytesWritten();
});
QObject::connect(
sok, &QSslSocket::disconnected,
q_func(), &QHttpClient::disconnected
);
}
void initLocalSocket() { void initLocalSocket() {
QLocalSocket* sok = new QLocalSocket(q_func()); QLocalSocket* sok = new QLocalSocket(q_func());
isocket.ilocalSocket = sok; isocket.ilocalSocket = sok;

View File

@ -70,7 +70,7 @@ public:
void initialize(TBackend backend, QHttpServer* parent) { void initialize(TBackend backend, QHttpServer* parent) {
ibackend = backend; ibackend = backend;
if ( ibackend == ETcpSocket ) { if ( ibackend == ETcpSocket || ibackend == ESslSocket ) {
itcpServer.reset( new BackendServer<QTcpServer>(parent) ); itcpServer.reset( new BackendServer<QTcpServer>(parent) );
ilocalServer.reset( nullptr ); ilocalServer.reset( nullptr );

View File

@ -50,6 +50,9 @@ public:
if ( bend == ETcpSocket ) { if ( bend == ETcpSocket ) {
initTcpSocket(sokDesc); initTcpSocket(sokDesc);
} else if ( bend == ESslSocket) {
initSslSocket(sokDesc);
} else if ( bend == ELocalSocket ) { } else if ( bend == ELocalSocket ) {
initLocalSocket(sokDesc); initLocalSocket(sokDesc);
} }
@ -131,6 +134,29 @@ private:
); );
} }
void initSslSocket(qintptr sokDesc) {
QSslSocket* sok = new QSslSocket( q_func() );
isocket.itcpSocket = sok;
sok->setSocketDescriptor(sokDesc);
QObject::connect(
sok, &QSslSocket::readyRead,
[this](){ onReadyRead(); }
);
QObject::connect(
sok, &QSslSocket::bytesWritten,
[this](){
auto btw = isocket.itcpSocket->bytesToWrite();
if ( btw == 0 && ilastResponse )
emit ilastResponse->allBytesWritten();
});
QObject::connect(
sok, &QSslSocket::disconnected,
q_func(), &QHttpConnection::disconnected,
Qt::QueuedConnection
);
}
void initLocalSocket(qintptr sokDesc) { void initLocalSocket(qintptr sokDesc) {
QLocalSocket* sok = new QLocalSocket( q_func() ); QLocalSocket* sok = new QLocalSocket( q_func() );
isocket.ilocalSocket = sok; isocket.ilocalSocket = sok;

View File

@ -13,6 +13,7 @@
#include "qhttpfwd.hpp" #include "qhttpfwd.hpp"
#include <QTcpSocket> #include <QTcpSocket>
#include <QSslSocket>
#include <QLocalSocket> #include <QLocalSocket>
#include <QUrl> #include <QUrl>
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
@ -73,8 +74,12 @@ public:
} }
void connectTo(const QString& host, quint16 port) { void connectTo(const QString& host, quint16 port) {
if ( itcpSocket ) if ( itcpSocket ) {
itcpSocket->connectToHost(host, port); if ( ibackendType == ESslSocket )
static_cast<QSslSocket*>(itcpSocket)->connectToHostEncrypted(host, port);
else
itcpSocket->connectToHost(host, port);
}
} }
qint64 readRaw(char* buffer, int maxlen) { qint64 readRaw(char* buffer, int maxlen) {
@ -88,8 +93,9 @@ public:
} }
void writeRaw(const QByteArray& data) { void writeRaw(const QByteArray& data) {
if ( itcpSocket ) if ( itcpSocket ) {
itcpSocket->write(data); itcpSocket->write(data);
}
else if ( ilocalSocket ) else if ( ilocalSocket )
ilocalSocket->write(data); ilocalSocket->write(data);

View File

@ -127,7 +127,9 @@ QHttpClient::request(THttpMethod method, QUrl url,
d->isocket.connectTo(url); d->isocket.connectTo(url);
} else { } else {
d->isocket.ibackendType = ETcpSocket; bool ssl = url.scheme() == "https";
d->isocket.ibackendType = ssl ? ESslSocket : ETcpSocket;
d->initializeSocket(); d->initializeSocket();
requestCreator(); requestCreator();
@ -135,7 +137,7 @@ QHttpClient::request(THttpMethod method, QUrl url,
if ( d->isocket.isOpen() ) if ( d->isocket.isOpen() )
d->onConnected(); d->onConnected();
else else
d->isocket.connectTo(url.host(), url.port(80)); d->isocket.connectTo(url.host(), url.port(ssl ? 443 : 80));
} }
return true; return true;

View File

@ -13,6 +13,7 @@
#include "qhttpfwd.hpp" #include "qhttpfwd.hpp"
#include <QTcpSocket> #include <QTcpSocket>
#include <QSslSocket>
#include <QUrl> #include <QUrl>
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////

View File

@ -151,7 +151,7 @@ enum TStatusCode {
/** The backend of QHttp library. */ /** The backend of QHttp library. */
enum TBackend { enum TBackend {
ETcpSocket = 0, ///< client / server work on top of TCP/IP stack. (default) ETcpSocket = 0, ///< client / server work on top of TCP/IP stack. (default)
ESslSocket = 1, ///< client / server work on SSL/TLS tcp stack. (not implemented yet) ESslSocket = 1, ///< client / server work on SSL/TLS tcp stack.
ELocalSocket = 2 ///< client / server work on local socket (unix socket). ELocalSocket = 2 ///< client / server work on local socket (unix socket).
}; };

View File

@ -35,7 +35,7 @@ bool
QHttpServer::listen(const QHostAddress& address, quint16 port, const qhttp::server::TServerHandler& handler) { QHttpServer::listen(const QHostAddress& address, quint16 port, const qhttp::server::TServerHandler& handler) {
Q_D(QHttpServer); Q_D(QHttpServer);
d->initialize(ETcpSocket, this); d->initialize(d->ibackend, this);
d->ihandler = handler; d->ihandler = handler;
return d->itcpServer->listen(address, port); return d->itcpServer->listen(address, port);
} }
@ -44,10 +44,10 @@ bool
QHttpServer::isListening() const { QHttpServer::isListening() const {
const Q_D(QHttpServer); const Q_D(QHttpServer);
if ( d->ibackend == ETcpSocket && d->itcpServer ) if ( ( d->ibackend == ETcpSocket || d->ibackend == ESslSocket ) && d->itcpServer )
return d->itcpServer->isListening(); return d->itcpServer->isListening();
else if ( d->ibackend == ELocalSocket && d->ilocalServer ) else if ( d->ibackend == ELocalSocket && d->ilocalServer )
return d->ilocalServer->isListening(); return d->ilocalServer->isListening();
return false; return false;

View File

@ -147,7 +147,7 @@ QHttpConnectionPrivate::headersComplete(http_parser* parser) {
); );
// set client information // set client information
if ( isocket.ibackendType == ETcpSocket ) { if ( isocket.ibackendType == ETcpSocket || isocket.ibackendType == ESslSocket ) {
ilastRequest->d_func()->iremoteAddress = isocket.itcpSocket->peerAddress().toString(); ilastRequest->d_func()->iremoteAddress = isocket.itcpSocket->peerAddress().toString();
ilastRequest->d_func()->iremotePort = isocket.itcpSocket->peerPort(); ilastRequest->d_func()->iremotePort = isocket.itcpSocket->peerPort();