1 #include "handshakerequest_p.h"
8 #include "qwebsocketprotocol.h"
15 HandshakeRequest::HandshakeRequest(int port, bool isSecure) :
32 HandshakeRequest::~HandshakeRequest()
39 void HandshakeRequest::clear()
56 int HandshakeRequest::getPort() const
58 return m_requestUrl.port(m_port);
64 bool HandshakeRequest::isSecure() const
72 bool HandshakeRequest::isValid() const
80 QMap<QString, QString> HandshakeRequest::getHeaders() const
88 QList<QWebSocketProtocol::Version> HandshakeRequest::getVersions() const
96 QString HandshakeRequest::getResourceName() const
98 return m_requestUrl.path();
104 QString HandshakeRequest::getKey() const
112 QString HandshakeRequest::getHost() const
114 return m_requestUrl.host();
120 QString HandshakeRequest::getOrigin() const
128 QList<QString> HandshakeRequest::getProtocols() const
136 QList<QString> HandshakeRequest::getExtensions() const
144 QUrl HandshakeRequest::getRequestUrl() const
152 QTextStream &HandshakeRequest::readFromStream(QTextStream &textStream)
156 if (textStream.status() == QTextStream::Ok)
158 QString requestLine = textStream.readLine();
159 QStringList tokens = requestLine.split(' ', QString::SkipEmptyParts);
160 QString verb = tokens[0];
161 QString resourceName = tokens[1];
162 QString httpProtocol = tokens[2];
163 bool conversionOk = false;
164 float httpVersion = httpProtocol.midRef(5).toFloat(&conversionOk);
166 QString headerLine = textStream.readLine();
168 while (!headerLine.isEmpty())
170 QStringList headerField = headerLine.split(QString(": "), QString::SkipEmptyParts);
171 m_headers.insertMulti(headerField[0], headerField[1]);
172 headerLine = textStream.readLine();
175 QString host = m_headers.value("Host", "");
176 m_requestUrl = QUrl::fromEncoded(resourceName.toLatin1());
177 if (m_requestUrl.isRelative())
179 m_requestUrl.setHost(host);
181 if (m_requestUrl.scheme().isEmpty())
183 QString scheme = isSecure() ? "wss://" : "ws://";
184 m_requestUrl.setScheme(scheme);
187 QStringList versionLines = m_headers.values("Sec-WebSocket-Version");
188 Q_FOREACH(QString versionLine, versionLines)
190 QStringList versions = versionLine.split(",", QString::SkipEmptyParts);
191 Q_FOREACH(QString version, versions)
193 QWebSocketProtocol::Version ver = QWebSocketProtocol::versionFromString(version.trimmed());
197 qStableSort(m_versions.begin(), m_versions.end(), qGreater<QWebSocketProtocol::Version>()); //sort in descending order
198 m_key = m_headers.value("Sec-WebSocket-Key", "");
199 QString upgrade = m_headers.value("Upgrade", ""); //must be equal to "websocket", case-insensitive
200 QString connection = m_headers.value("Connection", ""); //must contain "Upgrade", case-insensitive
201 QStringList connectionLine = connection.split(",", QString::SkipEmptyParts);
202 QStringList connectionValues;
203 Q_FOREACH(QString connection, connectionLine)
205 connectionValues << connection.trimmed();
209 m_origin = m_headers.value("Sec-WebSocket-Origin", "");
210 QStringList protocolLines = m_headers.values("Sec-WebSocket-Protocol");
211 Q_FOREACH(QString protocolLine, protocolLines)
213 QStringList protocols = protocolLine.split(",", QString::SkipEmptyParts);
214 Q_FOREACH(QString protocol, protocols)
216 m_protocols << protocol.trimmed();
219 QStringList extensionLines = m_headers.values("Sec-WebSocket-Extensions");
220 Q_FOREACH(QString extensionLine, extensionLines)
222 QStringList extensions = extensionLine.split(",", QString::SkipEmptyParts);
223 Q_FOREACH(QString extension, extensions)
225 m_extensions << extension.trimmed();
228 //TODO: authentication field
230 m_isValid = !(host.isEmpty() ||
231 resourceName.isEmpty() ||
232 m_versions.isEmpty() ||
235 (!conversionOk || (httpVersion < 1.1f)) ||
236 (upgrade.toLower() != "websocket") ||
237 (!connectionValues.contains("upgrade", Qt::CaseInsensitive)));
245 QTextStream &operator >>(QTextStream &stream, HandshakeRequest &request)
247 return request.readFromStream(stream);