Renamed qwebsocket.pri to qwebsockets.pri
[contrib/qtwebsockets.git] / src / qwebsocketserver_p.cpp
1 /*
2 QWebSockets implements the WebSocket protocol as defined in RFC 6455.
3 Copyright (C) 2013 Kurt Pattyn (pattyn.kurt@gmail.com)
4
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.
9
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.
14
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
18 */
19
20 #include <QTcpServer>
21 #include <QTcpSocket>
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
31 QT_BEGIN_NAMESPACE
32
33 /*!
34         \internal
35  */
36 QWebSocketServerPrivate::QWebSocketServerPrivate(const QString &serverName, QWebSocketServer * const pWebSocketServer, QObject *parent) :
37         QObject(parent),
38         q_ptr(pWebSocketServer),
39         m_pTcpServer(0),
40         m_serverName(serverName),
41         m_pendingConnections()
42 {
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()));
47 }
48
49 /*!
50         \internal
51  */
52 QWebSocketServerPrivate::~QWebSocketServerPrivate()
53 {
54         while (!m_pendingConnections.isEmpty())
55         {
56                 QWebSocket *pWebSocket = m_pendingConnections.dequeue();
57                 pWebSocket->close(QWebSocketProtocol::CC_GOING_AWAY, "Server closed.");
58                 pWebSocket->deleteLater();
59         }
60         m_pTcpServer->deleteLater();
61 }
62
63 /*!
64         \internal
65  */
66 void QWebSocketServerPrivate::close()
67 {
68         m_pTcpServer->close();
69 }
70
71 /*!
72         \internal
73  */
74 QString QWebSocketServerPrivate::errorString() const
75 {
76         return m_pTcpServer->errorString();
77 }
78
79 /*!
80         \internal
81  */
82 bool QWebSocketServerPrivate::hasPendingConnections() const
83 {
84         return !m_pendingConnections.isEmpty();
85 }
86
87 /*!
88         \internal
89  */
90 bool QWebSocketServerPrivate::isListening() const
91 {
92         return m_pTcpServer->isListening();
93 }
94
95 /*!
96         \internal
97  */
98 bool QWebSocketServerPrivate::listen(const QHostAddress &address, quint16 port)
99 {
100         return m_pTcpServer->listen(address, port);
101 }
102
103 /*!
104         \internal
105  */
106 int QWebSocketServerPrivate::maxPendingConnections() const
107 {
108         return m_pTcpServer->maxPendingConnections();
109 }
110
111 /*!
112         \internal
113  */
114 void QWebSocketServerPrivate::addPendingConnection(QWebSocket *pWebSocket)
115 {
116         if (m_pendingConnections.size() < maxPendingConnections())
117         {
118                 m_pendingConnections.enqueue(pWebSocket);
119         }
120 }
121
122 /*!
123         \internal
124  */
125 QWebSocket *QWebSocketServerPrivate::nextPendingConnection()
126 {
127         QWebSocket *pWebSocket = 0;
128         if (!m_pendingConnections.isEmpty())
129         {
130                 pWebSocket = m_pendingConnections.dequeue();
131         }
132         return pWebSocket;
133 }
134
135 /*!
136         \internal
137  */
138 void QWebSocketServerPrivate::pauseAccepting()
139 {
140         m_pTcpServer->pauseAccepting();
141 }
142
143 #ifndef QT_NO_NETWORKPROXY
144 /*!
145         \internal
146  */
147 QNetworkProxy QWebSocketServerPrivate::proxy() const
148 {
149         return m_pTcpServer->proxy();
150 }
151
152 /*!
153         \internal
154  */
155 void QWebSocketServerPrivate::setProxy(const QNetworkProxy &networkProxy)
156 {
157         m_pTcpServer->setProxy(networkProxy);
158 }
159 #endif
160 /*!
161         \internal
162  */
163 void QWebSocketServerPrivate::resumeAccepting()
164 {
165         m_pTcpServer->resumeAccepting();
166 }
167
168 /*!
169         \internal
170  */
171 QHostAddress QWebSocketServerPrivate::serverAddress() const
172 {
173         return m_pTcpServer->serverAddress();
174 }
175
176 /*!
177         \internal
178  */
179 QAbstractSocket::SocketError QWebSocketServerPrivate::serverError() const
180 {
181         return m_pTcpServer->serverError();
182 }
183
184 /*!
185         \internal
186  */
187 quint16 QWebSocketServerPrivate::serverPort() const
188 {
189         return m_pTcpServer->serverPort();
190 }
191
192 /*!
193         \internal
194  */
195 void QWebSocketServerPrivate::setMaxPendingConnections(int numConnections)
196 {
197         m_pTcpServer->setMaxPendingConnections(numConnections);
198 }
199
200 /*!
201         \internal
202  */
203 bool QWebSocketServerPrivate::setSocketDescriptor(int socketDescriptor)
204 {
205         return m_pTcpServer->setSocketDescriptor(socketDescriptor);
206 }
207
208 /*!
209         \internal
210  */
211 int QWebSocketServerPrivate::socketDescriptor() const
212 {
213         return m_pTcpServer->socketDescriptor();
214 }
215
216 /*!
217         \internal
218  */
219 bool QWebSocketServerPrivate::waitForNewConnection(int msec, bool *timedOut)
220 {
221         return m_pTcpServer->waitForNewConnection(msec, timedOut);
222 }
223
224 /*!
225         \internal
226  */
227 QList<QWebSocketProtocol::Version> QWebSocketServerPrivate::supportedVersions() const
228 {
229         QList<QWebSocketProtocol::Version> supportedVersions;
230         supportedVersions << QWebSocketProtocol::currentVersion();      //we only support V13
231         return supportedVersions;
232 }
233
234 /*!
235         \internal
236  */
237 QList<QString> QWebSocketServerPrivate::supportedProtocols() const
238 {
239         QList<QString> supportedProtocols;
240         return supportedProtocols;      //no protocols are currently supported
241 }
242
243 /*!
244         \internal
245  */
246 QList<QString> QWebSocketServerPrivate::supportedExtensions() const
247 {
248         QList<QString> supportedExtensions;
249         return supportedExtensions;     //no extensions are currently supported
250 }
251
252 /*!
253         \internal
254  */
255 void QWebSocketServerPrivate::onNewConnection()
256 {
257         QTcpSocket *pTcpSocket = m_pTcpServer->nextPendingConnection();
258         connect(pTcpSocket, SIGNAL(readyRead()), this, SLOT(handshakeReceived()));
259 }
260
261 /*!
262         \internal
263  */
264 void QWebSocketServerPrivate::onCloseConnection()
265 {
266         QTcpSocket *pTcpSocket = qobject_cast<QTcpSocket*>(sender());
267         if (pTcpSocket != 0)
268         {
269                 pTcpSocket->close();
270         }
271 }
272
273 /*!
274         \internal
275  */
276 void QWebSocketServerPrivate::handshakeReceived()
277 {
278         QTcpSocket *pTcpSocket = qobject_cast<QTcpSocket*>(sender());
279         if (pTcpSocket != 0)
280         {
281                 bool success = false;
282                 bool isSecure = false;
283                 HandshakeRequest request(pTcpSocket->peerPort(), isSecure);
284                 QTextStream textStream(pTcpSocket);
285                 textStream >> request;
286
287                 HandshakeResponse response(request,
288                                                                    m_serverName,
289                                                                    q_ptr->isOriginAllowed(request.getOrigin()),
290                                                                    supportedVersions(),
291                                                                    supportedProtocols(),
292                                                                    supportedExtensions());
293                 disconnect(pTcpSocket, SIGNAL(readyRead()), this, SLOT(handshakeReceived()));
294
295                 if (response.isValid())
296                 {
297                         QTextStream httpStream(pTcpSocket);
298                         httpStream << response;
299                         httpStream.flush();
300
301                         if (response.canUpgrade())
302                         {
303                                 QWebSocket *pWebSocket = QWebSocketPrivate::upgradeFrom(pTcpSocket, request, response);
304                                 if (pWebSocket)
305                                 {
306                                         pWebSocket->setParent(this);
307                                         addPendingConnection(pWebSocket);
308                                         Q_EMIT q_ptr->newConnection();
309                                         success = true;
310                                 }
311                                 else
312                                 {
313                                         qDebug() << "QWebSocketServerPrivate::handshakeReceived: Upgrading to WebSocket failed.";
314                                 }
315                         }
316                         else
317                         {
318                                 qDebug() << "QWebSocketServerPrivate::handshakeReceived: Cannot upgrade to websocket.";
319                         }
320                 }
321                 else
322                 {
323                         qDebug() << "QWebSocketServerPrivate::handshakeReceived: Invalid response. This should not happen!!!";
324                 }
325                 if (!success)
326                 {
327                         qDebug() << "QWebSocketServerPrivate::handshakeReceived: Closing socket because of invalid or unsupported request";
328                         pTcpSocket->close();
329                 }
330         }
331         else
332         {
333                 qDebug() << "WebSocketServerPrivate::handshakeReceived: Sender socket is NULL. This should not happen!!!";
334         }
335 }
336
337 QT_END_NAMESPACE