2 QWebSockets implements the WebSocket protocol as defined in RFC 6455.
3 Copyright (C) 2013 Kurt Pattyn (pattyn.kurt@gmail.com)
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.
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.
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
20 #include "qwebsocket.h"
21 #include "qwebsocket_p.h"
22 #include "handshakerequest_p.h"
23 #include "handshakeresponse_p.h"
28 #include <QCryptographicHash>
29 #include <QRegularExpression>
30 #include <QStringList>
31 #include <QHostAddress>
32 #include <QStringBuilder> //for more efficient string concatenation
33 #ifndef QT_NONETWORKPROXY
34 #include <QNetworkProxy>
43 const quint64 FRAME_SIZE_IN_BYTES = 512 * 512 * 2; //maximum size of a frame when sending a message
48 QWebSocketPrivate::QWebSocketPrivate(const QString &origin, QWebSocketProtocol::Version version, QWebSocket *pWebSocket, QObject *parent) :
51 m_pSocket(new QTcpSocket(this)),
59 m_socketState(QAbstractSocket::UnconnectedState),
62 m_isClosingHandshakeSent(false),
63 m_isClosingHandshakeReceived(false),
67 Q_ASSERT(pWebSocket != 0);
68 makeConnections(m_pSocket);
69 qsrand(static_cast<uint>(QDateTime::currentMSecsSinceEpoch()));
75 QWebSocketPrivate::QWebSocketPrivate(QTcpSocket *pTcpSocket, QWebSocketProtocol::Version version, QWebSocket *pWebSocket, QObject *parent) :
78 m_pSocket(pTcpSocket),
79 m_errorString(pTcpSocket->errorString()),
86 m_socketState(pTcpSocket->state()),
89 m_isClosingHandshakeSent(false),
90 m_isClosingHandshakeReceived(false),
94 Q_ASSERT(pWebSocket != 0);
95 makeConnections(m_pSocket);
101 QWebSocketPrivate::~QWebSocketPrivate()
103 if (state() == QAbstractSocket::ConnectedState)
105 close(QWebSocketProtocol::CC_GOING_AWAY, tr("Connection closed"));
107 releaseConnections(m_pSocket);
108 m_pSocket->deleteLater();
115 void QWebSocketPrivate::abort()
123 QAbstractSocket::SocketError QWebSocketPrivate::error() const
125 return m_pSocket->error();
131 QString QWebSocketPrivate::errorString() const
133 if (!m_errorString.isEmpty())
135 return m_errorString;
139 return m_pSocket->errorString();
146 bool QWebSocketPrivate::flush()
148 return m_pSocket->flush();
154 qint64 QWebSocketPrivate::write(const char *message)
156 return write(QString::fromUtf8(message));
162 qint64 QWebSocketPrivate::write(const char *message, qint64 maxSize)
164 return write(QString::fromUtf8(message, static_cast<int>(maxSize)));
170 qint64 QWebSocketPrivate::write(const QString &message)
172 return doWriteData(message.toUtf8(), false);
178 qint64 QWebSocketPrivate::write(const QByteArray &data)
180 return doWriteData(data, true);
186 QWebSocket *QWebSocketPrivate::upgradeFrom(QTcpSocket *pTcpSocket,
187 const HandshakeRequest &request,
188 const HandshakeResponse &response,
191 QWebSocket *pWebSocket = new QWebSocket(pTcpSocket, response.getAcceptedVersion(), parent);
192 pWebSocket->d_func()->setExtension(response.getAcceptedExtension());
193 pWebSocket->d_func()->setOrigin(request.getOrigin());
194 pWebSocket->d_func()->setRequestUrl(request.getRequestUrl());
195 pWebSocket->d_func()->setProtocol(response.getAcceptedProtocol());
196 pWebSocket->d_func()->setResourceName(request.getRequestUrl().toString(QUrl::RemoveUserInfo));
197 pWebSocket->d_func()->enableMasking(false); //a server should not send masked frames
205 void QWebSocketPrivate::close(QWebSocketProtocol::CloseCode closeCode, QString reason)
208 if (!m_isClosingHandshakeSent)
210 quint32 maskingKey = 0;
213 maskingKey = generateMaskingKey();
215 quint16 code = qToBigEndian<quint16>(closeCode);
217 payload.append(static_cast<const char *>(static_cast<const void *>(&code)), 2);
218 if (!reason.isEmpty())
220 payload.append(reason.toUtf8());
224 QWebSocketProtocol::mask(payload.data(), payload.size(), maskingKey);
226 QByteArray frame = getFrameHeader(QWebSocketProtocol::OC_CLOSE, payload.size(), maskingKey, true);
227 frame.append(payload);
228 m_pSocket->write(frame);
231 m_isClosingHandshakeSent = true;
233 Q_EMIT q->aboutToClose();
241 void QWebSocketPrivate::open(const QUrl &url, bool mask)
243 m_dataProcessor.clear();
244 m_isClosingHandshakeReceived = false;
245 m_isClosingHandshakeSent = false;
248 QString resourceName = url.path();
249 if (!url.query().isEmpty())
251 resourceName.append("?" + url.query());
253 if (resourceName.isEmpty())
257 setResourceName(resourceName);
260 setSocketState(QAbstractSocket::ConnectingState);
262 m_pSocket->connectToHost(url.host(), url.port(80));
268 void QWebSocketPrivate::ping(const QByteArray &payload)
270 Q_ASSERT(payload.length() < 126);
271 m_pingTimer.restart();
272 QByteArray pingFrame = getFrameHeader(QWebSocketProtocol::OC_PING, payload.size(), 0 /*do not mask*/, true);
273 pingFrame.append(payload);
274 writeFrame(pingFrame);
279 Sets the version to use for the websocket protocol; this must be set before the socket is opened.
281 void QWebSocketPrivate::setVersion(QWebSocketProtocol::Version version)
288 Sets the resource name of the connection; must be set before the socket is openend
290 void QWebSocketPrivate::setResourceName(const QString &resourceName)
292 m_resourceName = resourceName;
298 void QWebSocketPrivate::setRequestUrl(const QUrl &requestUrl)
300 m_requestUrl = requestUrl;
306 void QWebSocketPrivate::setOrigin(const QString &origin)
314 void QWebSocketPrivate::setProtocol(const QString &protocol)
316 m_protocol = protocol;
322 void QWebSocketPrivate::setExtension(const QString &extension)
324 m_extension = extension;
330 void QWebSocketPrivate::enableMasking(bool enable)
338 qint64 QWebSocketPrivate::doWriteData(const QByteArray &data, bool isBinary)
340 return doWriteFrames(data, isBinary);
346 void QWebSocketPrivate::makeConnections(const QTcpSocket *pTcpSocket)
349 //pass through signals
350 connect(pTcpSocket, SIGNAL(error(QAbstractSocket::SocketError)), q, SIGNAL(error(QAbstractSocket::SocketError)));
351 connect(pTcpSocket, SIGNAL(proxyAuthenticationRequired(const QNetworkProxy &, QAuthenticator *)), q, SIGNAL(proxyAuthenticationRequired(const QNetworkProxy &, QAuthenticator *)));
352 connect(pTcpSocket, SIGNAL(readChannelFinished()), q, SIGNAL(readChannelFinished()));
353 connect(pTcpSocket, SIGNAL(aboutToClose()), q, SIGNAL(aboutToClose()));
354 //connect(pTcpSocket, SIGNAL(bytesWritten(qint64)), q, SIGNAL(bytesWritten(qint64)));
357 connect(pTcpSocket, SIGNAL(stateChanged(QAbstractSocket::SocketState)), this, SLOT(processStateChanged(QAbstractSocket::SocketState)));
358 connect(pTcpSocket, SIGNAL(readyRead()), this, SLOT(processData()));
360 connect(&m_dataProcessor, SIGNAL(textFrameReceived(QString,bool)), q, SIGNAL(textFrameReceived(QString,bool)));
361 connect(&m_dataProcessor, SIGNAL(binaryFrameReceived(QByteArray,bool)), q, SIGNAL(binaryFrameReceived(QByteArray,bool)));
362 connect(&m_dataProcessor, SIGNAL(binaryMessageReceived(QByteArray)), q, SIGNAL(binaryMessageReceived(QByteArray)));
363 connect(&m_dataProcessor, SIGNAL(textMessageReceived(QString)), q, SIGNAL(textMessageReceived(QString)));
364 connect(&m_dataProcessor, SIGNAL(errorEncountered(QWebSocketProtocol::CloseCode,QString)), this, SLOT(close(QWebSocketProtocol::CloseCode,QString)));
365 connect(&m_dataProcessor, SIGNAL(pingReceived(QByteArray)), this, SLOT(processPing(QByteArray)));
366 connect(&m_dataProcessor, SIGNAL(pongReceived(QByteArray)), this, SLOT(processPong(QByteArray)));
367 connect(&m_dataProcessor, SIGNAL(closeReceived(QWebSocketProtocol::CloseCode,QString)), this, SLOT(processClose(QWebSocketProtocol::CloseCode,QString)));
373 void QWebSocketPrivate::releaseConnections(const QTcpSocket *pTcpSocket)
378 //pass through signals
379 disconnect(pTcpSocket, SIGNAL(error(QAbstractSocket::SocketError)), q, SIGNAL(error(QAbstractSocket::SocketError)));
380 disconnect(pTcpSocket, SIGNAL(proxyAuthenticationRequired(const QNetworkProxy &, QAuthenticator *)), q, SIGNAL(proxyAuthenticationRequired(const QNetworkProxy &, QAuthenticator *)));
381 disconnect(pTcpSocket, SIGNAL(readChannelFinished()), q, SIGNAL(readChannelFinished()));
382 disconnect(pTcpSocket, SIGNAL(aboutToClose()), q, SIGNAL(aboutToClose()));
383 //disconnect(pTcpSocket, SIGNAL(bytesWritten(qint64)), q, SIGNAL(bytesWritten(qint64)));
386 disconnect(pTcpSocket, SIGNAL(stateChanged(QAbstractSocket::SocketState)), this, SLOT(processStateChanged(QAbstractSocket::SocketState)));
387 disconnect(pTcpSocket, SIGNAL(readyRead()), this, SLOT(processData()));
389 disconnect(&m_dataProcessor, SIGNAL(pingReceived(QByteArray)), this, SLOT(processPing(QByteArray)));
390 disconnect(&m_dataProcessor, SIGNAL(pongReceived(QByteArray)), this, SLOT(processPong(QByteArray)));
391 disconnect(&m_dataProcessor, SIGNAL(closeReceived(QWebSocketProtocol::CloseCode,QString)), this, SLOT(processClose(QWebSocketProtocol::CloseCode,QString)));
392 disconnect(&m_dataProcessor, SIGNAL(textFrameReceived(QString,bool)), q, SIGNAL(textFrameReceived(QString,bool)));
393 disconnect(&m_dataProcessor, SIGNAL(binaryFrameReceived(QByteArray,bool)), q, SIGNAL(binaryFrameReceived(QByteArray,bool)));
394 disconnect(&m_dataProcessor, SIGNAL(binaryMessageReceived(QByteArray)), q, SIGNAL(binaryMessageReceived(QByteArray)));
395 disconnect(&m_dataProcessor, SIGNAL(textMessageReceived(QString)), q, SIGNAL(textMessageReceived(QString)));
396 disconnect(&m_dataProcessor, SIGNAL(errorEncountered(QWebSocketProtocol::CloseCode,QString)), this, SLOT(close(QWebSocketProtocol::CloseCode,QString)));
402 QWebSocketProtocol::Version QWebSocketPrivate::version() const
410 QString QWebSocketPrivate::resourceName() const
412 return m_resourceName;
418 QUrl QWebSocketPrivate::requestUrl() const
426 QString QWebSocketPrivate::origin() const
434 QString QWebSocketPrivate::protocol() const
442 QString QWebSocketPrivate::extension() const
450 QByteArray QWebSocketPrivate::getFrameHeader(QWebSocketProtocol::OpCode opCode, quint64 payloadLength, quint32 maskingKey, bool lastFrame) const
454 bool ok = payloadLength <= 0x7FFFFFFFFFFFFFFFULL;
458 //FIN, RSV1-3, opcode
459 byte = static_cast<quint8>((opCode & 0x0F) | (lastFrame ? 0x80 : 0x00)); //FIN, opcode
460 //RSV-1, RSV-2 and RSV-3 are zero
461 header.append(static_cast<char>(byte));
463 //Now write the masking bit and the payload length byte
469 if (payloadLength <= 125)
471 byte |= static_cast<quint8>(payloadLength);
472 header.append(static_cast<char>(byte));
474 else if (payloadLength <= 0xFFFFU)
477 header.append(static_cast<char>(byte));
478 quint16 swapped = qToBigEndian<quint16>(static_cast<quint16>(payloadLength));
479 header.append(static_cast<const char *>(static_cast<const void *>(&swapped)), 2);
481 else if (payloadLength <= 0x7FFFFFFFFFFFFFFFULL)
484 header.append(static_cast<char>(byte));
485 quint64 swapped = qToBigEndian<quint64>(payloadLength);
486 header.append(static_cast<const char *>(static_cast<const void *>(&swapped)), 8);
492 header.append(static_cast<const char *>(static_cast<const void *>(&maskingKey)), sizeof(quint32));
497 //setErrorString("WebSocket::getHeader: payload too big!");
498 //Q_EMIT q_ptr->error(QAbstractSocket::DatagramTooLargeError);
499 qDebug() << "WebSocket::getHeader: payload too big!";
508 qint64 QWebSocketPrivate::doWriteFrames(const QByteArray &data, bool isBinary)
511 const QWebSocketProtocol::OpCode firstOpCode = isBinary ? QWebSocketProtocol::OC_BINARY : QWebSocketProtocol::OC_TEXT;
513 int numFrames = data.size() / FRAME_SIZE_IN_BYTES;
514 QByteArray tmpData(data);
516 char *payload = tmpData.data();
517 quint64 sizeLeft = static_cast<quint64>(data.size()) % FRAME_SIZE_IN_BYTES;
522 if (numFrames == 0) //catch the case where the payload is zero bytes; in that case, we still need to send a frame
526 quint64 currentPosition = 0;
527 qint64 bytesWritten = 0;
528 qint64 payloadWritten = 0;
529 quint64 bytesLeft = data.size();
531 for (int i = 0; i < numFrames; ++i)
533 quint32 maskingKey = 0;
536 maskingKey = generateMaskingKey();
539 bool isLastFrame = (i == (numFrames - 1));
540 bool isFirstFrame = (i == 0);
542 quint64 size = qMin(bytesLeft, FRAME_SIZE_IN_BYTES);
543 QWebSocketProtocol::OpCode opcode = isFirstFrame ? firstOpCode : QWebSocketProtocol::OC_CONTINUE;
546 bytesWritten += m_pSocket->write(getFrameHeader(opcode, size, maskingKey, isLastFrame));
551 char *currentData = payload + currentPosition;
554 QWebSocketProtocol::mask(currentData, size, maskingKey);
556 qint64 written = m_pSocket->write(currentData, static_cast<qint64>(size));
559 bytesWritten += written;
560 payloadWritten += written;
564 setErrorString(tr("Error writing bytes to socket: %1.").arg(m_pSocket->errorString()));
565 qDebug() << errorString();
567 Q_EMIT q->error(QAbstractSocket::NetworkError);
571 currentPosition += size;
574 if (payloadWritten != data.size())
576 setErrorString(tr("Bytes written %1 != %2.").arg(payloadWritten).arg(data.size()));
577 qDebug() << errorString();
578 Q_EMIT q->error(QAbstractSocket::NetworkError);
580 return payloadWritten;
586 quint32 QWebSocketPrivate::generateRandomNumber() const
588 return static_cast<quint32>((static_cast<double>(qrand()) / RAND_MAX) * std::numeric_limits<quint32>::max());
594 quint32 QWebSocketPrivate::generateMaskingKey() const
596 return generateRandomNumber();
602 QByteArray QWebSocketPrivate::generateKey() const
606 for (int i = 0; i < 4; ++i)
608 quint32 tmp = generateRandomNumber();
609 key.append(static_cast<const char *>(static_cast<const void *>(&tmp)), sizeof(quint32));
612 return key.toBase64();
619 QString QWebSocketPrivate::calculateAcceptKey(const QString &key) const
621 QString tmpKey = key % "258EAFA5-E914-47DA-95CA-C5AB0DC85B11";
622 QByteArray hash = QCryptographicHash::hash(tmpKey.toLatin1(), QCryptographicHash::Sha1);
623 return QString(hash.toBase64());
629 qint64 QWebSocketPrivate::writeFrames(const QList<QByteArray> &frames)
632 for (int i = 0; i < frames.size(); ++i)
634 written += writeFrame(frames[i]);
642 qint64 QWebSocketPrivate::writeFrame(const QByteArray &frame)
644 return m_pSocket->write(frame);
650 QString readLine(QTcpSocket *pSocket)
654 while (pSocket->getChar(&c))
658 pSocket->getChar(&c);
663 line.append(QChar(c));
669 //called on the client for a server handshake response
673 void QWebSocketPrivate::processHandshake(QTcpSocket *pSocket)
682 QString errorDescription;
684 const QString regExpStatusLine("^(HTTP/[0-9]+\\.[0-9]+)\\s([0-9]+)\\s(.*)");
685 const QRegularExpression regExp(regExpStatusLine);
686 QString statusLine = readLine(pSocket);
687 QString httpProtocol;
689 QString httpStatusMessage;
690 QRegularExpressionMatch match = regExp.match(statusLine);
691 if (match.hasMatch())
693 QStringList tokens = match.capturedTexts();
694 tokens.removeFirst(); //remove the search string
695 if (tokens.length() == 3)
697 httpProtocol = tokens[0];
698 httpStatusCode = tokens[1].toInt();
699 httpStatusMessage = tokens[2].trimmed();
705 errorDescription = tr("Invalid statusline in response: %1.").arg(statusLine);
709 QString headerLine = readLine(pSocket);
710 QMap<QString, QString> headers;
711 while (!headerLine.isEmpty())
713 QStringList headerField = headerLine.split(QString(": "), QString::SkipEmptyParts);
714 headers.insertMulti(headerField[0], headerField[1]);
715 headerLine = readLine(pSocket);
718 QString acceptKey = headers.value("Sec-WebSocket-Accept", "");
719 QString upgrade = headers.value("Upgrade", "");
720 QString connection = headers.value("Connection", "");
721 //unused for the moment
722 //QString extensions = headers.value("Sec-WebSocket-Extensions", "");
723 //QString protocol = headers.value("Sec-WebSocket-Protocol", "");
724 QString version = headers.value("Sec-WebSocket-Version", "");
726 if (httpStatusCode == 101) //HTTP/x.y 101 Switching Protocols
728 bool conversionOk = false;
729 float version = httpProtocol.midRef(5).toFloat(&conversionOk);
730 //TODO: do not check the httpStatusText right now
731 ok = !(acceptKey.isEmpty() ||
732 (!conversionOk || (version < 1.1f)) ||
733 (upgrade.toLower() != "websocket") ||
734 (connection.toLower() != "upgrade"));
737 QString accept = calculateAcceptKey(m_key);
738 ok = (accept == acceptKey);
741 errorDescription = tr("Accept-Key received from server %1 does not match the client key %2.").arg(acceptKey).arg(accept);
746 errorDescription = tr("Invalid statusline in response: %1.").arg(statusLine);
749 else if (httpStatusCode == 400) //HTTP/1.1 400 Bad Request
751 if (!version.isEmpty())
753 QStringList versions = version.split(", ", QString::SkipEmptyParts);
754 if (!versions.contains(QString::number(QWebSocketProtocol::currentVersion())))
756 //if needed to switch protocol version, then we are finished here
757 //because we cannot handle other protocols than the RFC one (v13)
758 errorDescription = tr("Handshake: Server requests a version that we don't support: %1.").arg(versions.join(", "));
763 //we tried v13, but something different went wrong
764 errorDescription = tr("Unknown error condition encountered. Aborting connection.");
771 errorDescription = tr("Unhandled http status code: %1.").arg(httpStatusCode);
777 qDebug() << errorDescription;
778 setErrorString(errorDescription);
779 Q_EMIT q->error(QAbstractSocket::ConnectionRefusedError);
783 //handshake succeeded
784 setSocketState(QAbstractSocket::ConnectedState);
785 Q_EMIT q->connected();
793 void QWebSocketPrivate::processStateChanged(QAbstractSocket::SocketState socketState)
796 QAbstractSocket::SocketState webSocketState = this->state();
799 case QAbstractSocket::ConnectedState:
801 if (webSocketState == QAbstractSocket::ConnectingState)
803 m_key = generateKey();
804 QString handshake = createHandShakeRequest(m_resourceName, m_requestUrl.host() % ":" % QString::number(m_requestUrl.port(80)), origin(), "", "", m_key);
805 m_pSocket->write(handshake.toLatin1());
809 case QAbstractSocket::ClosingState:
811 if (webSocketState == QAbstractSocket::ConnectedState)
813 setSocketState(QAbstractSocket::ClosingState);
817 case QAbstractSocket::UnconnectedState:
819 if (webSocketState != QAbstractSocket::UnconnectedState)
821 setSocketState(QAbstractSocket::UnconnectedState);
822 Q_EMIT q->disconnected();
826 case QAbstractSocket::HostLookupState:
827 case QAbstractSocket::ConnectingState:
828 case QAbstractSocket::BoundState:
829 case QAbstractSocket::ListeningState:
832 //to make C++ compiler happy;
843 //connectToHost is called
844 //our socket state is set to "connecting", and tcpSocket->connectToHost is called
845 //the tcpsocket is opened, a handshake message is sent; a readyRead signal is thrown
846 //this signal is catched by processData
847 //when OUR socket state is in the "connecting state", this means that
848 //we have received data from the server (response to handshake), and that we
849 //should "upgrade" our socket to a websocket (connected state)
850 //if our socket was already upgraded, then we need to process websocket data
854 void QWebSocketPrivate::processData()
856 while (m_pSocket->bytesAvailable())
858 if (state() == QAbstractSocket::ConnectingState)
860 processHandshake(m_pSocket);
864 m_dataProcessor.process(m_pSocket);
872 void QWebSocketPrivate::processPing(QByteArray data)
874 quint32 maskingKey = 0;
877 maskingKey = generateMaskingKey();
879 m_pSocket->write(getFrameHeader(QWebSocketProtocol::OC_PONG, data.size(), maskingKey, true));
884 QWebSocketProtocol::mask(&data, maskingKey);
886 m_pSocket->write(data);
893 void QWebSocketPrivate::processPong(QByteArray data)
896 Q_EMIT q->pong(static_cast<quint64>(m_pingTimer.elapsed()), data);
902 void QWebSocketPrivate::processClose(QWebSocketProtocol::CloseCode closeCode, QString closeReason)
904 m_isClosingHandshakeReceived = true;
905 close(closeCode, closeReason);
911 QString QWebSocketPrivate::createHandShakeRequest(QString resourceName,
918 QStringList handshakeRequest;
920 handshakeRequest << "GET " % resourceName % " HTTP/1.1" <<
922 "Upgrade: websocket" <<
923 "Connection: Upgrade" <<
924 "Sec-WebSocket-Key: " % QString(key);
925 if (!origin.isEmpty())
927 handshakeRequest << "Origin: " % origin;
929 handshakeRequest << "Sec-WebSocket-Version: " % QString::number(QWebSocketProtocol::currentVersion());
930 if (extensions.length() > 0)
932 handshakeRequest << "Sec-WebSocket-Extensions: " % extensions;
934 if (protocols.length() > 0)
936 handshakeRequest << "Sec-WebSocket-Protocol: " % protocols;
938 handshakeRequest << "\r\n";
940 return handshakeRequest.join("\r\n");
946 QAbstractSocket::SocketState QWebSocketPrivate::state() const
948 return m_socketState;
954 bool QWebSocketPrivate::waitForConnected(int msecs)
956 return m_pSocket->waitForConnected(msecs);
962 bool QWebSocketPrivate::waitForDisconnected(int msecs)
964 return m_pSocket->waitForDisconnected(msecs);
970 void QWebSocketPrivate::setSocketState(QAbstractSocket::SocketState state)
973 if (m_socketState != state)
975 m_socketState = state;
976 Q_EMIT q->stateChanged(m_socketState);
983 void QWebSocketPrivate::setErrorString(const QString &errorString)
985 m_errorString = errorString;
991 QHostAddress QWebSocketPrivate::localAddress() const
993 return m_pSocket->localAddress();
999 quint16 QWebSocketPrivate::localPort() const
1001 return m_pSocket->localPort();
1007 QAbstractSocket::PauseModes QWebSocketPrivate::pauseMode() const
1009 return m_pSocket->pauseMode();
1015 QHostAddress QWebSocketPrivate::peerAddress() const
1017 return m_pSocket->peerAddress();
1023 QString QWebSocketPrivate::peerName() const
1025 return m_pSocket->peerName();
1031 quint16 QWebSocketPrivate::peerPort() const
1033 return m_pSocket->peerPort();
1039 QNetworkProxy QWebSocketPrivate::proxy() const
1041 return m_pSocket->proxy();
1047 qint64 QWebSocketPrivate::readBufferSize() const
1049 return m_pSocket->readBufferSize();
1055 void QWebSocketPrivate::resume()
1057 m_pSocket->resume();
1063 void QWebSocketPrivate::setPauseMode(QAbstractSocket::PauseModes pauseMode)
1065 m_pSocket->setPauseMode(pauseMode);
1071 void QWebSocketPrivate::setProxy(const QNetworkProxy &networkProxy)
1073 m_pSocket->setProxy(networkProxy);
1079 void QWebSocketPrivate::setReadBufferSize(qint64 size)
1081 m_pSocket->setReadBufferSize(size);
1087 void QWebSocketPrivate::setSocketOption(QAbstractSocket::SocketOption option, const QVariant &value)
1089 m_pSocket->setSocketOption(option, value);
1095 QVariant QWebSocketPrivate::socketOption(QAbstractSocket::SocketOption option)
1097 return m_pSocket->socketOption(option);
1103 bool QWebSocketPrivate::isValid() const
1105 return m_pSocket->isValid();