void CClient::connect() { if (m_stream != NULL) { return; } if (m_suspended) { m_connectOnResume = true; return; } try { // resolve the server hostname. do this every time we connect // in case we couldn't resolve the address earlier or the address // has changed (which can happen frequently if this is a laptop // being shuttled between various networks). patch by Brent // Priddy. m_serverAddress.resolve(); // m_serverAddress will be null if the hostname address is not reolved if (m_serverAddress.getAddress() != NULL) { // to help users troubleshoot, show server host name (issue: 60) LOG((CLOG_NOTE "connecting to '%s': %s:%i", m_serverAddress.getHostname().c_str(), ARCH->addrToString(m_serverAddress.getAddress()).c_str(), m_serverAddress.getPort())); } // create the socket IDataSocket* socket = m_socketFactory->create(); // filter socket messages, including a packetizing filter m_stream = socket; if (m_streamFilterFactory != NULL) { m_stream = m_streamFilterFactory->create(m_stream, true); } m_stream = new CPacketStreamFilter(m_events, m_stream, true); if (m_crypto.m_mode != kDisabled) { m_cryptoStream = new CCryptoStream( m_events, m_stream, m_crypto, true); m_stream = m_cryptoStream; } // connect LOG((CLOG_DEBUG1 "connecting to server")); setupConnecting(); setupTimer(); socket->connect(m_serverAddress); } catch (XBase& e) { cleanupTimer(); cleanupConnecting(); delete m_stream; m_stream = NULL; LOG((CLOG_DEBUG1 "connection failed")); sendConnectionFailedEvent(e.what()); return; } }
void Client::handleDisconnected(const Event&, void*) { cleanupTimer(); cleanupScreen(); cleanupConnection(); LOG((CLOG_DEBUG1 "disconnected")); sendEvent(m_events->forClient().disconnected(), NULL); }
void Client::handleOutputError(const Event&, void*) { cleanupTimer(); cleanupScreen(); cleanupConnection(); LOG((CLOG_WARN "error sending to server")); sendEvent(m_events->forClient().disconnected(), NULL); }
void CClient::handleDisconnected(const CEvent&, void*) { cleanupTimer(); cleanupScreen(); cleanupConnection(); LOG((CLOG_DEBUG1 "disconnected")); sendEvent(getDisconnectedEvent(), NULL); }
void CClient::handleOutputError(const CEvent&, void*) { cleanupTimer(); cleanupScreen(); cleanupConnection(); LOG((CLOG_WARN "error sending to server")); sendEvent(getDisconnectedEvent(), NULL); }
void Client::handleConnectTimeout(const Event&, void*) { cleanupTimer(); cleanupConnecting(); cleanupConnection(); cleanupStream(); LOG((CLOG_DEBUG1 "connection timed out")); sendConnectionFailedEvent("Timed out"); }
void CClient::handleConnectTimeout(const CEvent&, void*) { cleanupTimer(); cleanupConnecting(); cleanupConnection(); delete m_stream; m_stream = NULL; LOG((CLOG_DEBUG1 "connection timed out")); sendConnectionFailedEvent("Timed out"); }
void Client::handleHello(const Event&, void*) { SInt16 major, minor; if (!ProtocolUtil::readf(m_stream, kMsgHello, &major, &minor)) { sendConnectionFailedEvent("Protocol error from server, check encryption settings"); cleanupTimer(); cleanupConnection(); return; } // check versions LOG((CLOG_DEBUG1 "got hello version %d.%d", major, minor)); if (major < kProtocolMajorVersion || (major == kProtocolMajorVersion && minor < kProtocolMinorVersion)) { sendConnectionFailedEvent(XIncompatibleClient(major, minor).what()); cleanupTimer(); cleanupConnection(); return; } // say hello back LOG((CLOG_DEBUG1 "say hello version %d.%d", kProtocolMajorVersion, kProtocolMinorVersion)); ProtocolUtil::writef(m_stream, kMsgHelloBack, kProtocolMajorVersion, kProtocolMinorVersion, &m_name); // now connected but waiting to complete handshake setupScreen(); cleanupTimer(); // make sure we process any remaining messages later. we won't // receive another event for already pending messages so we fake // one. if (m_stream->isReady()) { m_events->addEvent(Event(m_events->forIStream().inputReady(), m_stream->getEventTarget())); } }
void Client::handleConnectionFailed(const Event& event, void*) { IDataSocket::ConnectionFailedInfo* info = reinterpret_cast<IDataSocket::ConnectionFailedInfo*>(event.getData()); cleanupTimer(); cleanupConnecting(); cleanupStream(); LOG((CLOG_DEBUG1 "connection failed")); sendConnectionFailedEvent(info->m_what.c_str()); delete info; }
CClient::~CClient() { EVENTQUEUE->removeHandler(IScreen::getSuspendEvent(), getEventTarget()); EVENTQUEUE->removeHandler(IScreen::getResumeEvent(), getEventTarget()); cleanupTimer(); cleanupScreen(); cleanupConnecting(); cleanupConnection(); delete m_socketFactory; delete m_streamFilterFactory; }
void Client::disconnect(const char* msg) { m_connectOnResume = false; cleanupTimer(); cleanupScreen(); cleanupConnecting(); cleanupConnection(); if (msg != NULL) { sendConnectionFailedEvent(msg); } else { sendEvent(m_events->forClient().disconnected(), NULL); } }
void HTTPResourceRequest::onTimeout() { qDebug() << "Timeout: " << _url << ":" << _reply->isFinished(); Q_ASSERT(_state == InProgress); _reply->disconnect(this); _reply->abort(); _reply->deleteLater(); _reply = nullptr; cleanupTimer(); _result = Timeout; _state = Finished; emit finished(); DependencyManager::get<StatTracker>()->incrementStat(STAT_HTTP_REQUEST_FAILED); }
Client::~Client() { if (m_mock) { return; } m_events->removeHandler(m_events->forIScreen().suspend(), getEventTarget()); m_events->removeHandler(m_events->forIScreen().resume(), getEventTarget()); cleanupTimer(); cleanupScreen(); cleanupConnecting(); cleanupConnection(); delete m_socketFactory; }
void CClient::connect() { if (m_stream != NULL) { return; } if (m_suspended) { m_connectOnResume = true; return; } try { // resolve the server hostname. do this every time we connect // in case we couldn't resolve the address earlier or the address // has changed (which can happen frequently if this is a laptop // being shuttled between various networks). patch by Brent // Priddy. m_serverAddress.resolve(); // create the socket IDataSocket* socket = m_socketFactory->create(); // filter socket messages, including a packetizing filter m_stream = socket; if (m_streamFilterFactory != NULL) { m_stream = m_streamFilterFactory->create(m_stream, true); } m_stream = new CPacketStreamFilter(m_stream, true); // connect LOG((CLOG_DEBUG1 "connecting to server")); setupConnecting(); setupTimer(); socket->connect(m_serverAddress); } catch (XBase& e) { cleanupTimer(); cleanupConnecting(); delete m_stream; m_stream = NULL; LOG((CLOG_DEBUG1 "connection failed")); sendConnectionFailedEvent(e.what()); return; } }
CClient::~CClient() { // HACK: can't disable dtor with mocks if (m_mock) return; m_eventQueue.removeHandler(IScreen::getSuspendEvent(), getEventTarget()); m_eventQueue.removeHandler(IScreen::getResumeEvent(), getEventTarget()); cleanupTimer(); cleanupScreen(); cleanupConnecting(); cleanupConnection(); delete m_socketFactory; delete m_streamFilterFactory; }
void HTTPResourceRequest::onRequestFinished() { Q_ASSERT(_state == InProgress); Q_ASSERT(_reply); cleanupTimer(); // Content-Range headers have the form: // // Content-Range: <unit> <range-start>-<range-end>/<size> // Content-Range: <unit> <range-start>-<range-end>/* // Content-Range: <unit> */<size> // auto parseContentRangeHeader = [](QString contentRangeHeader) -> std::pair<bool, uint64_t> { auto unitRangeParts = contentRangeHeader.split(' '); if (unitRangeParts.size() != 2) { return { false, 0 }; } auto rangeSizeParts = unitRangeParts[1].split('/'); if (rangeSizeParts.size() != 2) { return { false, 0 }; } auto sizeStr = rangeSizeParts[1]; if (sizeStr == "*") { return { true, 0 }; } else { bool ok; auto size = sizeStr.toLong(&ok); return { ok, size }; } }; switch(_reply->error()) { case QNetworkReply::NoError: _data = _reply->readAll(); _loadedFromCache = _reply->attribute(QNetworkRequest::SourceIsFromCacheAttribute).toBool(); _result = Success; if (_byteRange.isSet()) { auto statusCode = _reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(); if (statusCode == 206) { _rangeRequestSuccessful = true; auto contentRangeHeader = _reply->rawHeader("Content-Range"); bool success; uint64_t size; std::tie(success, size) = parseContentRangeHeader(contentRangeHeader); if (success) { _totalSizeOfResource = size; } else { qWarning(networking) << "Error parsing content-range header: " << contentRangeHeader; _totalSizeOfResource = 0; } } else { _rangeRequestSuccessful = false; _totalSizeOfResource = _data.size(); } } recordBytesDownloadedInStats(STAT_HTTP_RESOURCE_TOTAL_BYTES, _data.size()); break; case QNetworkReply::TimeoutError: _result = Timeout; break; case QNetworkReply::ContentNotFoundError: // Script.include('https://httpbin.org/status/404') _result = NotFound; break; case QNetworkReply::ProtocolInvalidOperationError: // Script.include('https://httpbin.org/status/400') _result = InvalidURL; break; case QNetworkReply::UnknownContentError: // Script.include('QUrl("https://httpbin.org/status/402")') case QNetworkReply::ContentOperationNotPermittedError: //Script.include('https://httpbin.org/status/403') case QNetworkReply::AuthenticationRequiredError: // Script.include('https://httpbin.org/basic-auth/user/passwd') _result = AccessDenied; break; case QNetworkReply::RemoteHostClosedError: // Script.include('http://127.0.0.1:22') case QNetworkReply::ConnectionRefusedError: // Script.include(http://127.0.0.1:1') case QNetworkReply::HostNotFoundError: // Script.include('http://foo.bar.highfidelity.io') case QNetworkReply::ServiceUnavailableError: // Script.include('QUrl("https://httpbin.org/status/503")') _result = ServerUnavailable; break; case QNetworkReply::UnknownServerError: // Script.include('QUrl("https://httpbin.org/status/504")') case QNetworkReply::InternalServerError: // Script.include('QUrl("https://httpbin.org/status/500")') default: qCDebug(networking) << "HTTPResourceRequest error:" << QMetaEnum::fromType<QNetworkReply::NetworkError>().valueToKey(_reply->error()); _result = Error; break; } _reply->disconnect(this); _reply->deleteLater(); _reply = nullptr; _state = Finished; emit finished(); auto statTracker = DependencyManager::get<StatTracker>(); if (_result == Success) { statTracker->incrementStat(STAT_HTTP_REQUEST_SUCCESS); if (loadedFromCache()) { statTracker->incrementStat(STAT_HTTP_REQUEST_CACHE); } } else { statTracker->incrementStat(STAT_HTTP_REQUEST_FAILED); } }