// Copyright 2020 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. #ifndef CAST_STREAMING_SESSION_MESSAGER_H_ #define CAST_STREAMING_SESSION_MESSAGER_H_ #include #include #include #include #include "absl/types/optional.h" #include "absl/types/variant.h" #include "cast/common/public/message_port.h" #include "cast/streaming/answer_messages.h" #include "cast/streaming/offer_messages.h" #include "cast/streaming/receiver_message.h" #include "cast/streaming/sender_message.h" #include "json/value.h" #include "platform/api/task_runner.h" #include "util/flat_map.h" #include "util/weak_ptr.h" namespace openscreen { namespace cast { // A message port interface designed specifically for use by the Receiver // and Sender session classes. class SessionMessager : public MessagePort::Client { public: using ErrorCallback = std::function; SessionMessager(MessagePort* message_port, std::string source_id, ErrorCallback cb); ~SessionMessager() override; protected: // Barebones message sending method shared by both children. Error SendMessage(const std::string& destination_id, const std::string& namespace_, const Json::Value& message_root); // Used to report errors in subclasses. void ReportError(Error error); private: MessagePort* const message_port_; ErrorCallback error_callback_; }; class SenderSessionMessager final : public SessionMessager { public: using ReplyCallback = std::function; SenderSessionMessager(MessagePort* message_port, std::string source_id, std::string receiver_id, ErrorCallback cb, TaskRunner* task_runner); // Set receiver message handler. Note that this should only be // applied for messages that don't have sequence numbers, like RPC // and status messages. void SetHandler(ReceiverMessage::Type type, ReplyCallback cb); // Send a request (with optional reply callback). [[nodiscard]] Error SendOutboundMessage(SenderMessage message); [[nodiscard]] Error SendRequest(SenderMessage message, ReceiverMessage::Type reply_type, ReplyCallback cb); // MessagePort::Client overrides void OnMessage(const std::string& source_id, const std::string& message_namespace, const std::string& message) override; void OnError(Error error) override; private: TaskRunner* const task_runner_; // This messager should only be connected to one receiver, so |receiver_id_| // should not change. const std::string receiver_id_; // We keep a list here of replies we are expecting--if the reply is // received for this sequence number, we call its respective callback, // otherwise it is called after an internally specified timeout. FlatMap awaiting_replies_; // Currently we can only set a handler for RPC messages, so no need for // a flatmap here. ReplyCallback rpc_callback_; WeakPtrFactory weak_factory_{this}; }; class ReceiverSessionMessager final : public SessionMessager { public: using RequestCallback = std::function; ReceiverSessionMessager(MessagePort* message_port, std::string source_id, ErrorCallback cb); // Set sender message handler. void SetHandler(SenderMessage::Type type, RequestCallback cb); // Send a JSON message. [[nodiscard]] Error SendMessage(ReceiverMessage message); // MessagePort::Client overrides void OnMessage(const std::string& source_id, const std::string& message_namespace, const std::string& message) override; void OnError(Error error) override; private: // The sender ID of the SenderSession we are connected to. Set on the // first message we receive. std::string sender_session_id_; FlatMap callbacks_; }; } // namespace cast } // namespace openscreen #endif // CAST_STREAMING_SESSION_MESSAGER_H_