Ejemplo n.º 1
0
void
NewNet::TcpClientSocket::connect(const std::string & host, unsigned int port)
{
  assert((descriptor() == -1) || (socketState() == SocketUninitialized));

  setSocketState(SocketConnecting);

  NNLOG("newnet.net.debug", "Resolving host '%s'.", host.c_str());
  struct hostent *h = gethostbyname(host.c_str());
  if(! h)
  {
    NNLOG("newnet.net.warn", "Cannot resolve host '%s'.", host.c_str());
    setSocketError(ErrorCannotResolve);
    cannotConnectEvent(this);
    return;
  }

  struct sockaddr_in address;
  memset(&address, 0, sizeof(address));
  address.sin_family = AF_INET;
  memcpy(&(address.sin_addr.s_addr), *(h->h_addr_list), sizeof(address.sin_addr.s_addr));
  address.sin_port = htons(port);

  NNLOG("newnet.net.debug", "Connecting to host '%s:%u'.", host.c_str(), port);

  int s = socket(PF_INET, SOCK_STREAM, 0);
  if (!setnonblocking(s))
    NNLOG("newnet.net.warn", "Couldn't set socket %i to non blocking (errno: %i)", s, errno);
  setDescriptor(s);

  if(s < 0)
    {
      NNLOG("newnet.net.warn", "Cannot connect to host '%s:%u', error: %i.", host.c_str(), port, WSAGetLastError());
      setSocketError(ErrorCannotConnect);
      cannotConnectEvent(this);
      return;
    }

  // Add a connection timeout
  if (reactor()) {
    m_ConnectionTimeout = reactor()->addTimeout(120000, this, &TcpClientSocket::onConnectionTimeout);
  }

  connectedEvent.connect(this, &TcpClientSocket::onConnected);

  if(::connect(s, (struct sockaddr *)&address, sizeof(struct sockaddr_in)) == 0)
  {
    // When using non blocking socket (most of the time), we don't get here.
    NNLOG("newnet.net.debug", "Connected to host '%s:%u'.", host.c_str(), port);
    setSocketState(SocketConnected);
    connectedEvent(this);
  }
  else if(WSAGetLastError() != WSAEWOULDBLOCK)
  {
    // When using non blocking socket (most of the time), we don't get here.
    NNLOG("newnet.net.warn", "Cannot connect to host '%s:%u', error: %i.", host.c_str(), port, WSAGetLastError());
    setSocketError(ErrorCannotConnect);
    cannotConnectEvent(this);
  }
}
Ejemplo n.º 2
0
/*!
    \internal
 */
void QWebSocketPrivate::processStateChanged(QAbstractSocket::SocketState socketState)
{
    Q_ASSERT(m_pSocket);
    Q_Q(QWebSocket);
    QAbstractSocket::SocketState webSocketState = this->state();
    int port = 80;
    if (m_requestUrl.scheme() == QStringLiteral("wss"))
        port = 443;

    switch (socketState) {
    case QAbstractSocket::ConnectedState:
        if (webSocketState == QAbstractSocket::ConnectingState) {
            m_key = generateKey();
            const QString handshake =
                    createHandShakeRequest(m_resourceName,
                                           m_requestUrl.host()
                                                % QStringLiteral(":")
                                                % QString::number(m_requestUrl.port(port)),
                                           origin(),
                                           QString(),
                                           QString(),
                                           m_key);
            if (handshake.isEmpty()) {
                m_pSocket->abort();
                Q_EMIT q->error(QAbstractSocket::ConnectionRefusedError);
                return;
            }
            m_pSocket->write(handshake.toLatin1());
        }
        break;

    case QAbstractSocket::ClosingState:
        if (webSocketState == QAbstractSocket::ConnectedState)
            setSocketState(QAbstractSocket::ClosingState);
        break;

    case QAbstractSocket::UnconnectedState:
        if (webSocketState != QAbstractSocket::UnconnectedState) {
            setSocketState(QAbstractSocket::UnconnectedState);
            Q_EMIT q->disconnected();
        }
        break;

    case QAbstractSocket::HostLookupState:
    case QAbstractSocket::ConnectingState:
    case QAbstractSocket::BoundState:
    case QAbstractSocket::ListeningState:
        //do nothing
        //to make C++ compiler happy;
        break;
    default:
        break;
    }
}
Ejemplo n.º 3
0
void QBluetoothSocket::doDeviceDiscovery(const QBluetoothServiceInfo &service, OpenMode openMode)
{
    Q_D(QBluetoothSocket);

    setSocketState(QBluetoothSocket::ServiceLookupState);
    qCDebug(QT_BT) << "Starting discovery";

    if(d->discoveryAgent) {
        d->discoveryAgent->stop();
        delete d->discoveryAgent;
    }

    d->discoveryAgent = new QBluetoothServiceDiscoveryAgent(this);
    d->discoveryAgent->setRemoteAddress(service.device().address());

    //qDebug() << "Got agent";

    connect(d->discoveryAgent, SIGNAL(serviceDiscovered(QBluetoothServiceInfo)), this, SLOT(serviceDiscovered(QBluetoothServiceInfo)));
    connect(d->discoveryAgent, SIGNAL(finished()), this, SLOT(discoveryFinished()));

    d->openMode = openMode;

    if(!service.serviceUuid().isNull())
        d->discoveryAgent->setUuidFilter(service.serviceUuid());

    if(!service.serviceClassUuids().isEmpty())
        d->discoveryAgent->setUuidFilter(service.serviceClassUuids());

    // we have to ID the service somehow
    Q_ASSERT(!d->discoveryAgent->uuidFilter().isEmpty());

    qCDebug(QT_BT) << "UUID filter" << d->discoveryAgent->uuidFilter();

    d->discoveryAgent->start(QBluetoothServiceDiscoveryAgent::FullDiscovery);
}
Ejemplo n.º 4
0
void QBluetoothSocket::abort()
{
    if (state() == UnconnectedState)
        return;

    Q_D(QBluetoothSocket);
    setOpenMode(QIODevice::NotOpen);
    setSocketState(ClosingState);
    d->abort();

#ifndef QT_ANDROID_BLUETOOTH
    //Android closes when the Java event loop comes around
    setSocketState(QBluetoothSocket::UnconnectedState);
    emit disconnected();
#endif
}
Ejemplo n.º 5
0
/*!
	\internal
 */
void WebSocket::processStateChanged(QAbstractSocket::SocketState socketState)
{
	QAbstractSocket::SocketState webSocketState = this->state();
	switch (socketState)
	{
		case QAbstractSocket::ConnectedState:
		{
			if (webSocketState == QAbstractSocket::ConnectingState)
			{
				m_key = generateKey();
				QString handshake = createHandShakeRequest(m_resourceName, m_requestUrl.host() + ":" + QString::number(m_requestUrl.port(80)), getOrigin(), "", "", m_key);
				m_pSocket->write(handshake.toLatin1());
			}
			break;
		}
		case QAbstractSocket::ClosingState:
		{
			if (webSocketState == QAbstractSocket::ConnectedState)
			{
				setSocketState(QAbstractSocket::ClosingState);
			}
			break;
		}
		case QAbstractSocket::UnconnectedState:
		{
			if (webSocketState != QAbstractSocket::UnconnectedState)
			{
				setSocketState(QAbstractSocket::UnconnectedState);
				Q_EMIT disconnected();
			}
			break;
		}
		case QAbstractSocket::HostLookupState:
		case QAbstractSocket::ConnectingState:
		case QAbstractSocket::BoundState:
		case QAbstractSocket::ListeningState:
		{
			//do nothing
			//to make C++ compiler happy;
			break;
		}
		default:
		{
			break;
		}
	}
}
Ejemplo n.º 6
0
void CNetworkConnection::socketStateChanged(QAbstractSocket::SocketState state)
{
    setLocalAddress(m_pSocket->localAddress());
    setLocalPort(m_pSocket->localPort());
    setPeerName(m_pSocket->peerName());
    setPeerAddress(m_pSocket->peerAddress());
    setPeerPort(m_pSocket->peerPort());
    setSocketState(state);
}
void PeerWireClient::socketStateChanged(QAbstractSocket::SocketState state)
{
    setLocalAddress(socket.localAddress());
    setLocalPort(socket.localPort());
    setPeerName(socket.peerName());
    setPeerAddress(socket.peerAddress());
    setPeerPort(socket.peerPort());
    setSocketState(state);
}
Ejemplo n.º 8
0
void QBluetoothSocket::discoveryFinished()
{
    qCDebug(QT_BT) << "Socket discovery finished";
    Q_D(QBluetoothSocket);
    if (d->discoveryAgent){
        qCDebug(QT_BT) << "Didn't find any";
        d->errorString = tr("Service cannot be found");
        setSocketError(ServiceNotFoundError);
        setSocketState(QBluetoothSocket::UnconnectedState);
        d->discoveryAgent->deleteLater();
        d->discoveryAgent = 0;
    }
}
Ejemplo n.º 9
0
void
NewNet::UnixServerSocket::listen(const std::string & path)
{
    if(path.length() >= UNIX_PATH_MAX)
    {
        NNLOG("newnet.net.warn", "Unix socket path too long: '%s'.", path.c_str());
        setSocketError(ErrorInvalidPath);
        cannotListenEvent(this);
    }

    unlink(path.c_str());

    struct sockaddr_un address;
    memset(&address, 0, sizeof(address));

    address.sun_family = AF_UNIX;
    memcpy(address.sun_path, path.c_str(), path.length());

    int sock = socket(PF_UNIX, SOCK_STREAM, 0);
    fcntl(sock, F_SETFL, O_NONBLOCK);

    mode_t old_umask = umask(0177);
    int ret = bind(sock, (struct sockaddr *)&address, sizeof(struct sockaddr_un));
    umask(old_umask);
    if(ret != 0)
    {
        NNLOG("newnet.net.warn", "Cannot bind unix socket to '%s', error: %i.", path.c_str(), errno);
        closesocket(sock);
        setSocketError(ErrorCannotBind);
        cannotListenEvent(this);
        return;
    }

    if (::listen(sock, 3) != 0)
    {
        NNLOG("newnet.net.warn", "Cannot listen on unix socket '%s', error: %i.", path.c_str(), errno);
        closesocket(sock);
        setSocketError(ErrorCannotListen);
        cannotListenEvent(this);
        return;
    }

    m_Path = path;
    setDescriptor(sock);
    setSocketState(SocketListening);
    listeningEvent(this);

    NNLOG("newnet.net.debug", "Listening on unix socket '%s'.", path.c_str());
}
Ejemplo n.º 10
0
void QBluetoothSocket::close()
{
    if (state() == UnconnectedState)
        return;

    Q_D(QBluetoothSocket);
    setOpenMode(QIODevice::NotOpen);

    if (state() == ServiceLookupState && d->discoveryAgent) {
        d->discoveryAgent->disconnect();
        d->discoveryAgent->stop();
        d->discoveryAgent = 0;
    }

    setSocketState(ClosingState);

    d->close();

#ifndef QT_ANDROID_BLUETOOTH
    //Android closes when the Java event loop comes around
    setSocketState(UnconnectedState);
    emit disconnected();
#endif
}
Ejemplo n.º 11
0
/*!
 * \brief Opens a websocket connection using the given \a url.
 * If \a mask is true, all frames will be masked; this is only necessary for client side sockets; servers should never mask
 * \param url The url to connect to
 * \param mask When true, all frames are masked
 * \note A client socket must *always* mask its frames; servers may *never* mask its frames
 */
void WebSocket::open(const QUrl &url, bool mask)
{
	m_dataProcessor.clear();
	m_isClosingHandshakeReceived = false;
	m_isClosingHandshakeSent = false;

	setRequestUrl(url);
    QString resourceName = url.path() + url.toEncoded(); // NOTE 4.8
	if (resourceName.isEmpty())
	{
		resourceName = "/";
	}
	setResourceName(resourceName);
	enableMasking(mask);

	setSocketState(QAbstractSocket::ConnectingState);

	m_pSocket->connectToHost(url.host(), url.port(80));
}
Ejemplo n.º 12
0
void CNetworkConnection::initializeSocket()
{
	m_pSocket->moveToThread(thread());
    m_pSocket->setReadBufferSize(m_nInputSize);
    connect(m_pSocket, SIGNAL(connected()),
            this, SIGNAL(connected()));
	connect(m_pSocket, SIGNAL(readyRead()),
			this, SIGNAL(readyRead()));
    connect(m_pSocket, SIGNAL(disconnected()),
            this, SIGNAL(disconnected()));
    connect(m_pSocket, SIGNAL(error(QAbstractSocket::SocketError)),
            this, SIGNAL(error(QAbstractSocket::SocketError)));
    connect(m_pSocket, SIGNAL(bytesWritten(qint64)),
            this, SIGNAL(bytesWritten(qint64)));
    connect(m_pSocket, SIGNAL(stateChanged(QAbstractSocket::SocketState)),
            this, SLOT(socketStateChanged(QAbstractSocket::SocketState)));
	connect(m_pSocket, SIGNAL(aboutToClose()), this, SIGNAL(aboutToClose()));
    setOpenMode(m_pSocket->openMode());
    setSocketState(m_pSocket->state());
}
/*!
    \internal
 */
void QWebSocketPrivate::processHandshake(QTcpSocket *pSocket)
{
    Q_Q(QWebSocket);
    if (Q_UNLIKELY(!pSocket))
        return;

    bool ok = false;
    QString errorDescription;

    const QString regExpStatusLine(QStringLiteral("^(HTTP/[0-9]+\\.[0-9]+)\\s([0-9]+)\\s(.*)"));
    const QRegularExpression regExp(regExpStatusLine);
    const QString statusLine = readLine(pSocket);
    QString httpProtocol;
    int httpStatusCode;
    QString httpStatusMessage;
    const QRegularExpressionMatch match = regExp.match(statusLine);
    if (Q_LIKELY(match.hasMatch())) {
        QStringList tokens = match.capturedTexts();
        tokens.removeFirst();	//remove the search string
        if (tokens.length() == 3) {
            httpProtocol = tokens[0];
            httpStatusCode = tokens[1].toInt();
            httpStatusMessage = tokens[2].trimmed();
            ok = true;
        }
    }
    if (Q_UNLIKELY(!ok)) {
        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);
            if (headerField.size() == 2) {
                headers.insertMulti(headerField[0].toLower(), headerField[1]);
            }
            headerLine = readLine(pSocket);
        }

        const QString acceptKey = headers.value(QStringLiteral("sec-websocket-accept"),
                                                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"),
//                                                 QString());
//        const QString protocol = headers.value(QStringLiteral("sec-websocket-protocol"),
//                                               QString());
        const QString version = headers.value(QStringLiteral("sec-websocket-version"),
                                              QString());

        if (Q_LIKELY(httpStatusCode == 101)) {
            //HTTP/x.y 101 Switching Protocols
            bool conversionOk = false;
            const float version = httpProtocol.midRef(5).toFloat(&conversionOk);
            //TODO: do not check the httpStatusText right now
            ok = !(acceptKey.isEmpty() ||
                   (!conversionOk || (version < 1.1f)) ||
                   (upgrade.toLower() != QStringLiteral("websocket")) ||
                   (connection.toLower() != QStringLiteral("upgrade")));
            if (ok) {
                const QString accept = calculateAcceptKey(m_key);
                ok = (accept == acceptKey);
                if (!ok)
                    errorDescription =
                      QWebSocket::tr("Accept-Key received from server %1 does not match the client key %2.")
                            .arg(acceptKey).arg(accept);
            } else {
                errorDescription =
                    QWebSocket::tr("QWebSocketPrivate::processHandshake: Invalid statusline in response: %1.")
                        .arg(statusLine);
            }
        } else if (httpStatusCode == 400) {
            //HTTP/1.1 400 Bad Request
            if (!version.isEmpty()) {
                const QStringList versions = version.split(QStringLiteral(", "),
                                                           QString::SkipEmptyParts);
                if (!versions.contains(QString::number(QWebSocketProtocol::currentVersion()))) {
                    //if needed to switch protocol version, then we are finished here
                    //because we cannot handle other protocols than the RFC one (v13)
                    errorDescription =
                            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 =
                        QWebSocket::tr("QWebSocketPrivate::processHandshake: Unknown error condition encountered. Aborting connection.");
                    ok = false;
                }
            }
        } else {
            errorDescription =
                    QWebSocket::tr("QWebSocketPrivate::processHandshake: Unhandled http status code: %1 (%2).")
                        .arg(httpStatusCode).arg(httpStatusMessage);
            ok = false;
        }

        if (!ok) {
            setErrorString(errorDescription);
            Q_EMIT q->error(QAbstractSocket::ConnectionRefusedError);
        } else {
            //handshake succeeded
            setSocketState(QAbstractSocket::ConnectedState);
            Q_EMIT q->connected();
        }
    }
}
/*!
    \internal
 */
void QWebSocketPrivate::open(const QUrl &url, bool mask)
{
    //just delete the old socket for the moment;
    //later, we can add more 'intelligent' handling by looking at the URL
    //m_pSocket.reset();
    Q_Q(QWebSocket);
    if (!url.isValid() || url.toString().contains(QStringLiteral("\r\n"))) {
        setErrorString(QWebSocket::tr("Invalid URL."));
        Q_EMIT q->error(QAbstractSocket::ConnectionRefusedError);
        return;
    }
    QTcpSocket *pTcpSocket = m_pSocket.take();
    if (pTcpSocket) {
        releaseConnections(pTcpSocket);
        pTcpSocket->deleteLater();
    }
    //if (m_url != url)
    if (Q_LIKELY(!m_pSocket)) {
        m_dataProcessor.clear();
        m_isClosingHandshakeReceived = false;
        m_isClosingHandshakeSent = false;

        setRequestUrl(url);
        QString resourceName = url.path();
        if (resourceName.contains(QStringLiteral("\r\n"))) {
            setRequestUrl(QUrl());  //clear requestUrl
            setErrorString(QWebSocket::tr("Invalid resource name."));
            Q_EMIT q->error(QAbstractSocket::ConnectionRefusedError);
            return;
        }
        if (!url.query().isEmpty()) {
            if (!resourceName.endsWith(QChar::fromLatin1('?'))) {
                resourceName.append(QChar::fromLatin1('?'));
            }
            resourceName.append(url.query());
        }
        if (resourceName.isEmpty())
            resourceName = QStringLiteral("/");
        setResourceName(resourceName);
        enableMasking(mask);

    #ifndef QT_NO_SSL
        if (url.scheme() == QStringLiteral("wss")) {
            if (!QSslSocket::supportsSsl()) {
                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;
                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());
                    QObject::connect(sslSocket, &QSslSocket::encryptedBytesWritten, q,
                                     &QWebSocket::bytesWritten);
                    typedef void (QSslSocket:: *sslErrorSignalType)(const QList<QSslError> &);
                    QObject::connect(sslSocket,
                                     static_cast<sslErrorSignalType>(&QSslSocket::sslErrors),
                                     q, &QWebSocket::sslErrors);
                    setSocketState(QAbstractSocket::ConnectingState);

                    sslSocket->setSslConfiguration(m_configuration.m_sslConfiguration);
                    if (Q_UNLIKELY(m_configuration.m_ignoreSslErrors))
                        sslSocket->ignoreSslErrors();
                    else
                        sslSocket->ignoreSslErrors(m_configuration.m_ignoredSslErrors);
    #ifndef QT_NO_NETWORKPROXY
                    sslSocket->setProxy(m_configuration.m_proxy);
    #endif
                    sslSocket->connectToHostEncrypted(url.host(), url.port(443));
                } else {
                    const QString message = QWebSocket::tr("Out of memory.");
                    setErrorString(message);
                    Q_EMIT q->error(QAbstractSocket::SocketResourceError);
                }
            }
        } else
    #endif
        if (url.scheme() == QStringLiteral("ws")) {
            m_pSocket.reset(new QTcpSocket);
            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());
                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 = QWebSocket::tr("Out of memory.");
                setErrorString(message);
                Q_EMIT q->error(QAbstractSocket::SocketResourceError);
            }
        } else {
            const QString message =
                    QWebSocket::tr("Unsupported WebSocket scheme: %1").arg(url.scheme());
            setErrorString(message);
            Q_EMIT q->error(QAbstractSocket::UnsupportedSocketOperationError);
        }
    }
}
Ejemplo n.º 15
0
/*!
    \internal
 */
void QWebSocketPrivate::processHandshake(QTcpSocket *pSocket)
{
    Q_Q(QWebSocket);
    if (Q_UNLIKELY(!pSocket))
        return;
    // Reset handshake on a new connection.
    if (m_handshakeState == AllDoneState)
        m_handshakeState = NothingDoneState;

    QString errorDescription;

    switch (m_handshakeState) {
    case NothingDoneState:
        m_headers.clear();
        m_handshakeState = ReadingStatusState;
        // no break
    case ReadingStatusState:
        if (!pSocket->canReadLine())
            return;
        m_statusLine = pSocket->readLine();
        if (Q_UNLIKELY(!parseStatusLine(m_statusLine, &m_httpMajorVersion, &m_httpMinorVersion, &m_httpStatusCode, &m_httpStatusMessage))) {
            errorDescription = QWebSocket::tr("Invalid statusline in response: %1.").arg(QString::fromLatin1(m_statusLine));
            break;
        }
        m_handshakeState = ReadingHeaderState;
        // no break
    case ReadingHeaderState:
        while (pSocket->canReadLine()) {
            QString headerLine = readLine(pSocket);
            const QStringList headerField = headerLine.split(QStringLiteral(": "),
                                                             QString::SkipEmptyParts);
            if (headerField.size() == 2) {
                m_headers.insertMulti(headerField[0].toLower(), headerField[1]);
            }
            if (headerField.isEmpty()) {
                m_handshakeState = ParsingHeaderState;
                break;
            }
        }

        if (m_handshakeState != ParsingHeaderState) {
            if (pSocket->atEnd()) {
                errorDescription = QWebSocket::tr("QWebSocketPrivate::processHandshake: Connection closed while reading header.");
                break;
            }
            return;
        }
        // no break
    case ParsingHeaderState: {
        const QString acceptKey = m_headers.value(QStringLiteral("sec-websocket-accept"), QString());
        const QString upgrade = m_headers.value(QStringLiteral("upgrade"), QString());
        const QString connection = m_headers.value(QStringLiteral("connection"), QString());
//        unused for the moment
//        const QString extensions = m_headers.value(QStringLiteral("sec-websocket-extensions"),
//                                                 QString());
//        const QString protocol = m_headers.value(QStringLiteral("sec-websocket-protocol"),
//                                               QString());
        const QString version = m_headers.value(QStringLiteral("sec-websocket-version"), QString());

        bool ok = false;
        if (Q_LIKELY(m_httpStatusCode == 101)) {
            //HTTP/x.y 101 Switching Protocols
            //TODO: do not check the httpStatusText right now
            ok = !(acceptKey.isEmpty() ||
                   (m_httpMajorVersion < 1 || m_httpMinorVersion < 1) ||
                   (upgrade.toLower() != QStringLiteral("websocket")) ||
                   (connection.toLower() != QStringLiteral("upgrade")));
            if (ok) {
                const QString accept = calculateAcceptKey(m_key);
                ok = (accept == acceptKey);
                if (!ok)
                    errorDescription =
                      QWebSocket::tr("Accept-Key received from server %1 does not match the client key %2.")
                            .arg(acceptKey).arg(accept);
            } else {
                errorDescription =
                    QWebSocket::tr("QWebSocketPrivate::processHandshake: Invalid statusline in response: %1.")
                        .arg(QString::fromLatin1(m_statusLine));
            }
        } else if (m_httpStatusCode == 400) {
            //HTTP/1.1 400 Bad Request
            if (!version.isEmpty()) {
                const QStringList versions = version.split(QStringLiteral(", "),
                                                           QString::SkipEmptyParts);
                if (!versions.contains(QString::number(QWebSocketProtocol::currentVersion()))) {
                    //if needed to switch protocol version, then we are finished here
                    //because we cannot handle other protocols than the RFC one (v13)
                    errorDescription =
                            QWebSocket::tr("Handshake: Server requests a version that we don't support: %1.")
                            .arg(versions.join(QStringLiteral(", ")));
                } else {
                    //we tried v13, but something different went wrong
                    errorDescription =
                        QWebSocket::tr("QWebSocketPrivate::processHandshake: Unknown error condition encountered. Aborting connection.");
                }
            } else {
                    errorDescription =
                        QWebSocket::tr("QWebSocketPrivate::processHandshake: Unknown error condition encountered. Aborting connection.");
            }
        } else {
            errorDescription =
                    QWebSocket::tr("QWebSocketPrivate::processHandshake: Unhandled http status code: %1 (%2).")
                        .arg(m_httpStatusCode).arg(m_httpStatusMessage);
        }
        if (ok)
            m_handshakeState = AllDoneState;
        break;
    }
    case AllDoneState:
        Q_UNREACHABLE();
        break;
    }

    if (m_handshakeState == AllDoneState) {
        // handshake succeeded
        setSocketState(QAbstractSocket::ConnectedState);
        Q_EMIT q->connected();
    } else {
        // handshake failed
        m_handshakeState = AllDoneState;
        setErrorString(errorDescription);
        Q_EMIT q->error(QAbstractSocket::ConnectionRefusedError);
    }
}
Ejemplo n.º 16
0
void DhQAbstractSocket::DvhsetSocketState(long x1) {
  return setSocketState((QAbstractSocket::SocketState)x1);
}
Ejemplo n.º 17
0
/*!
	\internal
 */
void WebSocket::processHandshake(QTcpSocket *pSocket)
{
	if (pSocket == 0)
	{
		return;
	}

	bool ok = false;
	QString errorDescription;

	const QString regExpStatusLine("^(HTTP/1.1)\\s([0-9]+)\\s(.*)");
	const QRegExp regExp(regExpStatusLine);
	QString statusLine = readLine(pSocket);
	QString httpProtocol;
	int httpStatusCode;
	QString httpStatusMessage;
	if (regExp.indexIn(statusLine) != -1)
	{
		QStringList tokens = regExp.capturedTexts();
		tokens.removeFirst();	//remove the search string
		if (tokens.length() == 3)
		{
			httpProtocol = tokens[0];
			httpStatusCode = tokens[1].toInt();
			httpStatusMessage = tokens[2].trimmed();
			ok = true;
		}
	}
	if (!ok)
	{
		errorDescription = "WebSocket::processHandshake: Invalid statusline in response: " + statusLine;
	}
	else
	{
		QString headerLine = readLine(pSocket);
		QMap<QString, QString> headers;
		while (!headerLine.isEmpty())
		{
			QStringList headerField = headerLine.split(QString(": "), QString::SkipEmptyParts);
			headers.insertMulti(headerField[0], headerField[1]);
			headerLine = readLine(pSocket);
		}

		QString acceptKey = headers.value("Sec-WebSocket-Accept", "");
		QString upgrade = headers.value("Upgrade", "");
		QString connection = headers.value("Connection", "");
		QString extensions = headers.value("Sec-WebSocket-Extensions", "");
		QString protocol = headers.value("Sec-WebSocket-Protocol", "");
		QString version = headers.value("Sec-WebSocket-Version", "");

		if (httpStatusCode == 101)	//HTTP/1.1 101 Switching Protocols
		{
			//TODO: do not check the httpStatusText right now
			ok = !(acceptKey.isEmpty() ||
				   (httpProtocol.toLower() != "http/1.1") ||
				   (upgrade.toLower() != "websocket") ||
				   (connection.toLower() != "upgrade"));
			if (ok)
			{
				QString accept = calculateAcceptKey(m_key);
				ok = (accept == acceptKey);
				if (!ok)
				{
					errorDescription = "WebSocket::processHandshake: Accept-Key received from server " + acceptKey + " does not match the client key " + accept;
				}
			}
			else
			{
				errorDescription = "WebSocket::processHandshake: Invalid statusline in response: " + statusLine;
			}
		}
		else if (httpStatusCode == 400)	//HTTP/1.1 400 Bad Request
		{
			if (!version.isEmpty())
			{
				QStringList versions = version.split(", ", QString::SkipEmptyParts);
				if (!versions.contains("13"))
				{
					//if needed to switch protocol version, then we are finished here
					//because we cannot handle other protocols than the RFC one (v13)
					errorDescription = "WebSocket::processHandshake: Server requests a version that we don't support: " + versions.join(", ");
					ok = false;
				}
				else
				{
					//we tried v13, but something different went wrong
					errorDescription = "WebSocket::processHandshake: Unknown error condition encountered. Aborting connection.";
					ok = false;
				}
			}
		}
		else
		{
			errorDescription = "WebSocket::processHandshake: Unhandled http status code " + QString::number(httpStatusCode);
			ok = false;
		}

		if (!ok)
		{
			qDebug() << errorDescription;
			setErrorString(errorDescription);
			Q_EMIT error(QAbstractSocket::ConnectionRefusedError);
		}
		else
		{
			//handshake succeeded
			setSocketState(QAbstractSocket::ConnectedState);
			Q_EMIT connected();
		}
	}
}