Added check on QT_NO_NETWORKPROXY to include proxy functionality only when required
[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 #ifndef QT_NO_NETWORKPROXY
116 /*!
117         \internal
118  */
119 QNetworkProxy QWebSocketServerPrivate::proxy() const
120 {
121         return m_pTcpServer->proxy();
122 }
123
124 /*!
125         \internal
126  */
127 void QWebSocketServerPrivate::setProxy(const QNetworkProxy &networkProxy)
128 {
129         m_pTcpServer->setProxy(networkProxy);
130 }
131 #endif
132 /*!
133         \internal
134  */
135 QHostAddress QWebSocketServerPrivate::serverAddress() const
136 {
137         return m_pTcpServer->serverAddress();
138 }
139
140 /*!
141         \internal
142  */
143 QAbstractSocket::SocketError QWebSocketServerPrivate::serverError() const
144 {
145         return m_pTcpServer->serverError();
146 }
147
148 /*!
149         \internal
150  */
151 quint16 QWebSocketServerPrivate::serverPort() const
152 {
153         return m_pTcpServer->serverPort();
154 }
155
156 /*!
157         \internal
158  */
159 void QWebSocketServerPrivate::setMaxPendingConnections(int numConnections)
160 {
161         m_pTcpServer->setMaxPendingConnections(numConnections);
162 }
163
164 /*!
165         \internal
166  */
167 bool QWebSocketServerPrivate::setSocketDescriptor(int socketDescriptor)
168 {
169         return m_pTcpServer->setSocketDescriptor(socketDescriptor);
170 }
171
172 /*!
173         \internal
174  */
175 int QWebSocketServerPrivate::socketDescriptor() const
176 {
177         return m_pTcpServer->socketDescriptor();
178 }
179
180 /*!
181         \internal
182  */
183 bool QWebSocketServerPrivate::waitForNewConnection(int msec, bool *timedOut)
184 {
185         return m_pTcpServer->waitForNewConnection(msec, timedOut);
186 }
187
188 /*!
189         \internal
190  */
191 QList<QWebSocketProtocol::Version> QWebSocketServerPrivate::supportedVersions() const
192 {
193         QList<QWebSocketProtocol::Version> supportedVersions;
194         supportedVersions << QWebSocketProtocol::currentVersion();      //we only support V13
195         return supportedVersions;
196 }
197
198 /*!
199         \internal
200  */
201 QList<QString> QWebSocketServerPrivate::supportedProtocols() const
202 {
203         QList<QString> supportedProtocols;
204         return supportedProtocols;      //no protocols are currently supported
205 }
206
207 /*!
208         \internal
209  */
210 QList<QString> QWebSocketServerPrivate::supportedExtensions() const
211 {
212         QList<QString> supportedExtensions;
213         return supportedExtensions;     //no extensions are currently supported
214 }
215
216 /*!
217         \internal
218  */
219 void QWebSocketServerPrivate::onNewConnection()
220 {
221         QTcpSocket *pTcpSocket = m_pTcpServer->nextPendingConnection();
222         connect(pTcpSocket, SIGNAL(readyRead()), this, SLOT(handshakeReceived()));
223 }
224
225 /*!
226         \internal
227  */
228 void QWebSocketServerPrivate::onCloseConnection()
229 {
230         QTcpSocket *pTcpSocket = qobject_cast<QTcpSocket*>(sender());
231         if (pTcpSocket != 0)
232         {
233                 pTcpSocket->close();
234         }
235 }
236
237 /*!
238         \internal
239  */
240 void QWebSocketServerPrivate::handshakeReceived()
241 {
242         QTcpSocket *pTcpSocket = qobject_cast<QTcpSocket*>(sender());
243         if (pTcpSocket != 0)
244         {
245                 bool success = false;
246                 bool isSecure = false;
247                 HandshakeRequest request(pTcpSocket->peerPort(), isSecure);
248                 QTextStream textStream(pTcpSocket);
249                 textStream >> request;
250
251                 HandshakeResponse response(request,
252                                                                    m_serverName,
253                                                                    q_ptr->isOriginAllowed(request.getOrigin()),
254                                                                    supportedVersions(),
255                                                                    supportedProtocols(),
256                                                                    supportedExtensions());
257                 disconnect(pTcpSocket, SIGNAL(readyRead()), this, SLOT(handshakeReceived()));
258
259                 if (response.isValid())
260                 {
261                         QTextStream httpStream(pTcpSocket);
262                         httpStream << response;
263                         httpStream.flush();
264
265                         if (response.canUpgrade())
266                         {
267                                 QWebSocket *pWebSocket = QWebSocketPrivate::upgradeFrom(pTcpSocket, request, response);
268                                 if (pWebSocket)
269                                 {
270                                         pWebSocket->setParent(this);
271                                         addPendingConnection(pWebSocket);
272                                         Q_EMIT q_ptr->newConnection();
273                                         success = true;
274                                 }
275                                 else
276                                 {
277                                         qDebug() << "QWebSocketServerPrivate::handshakeReceived: Upgrading to WebSocket failed.";
278                                 }
279                         }
280                         else
281                         {
282                                 qDebug() << "QWebSocketServerPrivate::handshakeReceived: Cannot upgrade to websocket.";
283                         }
284                 }
285                 else
286                 {
287                         qDebug() << "QWebSocketServerPrivate::handshakeReceived: Invalid response. This should not happen!!!";
288                 }
289                 if (!success)
290                 {
291                         qDebug() << "QWebSocketServerPrivate::handshakeReceived: Closing socket because of invalid or unsupported request";
292                         pTcpSocket->close();
293                 }
294         }
295         else
296         {
297                 qDebug() << "WebSocketServerPrivate::handshakeReceived: Sender socket is NULL. This should not happen!!!";
298         }
299 }
300
301 QT_END_NAMESPACE