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