1 #include "qwebsocket.h"
2 #include "qwebsocket_p.h"
3 #include "handshakerequest_p.h"
4 #include "handshakeresponse_p.h"
9 #include <QCryptographicHash>
10 #include <QRegularExpression>
11 #include <QStringList>
12 #include <QHostAddress>
13 #ifndef QT_NONETWORKPROXY
14 #include <QNetworkProxy>
23 const quint64 FRAME_SIZE_IN_BYTES = 512 * 512 * 2; //maximum size of a frame when sending a message
28 QWebSocketPrivate::QWebSocketPrivate(QString origin, QWebSocketProtocol::Version version, QWebSocket *pWebSocket, QObject *parent) :
31 m_pSocket(new QTcpSocket(this)),
39 m_socketState(QAbstractSocket::UnconnectedState),
42 m_isClosingHandshakeSent(false),
43 m_isClosingHandshakeReceived(false),
47 Q_ASSERT(pWebSocket != 0);
48 makeConnections(m_pSocket);
49 qsrand(static_cast<uint>(QDateTime::currentMSecsSinceEpoch()));
55 QWebSocketPrivate::QWebSocketPrivate(QTcpSocket *pTcpSocket, QWebSocketProtocol::Version version, QWebSocket *pWebSocket, QObject *parent) :
58 m_pSocket(pTcpSocket),
59 m_errorString(pTcpSocket->errorString()),
66 m_socketState(pTcpSocket->state()),
69 m_isClosingHandshakeSent(false),
70 m_isClosingHandshakeReceived(false),
74 Q_ASSERT(pWebSocket != 0);
75 makeConnections(m_pSocket);
81 QWebSocketPrivate::~QWebSocketPrivate()
83 if (state() == QAbstractSocket::ConnectedState)
85 close(QWebSocketProtocol::CC_GOING_AWAY, "Connection closed");
87 releaseConnections(m_pSocket);
88 m_pSocket->deleteLater();
95 void QWebSocketPrivate::abort()
103 QAbstractSocket::SocketError QWebSocketPrivate::error() const
105 return m_pSocket->error();
111 QString QWebSocketPrivate::errorString() const
113 if (!m_errorString.isEmpty())
115 return m_errorString;
119 return m_pSocket->errorString();
126 bool QWebSocketPrivate::flush()
128 return m_pSocket->flush();
134 qint64 QWebSocketPrivate::write(const char *message)
136 return write(QString::fromUtf8(message));
142 qint64 QWebSocketPrivate::write(const char *message, qint64 maxSize)
144 return write(QString::fromUtf8(message, static_cast<int>(maxSize)));
150 qint64 QWebSocketPrivate::write(const QString &message)
152 return doWriteData(message.toUtf8(), false);
158 qint64 QWebSocketPrivate::write(const QByteArray &data)
160 return doWriteData(data, true);
166 QWebSocket *QWebSocketPrivate::upgradeFrom(QTcpSocket *pTcpSocket,
167 const HandshakeRequest &request,
168 const HandshakeResponse &response,
171 QWebSocket *pWebSocket = new QWebSocket(pTcpSocket, response.getAcceptedVersion(), parent);
172 pWebSocket->d_ptr->setExtension(response.getAcceptedExtension());
173 pWebSocket->d_ptr->setOrigin(request.getOrigin());
174 pWebSocket->d_ptr->setRequestUrl(request.getRequestUrl());
175 pWebSocket->d_ptr->setProtocol(response.getAcceptedProtocol());
176 pWebSocket->d_ptr->setResourceName(request.getRequestUrl().toString(QUrl::RemoveUserInfo));
177 pWebSocket->d_ptr->enableMasking(false); //a server should not send masked frames
185 void QWebSocketPrivate::close(QWebSocketProtocol::CloseCode closeCode, QString reason)
187 if (!m_isClosingHandshakeSent)
189 quint32 maskingKey = 0;
192 maskingKey = generateMaskingKey();
194 quint16 code = qToBigEndian<quint16>(closeCode);
196 payload.append(static_cast<const char *>(static_cast<const void *>(&code)), 2);
197 if (!reason.isEmpty())
199 payload.append(reason.toUtf8());
203 QWebSocketProtocol::mask(payload.data(), payload.size(), maskingKey);
205 QByteArray frame = getFrameHeader(QWebSocketProtocol::OC_CLOSE, payload.size(), maskingKey, true);
206 frame.append(payload);
207 m_pSocket->write(frame);
210 m_isClosingHandshakeSent = true;
212 Q_EMIT q_ptr->aboutToClose();
220 void QWebSocketPrivate::open(const QUrl &url, bool mask)
222 m_dataProcessor.clear();
223 m_isClosingHandshakeReceived = false;
224 m_isClosingHandshakeSent = false;
227 QString resourceName = url.path() + url.query();
228 if (resourceName.isEmpty())
232 setResourceName(resourceName);
235 setSocketState(QAbstractSocket::ConnectingState);
237 m_pSocket->connectToHost(url.host(), url.port(80));
243 void QWebSocketPrivate::ping()
245 m_pingTimer.restart();
246 QByteArray pingFrame = getFrameHeader(QWebSocketProtocol::OC_PING, 0, 0, true);
247 writeFrame(pingFrame);
252 Sets the version to use for the websocket protocol; this must be set before the socket is opened.
254 void QWebSocketPrivate::setVersion(QWebSocketProtocol::Version version)
261 Sets the resource name of the connection; must be set before the socket is openend
263 void QWebSocketPrivate::setResourceName(QString resourceName)
265 m_resourceName = resourceName;
271 void QWebSocketPrivate::setRequestUrl(QUrl requestUrl)
273 m_requestUrl = requestUrl;
279 void QWebSocketPrivate::setOrigin(QString origin)
287 void QWebSocketPrivate::setProtocol(QString protocol)
289 m_protocol = protocol;
295 void QWebSocketPrivate::setExtension(QString extension)
297 m_extension = extension;
303 void QWebSocketPrivate::enableMasking(bool enable)
311 qint64 QWebSocketPrivate::doWriteData(const QByteArray &data, bool isBinary)
313 return doWriteFrames(data, isBinary);
319 void QWebSocketPrivate::makeConnections(const QTcpSocket *pTcpSocket)
321 //pass through signals
322 connect(pTcpSocket, SIGNAL(error(QAbstractSocket::SocketError)), q_ptr, SIGNAL(error(QAbstractSocket::SocketError)));
323 connect(pTcpSocket, SIGNAL(proxyAuthenticationRequired(const QNetworkProxy &, QAuthenticator *)), q_ptr, SIGNAL(proxyAuthenticationRequired(const QNetworkProxy &, QAuthenticator *)));
324 connect(pTcpSocket, SIGNAL(readChannelFinished()), q_ptr, SIGNAL(readChannelFinished()));
325 //connect(pTcpSocket, SIGNAL(aboutToClose()), q_ptr, SIGNAL(aboutToClose()));
326 //connect(pTcpSocket, SIGNAL(bytesWritten(qint64)), q_ptr, SIGNAL(bytesWritten(qint64)));
329 connect(pTcpSocket, SIGNAL(stateChanged(QAbstractSocket::SocketState)), this, SLOT(processStateChanged(QAbstractSocket::SocketState)));
330 connect(pTcpSocket, SIGNAL(readyRead()), this, SLOT(processData()));
332 connect(&m_dataProcessor, SIGNAL(controlFrameReceived(QWebSocketProtocol::OpCode, QByteArray)), this, SLOT(processControlFrame(QWebSocketProtocol::OpCode, QByteArray)));
333 connect(&m_dataProcessor, SIGNAL(textFrameReceived(QString,bool)), q_ptr, SIGNAL(textFrameReceived(QString,bool)));
334 connect(&m_dataProcessor, SIGNAL(binaryFrameReceived(QByteArray,bool)), q_ptr, SIGNAL(binaryFrameReceived(QByteArray,bool)));
335 connect(&m_dataProcessor, SIGNAL(binaryMessageReceived(QByteArray)), q_ptr, SIGNAL(binaryMessageReceived(QByteArray)));
336 connect(&m_dataProcessor, SIGNAL(textMessageReceived(QString)), q_ptr, SIGNAL(textMessageReceived(QString)));
337 connect(&m_dataProcessor, SIGNAL(errorEncountered(QWebSocketProtocol::CloseCode,QString)), this, SLOT(close(QWebSocketProtocol::CloseCode,QString)));
343 void QWebSocketPrivate::releaseConnections(const QTcpSocket *pTcpSocket)
347 //pass through signals
348 disconnect(pTcpSocket, SIGNAL(error(QAbstractSocket::SocketError)), q_ptr, SIGNAL(error(QAbstractSocket::SocketError)));
349 disconnect(pTcpSocket, SIGNAL(proxyAuthenticationRequired(const QNetworkProxy &, QAuthenticator *)), q_ptr, SIGNAL(proxyAuthenticationRequired(const QNetworkProxy &, QAuthenticator *)));
350 disconnect(pTcpSocket, SIGNAL(readChannelFinished()), q_ptr, SIGNAL(readChannelFinished()));
351 //disconnect(pTcpSocket, SIGNAL(aboutToClose()), q_ptr, SIGNAL(aboutToClose()));
352 //disconnect(pTcpSocket, SIGNAL(bytesWritten(qint64)), q_ptr, SIGNAL(bytesWritten(qint64)));
355 disconnect(pTcpSocket, SIGNAL(stateChanged(QAbstractSocket::SocketState)), this, SLOT(processStateChanged(QAbstractSocket::SocketState)));
356 disconnect(pTcpSocket, SIGNAL(readyRead()), this, SLOT(processData()));
358 disconnect(&m_dataProcessor, SIGNAL(controlFrameReceived(QWebSocketProtocol::OpCode,QByteArray)), this, SLOT(processControlFrame(QWebSocketProtocol::OpCode,QByteArray)));
359 disconnect(&m_dataProcessor, SIGNAL(textFrameReceived(QString,bool)), q_ptr, SIGNAL(textFrameReceived(QString,bool)));
360 disconnect(&m_dataProcessor, SIGNAL(binaryFrameReceived(QByteArray,bool)), q_ptr, SIGNAL(binaryFrameReceived(QByteArray,bool)));
361 disconnect(&m_dataProcessor, SIGNAL(binaryMessageReceived(QByteArray)), q_ptr, SIGNAL(binaryMessageReceived(QByteArray)));
362 disconnect(&m_dataProcessor, SIGNAL(textMessageReceived(QString)), q_ptr, SIGNAL(textMessageReceived(QString)));
363 disconnect(&m_dataProcessor, SIGNAL(errorEncountered(QWebSocketProtocol::CloseCode,QString)), this, SLOT(close(QWebSocketProtocol::CloseCode,QString)));
369 QWebSocketProtocol::Version QWebSocketPrivate::version()
377 QString QWebSocketPrivate::resourceName()
379 return m_resourceName;
385 QUrl QWebSocketPrivate::requestUrl()
393 QString QWebSocketPrivate::origin()
401 QString QWebSocketPrivate::protocol()
409 QString QWebSocketPrivate::extension()
417 QByteArray QWebSocketPrivate::getFrameHeader(QWebSocketProtocol::OpCode opCode, quint64 payloadLength, quint32 maskingKey, bool lastFrame) const
421 bool ok = payloadLength <= 0x7FFFFFFFFFFFFFFFULL;
425 //FIN, RSV1-3, opcode
426 byte = static_cast<quint8>((opCode & 0x0F) | (lastFrame ? 0x80 : 0x00)); //FIN, opcode
427 //RSV-1, RSV-2 and RSV-3 are zero
428 header.append(static_cast<char>(byte));
430 //Now write the masking bit and the payload length byte
436 if (payloadLength <= 125)
438 byte |= static_cast<quint8>(payloadLength);
439 header.append(static_cast<char>(byte));
441 else if (payloadLength <= 0xFFFFU)
444 header.append(static_cast<char>(byte));
445 quint16 swapped = qToBigEndian<quint16>(static_cast<quint16>(payloadLength));
446 header.append(static_cast<const char *>(static_cast<const void *>(&swapped)), 2);
448 else if (payloadLength <= 0x7FFFFFFFFFFFFFFFULL)
451 header.append(static_cast<char>(byte));
452 quint64 swapped = qToBigEndian<quint64>(payloadLength);
453 header.append(static_cast<const char *>(static_cast<const void *>(&swapped)), 8);
459 header.append(static_cast<const char *>(static_cast<const void *>(&maskingKey)), sizeof(quint32));
464 //setErrorString("WebSocket::getHeader: payload too big!");
465 //Q_EMIT q_ptr->error(QAbstractSocket::DatagramTooLargeError);
466 qDebug() << "WebSocket::getHeader: payload too big!";
475 qint64 QWebSocketPrivate::doWriteFrames(const QByteArray &data, bool isBinary)
477 const QWebSocketProtocol::OpCode firstOpCode = isBinary ? QWebSocketProtocol::OC_BINARY : QWebSocketProtocol::OC_TEXT;
479 int numFrames = data.size() / FRAME_SIZE_IN_BYTES;
480 QByteArray tmpData(data);
482 char *payload = tmpData.data();
483 quint64 sizeLeft = static_cast<quint64>(data.size()) % FRAME_SIZE_IN_BYTES;
488 if (numFrames == 0) //catch the case where the payload is zero bytes; in that case, we still need to send a frame
492 quint64 currentPosition = 0;
493 qint64 bytesWritten = 0;
494 qint64 payloadWritten = 0;
495 quint64 bytesLeft = data.size();
497 for (int i = 0; i < numFrames; ++i)
499 quint32 maskingKey = 0;
502 maskingKey = generateMaskingKey();
505 bool isLastFrame = (i == (numFrames - 1));
506 bool isFirstFrame = (i == 0);
508 quint64 size = qMin(bytesLeft, FRAME_SIZE_IN_BYTES);
509 QWebSocketProtocol::OpCode opcode = isFirstFrame ? firstOpCode : QWebSocketProtocol::OC_CONTINUE;
512 bytesWritten += m_pSocket->write(getFrameHeader(opcode, size, maskingKey, isLastFrame));
517 char *currentData = payload + currentPosition;
520 QWebSocketProtocol::mask(currentData, size, maskingKey);
522 qint64 written = m_pSocket->write(currentData, static_cast<qint64>(size));
525 bytesWritten += written;
526 payloadWritten += written;
530 setErrorString("WebSocket::doWriteFrames: Error writing bytes to socket: " + m_pSocket->errorString());
531 qDebug() << errorString();
533 Q_EMIT q_ptr->error(QAbstractSocket::NetworkError);
537 currentPosition += size;
540 if (payloadWritten != data.size())
542 setErrorString("Bytes written " + QString::number(payloadWritten) + " != " + QString::number(data.size()));
543 qDebug() << errorString();
544 Q_EMIT q_ptr->error(QAbstractSocket::NetworkError);
546 return payloadWritten;
552 quint32 QWebSocketPrivate::generateRandomNumber() const
554 return static_cast<quint32>((static_cast<double>(qrand()) / RAND_MAX) * std::numeric_limits<quint32>::max());
560 quint32 QWebSocketPrivate::generateMaskingKey() const
562 return generateRandomNumber();
568 QByteArray QWebSocketPrivate::generateKey() const
572 for (int i = 0; i < 4; ++i)
574 quint32 tmp = generateRandomNumber();
575 key.append(static_cast<const char *>(static_cast<const void *>(&tmp)), sizeof(quint32));
578 return key.toBase64();
585 QString QWebSocketPrivate::calculateAcceptKey(const QString &key) const
587 QString tmpKey = key + "258EAFA5-E914-47DA-95CA-C5AB0DC85B11";
588 QByteArray hash = QCryptographicHash::hash(tmpKey.toLatin1(), QCryptographicHash::Sha1);
589 return QString(hash.toBase64());
595 qint64 QWebSocketPrivate::writeFrames(const QList<QByteArray> &frames)
598 for (int i = 0; i < frames.size(); ++i)
600 written += writeFrame(frames[i]);
608 qint64 QWebSocketPrivate::writeFrame(const QByteArray &frame)
610 return m_pSocket->write(frame);
616 QString readLine(QTcpSocket *pSocket)
620 while (pSocket->getChar(&c))
624 pSocket->getChar(&c);
629 line.append(QChar(c));
635 //called on the client for a server handshake response
639 void QWebSocketPrivate::processHandshake(QTcpSocket *pSocket)
647 QString errorDescription;
649 const QString regExpStatusLine("^(HTTP/[0-9]+\\.[0-9]+)\\s([0-9]+)\\s(.*)");
650 const QRegularExpression regExp(regExpStatusLine);
651 QString statusLine = readLine(pSocket);
652 QString httpProtocol;
654 QString httpStatusMessage;
655 QRegularExpressionMatch match = regExp.match(statusLine);
656 if (match.hasMatch())
658 QStringList tokens = match.capturedTexts();
659 tokens.removeFirst(); //remove the search string
660 if (tokens.length() == 3)
662 httpProtocol = tokens[0];
663 httpStatusCode = tokens[1].toInt();
664 httpStatusMessage = tokens[2].trimmed();
670 errorDescription = "WebSocket::processHandshake: Invalid statusline in response: " + statusLine;
674 QString headerLine = readLine(pSocket);
675 QMap<QString, QString> headers;
676 while (!headerLine.isEmpty())
678 QStringList headerField = headerLine.split(QString(": "), QString::SkipEmptyParts);
679 headers.insertMulti(headerField[0], headerField[1]);
680 headerLine = readLine(pSocket);
683 QString acceptKey = headers.value("Sec-WebSocket-Accept", "");
684 QString upgrade = headers.value("Upgrade", "");
685 QString connection = headers.value("Connection", "");
686 //unused for the moment
687 //QString extensions = headers.value("Sec-WebSocket-Extensions", "");
688 //QString protocol = headers.value("Sec-WebSocket-Protocol", "");
689 QString version = headers.value("Sec-WebSocket-Version", "");
691 if (httpStatusCode == 101) //HTTP/x.y 101 Switching Protocols
693 bool conversionOk = false;
694 float version = httpProtocol.midRef(5).toFloat(&conversionOk);
695 //TODO: do not check the httpStatusText right now
696 ok = !(acceptKey.isEmpty() ||
697 (!conversionOk || (version < 1.1f)) ||
698 (upgrade.toLower() != "websocket") ||
699 (connection.toLower() != "upgrade"));
702 QString accept = calculateAcceptKey(m_key);
703 ok = (accept == acceptKey);
706 errorDescription = "WebSocket::processHandshake: Accept-Key received from server " + acceptKey + " does not match the client key " + accept;
711 errorDescription = "WebSocket::processHandshake: Invalid statusline in response: " + statusLine;
714 else if (httpStatusCode == 400) //HTTP/1.1 400 Bad Request
716 if (!version.isEmpty())
718 QStringList versions = version.split(", ", QString::SkipEmptyParts);
719 if (!versions.contains(QString::number(QWebSocketProtocol::currentVersion())))
721 //if needed to switch protocol version, then we are finished here
722 //because we cannot handle other protocols than the RFC one (v13)
723 errorDescription = "WebSocket::processHandshake: Server requests a version that we don't support: " + versions.join(", ");
728 //we tried v13, but something different went wrong
729 errorDescription = "WebSocket::processHandshake: Unknown error condition encountered. Aborting connection.";
736 errorDescription = "WebSocket::processHandshake: Unhandled http status code " + QString::number(httpStatusCode);
742 qDebug() << errorDescription;
743 setErrorString(errorDescription);
744 Q_EMIT q_ptr->error(QAbstractSocket::ConnectionRefusedError);
748 //handshake succeeded
749 setSocketState(QAbstractSocket::ConnectedState);
750 Q_EMIT q_ptr->connected();
758 void QWebSocketPrivate::processStateChanged(QAbstractSocket::SocketState socketState)
760 QAbstractSocket::SocketState webSocketState = this->state();
763 case QAbstractSocket::ConnectedState:
765 if (webSocketState == QAbstractSocket::ConnectingState)
767 m_key = generateKey();
768 QString handshake = createHandShakeRequest(m_resourceName, m_requestUrl.host() + ":" + QString::number(m_requestUrl.port(80)), origin(), "", "", m_key);
769 m_pSocket->write(handshake.toLatin1());
773 case QAbstractSocket::ClosingState:
775 if (webSocketState == QAbstractSocket::ConnectedState)
777 setSocketState(QAbstractSocket::ClosingState);
781 case QAbstractSocket::UnconnectedState:
783 if (webSocketState != QAbstractSocket::UnconnectedState)
785 setSocketState(QAbstractSocket::UnconnectedState);
786 Q_EMIT q_ptr->disconnected();
790 case QAbstractSocket::HostLookupState:
791 case QAbstractSocket::ConnectingState:
792 case QAbstractSocket::BoundState:
793 case QAbstractSocket::ListeningState:
796 //to make C++ compiler happy;
807 //connectToHost is called
808 //our socket state is set to "connecting", and tcpSocket->connectToHost is called
809 //the tcpsocket is opened, a handshake message is sent; a readyRead signal is thrown
810 //this signal is catched by processData
811 //when OUR socket state is in the "connecting state", this means that
812 //we have received data from the server (response to handshake), and that we
813 //should "upgrade" our socket to a websocket (connected state)
814 //if our socket was already upgraded, then we need to process websocket data
818 void QWebSocketPrivate::processData()
820 while (m_pSocket->bytesAvailable())
822 if (state() == QAbstractSocket::ConnectingState)
824 processHandshake(m_pSocket);
828 m_dataProcessor.process(m_pSocket);
836 void QWebSocketPrivate::processControlFrame(QWebSocketProtocol::OpCode opCode, QByteArray frame)
840 case QWebSocketProtocol::OC_PING:
842 quint32 maskingKey = 0;
845 maskingKey = generateMaskingKey();
847 m_pSocket->write(getFrameHeader(QWebSocketProtocol::OC_PONG, frame.size(), maskingKey, true));
848 if (frame.size() > 0)
852 QWebSocketProtocol::mask(&frame, maskingKey);
854 m_pSocket->write(frame);
858 case QWebSocketProtocol::OC_PONG:
860 Q_EMIT q_ptr->pong(static_cast<quint64>(m_pingTimer.elapsed()));
863 case QWebSocketProtocol::OC_CLOSE:
865 quint16 closeCode = QWebSocketProtocol::CC_NORMAL;
867 if (frame.size() > 0) //close frame can have a close code and reason
869 closeCode = qFromBigEndian<quint16>(reinterpret_cast<const uchar *>(frame.constData()));
870 if (!QWebSocketProtocol::isCloseCodeValid(closeCode))
872 closeCode = QWebSocketProtocol::CC_PROTOCOL_ERROR;
873 closeReason = QString("Invalid close code %1 detected").arg(closeCode);
877 if (frame.size() > 2)
879 QTextCodec *tc = QTextCodec::codecForName("UTF-8");
880 QTextCodec::ConverterState state(QTextCodec::ConvertInvalidToNull);
881 closeReason = tc->toUnicode(frame.constData() + 2, frame.size() - 2, &state);
882 bool failed = (state.invalidChars != 0) || (state.remainingChars != 0);
885 closeCode = QWebSocketProtocol::CC_WRONG_DATATYPE;
886 closeReason = "Invalid UTF-8 code encountered.";
891 m_isClosingHandshakeReceived = true;
892 close(static_cast<QWebSocketProtocol::CloseCode>(closeCode), closeReason);
895 case QWebSocketProtocol::OC_CONTINUE:
896 case QWebSocketProtocol::OC_BINARY:
897 case QWebSocketProtocol::OC_TEXT:
898 case QWebSocketProtocol::OC_RESERVED_3:
899 case QWebSocketProtocol::OC_RESERVED_4:
900 case QWebSocketProtocol::OC_RESERVED_5:
901 case QWebSocketProtocol::OC_RESERVED_6:
902 case QWebSocketProtocol::OC_RESERVED_7:
903 case QWebSocketProtocol::OC_RESERVED_B:
904 case QWebSocketProtocol::OC_RESERVED_D:
905 case QWebSocketProtocol::OC_RESERVED_E:
906 case QWebSocketProtocol::OC_RESERVED_F:
907 case QWebSocketProtocol::OC_RESERVED_V:
910 //case added to make C++ compiler happy
915 qDebug() << "WebSocket::processData: Invalid opcode detected:" << static_cast<int>(opCode);
925 QString QWebSocketPrivate::createHandShakeRequest(QString resourceName,
932 QStringList handshakeRequest;
934 handshakeRequest << "GET " + resourceName + " HTTP/1.1" <<
936 "Upgrade: websocket" <<
937 "Connection: Upgrade" <<
938 "Sec-WebSocket-Key: " + QString(key);
939 if (!origin.isEmpty())
941 handshakeRequest << "Origin: " + origin;
943 handshakeRequest << "Sec-WebSocket-Version: " + QString::number(QWebSocketProtocol::currentVersion());
944 if (extensions.length() > 0)
946 handshakeRequest << "Sec-WebSocket-Extensions: " + extensions;
948 if (protocols.length() > 0)
950 handshakeRequest << "Sec-WebSocket-Protocol: " + protocols;
952 handshakeRequest << "\r\n";
954 return handshakeRequest.join("\r\n");
960 QAbstractSocket::SocketState QWebSocketPrivate::state() const
962 return m_socketState;
968 bool QWebSocketPrivate::waitForConnected(int msecs)
973 retVal = m_pSocket->waitForConnected(msecs);
981 bool QWebSocketPrivate::waitForDisconnected(int msecs)
986 retVal = m_pSocket->waitForDisconnected(msecs);
994 void QWebSocketPrivate::setSocketState(QAbstractSocket::SocketState state)
996 if (m_socketState != state)
998 m_socketState = state;
999 Q_EMIT q_ptr->stateChanged(m_socketState);
1006 void QWebSocketPrivate::setErrorString(QString errorString)
1008 m_errorString = errorString;
1014 QHostAddress QWebSocketPrivate::localAddress() const
1016 QHostAddress address;
1019 address = m_pSocket->localAddress();
1027 quint16 QWebSocketPrivate::localPort() const
1032 port = m_pSocket->localPort();
1040 QAbstractSocket::PauseModes QWebSocketPrivate::pauseMode() const
1042 QAbstractSocket::PauseModes mode = QAbstractSocket::PauseNever;
1045 mode = m_pSocket->pauseMode();
1053 QHostAddress QWebSocketPrivate::peerAddress() const
1058 peer = m_pSocket->peerAddress();
1066 QString QWebSocketPrivate::peerName() const
1071 name = m_pSocket->peerName();
1079 quint16 QWebSocketPrivate::peerPort() const
1084 port = m_pSocket->peerPort();
1092 QNetworkProxy QWebSocketPrivate::proxy() const
1094 QNetworkProxy proxy;
1097 proxy = m_pSocket->proxy();
1105 qint64 QWebSocketPrivate::readBufferSize() const
1107 qint64 readBuffer = 0;
1110 readBuffer = m_pSocket->readBufferSize();
1118 void QWebSocketPrivate::resume()
1122 m_pSocket->resume();
1129 void QWebSocketPrivate::setPauseMode(QAbstractSocket::PauseModes pauseMode)
1133 m_pSocket->setPauseMode(pauseMode);
1140 void QWebSocketPrivate::setProxy(const QNetworkProxy &networkProxy)
1144 m_pSocket->setProxy(networkProxy);
1151 void QWebSocketPrivate::setReadBufferSize(qint64 size)
1155 m_pSocket->setReadBufferSize(size);
1162 void QWebSocketPrivate::setSocketOption(QAbstractSocket::SocketOption option, const QVariant &value)
1166 m_pSocket->setSocketOption(option, value);
1173 QVariant QWebSocketPrivate::socketOption(QAbstractSocket::SocketOption option)
1178 result = m_pSocket->socketOption(option);
1186 bool QWebSocketPrivate::isValid()
1191 valid = m_pSocket->isValid();