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 ) {
initTcpSocket();
} else if ( isocket.ibackendType == ESslSocket ) {
initSslSocket();
} else if ( isocket.ibackendType == ELocalSocket ) {
initLocalSocket();
}
@ -86,7 +89,7 @@ public:
public:
int messageBegin(http_parser* parser);
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 headerField(http_parser* parser, const char* at, size_t length);
@ -112,7 +115,7 @@ protected:
while ( isocket.bytesAvailable() > 0 ) {
char buffer[4097] = {0};
size_t readLength = (size_t) isocket.readRaw(buffer, 4096);
parse(buffer, readLength);
}
}
@ -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() {
QLocalSocket* sok = new QLocalSocket(q_func());
isocket.ilocalSocket = sok;

View File

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

View File

@ -49,6 +49,9 @@ public:
if ( bend == ETcpSocket ) {
initTcpSocket(sokDesc);
} else if ( bend == ESslSocket) {
initSslSocket(sokDesc);
} else if ( bend == ELocalSocket ) {
initLocalSocket(sokDesc);
@ -130,6 +133,29 @@ private:
Qt::QueuedConnection
);
}
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) {
QLocalSocket* sok = new QLocalSocket( q_func() );

View File

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

View File

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

View File

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

View File

@ -151,7 +151,7 @@ enum TStatusCode {
/** The backend of QHttp library. */
enum TBackend {
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).
};

View File

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

View File

@ -147,7 +147,7 @@ QHttpConnectionPrivate::headersComplete(http_parser* parser) {
);
// 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()->iremotePort = isocket.itcpSocket->peerPort();