123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667 |
- // Copyright 2018 The Chromium Authors. All rights reserved.
- // Use of this source code is governed by a BSD-style license that can be
- // found in the LICENSE file.
- #include "components/cast_channel/cast_message_handler.h"
- #include <tuple>
- #include <utility>
- #include <vector>
- #include "base/bind.h"
- #include "base/containers/cxx20_erase.h"
- #include "base/observer_list.h"
- #include "base/rand_util.h"
- #include "base/strings/stringprintf.h"
- #include "base/time/default_tick_clock.h"
- #include "components/cast_channel/cast_message_util.h"
- #include "components/cast_channel/cast_socket_service.h"
- namespace cast_channel {
- namespace {
- // The max launch timeout amount for session launch requests.
- constexpr base::TimeDelta kLaunchMaxTimeout = base::Minutes(2);
- // The max size of Cast Message is 64KB.
- constexpr int kMaxCastMessagePayload = 64 * 1024;
- void ReportParseError(const std::string& error) {
- DVLOG(1) << "Error parsing JSON message: " << error;
- }
- } // namespace
- GetAppAvailabilityRequest::GetAppAvailabilityRequest(
- int request_id,
- GetAppAvailabilityCallback callback,
- const base::TickClock* clock,
- const std::string& app_id)
- : PendingRequest(request_id, std::move(callback), clock), app_id(app_id) {}
- GetAppAvailabilityRequest::~GetAppAvailabilityRequest() = default;
- VirtualConnection::VirtualConnection(int channel_id,
- const std::string& source_id,
- const std::string& destination_id)
- : channel_id(channel_id),
- source_id(source_id),
- destination_id(destination_id) {}
- VirtualConnection::~VirtualConnection() = default;
- bool VirtualConnection::operator<(const VirtualConnection& other) const {
- return std::tie(channel_id, source_id, destination_id) <
- std::tie(other.channel_id, other.source_id, other.destination_id);
- }
- InternalMessage::InternalMessage(CastMessageType type,
- const std::string& message_namespace,
- base::Value::Dict message)
- : type(type),
- message_namespace(message_namespace),
- message(std::move(message)) {}
- InternalMessage::~InternalMessage() = default;
- CastMessageHandler::CastMessageHandler(CastSocketService* socket_service,
- ParseJsonCallback parse_json,
- const std::string& user_agent,
- const std::string& browser_version,
- const std::string& locale)
- : sender_id_(base::StringPrintf("sender-%d", base::RandInt(0, 1000000))),
- parse_json_(std::move(parse_json)),
- user_agent_(user_agent),
- browser_version_(browser_version),
- locale_(locale),
- socket_service_(socket_service),
- clock_(base::DefaultTickClock::GetInstance()) {
- DETACH_FROM_SEQUENCE(sequence_checker_);
- socket_service_->task_runner()->PostTask(
- FROM_HERE, base::BindOnce(&CastSocketService::AddObserver,
- base::Unretained(socket_service_),
- base::Unretained(this)));
- }
- CastMessageHandler::~CastMessageHandler() {
- DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- socket_service_->RemoveObserver(this);
- }
- void CastMessageHandler::EnsureConnection(
- int channel_id,
- const std::string& source_id,
- const std::string& destination_id,
- VirtualConnectionType connection_type) {
- DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- CastSocket* socket = socket_service_->GetSocket(channel_id);
- if (!socket) {
- DVLOG(2) << "Socket not found: " << channel_id;
- return;
- }
- DoEnsureConnection(socket, source_id, destination_id, connection_type);
- }
- void CastMessageHandler::CloseConnection(int channel_id,
- const std::string& source_id,
- const std::string& destination_id) {
- DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- CastSocket* socket = socket_service_->GetSocket(channel_id);
- if (!socket) {
- return;
- }
- VirtualConnection connection(socket->id(), source_id, destination_id);
- if (virtual_connections_.find(connection) == virtual_connections_.end())
- return;
- VLOG(1) << "Closing VC for channel: " << connection.channel_id
- << ", source: " << connection.source_id
- << ", dest: " << connection.destination_id;
- socket->transport()->SendMessage(
- CreateVirtualConnectionClose(connection.source_id,
- connection.destination_id),
- base::BindOnce(&CastMessageHandler::OnMessageSent,
- weak_ptr_factory_.GetWeakPtr()));
- // Assume the virtual connection close will succeed. Eventually the receiver
- // will remove the connection even if it doesn't.
- virtual_connections_.erase(connection);
- }
- CastMessageHandler::PendingRequests*
- CastMessageHandler::GetOrCreatePendingRequests(int channel_id) {
- CastMessageHandler::PendingRequests* requests = nullptr;
- auto pending_it = pending_requests_.find(channel_id);
- if (pending_it != pending_requests_.end()) {
- return pending_it->second.get();
- }
- auto new_requests = std::make_unique<CastMessageHandler::PendingRequests>();
- requests = new_requests.get();
- pending_requests_.emplace(channel_id, std::move(new_requests));
- return requests;
- }
- void CastMessageHandler::RequestAppAvailability(
- CastSocket* socket,
- const std::string& app_id,
- GetAppAvailabilityCallback callback) {
- DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- int channel_id = socket->id();
- auto* requests = GetOrCreatePendingRequests(channel_id);
- int request_id = NextRequestId();
- DVLOG(2) << __func__ << ", channel_id: " << channel_id
- << ", app_id: " << app_id << ", request_id: " << request_id;
- if (requests->AddAppAvailabilityRequest(
- std::make_unique<GetAppAvailabilityRequest>(
- request_id, std::move(callback), clock_, app_id))) {
- SendCastMessageToSocket(socket, CreateGetAppAvailabilityRequest(
- sender_id_, request_id, app_id));
- }
- }
- void CastMessageHandler::RequestReceiverStatus(int channel_id) {
- DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- CastSocket* socket = socket_service_->GetSocket(channel_id);
- if (!socket) {
- DVLOG(2) << __func__ << ": socket not found: " << channel_id;
- return;
- }
- int request_id = NextRequestId();
- SendCastMessageToSocket(socket,
- CreateReceiverStatusRequest(sender_id_, request_id));
- }
- Result CastMessageHandler::SendBroadcastMessage(
- int channel_id,
- const std::vector<std::string>& app_ids,
- const BroadcastRequest& request) {
- DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- CastSocket* socket = socket_service_->GetSocket(channel_id);
- if (!socket) {
- DVLOG(2) << __func__ << ": socket not found: " << channel_id;
- return Result::kFailed;
- }
- int request_id = NextRequestId();
- DVLOG(2) << __func__ << ", channel_id: " << channel_id
- << ", request_id: " << request_id;
- // Note: Even though the message is formatted like a request, we don't care
- // about the response, as broadcasts are fire-and-forget.
- CastMessage message =
- CreateBroadcastRequest(sender_id_, request_id, app_ids, request);
- if (message.ByteSizeLong() > kMaxCastMessagePayload) {
- return Result::kFailed;
- }
- SendCastMessageToSocket(socket, message);
- return Result::kOk;
- }
- void CastMessageHandler::LaunchSession(
- int channel_id,
- const std::string& app_id,
- base::TimeDelta launch_timeout,
- const std::vector<std::string>& supported_app_types,
- const absl::optional<base::Value>& app_params,
- LaunchSessionCallback callback) {
- DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- CastSocket* socket = socket_service_->GetSocket(channel_id);
- if (!socket) {
- std::move(callback).Run(GetLaunchSessionResponseError(
- base::StringPrintf("Socket not found: %d.", channel_id)));
- return;
- }
- auto* requests = GetOrCreatePendingRequests(channel_id);
- int request_id = NextRequestId();
- // Cap the max launch timeout to avoid long-living pending requests.
- launch_timeout = std::min(launch_timeout, kLaunchMaxTimeout);
- DVLOG(2) << __func__ << ", channel_id: " << channel_id
- << ", request_id: " << request_id;
- CastMessage message = CreateLaunchRequest(
- sender_id_, request_id, app_id, locale_, supported_app_types, app_params);
- if (message.ByteSizeLong() > kMaxCastMessagePayload) {
- std::move(callback).Run(GetLaunchSessionResponseError(
- "Message size exceeds maximum cast channel message payload."));
- return;
- }
- if (requests->AddLaunchRequest(std::make_unique<LaunchSessionRequest>(
- request_id, std::move(callback), clock_),
- launch_timeout)) {
- SendCastMessageToSocket(socket, message);
- }
- }
- void CastMessageHandler::StopSession(
- int channel_id,
- const std::string& session_id,
- const absl::optional<std::string>& client_id,
- ResultCallback callback) {
- DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- CastSocket* socket = socket_service_->GetSocket(channel_id);
- if (!socket) {
- DVLOG(2) << __func__ << ": socket not found: " << channel_id;
- std::move(callback).Run(cast_channel::Result::kFailed);
- return;
- }
- auto* requests = GetOrCreatePendingRequests(channel_id);
- int request_id = NextRequestId();
- DVLOG(2) << __func__ << ", channel_id: " << channel_id
- << ", request_id: " << request_id;
- if (requests->AddStopRequest(std::make_unique<StopSessionRequest>(
- request_id, std::move(callback), clock_))) {
- SendCastMessageToSocket(
- socket, CreateStopRequest(client_id.value_or(sender_id_), request_id,
- session_id));
- }
- }
- Result CastMessageHandler::SendCastMessage(int channel_id,
- const CastMessage& message) {
- DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- CastSocket* socket = socket_service_->GetSocket(channel_id);
- if (!socket) {
- DVLOG(2) << __func__ << ": socket not found: " << channel_id;
- return Result::kFailed;
- }
- SendCastMessageToSocket(socket, message);
- return Result::kOk;
- }
- Result CastMessageHandler::SendAppMessage(int channel_id,
- const CastMessage& message) {
- DCHECK(!IsCastReservedNamespace(message.namespace_()))
- << ": unexpected app message namespace: " << message.namespace_();
- if (message.ByteSizeLong() > kMaxCastMessagePayload) {
- return Result::kFailed;
- }
- return SendCastMessage(channel_id, message);
- }
- absl::optional<int> CastMessageHandler::SendMediaRequest(
- int channel_id,
- const base::Value& body,
- const std::string& source_id,
- const std::string& destination_id) {
- DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- CastSocket* socket = socket_service_->GetSocket(channel_id);
- if (!socket) {
- DVLOG(2) << __func__ << ": socket not found: " << channel_id;
- return absl::nullopt;
- }
- int request_id = NextRequestId();
- SendCastMessageToSocket(
- socket, CreateMediaRequest(body, request_id, source_id, destination_id));
- return request_id;
- }
- void CastMessageHandler::SendSetVolumeRequest(int channel_id,
- const base::Value& body,
- const std::string& source_id,
- ResultCallback callback) {
- DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- CastSocket* socket = socket_service_->GetSocket(channel_id);
- if (!socket) {
- DVLOG(2) << __func__ << ": socket not found: " << channel_id;
- std::move(callback).Run(Result::kFailed);
- return;
- }
- auto* requests = GetOrCreatePendingRequests(channel_id);
- int request_id = NextRequestId();
- requests->AddVolumeRequest(std::make_unique<SetVolumeRequest>(
- request_id, std::move(callback), clock_));
- SendCastMessageToSocket(socket,
- CreateSetVolumeRequest(body, request_id, source_id));
- }
- void CastMessageHandler::AddObserver(Observer* observer) {
- observers_.AddObserver(observer);
- }
- void CastMessageHandler::RemoveObserver(Observer* observer) {
- observers_.RemoveObserver(observer);
- }
- void CastMessageHandler::OnError(const CastSocket& socket,
- ChannelError error_state) {
- DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- int channel_id = socket.id();
- base::EraseIf(virtual_connections_,
- [&channel_id](const VirtualConnection& connection) {
- return connection.channel_id == channel_id;
- });
- pending_requests_.erase(channel_id);
- }
- void CastMessageHandler::OnMessage(const CastSocket& socket,
- const CastMessage& message) {
- DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- // TODO(crbug.com/1291736): Splitting internal messages into a separate code
- // path with a separate data type is pretty questionable, because it causes
- // duplicated code paths in the downstream logic (manifested as separate
- // OnAppMessage and OnInternalMessage methods).
- if (IsCastReservedNamespace(message.namespace_())) {
- if (message.payload_type() ==
- cast::channel::CastMessage_PayloadType_STRING) {
- VLOG(1) << __func__ << ": channel_id: " << socket.id()
- << ", message: " << message;
- parse_json_.Run(
- message.payload_utf8(),
- base::BindOnce(&CastMessageHandler::HandleCastInternalMessage,
- weak_ptr_factory_.GetWeakPtr(), socket.id(),
- message.source_id(), message.destination_id(),
- message.namespace_()));
- } else {
- DLOG(ERROR) << "Dropping internal message with binary payload: "
- << message.namespace_();
- }
- } else {
- DVLOG(2) << "Got app message from cast channel with namespace: "
- << message.namespace_();
- for (auto& observer : observers_)
- observer.OnAppMessage(socket.id(), message);
- }
- }
- void CastMessageHandler::OnReadyStateChanged(const CastSocket& socket) {
- if (socket.ready_state() == ReadyState::CLOSED)
- pending_requests_.erase(socket.id());
- }
- void CastMessageHandler::HandleCastInternalMessage(
- int channel_id,
- const std::string& source_id,
- const std::string& destination_id,
- const std::string& namespace_,
- data_decoder::DataDecoder::ValueOrError parse_result) {
- if (!parse_result.has_value()) {
- ReportParseError(parse_result.error());
- return;
- }
- base::Value::Dict* payload = parse_result->GetIfDict();
- if (!payload) {
- ReportParseError("Parsed message not a dictionary");
- return;
- }
- // Check if the socket still exists as it might have been removed during
- // message parsing.
- if (!socket_service_->GetSocket(channel_id)) {
- DVLOG(2) << __func__ << ": socket not found: " << channel_id;
- return;
- }
- absl::optional<int> request_id = GetRequestIdFromResponse(*payload);
- if (request_id) {
- auto requests_it = pending_requests_.find(channel_id);
- if (requests_it != pending_requests_.end())
- // You might think this method should return in this case, but there is at
- // least one message type (RECEIVER_STATUS), that has a request ID but
- // also needs to be handled by the registered observers.
- requests_it->second->HandlePendingRequest(*request_id, *payload);
- }
- CastMessageType type = ParseMessageTypeFromPayload(*payload);
- if (type == CastMessageType::kOther) {
- DVLOG(2) << "Unknown type in message: " << payload;
- return;
- }
- if (type == CastMessageType::kCloseConnection) {
- // Source / destination is flipped.
- virtual_connections_.erase(
- VirtualConnection(channel_id, destination_id, source_id));
- return;
- }
- InternalMessage internal_message(type, namespace_, std::move(*payload));
- for (auto& observer : observers_)
- observer.OnInternalMessage(channel_id, internal_message);
- }
- void CastMessageHandler::SendCastMessageToSocket(CastSocket* socket,
- const CastMessage& message) {
- // A virtual connection must be opened to the receiver before other messages
- // can be sent.
- DoEnsureConnection(socket, message.source_id(), message.destination_id(),
- GetConnectionType(message.destination_id()));
- VLOG(1) << __func__ << ": channel_id: " << socket->id()
- << ", message: " << message;
- socket->transport()->SendMessage(
- message, base::BindOnce(&CastMessageHandler::OnMessageSent,
- weak_ptr_factory_.GetWeakPtr()));
- }
- void CastMessageHandler::DoEnsureConnection(
- CastSocket* socket,
- const std::string& source_id,
- const std::string& destination_id,
- VirtualConnectionType connection_type) {
- VirtualConnection connection(socket->id(), source_id, destination_id);
- // If there is already a connection, there is nothing to do.
- if (virtual_connections_.find(connection) != virtual_connections_.end())
- return;
- VLOG(1) << "Creating VC for channel: " << connection.channel_id
- << ", source: " << connection.source_id
- << ", dest: " << connection.destination_id;
- CastMessage virtual_connection_request = CreateVirtualConnectionRequest(
- connection.source_id, connection.destination_id, connection_type,
- user_agent_, browser_version_);
- socket->transport()->SendMessage(
- virtual_connection_request,
- base::BindOnce(&CastMessageHandler::OnMessageSent,
- weak_ptr_factory_.GetWeakPtr()));
- // We assume the virtual connection request will succeed; otherwise this
- // will eventually self-correct.
- virtual_connections_.insert(connection);
- }
- void CastMessageHandler::OnMessageSent(int result) {
- DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- DVLOG_IF(2, result < 0) << "SendMessage failed with code: " << result;
- }
- CastMessageHandler::PendingRequests::PendingRequests() = default;
- CastMessageHandler::PendingRequests::~PendingRequests() {
- for (auto& request : pending_app_availability_requests_) {
- std::move(request->callback)
- .Run(request->app_id, GetAppAvailabilityResult::kUnknown);
- }
- if (pending_launch_session_request_) {
- LaunchSessionResponse response;
- response.result = LaunchSessionResponse::kError;
- std::move(pending_launch_session_request_->callback)
- .Run(std::move(response));
- }
- if (pending_stop_session_request_)
- std::move(pending_stop_session_request_->callback).Run(Result::kFailed);
- for (auto& request : pending_volume_requests_by_id_)
- std::move(request.second->callback).Run(Result::kFailed);
- }
- bool CastMessageHandler::PendingRequests::AddAppAvailabilityRequest(
- std::unique_ptr<GetAppAvailabilityRequest> request) {
- const std::string& app_id = request->app_id;
- int request_id = request->request_id;
- request->timeout_timer.Start(
- FROM_HERE, kRequestTimeout,
- base::BindOnce(
- &CastMessageHandler::PendingRequests::AppAvailabilityTimedOut,
- base::Unretained(this), request_id));
- // Look for a request with the given app ID.
- bool found = std::find_if(pending_app_availability_requests_.begin(),
- pending_app_availability_requests_.end(),
- [&app_id](const auto& old_request) {
- return old_request->app_id == app_id;
- }) != pending_app_availability_requests_.end();
- pending_app_availability_requests_.emplace_back(std::move(request));
- return !found;
- }
- bool CastMessageHandler::PendingRequests::AddLaunchRequest(
- std::unique_ptr<LaunchSessionRequest> request,
- base::TimeDelta timeout) {
- if (pending_launch_session_request_) {
- std::move(request->callback)
- .Run(cast_channel::GetLaunchSessionResponseError(
- "There already exists a launch request for the channel"));
- return false;
- }
- int request_id = request->request_id;
- request->timeout_timer.Start(
- FROM_HERE, timeout,
- base::BindOnce(
- &CastMessageHandler::PendingRequests::LaunchSessionTimedOut,
- base::Unretained(this), request_id));
- pending_launch_session_request_ = std::move(request);
- return true;
- }
- bool CastMessageHandler::PendingRequests::AddStopRequest(
- std::unique_ptr<StopSessionRequest> request) {
- if (pending_stop_session_request_) {
- std::move(request->callback).Run(cast_channel::Result::kFailed);
- return false;
- }
- int request_id = request->request_id;
- request->timeout_timer.Start(
- FROM_HERE, kRequestTimeout,
- base::BindOnce(&CastMessageHandler::PendingRequests::StopSessionTimedOut,
- base::Unretained(this), request_id));
- pending_stop_session_request_ = std::move(request);
- return true;
- }
- void CastMessageHandler::PendingRequests::AddVolumeRequest(
- std::unique_ptr<SetVolumeRequest> request) {
- int request_id = request->request_id;
- request->timeout_timer.Start(
- FROM_HERE, kRequestTimeout,
- base::BindOnce(&CastMessageHandler::PendingRequests::SetVolumeTimedOut,
- base::Unretained(this), request_id));
- pending_volume_requests_by_id_.emplace(request_id, std::move(request));
- }
- void CastMessageHandler::PendingRequests::HandlePendingRequest(
- int request_id,
- const base::Value::Dict& response) {
- // Look up an app availability request by its |request_id|.
- auto app_availability_it =
- std::find_if(pending_app_availability_requests_.begin(),
- pending_app_availability_requests_.end(),
- [request_id](const auto& request_ptr) {
- return request_ptr->request_id == request_id;
- });
- // If we found a request, process and remove all requests with the same
- // |app_id|, which will of course include the one we just found.
- if (app_availability_it != pending_app_availability_requests_.end()) {
- std::string app_id = (*app_availability_it)->app_id;
- GetAppAvailabilityResult result =
- GetAppAvailabilityResultFromResponse(response, app_id);
- base::EraseIf(pending_app_availability_requests_,
- [&app_id, result](const auto& request_ptr) {
- if (request_ptr->app_id == app_id) {
- std::move(request_ptr->callback).Run(app_id, result);
- return true;
- }
- return false;
- });
- return;
- }
- if (pending_launch_session_request_ &&
- pending_launch_session_request_->request_id == request_id) {
- std::move(pending_launch_session_request_->callback)
- .Run(GetLaunchSessionResponse(response));
- pending_launch_session_request_.reset();
- return;
- }
- if (pending_stop_session_request_ &&
- pending_stop_session_request_->request_id == request_id) {
- std::move(pending_stop_session_request_->callback).Run(Result::kOk);
- pending_stop_session_request_.reset();
- return;
- }
- auto volume_it = pending_volume_requests_by_id_.find(request_id);
- if (volume_it != pending_volume_requests_by_id_.end()) {
- std::move(volume_it->second->callback).Run(Result::kOk);
- pending_volume_requests_by_id_.erase(volume_it);
- return;
- }
- }
- void CastMessageHandler::PendingRequests::AppAvailabilityTimedOut(
- int request_id) {
- DVLOG(1) << __func__ << ", request_id: " << request_id;
- auto it = std::find_if(pending_app_availability_requests_.begin(),
- pending_app_availability_requests_.end(),
- [&request_id](const auto& request) {
- return request->request_id == request_id;
- });
- CHECK(it != pending_app_availability_requests_.end());
- std::move((*it)->callback)
- .Run((*it)->app_id, GetAppAvailabilityResult::kUnknown);
- pending_app_availability_requests_.erase(it);
- }
- void CastMessageHandler::PendingRequests::LaunchSessionTimedOut(
- int request_id) {
- DVLOG(1) << __func__ << ", request_id: " << request_id;
- CHECK(pending_launch_session_request_);
- CHECK(pending_launch_session_request_->request_id == request_id);
- LaunchSessionResponse response;
- response.result = LaunchSessionResponse::kTimedOut;
- std::move(pending_launch_session_request_->callback).Run(std::move(response));
- pending_launch_session_request_.reset();
- }
- void CastMessageHandler::PendingRequests::StopSessionTimedOut(int request_id) {
- DVLOG(1) << __func__ << ", request_id: " << request_id;
- CHECK(pending_stop_session_request_);
- CHECK(pending_stop_session_request_->request_id == request_id);
- std::move(pending_stop_session_request_->callback).Run(Result::kFailed);
- pending_stop_session_request_.reset();
- }
- void CastMessageHandler::PendingRequests::SetVolumeTimedOut(int request_id) {
- DVLOG(1) << __func__ << ", request_id: " << request_id;
- auto it = pending_volume_requests_by_id_.find(request_id);
- DCHECK(it != pending_volume_requests_by_id_.end());
- std::move(it->second->callback).Run(Result::kFailed);
- pending_volume_requests_by_id_.erase(it);
- }
- } // namespace cast_channel
|