Skip to content
This repository was archived by the owner on Oct 25, 2021. It is now read-only.

Commit 1ee7d21

Browse files
committedAug 20, 2013
client implementation improved, so much optimisations
1 parent 20c5550 commit 1ee7d21

File tree

6 files changed

+221
-203
lines changed

6 files changed

+221
-203
lines changed
 

‎Example/Client/Client.cpp

+2-4
Original file line numberDiff line numberDiff line change
@@ -59,17 +59,15 @@ void Client::displayMessage(QString message)
5959
void Client::connectSocket()
6060
{
6161
bool ok;
62-
//QString ipAddress = QInputDialog::getText(this, tr("Client"), tr("Server IP:"), QLineEdit::Normal, "127.0.0.1:1337", &ok);
6362
//QString ipAddress = QInputDialog::getText(this, tr("Client"), tr("Server IP:"), QLineEdit::Normal, "ws://127.0.0.1:1337", &ok);
64-
//QString ipAddress = QInputDialog::getText(this, tr("Client"), tr("Server IP:"), QLineEdit::Normal, "localhost:1337", &ok);
6563
QString ipAddress = QInputDialog::getText(this, tr("Client"), tr("Server IP:"), QLineEdit::Normal, "ws://localhost:1337", &ok);
66-
//QString ipAddress = QInputDialog::getText(this, tr("Client"), tr("Server IP:"), QLineEdit::Normal, "echo.websocket.org:80", &ok);
6764
//QString ipAddress = QInputDialog::getText(this, tr("Client"), tr("Server IP:"), QLineEdit::Normal, "ws://echo.websocket.org:80", &ok);
65+
ipAddress = ipAddress.trimmed();
6866
if (ok && !ipAddress.isEmpty())
6967
{
7068
QString ip;
7169
quint16 port;
72-
if (ipAddress.count(':') >= 1)
70+
if (ipAddress.contains(QRegExp(QLatin1String(":([0-9]|[1-9][0-9]{1,3}|[1-5][0-9]{1,4}|6[0-4][0-9]{3}|65[0-4][0-9]{2}|655[0-2][0-9]|6553[0-5])$"))))
7371
{
7472
QStringList splitted = ipAddress.split(':');
7573
port = splitted.takeLast().toUInt();

‎QtWebsocket.sln

+6
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,14 @@ EndProject
66
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Client", "Example\Client\Client.vcxproj", "{B12702AD-ABFB-343A-A199-8E24837244A3}"
77
EndProject
88
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Server", "Example\Server\Server.vcxproj", "{5C7FFE1F-B387-4A78-AEDF-41F84E9FAB45}"
9+
ProjectSection(ProjectDependencies) = postProject
10+
{7E3A920C-4257-41A1-B9B9-BFA138C1C8A2} = {7E3A920C-4257-41A1-B9B9-BFA138C1C8A2}
11+
EndProjectSection
912
EndProject
1013
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ServerThreaded", "Example\ServerThreaded\ServerThreaded.vcxproj", "{5B11012D-3641-4AD8-9B65-11EA72C458DD}"
14+
ProjectSection(ProjectDependencies) = postProject
15+
{7E3A920C-4257-41A1-B9B9-BFA138C1C8A2} = {7E3A920C-4257-41A1-B9B9-BFA138C1C8A2}
16+
EndProjectSection
1117
EndProject
1218
Global
1319
GlobalSection(SolutionConfigurationPlatforms) = preSolution

‎QtWebsocket/QWsServer.cpp

+126-126
Original file line numberDiff line numberDiff line change
@@ -23,17 +23,15 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
2323
#include <QCryptographicHash>
2424
#include <QDateTime>
2525

26-
const QString QWsServer::regExpResourceNameStr(QLatin1String("^GET\\s(.*)\\sHTTP/1.1\r\n"));
27-
const QString QWsServer::regExpHostStr(QLatin1String("\r\nHost:\\s(.+(:\\d+)?)\r\n"));
28-
const QString QWsServer::regExpKeyStr(QLatin1String("\r\nSec-WebSocket-Key:\\s(.{24})\r\n"));
29-
const QString QWsServer::regExpKey1Str(QLatin1String("\r\nSec-WebSocket-Key1:\\s(.+)\r\n"));
30-
const QString QWsServer::regExpKey2Str(QLatin1String("\r\nSec-WebSocket-Key2:\\s(.+)\r\n"));
31-
//const QString QWsServer::regExpKey3Str(QLatin1String("\r\n(.{8})$"));
32-
const QString QWsServer::regExpVersionStr(QLatin1String("\r\nSec-WebSocket-Version:\\s(\\d+)\r\n"));
33-
const QString QWsServer::regExpOriginStr(QLatin1String("\r\nSec-WebSocket-Origin:\\s(.+)\r\n"));
34-
const QString QWsServer::regExpOrigin2Str(QLatin1String("\r\nOrigin:\\s(.+)\r\n"));
35-
const QString QWsServer::regExpProtocolStr(QLatin1String("\r\nSec-WebSocket-Protocol:\\s(.+)\r\n"));
36-
const QString QWsServer::regExpExtensionsStr(QLatin1String("\r\nSec-WebSocket-Extensions:\\s(.+)\r\n"));
26+
QRegExp QWsServer::regExpHttpRequest(QLatin1String("^GET\\s(.*)\\sHTTP/1.1\\r\\n"));
27+
QRegExp QWsServer::regExpHost(QLatin1String("\\r\\nHost:\\s(([^:]+)(:([0-9]|[1-9][0-9]{1,3}|[1-5][0-9]{1,4}|6[0-4][0-9]{3}|65[0-4][0-9]{2}|655[0-2][0-9]|6553[0-5]))?)\\r\\n"));
28+
QRegExp QWsServer::regExpKey(QLatin1String("\\r\\nSec-WebSocket-Key:\\s(.{24})\\r\\n"));
29+
QRegExp QWsServer::regExpKey1(QLatin1String("\\r\\nSec-WebSocket-Key1:\\s(.+)\\r\\n"));
30+
QRegExp QWsServer::regExpKey2(QLatin1String("\\r\\nSec-WebSocket-Key2:\\s(.+)\\r\\n"));
31+
QRegExp QWsServer::regExpVersion(QLatin1String("\\r\\nSec-WebSocket-Version:\\s(\\d+)\\r\\n"));
32+
QRegExp QWsServer::regExpOrigin(QLatin1String("\\r\\n(Origin|Sec-WebSocket-Origin):\\s(.+)\\r\\n"));
33+
QRegExp QWsServer::regExpProtocol(QLatin1String("\\r\\nSec-WebSocket-Protocol:\\s(.+)\\r\\n"));
34+
QRegExp QWsServer::regExpExtensions(QLatin1String("\\r\\nSec-WebSocket-Extensions:\\s(.+)\\r\\n"));
3735

3836
QWsServer::QWsServer(QObject* parent)
3937
: QObject(parent)
@@ -140,103 +138,108 @@ void QWsServer::dataReceived()
140138
return;
141139
}
142140

143-
QRegExp regExp;
144-
regExp.setMinimal(true);
145-
146-
// Extract mandatory datas
141+
// Extract mandatory fields
142+
143+
bool missingField = false;
144+
145+
// HTTP REQUEST and Resource name
146+
regExpHttpRequest.setMinimal(true);
147+
if (regExpHttpRequest.indexIn(request) == -1)
148+
{
149+
missingField = true;
150+
}
151+
QString resourceName = regExpHttpRequest.cap(1);
152+
153+
// Host (address & port)
154+
regExpHost.setMinimal(true);
155+
if (regExpHost.indexIn(request) == -1)
156+
{
157+
missingField = true;
158+
}
159+
QString host = regExpHost.cap(1);
160+
QString hostAddress = regExpHost.cap(2);
161+
QString hostPort = regExpHost.cap(4);
162+
147163
// Version
148-
regExp.setPattern(QWsServer::regExpVersionStr);
149-
regExp.indexIn(request);
150-
QString versionStr = regExp.cap(1);
151164
QByteArray key3;
152165
EWebsocketVersion version;
153-
if (! versionStr.isEmpty())
154-
{
155-
version = (EWebsocketVersion)versionStr.toInt();
156-
}
157-
else if (tcpSocket->bytesAvailable() >= 8)
166+
regExpVersion.setMinimal(true);
167+
if (regExpVersion.indexIn(request) == -1)
158168
{
159-
version = WS_V0;
160-
key3 = tcpSocket->read(8);
161-
request.append(key3);
169+
if (tcpSocket->bytesAvailable() == 8)
170+
{
171+
version = WS_V0;
172+
key3 = tcpSocket->read(8);
173+
request += key3;
174+
}
175+
else
176+
{
177+
version = WS_VUnknow;
178+
}
162179
}
163180
else
164181
{
165-
version = WS_VUnknow;
182+
version = (EWebsocketVersion)regExpVersion.cap(1).toUInt();
166183
}
167184

168-
// Resource name
169-
regExp.setPattern(QWsServer::regExpResourceNameStr);
170-
regExp.indexIn(request);
171-
QString resourceName = regExp.cap(1);
172-
173-
// Host (address & port)
174-
regExp.setPattern(QWsServer::regExpHostStr);
175-
regExp.indexIn(request);
176-
QString host = regExp.cap(1);
177-
QStringList hostTmp = host.split(':');
178-
QString hostAddress = hostTmp[0];
179-
QString hostPort;
180-
if (hostTmp.size() > 1)
181-
{
182-
hostPort = hostTmp.last(); // fix for IPv6
183-
}
184-
185185
// Key
186-
QString key, key1, key2;
186+
QByteArray key, key1, key2;
187187
if (version >= WS_V4)
188188
{
189-
regExp.setPattern(QWsServer::regExpKeyStr);
190-
regExp.indexIn(request);
191-
key = regExp.cap(1);
189+
regExpKey.setMinimal(true);
190+
regExpKey.indexIn(request);
191+
key = regExpKey.cap(1).toUtf8();
192192
}
193193
else
194194
{
195-
regExp.setPattern(QWsServer::regExpKey1Str);
196-
regExp.indexIn(request);
197-
key1 = regExp.cap(1);
198-
regExp.setPattern(QWsServer::regExpKey2Str);
199-
regExp.indexIn(request);
200-
key2 = regExp.cap(1);
195+
regExpKey1.setMinimal(true);
196+
regExpKey1.indexIn(request);
197+
key1 = regExpKey1.cap(1).toLatin1();
198+
199+
regExpKey2.setMinimal(true);
200+
regExpKey2.indexIn(request);
201+
key2 = regExpKey2.cap(1).toLatin1();
201202
}
202203

203-
////////////////////////////////////////////////////////////////////
204+
////////////////////////////////////////////////////////////////
204205

205206
// If the mandatory fields are not specified, we abord the connection to the Websocket server
206-
if (version == WS_VUnknow || resourceName.isEmpty() || hostAddress.isEmpty() || (key.isEmpty() && (key1.isEmpty() || key2.isEmpty() || key3.isEmpty())))
207+
if ( missingField
208+
|| version == WS_VUnknow
209+
|| resourceName.isEmpty()
210+
|| hostAddress.isEmpty()
211+
|| ((key.isEmpty() && (key1.isEmpty() || key2.isEmpty() || key3.isEmpty()))) )
207212
{
208213
showErrorAndClose(tcpSocket);
209214
return;
210215
}
211216

212-
////////////////////////////////////////////////////////////////////
217+
////////////////////////////////////////////////////////////////
213218

214-
QObject::disconnect(tcpSocket, SIGNAL(disconnected()), this, SLOT(disconnected()));
215-
headerBuffer.remove(tcpSocket);
216-
217-
// Extract optional datas
219+
// Extract optional fields
218220

219221
// Origin
220-
regExp.setPattern(QWsServer::regExpOriginStr);
221-
if (regExp.indexIn(request) == -1)
222-
{
223-
regExp.setPattern(QWsServer::regExpOrigin2Str);
224-
regExp.indexIn(request);
225-
}
226-
QString origin = regExp.cap(1);
222+
regExpOrigin.setMinimal(true);
223+
regExpOrigin.indexIn(request);
224+
QString origin = regExpOrigin.cap(2);
227225

228226
// Protocol
229-
regExp.setPattern(QWsServer::regExpProtocolStr);
230-
regExp.indexIn(request);
231-
QString protocol = regExp.cap(1);
227+
regExpProtocol.setMinimal(true);
228+
regExpProtocol.indexIn(request);
229+
QString protocol = regExpProtocol.cap(1);
232230

233231
// Extensions
234-
regExp.setPattern(QWsServer::regExpExtensionsStr);
235-
regExp.indexIn(request);
236-
QString extensions = regExp.cap(1);
232+
regExpExtensions.setMinimal(true);
233+
regExpExtensions.indexIn(request);
234+
QString extensions = regExpExtensions.cap(1);
237235

238-
////////////////////////////////////////////////////////////////////
236+
////////////////////////////////////////////////////////////////
239237

238+
// Handshake fully parsed
239+
QObject::disconnect(tcpSocket, SIGNAL(readyRead()), this, SLOT(dataReceived()));
240+
QObject::disconnect(tcpSocket, SIGNAL(disconnected()), this, SLOT(disconnected()));
241+
headerBuffer.remove(tcpSocket);
242+
240243
// Compose opening handshake response
241244
QString response;
242245

@@ -257,9 +260,6 @@ void QWsServer::dataReceived()
257260
response = QWsServer::composeOpeningHandshakeResponseV0(accept, origin, hostAddress, hostPort, resourceName , protocol);
258261
}
259262

260-
// Handshake OK, disconnect readyRead
261-
QObject::disconnect(tcpSocket, SIGNAL(readyRead()), this, SLOT(dataReceived()));
262-
263263
// Send opening handshake response
264264
if (version == WS_V0)
265265
{
@@ -372,10 +372,10 @@ bool QWsServer::waitForNewConnection(int msec, bool* timedOut)
372372
return tcpServer->waitForNewConnection(msec, timedOut);
373373
}
374374

375-
QByteArray QWsServer::computeAcceptV0(QString key1, QString key2, QByteArray key3)
375+
QByteArray QWsServer::computeAcceptV0(QByteArray key1, QByteArray key2, QByteArray key3)
376376
{
377-
quint32 key_number_1 = QString(key1).remove(QRegExp("[^\\d]")).toUInt();
378-
quint32 key_number_2 = QString(key2).remove(QRegExp("[^\\d]")).toUInt();
377+
quint32 key_number_1 = QString::fromLatin1(key1).remove(QRegExp(QLatin1String("[^\\d]"))).toUInt();
378+
quint32 key_number_2 = QString::fromLatin1(key2).remove(QRegExp(QLatin1String("[^\\d]"))).toUInt();
379379

380380
int spaces_1 = key1.count(' ');
381381
int spaces_2 = key2.count(' ');
@@ -393,10 +393,10 @@ QByteArray QWsServer::computeAcceptV0(QString key1, QString key2, QByteArray key
393393
return md5;
394394
}
395395

396-
QByteArray QWsServer::computeAcceptV4(QString key)
396+
QByteArray QWsServer::computeAcceptV4(QByteArray key)
397397
{
398398
key += QLatin1String("258EAFA5-E914-47DA-95CA-C5AB0DC85B11");
399-
QByteArray hash = QCryptographicHash::hash(key.toUtf8(), QCryptographicHash::Sha1);
399+
QByteArray hash = QCryptographicHash::hash(key, QCryptographicHash::Sha1);
400400
return hash.toBase64();
401401
}
402402

@@ -405,8 +405,8 @@ QByteArray QWsServer::generateNonce()
405405
qsrand(QDateTime::currentDateTime().toTime_t());
406406

407407
QByteArray nonce;
408-
int i = 16;
409408

409+
int i = 16;
410410
while(i--)
411411
{
412412
nonce.append(qrand() % 0x100);
@@ -418,85 +418,85 @@ QByteArray QWsServer::generateNonce()
418418
QString QWsServer::composeOpeningHandshakeResponseV0(QByteArray accept, QString origin, QString hostAddress, QString hostPort, QString resourceName, QString protocol)
419419
{
420420
QString response;
421-
422-
response.append(QLatin1String("HTTP/1.1 101 WebSocket Protocol Handshake\r\n"));
423-
response.append(QLatin1String("Upgrade: Websocket\r\n"));
424-
response.append(QLatin1String("Connection: Upgrade\r\n"));
425-
response.append(QLatin1String("Sec-WebSocket-Origin: ") + origin + QLatin1String("\r\n"));
426-
response.append(QLatin1String("Sec-WebSocket-Location: ws://") + hostAddress);
421+
response += QLatin1String("HTTP/1.1 101 WebSocket Protocol Handshake\r\n");
422+
response += QLatin1String("Upgrade: Websocket\r\n");
423+
response += QLatin1String("Connection: Upgrade\r\n");
424+
response += QString("Sec-WebSocket-Origin: %1\r\n").arg(origin);
425+
if (!hostAddress.startsWith("ws://", Qt::CaseInsensitive))
426+
{
427+
hostAddress.prepend(QLatin1String("ws://"));
428+
}
427429
if (!hostPort.isEmpty())
428430
{
429-
response.append(QLatin1String(":") + hostPort);
431+
hostPort.prepend(QLatin1Char(':'));
430432
}
431-
response.append(resourceName + QLatin1String("\r\n"));
432-
if (! protocol.isEmpty())
433+
response += QString("Sec-WebSocket-Location: %1%2%3\r\n").arg(hostAddress).arg(hostPort).arg(resourceName);
434+
if (!protocol.isEmpty())
433435
{
434-
response.append(QLatin1String("Sec-WebSocket-Protocol: ") + protocol + QLatin1String("\r\n"));
436+
response += QString("Sec-WebSocket-Protocol: %1\r\n").arg(protocol);
435437
}
436-
response.append(QLatin1String("\r\n"));
437-
response.append(QLatin1String(accept));
438+
response += QLatin1String("\r\n");
439+
response += QLatin1String(accept);
438440

439441
return response;
440442
}
441443

442444
QString QWsServer::composeOpeningHandshakeResponseV4(QByteArray accept, QByteArray nonce, QString protocol, QString extensions)
443445
{
444446
QString response;
445-
446-
response.append(QLatin1String("HTTP/1.1 101 Switching Protocols\r\n"));
447-
response.append(QLatin1String("Upgrade: websocket\r\n"));
448-
response.append(QLatin1String("Connection: Upgrade\r\n"));
449-
response.append(QLatin1String("Sec-WebSocket-Accept: ") + QLatin1String(accept) + QLatin1String("\r\n"));
450-
response.append(QLatin1String("Sec-WebSocket-Nonce: ") + QLatin1String(nonce) + QLatin1String("\r\n"));
451-
if (! protocol.isEmpty())
447+
response += QLatin1String("HTTP/1.1 101 WebSocket Protocol Handshake\r\n");
448+
response += QLatin1String("Upgrade: websocket\r\n");
449+
response += QLatin1String("Connection: Upgrade\r\n");
450+
response += QString("Sec-WebSocket-Accept: %1\r\n").arg(QLatin1String(accept));
451+
response += QString("Sec-WebSocket-Nonce: %1\r\n").arg(QLatin1String(nonce));
452+
if (!protocol.isEmpty())
452453
{
453-
response.append(QLatin1String("Sec-WebSocket-Protocol: ") + protocol + QLatin1String("\r\n"));
454+
response += QString("Sec-WebSocket-Protocol: %1\r\n").arg(protocol);
454455
}
455-
if (! extensions.isEmpty())
456+
if (!extensions.isEmpty())
456457
{
457-
response.append(QLatin1String("Sec-WebSocket-Extensions: ") + extensions + QLatin1String("\r\n"));
458+
response += QString("Sec-WebSocket-Extensions: %1\r\n").arg(extensions);
458459
}
459-
response.append(QLatin1String("\r\n"));
460-
460+
response += QLatin1String("\r\n");
461461
return response;
462462
}
463463

464464
QString QWsServer::composeOpeningHandshakeResponseV6(QByteArray accept, QString protocol, QString extensions)
465465
{
466466
QString response;
467-
468-
response.append(QLatin1String("HTTP/1.1 101 Switching Protocols\r\n"));
469-
response.append(QLatin1String("Upgrade: websocket\r\n"));
470-
response.append(QLatin1String("Connection: Upgrade\r\n"));
471-
response.append(QLatin1String("Sec-WebSocket-Accept: ") + QLatin1String(accept) + QLatin1String("\r\n"));
472-
if (! protocol.isEmpty())
467+
response += QLatin1String("HTTP/1.1 101 WebSocket Protocol Handshake\r\n");
468+
response += QLatin1String("Upgrade: websocket\r\n");
469+
response += QLatin1String("Connection: Upgrade\r\n");
470+
response += QString("Sec-WebSocket-Accept: %1\r\n").arg(QLatin1String(accept));
471+
if (!protocol.isEmpty())
473472
{
474-
response.append(QLatin1String("Sec-WebSocket-Protocol: ") + protocol + QLatin1String("\r\n"));
473+
response += QString("Sec-WebSocket-Protocol: %1\r\n").arg(protocol);
475474
}
476-
if (! extensions.isEmpty())
475+
if (!extensions.isEmpty())
477476
{
478-
response.append(QLatin1String("Sec-WebSocket-Extensions: ") + extensions + QLatin1String("\r\n"));
477+
response += QString("Sec-WebSocket-Extensions: %1\r\n").arg(extensions);
479478
}
480-
response.append(QLatin1String("\r\n"));
481-
479+
response += QLatin1String("\r\n");
482480
return response;
483481
}
484482

485483
QString QWsServer::composeBadRequestResponse(QList<EWebsocketVersion> versions)
486484
{
487485
QString response;
488-
489-
response.append(QLatin1String("HTTP/1.1 400 Bad Request\r\n"));
490-
if (! versions.isEmpty())
486+
response += QLatin1String("HTTP/1.1 400 Bad Request\r\n");
487+
if (!versions.isEmpty())
491488
{
492-
QString versionsStr = QString::number((int)versions.takeLast());
489+
QString versionsStr;
493490
int i = versions.size();
494491
while (i--)
495492
{
496-
versionsStr.append(QLatin1String(", ") + QString::number((int)versions.takeLast()));
493+
versionsStr += QString::number((quint16)versions.at(i));
494+
if (i)
495+
{
496+
versionsStr += QLatin1String(", ");
497+
}
497498
}
498-
response.append(QLatin1String("Sec-WebSocket-Version: ") + versionsStr + QLatin1String("\r\n"));
499+
response += QString("Sec-WebSocket-Version: %1\r\n").arg(versionsStr);
499500
}
500-
501501
return response;
502502
}

‎QtWebsocket/QWsServer.h

+11-13
Original file line numberDiff line numberDiff line change
@@ -79,26 +79,24 @@ private slots:
7979

8080
public:
8181
// public static functions
82-
static QByteArray computeAcceptV0(QString key1, QString key2, QByteArray thirdPart);
83-
static QByteArray computeAcceptV4(QString key);
82+
static QByteArray computeAcceptV0(QByteArray key1, QByteArray key2, QByteArray thirdPart);
83+
static QByteArray computeAcceptV4(QByteArray key);
8484
static QByteArray generateNonce();
8585
static QString composeOpeningHandshakeResponseV0(QByteArray accept, QString origin, QString hostAddress, QString hostPort, QString resourceName, QString protocol = "");
8686
static QString composeOpeningHandshakeResponseV4(QByteArray accept, QByteArray nonce, QString protocol = "", QString extensions = "");
8787
static QString composeOpeningHandshakeResponseV6(QByteArray accept, QString protocol = "", QString extensions = "");
8888
static QString composeBadRequestResponse(QList<EWebsocketVersion> versions = QList<EWebsocketVersion>());
8989

9090
// public static vars
91-
static const QString regExpResourceNameStr;
92-
static const QString regExpHostStr;
93-
static const QString regExpKeyStr;
94-
static const QString regExpKey1Str;
95-
static const QString regExpKey2Str;
96-
//static const QString regExpKey3Str;
97-
static const QString regExpVersionStr;
98-
static const QString regExpOriginStr;
99-
static const QString regExpOrigin2Str;
100-
static const QString regExpProtocolStr;
101-
static const QString regExpExtensionsStr;
91+
static QRegExp regExpHttpRequest;
92+
static QRegExp regExpHost;
93+
static QRegExp regExpKey;
94+
static QRegExp regExpKey1;
95+
static QRegExp regExpKey2;
96+
static QRegExp regExpVersion;
97+
static QRegExp regExpOrigin;
98+
static QRegExp regExpProtocol;
99+
static QRegExp regExpExtensions;
102100
};
103101

104102
#endif // QWSSERVER_H

‎QtWebsocket/QWsSocket.cpp

+66-51
Original file line numberDiff line numberDiff line change
@@ -24,10 +24,11 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
2424
#include "QWsServer.h"
2525

2626
int QWsSocket::maxBytesPerFrame = 1400;
27-
const QString QWsSocket::regExpIPv4(QLatin1String("^([1-9]?[0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])(\\.([1-9]?[0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])){3}$"));
28-
const QString QWsSocket::regExpAcceptStr(QLatin1String("Sec-WebSocket-Accept:\\s(.{28})\r\n"));
29-
const QString QWsSocket::regExpUpgradeStr(QLatin1String("Upgrade:\\s(.+)\r\n"));
30-
const QString QWsSocket::regExpConnectionStr(QLatin1String("Connection:\\s(.+)\r\n"));
27+
QRegExp QWsSocket::regExpIPv4(QLatin1String("^([1-9]?[0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])(\\.([1-9]?[0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])){3}$"));
28+
QRegExp QWsSocket::regExpHttpResponse(QLatin1String("^HTTP/1.1\\s(\\d{3})\\s(.+)\\r\\n"));
29+
QRegExp QWsSocket::regExpAccept(QLatin1String("\\r\\nSec-WebSocket-Accept:\\s(.{28})\\r\\n"));
30+
QRegExp QWsSocket::regExpUpgrade(QLatin1String("\\r\\nUpgrade:\\s(.+)\\r\\n"));
31+
QRegExp QWsSocket::regExpConnection(QLatin1String("\\r\\nConnection:\\s(.+)\\r\\n"));
3132

3233
QWsSocket::QWsSocket(QObject* parent, QTcpSocket* socket, EWebsocketVersion ws_v) :
3334
QAbstractSocket(QAbstractSocket::UnknownSocketType, parent),
@@ -80,23 +81,25 @@ QWsSocket::~QWsSocket()
8081

8182
void QWsSocket::connectToHost(const QString& hostName, quint16 port, OpenMode mode)
8283
{
84+
_hostPort = port;
8385
QString hostName2 = QString(hostName).remove("ws://", Qt::CaseInsensitive);
84-
QHostAddress hostAddress;
85-
if (hostName2.toLower() == QLatin1String("localhost"))
86+
if (hostName2.contains(QRegExp(QLatin1String("^localhost$"), Qt::CaseInsensitive)))
8687
{
87-
hostAddress = QHostAddress::LocalHost;
88+
_host = QLatin1String("localhost");
89+
_hostAddress = QHostAddress::LocalHost;
8890
}
89-
else if (hostName2.contains(QWsSocket::regExpIPv4))
91+
else if (hostName2.contains(QRegExp(QWsSocket::regExpIPv4)))
9092
{
91-
hostAddress = QHostAddress(hostName2);
93+
_host = QLatin1String("localhost");
94+
_hostAddress = QHostAddress(hostName2);
9295
}
9396
else
9497
{
9598
QHostInfo info = QHostInfo::fromName(hostName2);
9699
QList<QHostAddress> hostAddresses = info.addresses();
97-
hostAddress = hostAddresses[0];
100+
_hostAddress = hostAddresses[0];
98101
}
99-
QWsSocket::connectToHost(hostAddress, port, mode);
102+
QWsSocket::connectToHost(_hostAddress, _hostPort, mode);
100103
}
101104

102105
void QWsSocket::connectToHost(const QHostAddress& address, quint16 port, OpenMode mode)
@@ -273,43 +276,48 @@ void QWsSocket::processHandshake()
273276
return;
274277
}
275278

276-
QRegExp regExp;
277-
regExp.setMinimal(true);
279+
// check HTTP code
280+
regExpHttpResponse.setMinimal(true);
281+
regExpHttpResponse.indexIn(handshakeResponse);
282+
quint16 httpCode = regExpHttpResponse.cap(1).toUInt();
283+
QString httpMessage = regExpHttpResponse.cap(2);
278284

279-
// check accept field
280-
regExp.setPattern(regExpAcceptStr);
281-
regExp.indexIn(handshakeResponse);
282-
QString acceptFromServer = regExp.cap(1);
285+
if (httpCode != 101)
286+
{
287+
emit error(QAbstractSocket::ConnectionRefusedError);
288+
return;
289+
}
283290

284291
// check upgrade field
285-
regExp.setPattern(regExpUpgradeStr);
286-
regExp.indexIn(handshakeResponse);
287-
QString upgrade = regExp.cap(1);
292+
regExpUpgrade.setMinimal(true);
293+
regExpUpgrade.indexIn(handshakeResponse);
294+
QString upgrade = regExpUpgrade.cap(1);
288295

289296
// check connection field
290-
regExp.setPattern(regExpConnectionStr);
291-
regExp.indexIn(handshakeResponse);
292-
QString connection = regExp.cap(1);
297+
regExpConnection.setMinimal(true);
298+
regExpConnection.indexIn(handshakeResponse);
299+
QString connection = regExpConnection.cap(1);
300+
301+
// check accept field
302+
regExpAccept.setMinimal(true);
303+
regExpAccept.indexIn(handshakeResponse);
304+
QByteArray acceptFromServer = regExpAccept.cap(1).toLatin1();
293305

294306
// check extensions field
295-
regExp.setPattern(QWsServer::regExpExtensionsStr);
296-
regExp.indexIn(handshakeResponse);
297-
QString extensions = regExp.cap(1);
307+
QWsServer::regExpExtensions.setMinimal(true);
308+
QWsServer::regExpExtensions.indexIn(handshakeResponse);
309+
QString extensions = QWsServer::regExpExtensions.cap(1);
310+
311+
// check protocol field
312+
QWsServer::regExpProtocol.setMinimal(true);
313+
QWsServer::regExpProtocol.indexIn(handshakeResponse);
314+
QString protocol = QWsServer::regExpProtocol.cap(1);
298315

299-
//TODO: check extensions field
300316
// If the mandatory params are not setted, we abord the connection to the Websocket server
301-
if((acceptFromServer.isEmpty()) || (!upgrade.contains(QLatin1String("websocket"), Qt::CaseInsensitive)) || (!connection.contains(QLatin1String("Upgrade"), Qt::CaseInsensitive)))
302-
{
303-
emit error(QAbstractSocket::ConnectionRefusedError);
304-
return;
305-
}
306-
307-
//TODO: check HTTP code
308-
309-
//TODO: check protocol field
310-
311-
QString accept = QWsServer::computeAcceptV4(key);
312-
if(accept != acceptFromServer)
317+
if ( (acceptFromServer.isEmpty())
318+
|| (!upgrade.contains(QLatin1String("websocket"), Qt::CaseInsensitive))
319+
|| (!connection.contains(QLatin1String("Upgrade"), Qt::CaseInsensitive))
320+
|| (QWsServer::computeAcceptV4(key) != acceptFromServer) )
313321
{
314322
emit error(QAbstractSocket::ConnectionRefusedError);
315323
return;
@@ -577,7 +585,7 @@ void QWsSocket::processTcpStateChanged(QAbstractSocket::SocketState tcpSocketSta
577585
if (wsSocketState == QAbstractSocket::ConnectingState)
578586
{
579587
key = QWsServer::generateNonce();
580-
QString handshake = composeOpeningHandShake(QLatin1String("/"), QLatin1String("example.com"), QString(), QString(), key);
588+
QString handshake = composeOpeningHandShake(QLatin1String("/"), _host, QLatin1String("QtWebsocket application"), key);
581589
tcpSocket->write(handshake.toUtf8());
582590
}
583591
break;
@@ -757,18 +765,25 @@ QByteArray QWsSocket::composeHeader(bool end, EOpcode opcode, quint64 payloadLen
757765
return BA;
758766
}
759767

760-
QString QWsSocket::composeOpeningHandShake(QString resourceName, QString host, QString origin, QString extensions, QString key)
768+
QString QWsSocket::composeOpeningHandShake(QString resourceName, QString host, QString origin, QByteArray key, QString protocol, QString extensions)
761769
{
762770
QString hs;
763-
hs.append(QLatin1String("GET ") + resourceName.toLatin1() + QLatin1String(" HTTP/1.1\r\n"));
764-
hs.append(QLatin1String("Host: ") + host + "\r\n");
765-
hs.append(QLatin1String("Upgrade: websocket\r\n"));
766-
hs.append(QLatin1String("Connection: Upgrade\r\n"));
767-
hs.append(QLatin1String("Sec-WebSocket-Key: ") + key.toLatin1() + QLatin1String("\r\n"));
768-
hs.append(QLatin1String("Origin: ") + origin.toLatin1() + QLatin1String("\r\n"));
769-
hs.append(QLatin1String("Sec-WebSocket-Extensions: ") + extensions.toLatin1() + QLatin1String("\r\n"));
770-
hs.append(QLatin1String("Sec-WebSocket-Version: 13\r\n"));
771-
hs.append(QLatin1String("\r\n"));
771+
hs += QString("GET %1 HTTP/1.1\r\n").arg(resourceName);
772+
hs += QString("Host: %1\r\n").arg(host);
773+
hs += QLatin1String("Upgrade: websocket\r\n");
774+
hs += QLatin1String("Connection: Upgrade\r\n");
775+
hs += QString("Sec-WebSocket-Key: %1\r\n").arg(QLatin1String(key));
776+
hs += QString("Origin: %1\r\n").arg(origin);
777+
hs += QLatin1String("Sec-WebSocket-Version: 13\r\n");
778+
if (!protocol.isEmpty())
779+
{
780+
hs += QString("Sec-WebSocket-Protocol: %1\r\n").arg(protocol);
781+
}
782+
if (!extensions.isEmpty())
783+
{
784+
hs += QString("Sec-WebSocket-Extensions: %1\r\n").arg(extensions);
785+
}
786+
hs += QLatin1String("\r\n");
772787
return hs;
773788
}
774789

@@ -829,7 +844,7 @@ QString QWsSocket::host()
829844
return _host;
830845
}
831846

832-
QString QWsSocket::hostAddress()
847+
QHostAddress QWsSocket::hostAddress()
833848
{
834849
return _hostAddress;
835850
}

‎QtWebsocket/QWsSocket.h

+10-9
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@ class QWsSocket : public QAbstractSocket
8888
EWebsocketVersion version();
8989
QString resourceName();
9090
QString host();
91-
QString hostAddress();
91+
QHostAddress hostAddress();
9292
int hostPort();
9393
QString origin();
9494
QString protocol();
@@ -147,8 +147,8 @@ protected slots:
147147
EWebsocketVersion _version;
148148
QString _resourceName;
149149
QString _host;
150-
QString _hostAddress;
151-
int _hostPort;
150+
QHostAddress _hostAddress;
151+
quint16 _hostPort;
152152
QString _origin;
153153
QString _protocol;
154154
QString _extensions;
@@ -165,12 +165,13 @@ protected slots:
165165
QByteArray maskingKey;
166166
ECloseStatusCode closeStatusCode;
167167

168-
static const QString regExpIPv4;
169-
static const QString regExpAcceptStr;
170-
static const QString regExpUpgradeStr;
171-
static const QString regExpConnectionStr;
168+
static QRegExp regExpHttpResponse;
169+
static QRegExp regExpIPv4;
170+
static QRegExp regExpAccept;
171+
static QRegExp regExpUpgrade;
172+
static QRegExp regExpConnection;
172173
QString handshakeResponse;
173-
QString key;
174+
QByteArray key;
174175

175176
public:
176177
// Static functions
@@ -179,7 +180,7 @@ protected slots:
179180
static QByteArray mask(QByteArray & data, QByteArray & maskingKey);
180181
static QList<QByteArray> composeFrames(QByteArray byteArray, bool asBinary = false, int maxFrameBytes = 0);
181182
static QByteArray composeHeader(bool end, EOpcode opcode, quint64 payloadLength, QByteArray maskingKey = QByteArray());
182-
static QString composeOpeningHandShake(QString resourceName, QString host, QString origin, QString extensions, QString key);
183+
static QString composeOpeningHandShake(QString resourceName, QString host, QString origin, QByteArray key, QString protocol = "", QString extensions = "");
183184

184185
// static vars
185186
static int maxBytesPerFrame;

0 commit comments

Comments
 (0)
This repository has been archived.