// Copyright 2020 The Chromium Authors // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #ifndef CAST_STREAMING_PUBLIC_SESSION_MESSENGER_H_ #define CAST_STREAMING_PUBLIC_SESSION_MESSENGER_H_ #include #include #include #include #include "cast/common/public/message_port.h" #include "cast/streaming/public/answer_messages.h" #include "cast/streaming/public/offer_messages.h" #include "cast/streaming/public/receiver_message.h" #include "cast/streaming/sender_message.h" #include "json/value.h" #include "platform/api/task_runner.h" #include "platform/base/span.h" #include "util/flat_map.h" #include "util/raw_ref.h" #include "util/weak_ptr.h" namespace openscreen::cast { // A message port interface designed specifically for use by the Receiver // and Sender session classes. class SessionMessenger : public MessagePort::Client { public: using ErrorCallback = std::function; SessionMessenger(MessagePort& message_port, std::string source_id, ErrorCallback cb); ~SessionMessenger() override; MessagePort& message_port() { return *message_port_; } protected: // Barebones message sending method shared by both children. [[nodiscard]] Error SendMessage(const std::string& destination_id, const std::string& namespace_, const Json::Value& message_root); // Used to report errors in subclasses. void ReportError(const Error& error); const std::string& source_id() override { return source_id_; } private: const raw_ref message_port_; const std::string source_id_; ErrorCallback error_callback_; }; // Message port interface designed to handle sending messages to and // from a receiver. When possible, errors receiving messages are reported // to the ReplyCallback passed to SendRequest(), otherwise errors are // reported to the ErrorCallback passed in the constructor. class SenderSessionMessenger final : public SessionMessenger { public: using ReplyCallback = std::function)>; SenderSessionMessenger(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); void ResetHandler(ReceiverMessage::Type type); // Send a message that doesn't require a reply. [[nodiscard]] Error SendOutboundMessage(SenderMessage message); // Convenience method for sending a valid RPC message. [[nodiscard]] Error SendRpcMessage(ByteView message); // Convenience method for sending a valid INPUT message. [[nodiscard]] Error SendInputMessage(ByteView message); // Send a request (with optional reply callback). [[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(const Error& error) override; private: const raw_ref task_runner_; // This messenger 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_; ReplyCallback input_callback_; WeakPtrFactory weak_factory_{this}; }; // Message port interface designed for messaging to and from a sender. class ReceiverSessionMessenger final : public SessionMessenger { public: using RequestCallback = std::function; ReceiverSessionMessenger(MessagePort& message_port, std::string source_id, ErrorCallback cb); // Set sender message handler. void SetHandler(SenderMessage::Type type, RequestCallback cb); void ResetHandler(SenderMessage::Type type); // Convenience method for sending a valid RPC message. [[nodiscard]] Error SendRpcMessage(const std::string& source_id, ByteView message); // Convenience method for sending a valid INPUT message. [[nodiscard]] Error SendInputMessage(const std::string& source_id, ByteView message); // Send a JSON message. [[nodiscard]] Error SendMessage(const std::string& source_id, ReceiverMessage message); // Send a raw string message to a custom namespace. [[nodiscard]] Error SendMessage(std::string_view destination_id, std::string_view message_namespace, std::string_view message); using CustomMessageCallback = std::function; void SetCustomMessageHandler(std::string_view message_namespace, CustomMessageCallback cb); // MessagePort::Client overrides void OnMessage(const std::string& source_id, const std::string& message_namespace, const std::string& message) override; void OnError(const Error& error) override; private: FlatMap callbacks_; std::vector> custom_message_handlers_; }; } // namespace openscreen::cast #endif // CAST_STREAMING_PUBLIC_SESSION_MESSENGER_H_