void KaaChannelManager::onServerFailed(ITransportConnectionInfoPtr connectionInfo) { if (isShutdown_) { KAA_LOG_WARN("Can't update server. Channel manager is down"); return; } if (!connectionInfo) { KAA_LOG_WARN("Failed to process server failure: bad input data") throw KaaException("empty connection info pointer"); } if (connectionInfo->isFailedState()) { KAA_LOG_DEBUG("Connection already failed. Ignoring connection failover!"); return; } else { connectionInfo->setFailedState(); } if (connectionInfo->getServerType() == ServerType::BOOTSTRAP) { ITransportConnectionInfoPtr nextConnectionInfo = getNextBootstrapServer(connectionInfo->getTransportId(), false); if (nextConnectionInfo) { onTransportConnectionInfoUpdated(nextConnectionInfo); } else { FailoverStrategyDecision decision = failoverStrategy_->onFailover(Failover::BOOTSTRAP_SERVERS_NA); switch (decision.getAction()) { case FailoverStrategyAction::NOOP: KAA_LOG_WARN("No operation is performed according to failover strategy decision."); break; case FailoverStrategyAction::RETRY: { std::size_t period = decision.getRetryPeriod(); KAA_LOG_WARN(boost::format("Attempt to reconnect to first bootstrap server will be made in %1% secs " "according to failover strategy decision.") % period); bsTransportId_ = connectionInfo->getTransportId(); retryTimer_.stop(); retryTimer_.start(period, [&] { onTransportConnectionInfoUpdated(getNextBootstrapServer(bsTransportId_, true)); }); break; } case FailoverStrategyAction::STOP_APP: KAA_LOG_WARN("Stopping application according to failover strategy decision!"); exit(EXIT_FAILURE); break; default: break; } } } else { bootstrapManager_.useNextOperationsServer(connectionInfo->getTransportId()); } }
void KaaChannelManager::onTransportConnectionInfoUpdated(ITransportConnectionInfoPtr connectionInfo) { if (isShutdown_) { KAA_LOG_WARN("Can't update server. Channel manager is down"); return; } if (!connectionInfo) { KAA_LOG_WARN("Failed to update connection info: bad input data") throw KaaException("empty connection info pointer"); } connectionInfo->resetFailedState(); TransportProtocolId protocolId = connectionInfo->getTransportId(); if (connectionInfo->getServerType() == ServerType::OPERATIONS) { KAA_MUTEX_LOCKING("lastOpsServersGuard_"); KAA_MUTEX_UNIQUE_DECLARE(lastOpsServers_Lock, lastOpsServersGuard_); KAA_MUTEX_LOCKED("lastOpsServersGuard_"); lastOpsServers_[protocolId] = connectionInfo; } KAA_MUTEX_LOCKING("channelGuard_"); KAA_R_MUTEX_UNIQUE_DECLARE(channelLock, channelGuard_); KAA_MUTEX_LOCKED("channelGuard_"); for (auto& channel : channels_) { if (channel->getServerType() == connectionInfo->getServerType() && channel->getTransportProtocolId() == protocolId) { KAA_LOG_DEBUG(boost::format("Setting a new connection data for channel \"%1%\" %2%") % channel->getId() % LoggingUtils::TransportProtocolIdToString(protocolId)); channel->setServer(connectionInfo); } } }
void DefaultOperationTcpChannel::setServer(ITransportConnectionInfoPtr server) { KAA_MUTEX_LOCKING("channelGuard_"); KAA_MUTEX_UNIQUE_DECLARE(lock, channelGuard_); KAA_MUTEX_LOCKED("channelGuard_"); if (isShutdown_) { KAA_LOG_WARN(boost::format("Channel [%1%] ignore new server: channel is shut down") % getId()); return; } if (server->getTransportId() != getTransportProtocolId()) { KAA_LOG_WARN(boost::format("Channel [%1%] ignore new server: unsupported transport %2%") % getId() % LoggingUtils::toString(server->getTransportId())); return; } KAA_LOG_TRACE(boost::format("Channel [%1%] preparing to use new server %2%") % getId() % LoggingUtils::toString(*server)); currentServer_ = std::make_shared<IPTransportInfo>(server); encDec_ = std::make_shared<RsaEncoderDecoder>(clientKeys_.getPublicKey(), clientKeys_.getPrivateKey(), currentServer_->getPublicKey(), context_); isFailoverInProgress_ = false; if (!isPaused_) { KAA_MUTEX_UNLOCKING("channelGuard_"); KAA_UNLOCK(lock); KAA_MUTEX_UNLOCKED("channelGuard_"); closeConnection(); KAA_LOG_TRACE(boost::format("Channel [%1%] scheduling open connection") % getId()); io_.post(std::bind(&DefaultOperationTcpChannel::openConnection, this)); } }
IPTransportInfo::IPTransportInfo(ITransportConnectionInfoPtr connectionInfo) : GenericTransportInfo(connectionInfo->getServerType(), ProtocolMetaData()) { if (!connectionInfo || connectionInfo->getConnectionInfo().empty()) { KAA_LOG_ERROR("Failed to create IP transport data: bad input data"); throw KaaException("Bad connection data"); } serverType_ = connectionInfo->getServerType(); connectionData_ = connectionInfo->getConnectionInfo(); accessPointId_ = connectionInfo->getAccessPointId(); protocolId_ = connectionInfo->getTransportId(); std::uint8_t *data = connectionData_.data(); std::int32_t publicKeyLength = boost::asio::detail::socket_ops::network_to_host_long(*((int32_t *)data)); data += sizeof(std::int32_t); publicKey_ = PublicKey(data, publicKeyLength); data += publicKeyLength; std::int32_t hostLength = boost::asio::detail::socket_ops::network_to_host_long(*((int32_t *)data)); data += sizeof(std::int32_t); host_.assign(data, data + hostLength); data += hostLength; port_ = boost::asio::detail::socket_ops::network_to_host_long(*((int32_t *)data)); std::ostringstream ss; ss << "http://" << host_ << ":" << port_; url_.assign(ss.str()); if ((3 * sizeof(std::int32_t) + publicKeyLength + hostLength) > connectionData_.size()) { KAA_LOG_ERROR("Failed to create IP transport data: less size of input data than needed"); throw KaaException("Bad connection data"); } KAA_LOG_TRACE(boost::format("Create IP transport data: host=%1%, port=%2%, publicKeyLength=%3%") % host_% port_ % publicKey_.size()); }
void AbstractHttpChannel::setServer(ITransportConnectionInfoPtr server) { if (server->getTransportId() != getTransportProtocolId()) { KAA_LOG_ERROR(boost::format("Channel [%1%] ignored invalid server info") % getId()); return; } KAA_MUTEX_LOCKING("channelGuard_"); KAA_MUTEX_UNIQUE_DECLARE(lock, channelGuard_); KAA_MUTEX_LOCKED("channelGuard_"); KAA_LOG_TRACE(boost::format("Channel [%1%] preparing to use new server %2%") % getId() % LoggingUtils::toString(*server)); currentServer_ = std::make_shared<IPTransportInfo>(server); httpDataProcessor_.setEncoderDecoder( std::make_shared<RsaEncoderDecoder>(clientKeys_.getPublicKey(), clientKeys_.getPrivateKey(), currentServer_->getPublicKey(), context_)); }