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"
30 #include "qcorsauthenticator.h"
37 QWebSocketServerPrivate::QWebSocketServerPrivate(const QString &serverName, QWebSocketServer * const pWebSocketServer, QObject *parent) :
39 q_ptr(pWebSocketServer),
41 m_serverName(serverName),
42 m_pendingConnections()
44 Q_ASSERT(pWebSocketServer != 0);
45 m_pTcpServer = new QTcpServer(this);
46 connect(m_pTcpServer, SIGNAL(acceptError(QAbstractSocket::SocketError)), q_ptr, SIGNAL(acceptError(QAbstractSocket::SocketError)));
47 connect(m_pTcpServer, SIGNAL(newConnection()), this, SLOT(onNewConnection()));
53 QWebSocketServerPrivate::~QWebSocketServerPrivate()
55 while (!m_pendingConnections.isEmpty())
57 QWebSocket *pWebSocket = m_pendingConnections.dequeue();
58 pWebSocket->close(QWebSocketProtocol::CC_GOING_AWAY, tr("Server closed."));
59 pWebSocket->deleteLater();
61 m_pTcpServer->deleteLater();
67 void QWebSocketServerPrivate::close()
69 m_pTcpServer->close();
75 QString QWebSocketServerPrivate::errorString() const
77 return m_pTcpServer->errorString();
83 bool QWebSocketServerPrivate::hasPendingConnections() const
85 return !m_pendingConnections.isEmpty();
91 bool QWebSocketServerPrivate::isListening() const
93 return m_pTcpServer->isListening();
99 bool QWebSocketServerPrivate::listen(const QHostAddress &address, quint16 port)
101 return m_pTcpServer->listen(address, port);
107 int QWebSocketServerPrivate::maxPendingConnections() const
109 return m_pTcpServer->maxPendingConnections();
115 void QWebSocketServerPrivate::addPendingConnection(QWebSocket *pWebSocket)
117 if (m_pendingConnections.size() < maxPendingConnections())
119 m_pendingConnections.enqueue(pWebSocket);
126 QWebSocket *QWebSocketServerPrivate::nextPendingConnection()
128 QWebSocket *pWebSocket = 0;
129 if (!m_pendingConnections.isEmpty())
131 pWebSocket = m_pendingConnections.dequeue();
139 void QWebSocketServerPrivate::pauseAccepting()
141 m_pTcpServer->pauseAccepting();
144 #ifndef QT_NO_NETWORKPROXY
148 QNetworkProxy QWebSocketServerPrivate::proxy() const
150 return m_pTcpServer->proxy();
156 void QWebSocketServerPrivate::setProxy(const QNetworkProxy &networkProxy)
158 m_pTcpServer->setProxy(networkProxy);
164 void QWebSocketServerPrivate::resumeAccepting()
166 m_pTcpServer->resumeAccepting();
172 QHostAddress QWebSocketServerPrivate::serverAddress() const
174 return m_pTcpServer->serverAddress();
180 QAbstractSocket::SocketError QWebSocketServerPrivate::serverError() const
182 return m_pTcpServer->serverError();
188 quint16 QWebSocketServerPrivate::serverPort() const
190 return m_pTcpServer->serverPort();
196 void QWebSocketServerPrivate::setMaxPendingConnections(int numConnections)
198 m_pTcpServer->setMaxPendingConnections(numConnections);
204 bool QWebSocketServerPrivate::setSocketDescriptor(int socketDescriptor)
206 return m_pTcpServer->setSocketDescriptor(socketDescriptor);
212 int QWebSocketServerPrivate::socketDescriptor() const
214 return m_pTcpServer->socketDescriptor();
220 bool QWebSocketServerPrivate::waitForNewConnection(int msec, bool *timedOut)
222 return m_pTcpServer->waitForNewConnection(msec, timedOut);
228 QList<QWebSocketProtocol::Version> QWebSocketServerPrivate::supportedVersions() const
230 QList<QWebSocketProtocol::Version> supportedVersions;
231 supportedVersions << QWebSocketProtocol::currentVersion(); //we only support V13
232 return supportedVersions;
238 QList<QString> QWebSocketServerPrivate::supportedProtocols() const
240 QList<QString> supportedProtocols;
241 return supportedProtocols; //no protocols are currently supported
247 QList<QString> QWebSocketServerPrivate::supportedExtensions() const
249 QList<QString> supportedExtensions;
250 return supportedExtensions; //no extensions are currently supported
256 void QWebSocketServerPrivate::setServerName(const QString &serverName)
258 m_serverName = serverName;
264 QString QWebSocketServerPrivate::serverName() const
272 void QWebSocketServerPrivate::onNewConnection()
274 QTcpSocket *pTcpSocket = m_pTcpServer->nextPendingConnection();
275 connect(pTcpSocket, SIGNAL(readyRead()), this, SLOT(handshakeReceived()));
281 void QWebSocketServerPrivate::onCloseConnection()
283 QTcpSocket *pTcpSocket = qobject_cast<QTcpSocket*>(sender());
293 void QWebSocketServerPrivate::handshakeReceived()
295 Q_Q(QWebSocketServer);
296 QTcpSocket *pTcpSocket = qobject_cast<QTcpSocket*>(sender());
299 bool success = false;
300 bool isSecure = false;
301 HandshakeRequest request(pTcpSocket->peerPort(), isSecure);
302 QTextStream textStream(pTcpSocket);
303 textStream >> request;
305 QCorsAuthenticator corsAuthenticator(request.getOrigin());
306 Q_EMIT q->originAuthenticationRequired(&corsAuthenticator);
308 HandshakeResponse response(request,
310 corsAuthenticator.allowed(),
312 supportedProtocols(),
313 supportedExtensions());
314 disconnect(pTcpSocket, SIGNAL(readyRead()), this, SLOT(handshakeReceived()));
316 if (response.isValid())
318 QTextStream httpStream(pTcpSocket);
319 httpStream << response;
322 if (response.canUpgrade())
324 QWebSocket *pWebSocket = QWebSocketPrivate::upgradeFrom(pTcpSocket, request, response);
327 pWebSocket->setParent(this);
328 addPendingConnection(pWebSocket);
329 Q_EMIT q->newConnection();
334 //TODO: should set or emit error
335 qDebug() << tr("Upgrading to websocket failed.");
340 //TODO: should set or emit error
341 qDebug() << tr("Cannot upgrade to websocket.");
346 //TODO: should set or emit error
347 qDebug() << tr("Invalid response received.");
351 //TODO: should set or emit error
352 qDebug() << tr("Closing socket because of invalid or unsupported request.");
358 qWarning() << "Sender socket is NULL. This should not happen, otherwise it is a Qt bug!!!";