2 QWebSockets implements the WebSocket protocol as defined in RFC 6455.
3 Copyright (C) 2013 Kurt Pattyn (pattyn.kurt@gmail.com)
5 This library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Lesser General Public
7 License as published by the Free Software Foundation; either
8 version 2.1 of the License, or (at your option) any later version.
10 This library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Lesser General Public License for more details.
15 You should have received a copy of the GNU Lesser General Public
16 License along with this library; if not, write to the Free Software
17 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
22 #include <QNetworkProxy>
23 #include "qwebsocketserver.h"
24 #include "qwebsocketserver_p.h"
25 #include "qwebsocketprotocol.h"
26 #include "handshakerequest_p.h"
27 #include "handshakeresponse_p.h"
28 #include "qwebsocket.h"
29 #include "qwebsocket_p.h"
36 QWebSocketServerPrivate::QWebSocketServerPrivate(const QString &serverName, QWebSocketServer * const pWebSocketServer, QObject *parent) :
38 q_ptr(pWebSocketServer),
40 m_serverName(serverName),
41 m_pendingConnections()
43 Q_ASSERT(pWebSocketServer != 0);
44 m_pTcpServer = new QTcpServer(this);
45 connect(m_pTcpServer, SIGNAL(acceptError(QAbstractSocket::SocketError)), q_ptr, SIGNAL(acceptError(QAbstractSocket::SocketError)));
46 connect(m_pTcpServer, SIGNAL(newConnection()), this, SLOT(onNewConnection()));
52 QWebSocketServerPrivate::~QWebSocketServerPrivate()
54 while (!m_pendingConnections.isEmpty())
56 QWebSocket *pWebSocket = m_pendingConnections.dequeue();
57 pWebSocket->close(QWebSocketProtocol::CC_GOING_AWAY, QWebSocketServer::tr("Server closed."));
58 pWebSocket->deleteLater();
60 m_pTcpServer->deleteLater();
66 void QWebSocketServerPrivate::close()
68 m_pTcpServer->close();
74 QString QWebSocketServerPrivate::errorString() const
76 return m_pTcpServer->errorString();
82 bool QWebSocketServerPrivate::hasPendingConnections() const
84 return !m_pendingConnections.isEmpty();
90 bool QWebSocketServerPrivate::isListening() const
92 return m_pTcpServer->isListening();
98 bool QWebSocketServerPrivate::listen(const QHostAddress &address, quint16 port)
100 return m_pTcpServer->listen(address, port);
106 int QWebSocketServerPrivate::maxPendingConnections() const
108 return m_pTcpServer->maxPendingConnections();
114 void QWebSocketServerPrivate::addPendingConnection(QWebSocket *pWebSocket)
116 if (m_pendingConnections.size() < maxPendingConnections())
118 m_pendingConnections.enqueue(pWebSocket);
125 QWebSocket *QWebSocketServerPrivate::nextPendingConnection()
127 QWebSocket *pWebSocket = 0;
128 if (!m_pendingConnections.isEmpty())
130 pWebSocket = m_pendingConnections.dequeue();
138 void QWebSocketServerPrivate::pauseAccepting()
140 m_pTcpServer->pauseAccepting();
143 #ifndef QT_NO_NETWORKPROXY
147 QNetworkProxy QWebSocketServerPrivate::proxy() const
149 return m_pTcpServer->proxy();
155 void QWebSocketServerPrivate::setProxy(const QNetworkProxy &networkProxy)
157 m_pTcpServer->setProxy(networkProxy);
163 void QWebSocketServerPrivate::resumeAccepting()
165 m_pTcpServer->resumeAccepting();
171 QHostAddress QWebSocketServerPrivate::serverAddress() const
173 return m_pTcpServer->serverAddress();
179 QAbstractSocket::SocketError QWebSocketServerPrivate::serverError() const
181 return m_pTcpServer->serverError();
187 quint16 QWebSocketServerPrivate::serverPort() const
189 return m_pTcpServer->serverPort();
195 void QWebSocketServerPrivate::setMaxPendingConnections(int numConnections)
197 m_pTcpServer->setMaxPendingConnections(numConnections);
203 bool QWebSocketServerPrivate::setSocketDescriptor(int socketDescriptor)
205 return m_pTcpServer->setSocketDescriptor(socketDescriptor);
211 int QWebSocketServerPrivate::socketDescriptor() const
213 return m_pTcpServer->socketDescriptor();
219 bool QWebSocketServerPrivate::waitForNewConnection(int msec, bool *timedOut)
221 return m_pTcpServer->waitForNewConnection(msec, timedOut);
227 QList<QWebSocketProtocol::Version> QWebSocketServerPrivate::supportedVersions() const
229 QList<QWebSocketProtocol::Version> supportedVersions;
230 supportedVersions << QWebSocketProtocol::currentVersion(); //we only support V13
231 return supportedVersions;
237 QList<QString> QWebSocketServerPrivate::supportedProtocols() const
239 QList<QString> supportedProtocols;
240 return supportedProtocols; //no protocols are currently supported
246 QList<QString> QWebSocketServerPrivate::supportedExtensions() const
248 QList<QString> supportedExtensions;
249 return supportedExtensions; //no extensions are currently supported
255 void QWebSocketServerPrivate::onNewConnection()
257 QTcpSocket *pTcpSocket = m_pTcpServer->nextPendingConnection();
258 connect(pTcpSocket, SIGNAL(readyRead()), this, SLOT(handshakeReceived()));
264 void QWebSocketServerPrivate::onCloseConnection()
266 QTcpSocket *pTcpSocket = qobject_cast<QTcpSocket*>(sender());
276 void QWebSocketServerPrivate::handshakeReceived()
278 QTcpSocket *pTcpSocket = qobject_cast<QTcpSocket*>(sender());
281 bool success = false;
282 bool isSecure = false;
283 HandshakeRequest request(pTcpSocket->peerPort(), isSecure);
284 QTextStream textStream(pTcpSocket);
285 textStream >> request;
287 HandshakeResponse response(request,
289 q_ptr->isOriginAllowed(request.getOrigin()),
291 supportedProtocols(),
292 supportedExtensions());
293 disconnect(pTcpSocket, SIGNAL(readyRead()), this, SLOT(handshakeReceived()));
295 if (response.isValid())
297 QTextStream httpStream(pTcpSocket);
298 httpStream << response;
301 if (response.canUpgrade())
303 QWebSocket *pWebSocket = QWebSocketPrivate::upgradeFrom(pTcpSocket, request, response);
306 pWebSocket->setParent(this);
307 addPendingConnection(pWebSocket);
308 Q_EMIT q_ptr->newConnection();
313 //TODO: should set or emit error
314 qDebug() << QWebSocketServer::tr("Upgrading to websocket failed.");
319 //TODO: should set or emit error
320 qDebug() << QWebSocketServer::tr("Cannot upgrade to websocket.");
325 //TODO: should set or emit error
326 qDebug() << QWebSocketServer::tr("Invalid response received.");
330 //TODO: should set or emit error
331 qDebug() << QWebSocketServer::tr("Closing socket because of invalid or unsupported request.");
337 qWarning() << "Sender socket is NULL. This should not happen, otherwise it is a Qt bug!!!";