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); } }
/*! \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; } }
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); }
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 }
/*! \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; } } }
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); }
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; } }
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()); }
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 }
/*! * \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)); }
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); } } }
/*! \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); } }
void DhQAbstractSocket::DvhsetSocketState(long x1) { return setSocketState((QAbstractSocket::SocketState)x1); }
/*! \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(); } } }