Fix assertion when encountering invalid header line.
[contrib/qtwebsockets.git] / src / websockets / qwebsocket_p.cpp
index 7d6c7a9..5f59b54 100644 (file)
@@ -87,11 +87,11 @@ QWebSocketConfiguration::QWebSocketConfiguration() :
     \internal
 */
 QWebSocketPrivate::QWebSocketPrivate(const QString &origin, QWebSocketProtocol::Version version,
-                                     QWebSocket *pWebSocket, QObject *parent) :
-    QObject(parent),
+                                     QWebSocket *pWebSocket) :
+    QObjectPrivate(),
     q_ptr(pWebSocket),
     m_pSocket(),
-    m_errorString(),
+    m_errorString(QWebSocket::tr("Unknown error")),
     m_version(version),
     m_resourceName(),
     m_requestUrl(),
@@ -99,25 +99,26 @@ QWebSocketPrivate::QWebSocketPrivate(const QString &origin, QWebSocketProtocol::
     m_protocol(),
     m_extension(),
     m_socketState(QAbstractSocket::UnconnectedState),
+    m_pauseMode(QAbstractSocket::PauseNever),
+    m_readBufferSize(0),
     m_key(),
     m_mustMask(true),
     m_isClosingHandshakeSent(false),
     m_isClosingHandshakeReceived(false),
-    m_closeCode(QWebSocketProtocol::CC_NORMAL),
+    m_closeCode(QWebSocketProtocol::CloseCodeNormal),
     m_closeReason(),
     m_pingTimer(),
     m_dataProcessor(),
     m_configuration()
 {
-    init();
 }
 
 /*!
     \internal
 */
 QWebSocketPrivate::QWebSocketPrivate(QTcpSocket *pTcpSocket, QWebSocketProtocol::Version version,
-                                     QWebSocket *pWebSocket, QObject *parent) :
-    QObject(parent),
+                                     QWebSocket *pWebSocket) :
+    QObjectPrivate(),
     q_ptr(pWebSocket),
     m_pSocket(pTcpSocket),
     m_errorString(pTcpSocket->errorString()),
@@ -128,18 +129,18 @@ QWebSocketPrivate::QWebSocketPrivate(QTcpSocket *pTcpSocket, QWebSocketProtocol:
     m_protocol(),
     m_extension(),
     m_socketState(pTcpSocket->state()),
+    m_pauseMode(pTcpSocket->pauseMode()),
+    m_readBufferSize(pTcpSocket->readBufferSize()),
     m_key(),
     m_mustMask(true),
     m_isClosingHandshakeSent(false),
     m_isClosingHandshakeReceived(false),
-    m_closeCode(QWebSocketProtocol::CC_NORMAL),
+    m_closeCode(QWebSocketProtocol::CloseCodeNormal),
     m_closeReason(),
     m_pingTimer(),
     m_dataProcessor(),
     m_configuration()
 {
-    init();
-    makeConnections(m_pSocket.data());
 }
 
 /*!
@@ -148,7 +149,12 @@ QWebSocketPrivate::QWebSocketPrivate(QTcpSocket *pTcpSocket, QWebSocketProtocol:
 void QWebSocketPrivate::init()
 {
     Q_ASSERT(q_ptr);
+    //TODO: need a better randomizer
     qsrand(static_cast<uint>(QDateTime::currentMSecsSinceEpoch()));
+
+    if (m_pSocket) {
+        makeConnections(m_pSocket.data());
+    }
 }
 
 /*!
@@ -159,7 +165,7 @@ QWebSocketPrivate::~QWebSocketPrivate()
     if (!m_pSocket)
         return;
     if (state() == QAbstractSocket::ConnectedState)
-        close(QWebSocketProtocol::CC_GOING_AWAY, tr("Connection closed"));
+        close(QWebSocketProtocol::CloseCodeGoingAway, QWebSocket::tr("Connection closed"));
     releaseConnections(m_pSocket.data());
 }
 
@@ -177,7 +183,7 @@ void QWebSocketPrivate::abort()
  */
 QAbstractSocket::SocketError QWebSocketPrivate::error() const
 {
-    QAbstractSocket::SocketError err = QAbstractSocket::OperationError;
+    QAbstractSocket::SocketError err = QAbstractSocket::UnknownSocketError;
     if (Q_LIKELY(m_pSocket))
         err = m_pSocket->error();
     return err;
@@ -210,30 +216,7 @@ bool QWebSocketPrivate::flush()
 /*!
     \internal
  */
-qint64 QWebSocketPrivate::write(const char *message)
-{
-    if (!message || !*message)
-        return qint64(0);
-    uint size = qstrlen(message);
-    qint64 maxSize = qMin(qint64(size), qint64(std::numeric_limits<QString::size_type>::max()));
-    return doWriteFrames(QString::fromUtf8(message, maxSize).toUtf8(), false);
-}
-
-/*!
-    \internal
- */
-qint64 QWebSocketPrivate::write(const char *message, qint64 maxSize)
-{
-    if (!message || (maxSize <= qint64(0)) || !*message)
-        return qint64(0);
-    maxSize = qMin(maxSize, qint64(std::numeric_limits<QString::size_type>::max()));
-    return doWriteFrames(QString::fromUtf8(message, maxSize).toUtf8(), false);
-}
-
-/*!
-    \internal
- */
-qint64 QWebSocketPrivate::write(const QString &message)
+qint64 QWebSocketPrivate::sendTextMessage(const QString &message)
 {
     return doWriteFrames(message.toUtf8(), false);
 }
@@ -241,7 +224,7 @@ qint64 QWebSocketPrivate::write(const QString &message)
 /*!
     \internal
  */
-qint64 QWebSocketPrivate::write(const QByteArray &data)
+qint64 QWebSocketPrivate::sendBinaryMessage(const QByteArray &data)
 {
     return doWriteFrames(data, true);
 }
@@ -318,17 +301,17 @@ void QWebSocketPrivate::close(QWebSocketProtocol::CloseCode closeCode, QString r
         return;
     if (!m_isClosingHandshakeSent) {
         Q_Q(QWebSocket);
-        quint32 maskingKey = 0;
-        if (m_mustMask)
-            maskingKey = generateMaskingKey();
         const quint16 code = qToBigEndian<quint16>(closeCode);
         QByteArray payload;
         payload.append(static_cast<const char *>(static_cast<const void *>(&code)), 2);
         if (!reason.isEmpty())
             payload.append(reason.toUtf8());
-        if (m_mustMask)
+        quint32 maskingKey = 0;
+        if (m_mustMask) {
+            maskingKey = generateMaskingKey();
             QWebSocketProtocol::mask(payload.data(), payload.size(), maskingKey);
-        QByteArray frame = getFrameHeader(QWebSocketProtocol::OC_CLOSE,
+        }
+        QByteArray frame = getFrameHeader(QWebSocketProtocol::OpCodeClose,
                                           payload.size(), maskingKey, true);
         frame.append(payload);
         m_pSocket->write(frame);
@@ -378,19 +361,22 @@ void QWebSocketPrivate::open(const QUrl &url, bool mask)
     #ifndef QT_NO_SSL
         if (url.scheme() == QStringLiteral("wss")) {
             if (!QSslSocket::supportsSsl()) {
-                const QString message = tr("SSL Sockets are not supported on this platform.");
+                const QString message =
+                        QWebSocket::tr("SSL Sockets are not supported on this platform.");
                 setErrorString(message);
                 Q_EMIT q->error(QAbstractSocket::UnsupportedSocketOperationError);
             } else {
-                QSslSocket *sslSocket = new QSslSocket(this);
+                QSslSocket *sslSocket = new QSslSocket(q);
                 m_pSocket.reset(sslSocket);
                 if (Q_LIKELY(m_pSocket)) {
                     m_pSocket->setSocketOption(QAbstractSocket::LowDelayOption, 1);
                     m_pSocket->setSocketOption(QAbstractSocket::KeepAliveOption, 1);
+                    m_pSocket->setReadBufferSize(m_readBufferSize);
+                    m_pSocket->setPauseMode(m_pauseMode);
 
                     makeConnections(m_pSocket.data());
-                    connect(sslSocket, &QSslSocket::encryptedBytesWritten, q,
-                            &QWebSocket::bytesWritten);
+                    QObject::connect(sslSocket, &QSslSocket::encryptedBytesWritten, q,
+                                     &QWebSocket::bytesWritten);
                     setSocketState(QAbstractSocket::ConnectingState);
 
                     sslSocket->setSslConfiguration(m_configuration.m_sslConfiguration);
@@ -403,7 +389,7 @@ void QWebSocketPrivate::open(const QUrl &url, bool mask)
     #endif
                     sslSocket->connectToHostEncrypted(url.host(), url.port(443));
                 } else {
-                    const QString message = tr("Out of memory.");
+                    const QString message = QWebSocket::tr("Out of memory.");
                     setErrorString(message);
                     Q_EMIT q->error(QAbstractSocket::SocketResourceError);
                 }
@@ -411,26 +397,29 @@ void QWebSocketPrivate::open(const QUrl &url, bool mask)
         } else
     #endif
         if (url.scheme() == QStringLiteral("ws")) {
-            m_pSocket.reset(new QTcpSocket(this));
+            m_pSocket.reset(new QTcpSocket(q));
             if (Q_LIKELY(m_pSocket)) {
                 m_pSocket->setSocketOption(QAbstractSocket::LowDelayOption, 1);
                 m_pSocket->setSocketOption(QAbstractSocket::KeepAliveOption, 1);
+                m_pSocket->setReadBufferSize(m_readBufferSize);
+                m_pSocket->setPauseMode(m_pauseMode);
 
                 makeConnections(m_pSocket.data());
-                connect(m_pSocket.data(), &QAbstractSocket::bytesWritten, q,
-                        &QWebSocket::bytesWritten);
+                QObject::connect(m_pSocket.data(), &QAbstractSocket::bytesWritten, q,
+                                 &QWebSocket::bytesWritten);
                 setSocketState(QAbstractSocket::ConnectingState);
     #ifndef QT_NO_NETWORKPROXY
                 m_pSocket->setProxy(m_configuration.m_proxy);
     #endif
                 m_pSocket->connectToHost(url.host(), url.port(80));
             } else {
-                const QString message = tr("Out of memory.");
+                const QString message = QWebSocket::tr("Out of memory.");
                 setErrorString(message);
                 Q_EMIT q->error(QAbstractSocket::SocketResourceError);
             }
         } else {
-            const QString message = tr("Unsupported websockets scheme: %1").arg(url.scheme());
+            const QString message =
+                    QWebSocket::tr("Unsupported websockets scheme: %1").arg(url.scheme());
             setErrorString(message);
             Q_EMIT q->error(QAbstractSocket::UnsupportedSocketOperationError);
         }
@@ -440,15 +429,15 @@ void QWebSocketPrivate::open(const QUrl &url, bool mask)
 /*!
     \internal
  */
-void QWebSocketPrivate::ping(QByteArray payload)
+void QWebSocketPrivate::ping(const QByteArray &payload)
 {
-    if (payload.length() > 125)
-        payload.truncate(125);
+    QByteArray payloadTruncated = payload.left(125);
     m_pingTimer.restart();
-    QByteArray pingFrame = getFrameHeader(QWebSocketProtocol::OC_PING, payload.size(),
+    QByteArray pingFrame = getFrameHeader(QWebSocketProtocol::OpCodePing, payloadTruncated.size(),
                                           0 /*do not mask*/, true);
-    pingFrame.append(payload);
-    (void)writeFrame(pingFrame);
+    pingFrame.append(payloadTruncated);
+    qint64 ret = writeFrame(pingFrame);
+    Q_UNUSED(ret);
 }
 
 /*!
@@ -529,40 +518,40 @@ void QWebSocketPrivate::makeConnections(const QTcpSocket *pTcpSocket)
         //pass through signals
         typedef void (QAbstractSocket:: *ASErrorSignal)(QAbstractSocket::SocketError);
         typedef void (QWebSocket:: *WSErrorSignal)(QAbstractSocket::SocketError);
-        connect(pTcpSocket,
-                static_cast<ASErrorSignal>(&QAbstractSocket::error),
-                q, static_cast<WSErrorSignal>(&QWebSocket::error));
-        connect(pTcpSocket, &QAbstractSocket::proxyAuthenticationRequired, q,
-                &QWebSocket::proxyAuthenticationRequired);
-        connect(pTcpSocket, &QAbstractSocket::readChannelFinished, q,
-                &QWebSocket::readChannelFinished);
-        connect(pTcpSocket, &QAbstractSocket::aboutToClose, q, &QWebSocket::aboutToClose);
+        QObject::connect(pTcpSocket,
+                         static_cast<ASErrorSignal>(&QAbstractSocket::error),
+                         q, static_cast<WSErrorSignal>(&QWebSocket::error));
+        QObject::connect(pTcpSocket, &QAbstractSocket::proxyAuthenticationRequired, q,
+                         &QWebSocket::proxyAuthenticationRequired);
+        QObject::connect(pTcpSocket, &QAbstractSocket::readChannelFinished, q,
+                         &QWebSocket::readChannelFinished);
+        QObject::connect(pTcpSocket, &QAbstractSocket::aboutToClose, q, &QWebSocket::aboutToClose);
 
         //catch signals
-        connect(pTcpSocket, &QAbstractSocket::stateChanged, this,
-                &QWebSocketPrivate::processStateChanged);
+        QObjectPrivate::connect(pTcpSocket, &QAbstractSocket::stateChanged, this,
+                                &QWebSocketPrivate::processStateChanged);
         //!!!important to use a QueuedConnection here;
         //with QTcpSocket there is no problem, but with QSslSocket the processing hangs
-        connect(pTcpSocket, &QAbstractSocket::readyRead, this,
-                &QWebSocketPrivate::processData, Qt::QueuedConnection);
+        QObjectPrivate::connect(pTcpSocket, &QAbstractSocket::readyRead, this,
+                                &QWebSocketPrivate::processData, Qt::QueuedConnection);
     }
 
-    connect(&m_dataProcessor, &QWebSocketDataProcessor::textFrameReceived, q,
-            &QWebSocket::textFrameReceived);
-    connect(&m_dataProcessor, &QWebSocketDataProcessor::binaryFrameReceived, q,
-            &QWebSocket::binaryFrameReceived);
-    connect(&m_dataProcessor, &QWebSocketDataProcessor::binaryMessageReceived, q,
-            &QWebSocket::binaryMessageReceived);
-    connect(&m_dataProcessor, &QWebSocketDataProcessor::textMessageReceived, q,
-            &QWebSocket::textMessageReceived);
-    connect(&m_dataProcessor, &QWebSocketDataProcessor::errorEncountered, this,
-            &QWebSocketPrivate::close);
-    connect(&m_dataProcessor, &QWebSocketDataProcessor::pingReceived, this,
-            &QWebSocketPrivate::processPing);
-    connect(&m_dataProcessor, &QWebSocketDataProcessor::pongReceived, this,
-            &QWebSocketPrivate::processPong);
-    connect(&m_dataProcessor, &QWebSocketDataProcessor::closeReceived, this,
-            &QWebSocketPrivate::processClose);
+    QObject::connect(&m_dataProcessor, &QWebSocketDataProcessor::textFrameReceived, q,
+                     &QWebSocket::textFrameReceived);
+    QObject::connect(&m_dataProcessor, &QWebSocketDataProcessor::binaryFrameReceived, q,
+                     &QWebSocket::binaryFrameReceived);
+    QObject::connect(&m_dataProcessor, &QWebSocketDataProcessor::binaryMessageReceived, q,
+                     &QWebSocket::binaryMessageReceived);
+    QObject::connect(&m_dataProcessor, &QWebSocketDataProcessor::textMessageReceived, q,
+                     &QWebSocket::textMessageReceived);
+    QObjectPrivate::connect(&m_dataProcessor, &QWebSocketDataProcessor::errorEncountered, this,
+                            &QWebSocketPrivate::close);
+    QObjectPrivate::connect(&m_dataProcessor, &QWebSocketDataProcessor::pingReceived, this,
+                            &QWebSocketPrivate::processPing);
+    QObjectPrivate::connect(&m_dataProcessor, &QWebSocketDataProcessor::pongReceived, this,
+                            &QWebSocketPrivate::processPong);
+    QObjectPrivate::connect(&m_dataProcessor, &QWebSocketDataProcessor::closeReceived, this,
+                            &QWebSocketPrivate::processClose);
 }
 
 /*!
@@ -571,8 +560,8 @@ void QWebSocketPrivate::makeConnections(const QTcpSocket *pTcpSocket)
 void QWebSocketPrivate::releaseConnections(const QTcpSocket *pTcpSocket)
 {
     if (Q_LIKELY(pTcpSocket))
-        disconnect(pTcpSocket);
-    disconnect(&m_dataProcessor);
+        pTcpSocket->disconnect(pTcpSocket);
+    m_dataProcessor.disconnect(&m_dataProcessor);
 }
 
 /*!
@@ -651,9 +640,8 @@ QByteArray QWebSocketPrivate::getFrameHeader(QWebSocketProtocol::OpCode opCode,
     bool ok = payloadLength <= 0x7FFFFFFFFFFFFFFFULL;
 
     if (Q_LIKELY(ok)) {
-        //FIN, RSV1-3, opcode
-        byte = static_cast<quint8>((opCode & 0x0F) | (lastFrame ? 0x80 : 0x00));       //FIN, opcode
-        //RSV-1, RSV-2 and RSV-3 are zero
+        //FIN, RSV1-3, opcode (RSV-1, RSV-2 and RSV-3 are zero)
+        byte = static_cast<quint8>((opCode & 0x0F) | (lastFrame ? 0x80 : 0x00));
         header.append(static_cast<char>(byte));
 
         byte = 0x00;
@@ -693,12 +681,12 @@ QByteArray QWebSocketPrivate::getFrameHeader(QWebSocketProtocol::OpCode opCode,
 qint64 QWebSocketPrivate::doWriteFrames(const QByteArray &data, bool isBinary)
 {
     qint64 payloadWritten = 0;
-    if (Q_UNLIKELY(!m_pSocket))
+    if (Q_UNLIKELY(!m_pSocket) || (state() != QAbstractSocket::ConnectedState))
         return payloadWritten;
 
     Q_Q(QWebSocket);
     const QWebSocketProtocol::OpCode firstOpCode = isBinary ?
-                QWebSocketProtocol::OC_BINARY : QWebSocketProtocol::OC_TEXT;
+                QWebSocketProtocol::OpCodeBinary : QWebSocketProtocol::OpCodeText;
 
     int numFrames = data.size() / FRAME_SIZE_IN_BYTES;
     QByteArray tmpData(data);
@@ -726,7 +714,7 @@ qint64 QWebSocketPrivate::doWriteFrames(const QByteArray &data, bool isBinary)
 
         const quint64 size = qMin(bytesLeft, FRAME_SIZE_IN_BYTES);
         const QWebSocketProtocol::OpCode opcode = isFirstFrame ? firstOpCode
-                                                               : QWebSocketProtocol::OC_CONTINUE;
+                                                               : QWebSocketProtocol::OpCodeContinue;
 
         //write header
         bytesWritten += m_pSocket->write(getFrameHeader(opcode, size, maskingKey, isLastFrame));
@@ -742,7 +730,7 @@ qint64 QWebSocketPrivate::doWriteFrames(const QByteArray &data, bool isBinary)
                 payloadWritten += written;
             } else {
                 m_pSocket->flush();
-                setErrorString(tr("Error writing bytes to socket: %1.")
+                setErrorString(QWebSocket::tr("Error writing bytes to socket: %1.")
                                .arg(m_pSocket->errorString()));
                 Q_EMIT q->error(QAbstractSocket::NetworkError);
                 break;
@@ -752,7 +740,8 @@ qint64 QWebSocketPrivate::doWriteFrames(const QByteArray &data, bool isBinary)
         bytesLeft -= size;
     }
     if (Q_UNLIKELY(payloadWritten != data.size())) {
-        setErrorString(tr("Bytes written %1 != %2.").arg(payloadWritten).arg(data.size()));
+        setErrorString(QWebSocket::tr("Bytes written %1 != %2.")
+                       .arg(payloadWritten).arg(data.size()));
         Q_EMIT q->error(QAbstractSocket::NetworkError);
     }
     return payloadWritten;
@@ -763,6 +752,7 @@ qint64 QWebSocketPrivate::doWriteFrames(const QByteArray &data, bool isBinary)
  */
 quint32 QWebSocketPrivate::generateRandomNumber() const
 {
+    //TODO: need a better randomizer
     return quint32((double(qrand()) / RAND_MAX) * std::numeric_limits<quint32>::max());
 }
 
@@ -875,28 +865,30 @@ void QWebSocketPrivate::processHandshake(QTcpSocket *pSocket)
         }
     }
     if (Q_UNLIKELY(!ok)) {
-        errorDescription = tr("Invalid statusline in response: %1.").arg(statusLine);
+        errorDescription = QWebSocket::tr("Invalid statusline in response: %1.").arg(statusLine);
     } else {
         QString headerLine = readLine(pSocket);
         QMap<QString, QString> headers;
         while (!headerLine.isEmpty()) {
             const QStringList headerField = headerLine.split(QStringLiteral(": "),
                                                              QString::SkipEmptyParts);
-            headers.insertMulti(headerField[0], headerField[1]);
+            if (headerField.size() == 2) {
+                headers.insertMulti(headerField[0], headerField[1]);
+            }
             headerLine = readLine(pSocket);
         }
 
         const QString acceptKey = headers.value(QStringLiteral("Sec-WebSocket-Accept"),
-                                                QStringLiteral(""));
-        const QString upgrade = headers.value(QStringLiteral("Upgrade"), QStringLiteral(""));
-        const QString connection = headers.value(QStringLiteral("Connection"), QStringLiteral(""));
+                                                QString());
+        const QString upgrade = headers.value(QStringLiteral("Upgrade"), QString());
+        const QString connection = headers.value(QStringLiteral("Connection"), QString());
 //        unused for the moment
 //        const QString extensions = headers.value(QStringLiteral("Sec-WebSocket-Extensions"),
-//                                                 QStringLiteral(""));
+//                                                 QString());
 //        const QString protocol = headers.value(QStringLiteral("Sec-WebSocket-Protocol"),
-//                                               QStringLiteral(""));
+//                                               QString());
         const QString version = headers.value(QStringLiteral("Sec-WebSocket-Version"),
-                                              QStringLiteral(""));
+                                              QString());
 
         if (Q_LIKELY(httpStatusCode == 101)) {
             //HTTP/x.y 101 Switching Protocols
@@ -912,11 +904,11 @@ void QWebSocketPrivate::processHandshake(QTcpSocket *pSocket)
                 ok = (accept == acceptKey);
                 if (!ok)
                     errorDescription =
-                      tr("Accept-Key received from server %1 does not match the client key %2.")
+                      QWebSocket::tr("Accept-Key received from server %1 does not match the client key %2.")
                             .arg(acceptKey).arg(accept);
             } else {
                 errorDescription =
-                    tr("QWebSocketPrivate::processHandshake: Invalid statusline in response: %1.")
+                    QWebSocket::tr("QWebSocketPrivate::processHandshake: Invalid statusline in response: %1.")
                         .arg(statusLine);
             }
         } else if (httpStatusCode == 400) {
@@ -928,21 +920,20 @@ void QWebSocketPrivate::processHandshake(QTcpSocket *pSocket)
                     //if needed to switch protocol version, then we are finished here
                     //because we cannot handle other protocols than the RFC one (v13)
                     errorDescription =
-                            tr("Handshake: Server requests a version that we don't support: %1.")
+                            QWebSocket::tr("Handshake: Server requests a version that we don't support: %1.")
                             .arg(versions.join(QStringLiteral(", ")));
                     ok = false;
                 } else {
                     //we tried v13, but something different went wrong
                     errorDescription =
-                        tr("QWebSocketPrivate::processHandshake: Unknown error condition " \
-                           "encountered. Aborting connection.");
+                        QWebSocket::tr("QWebSocketPrivate::processHandshake: Unknown error condition encountered. Aborting connection.");
                     ok = false;
                 }
             }
         } else {
             errorDescription =
-                    tr("QWebSocketPrivate::processHandshake: Unhandled http status code: %1 (%2).")
-                    .arg(httpStatusCode).arg(httpStatusMessage);
+                    QWebSocket::tr("QWebSocketPrivate::processHandshake: Unhandled http status code: %1 (%2).")
+                        .arg(httpStatusCode).arg(httpStatusMessage);
             ok = false;
         }
 
@@ -975,8 +966,8 @@ void QWebSocketPrivate::processStateChanged(QAbstractSocket::SocketState socketS
                                                 % QStringLiteral(":")
                                                 % QString::number(m_requestUrl.port(80)),
                                            origin(),
-                                           QStringLiteral(""),
-                                           QStringLiteral(""),
+                                           QString(),
+                                           QString(),
                                            m_key);
             m_pSocket->write(handshake.toLatin1());
         }
@@ -1023,24 +1014,25 @@ void QWebSocketPrivate::processData()
 /*!
  \internal
  */
-void QWebSocketPrivate::processPing(QByteArray data)
+void QWebSocketPrivate::processPing(const QByteArray &data)
 {
     Q_ASSERT(m_pSocket);
     quint32 maskingKey = 0;
     if (m_mustMask)
         maskingKey = generateMaskingKey();
-    m_pSocket->write(getFrameHeader(QWebSocketProtocol::OC_PONG, data.size(), maskingKey, true));
+    m_pSocket->write(getFrameHeader(QWebSocketProtocol::OpCodePong, data.size(), maskingKey, true));
     if (data.size() > 0) {
+        QByteArray maskedData = data;
         if (m_mustMask)
-            QWebSocketProtocol::mask(&data, maskingKey);
-        m_pSocket->write(data);
+            QWebSocketProtocol::mask(&maskedData, maskingKey);
+        m_pSocket->write(maskedData);
     }
 }
 
 /*!
  \internal
  */
-void QWebSocketPrivate::processPong(QByteArray data)
+void QWebSocketPrivate::processPong(const QByteArray &data)
 {
     Q_Q(QWebSocket);
     Q_EMIT q->pong(static_cast<quint64>(m_pingTimer.elapsed()), data);
@@ -1141,10 +1133,7 @@ quint16 QWebSocketPrivate::localPort() const
  */
 QAbstractSocket::PauseModes QWebSocketPrivate::pauseMode() const
 {
-    QAbstractSocket::PauseModes mode = QAbstractSocket::PauseNever;
-    if (Q_LIKELY(m_pSocket))
-        mode = m_pSocket->pauseMode();
-    return mode;
+    return m_pauseMode;
 }
 
 /*!
@@ -1204,10 +1193,7 @@ void QWebSocketPrivate::setProxy(const QNetworkProxy &networkProxy)
  */
 qint64 QWebSocketPrivate::readBufferSize() const
 {
-    qint64 size = 0;
-    if (Q_LIKELY(m_pSocket))
-        size = m_pSocket->readBufferSize();
-    return size;
+    return m_readBufferSize;
 }
 
 /*!
@@ -1224,8 +1210,9 @@ void QWebSocketPrivate::resume()
  */
 void QWebSocketPrivate::setPauseMode(QAbstractSocket::PauseModes pauseMode)
 {
+    m_pauseMode = pauseMode;
     if (Q_LIKELY(m_pSocket))
-        m_pSocket->setPauseMode(pauseMode);
+        m_pSocket->setPauseMode(m_pauseMode);
 }
 
 /*!
@@ -1233,28 +1220,9 @@ void QWebSocketPrivate::setPauseMode(QAbstractSocket::PauseModes pauseMode)
  */
 void QWebSocketPrivate::setReadBufferSize(qint64 size)
 {
+    m_readBufferSize = size;
     if (Q_LIKELY(m_pSocket))
-        m_pSocket->setReadBufferSize(size);
-}
-
-/*!
-    \internal
- */
-void QWebSocketPrivate::setSocketOption(QAbstractSocket::SocketOption option, const QVariant &value)
-{
-    if (Q_LIKELY(m_pSocket))
-        m_pSocket->setSocketOption(option, value);
-}
-
-/*!
-    \internal
- */
-QVariant QWebSocketPrivate::socketOption(QAbstractSocket::SocketOption option)
-{
-    QVariant val;
-    if (Q_LIKELY(m_pSocket))
-        val = m_pSocket->socketOption(option);
-    return val;
+        m_pSocket->setReadBufferSize(m_readBufferSize);
 }
 
 /*!
@@ -1262,7 +1230,8 @@ QVariant QWebSocketPrivate::socketOption(QAbstractSocket::SocketOption option)
  */
 bool QWebSocketPrivate::isValid() const
 {
-    return (m_pSocket && m_pSocket->isValid());
+    return (m_pSocket && m_pSocket->isValid() &&
+            (m_socketState == QAbstractSocket::ConnectedState));
 }
 
 QT_END_NAMESPACE