aboutsummaryrefslogtreecommitdiff
path: root/cast/streaming/receiver_session.cc
diff options
context:
space:
mode:
authorJordan Bayles <jophba@chromium.org>2020-06-05 14:14:54 -0700
committerCommit Bot <commit-bot@chromium.org>2020-06-05 23:27:56 +0000
commit3afe77d7e243959f39568a58c8bff451eea87cbd (patch)
treee6986fedf34a47d1e8946b7b18b16175311c007e /cast/streaming/receiver_session.cc
parent977bb0c2f35a96500ecbd09b236ab39b6ddc55fd (diff)
downloadopenscreen-3afe77d7e243959f39568a58c8bff451eea87cbd.tar.gz
Implement Answer parsing
This patch adds Answer parsing and testing, similar to how Offer messages are currently parsed. As part of this work, the following improvements are also included: 1. To avoid Abseil usage in public APIs, a new Optional type with unit tests is included. 2. message_util.h helpers have been greatly expanded, moved to util/json/parsing_helpers.h, and unit tests added. 3. SimpleFraction has been moved from util/ to platform/base/, so it can be properly used in public APIs. 4. SessionConfig has been cleaned up to follow coding style guidelines. 5. ANSWER message creation (that encapsulates the Answer struct) has been moved to the ReceiverSession. Bug: b/152633271, b/158030843 Change-Id: I59c20a140a5174d45378fb9b647ccbe5e6d23d1b Reviewed-on: https://chromium-review.googlesource.com/c/openscreen/+/2219571 Commit-Queue: Jordan Bayles <jophba@chromium.org> Reviewed-by: mark a. foltz <mfoltz@chromium.org> Reviewed-by: Ryan Keane <rwkeane@google.com>
Diffstat (limited to 'cast/streaming/receiver_session.cc')
-rw-r--r--cast/streaming/receiver_session.cc70
1 files changed, 54 insertions, 16 deletions
diff --git a/cast/streaming/receiver_session.cc b/cast/streaming/receiver_session.cc
index 5d2e74bd..467fd27d 100644
--- a/cast/streaming/receiver_session.cc
+++ b/cast/streaming/receiver_session.cc
@@ -12,14 +12,15 @@
#include "absl/strings/numbers.h"
#include "cast/streaming/environment.h"
#include "cast/streaming/message_port.h"
-#include "cast/streaming/message_util.h"
#include "cast/streaming/offer_messages.h"
#include "cast/streaming/receiver.h"
+#include "util/json/json_helpers.h"
#include "util/osp_logging.h"
namespace openscreen {
namespace cast {
+/// NOTE: Constants here are all taken from the Cast V2: Mirroring Control
// JSON message field values specific to the Receiver Session.
static constexpr char kMessageTypeOffer[] = "OFFER";
@@ -28,6 +29,20 @@ static constexpr char kOfferMessageBody[] = "offer";
static constexpr char kKeyType[] = "type";
static constexpr char kSequenceNumber[] = "seqNum";
+/// Protocol specification: http://goto.google.com/mirroring-control-protocol
+// TODO(jophba): document the protocol in a public repository.
+static constexpr char kMessageKeyType[] = "type";
+static constexpr char kMessageTypeAnswer[] = "ANSWER";
+
+/// ANSWER message fields.
+static constexpr char kAnswerMessageBody[] = "answer";
+static constexpr char kResult[] = "result";
+static constexpr char kResultOk[] = "ok";
+static constexpr char kResultError[] = "error";
+static constexpr char kErrorMessageBody[] = "error";
+static constexpr char kErrorCode[] = "code";
+static constexpr char kErrorDescription[] = "description";
+
// Using statements for constructor readability.
using Preferences = ReceiverSession::Preferences;
using ConfiguredReceivers = ReceiverSession::ConfiguredReceivers;
@@ -76,7 +91,30 @@ const Stream* SelectStream(const std::vector<Codec>& preferred_codecs,
}
return nullptr;
}
+// Helper method that creates an invalid Answer response.
+Json::Value CreateInvalidAnswerMessage(Error error) {
+ Json::Value message_root;
+ message_root[kMessageKeyType] = kMessageTypeAnswer;
+ message_root[kResult] = kResultError;
+ message_root[kErrorMessageBody][kErrorCode] = static_cast<int>(error.code());
+ message_root[kErrorMessageBody][kErrorDescription] = error.message();
+
+ return message_root;
+}
+// Helper method that creates an Answer response. May be valid or invalid.
+Json::Value CreateAnswerMessage(const Answer& answer) {
+ if (!answer.IsValid()) {
+ return CreateInvalidAnswerMessage(Error(Error::Code::kParameterInvalid,
+ "Answer struct in invalid state"));
+ }
+
+ Json::Value message_root;
+ message_root[kMessageKeyType] = kMessageTypeAnswer;
+ message_root[kAnswerMessageBody] = answer.ToJson();
+ message_root[kResult] = kResultOk;
+ return message_root;
+}
} // namespace
Preferences::Preferences() = default;
@@ -129,21 +167,22 @@ void ReceiverSession::OnMessage(absl::string_view sender_id,
}
// TODO(jophba): add sender connected/disconnected messaging.
- auto sequence_number = ParseInt(message_json.value(), kSequenceNumber);
- if (!sequence_number) {
+ int sequence_number;
+ if (!json::ParseAndValidateInt(message_json.value()[kSequenceNumber],
+ &sequence_number)) {
OSP_LOG_WARN << "Invalid message sequence number";
return;
}
- auto key_or_error = ParseString(message_json.value(), kKeyType);
- if (!key_or_error) {
+ std::string key;
+ if (!json::ParseAndValidateString(message_json.value()[kKeyType], &key)) {
OSP_LOG_WARN << "Invalid message key";
return;
}
Message parsed_message{sender_id.data(), message_namespace.data(),
- sequence_number.value()};
- if (key_or_error.value() == kMessageTypeOffer) {
+ sequence_number};
+ if (key == kMessageTypeOffer) {
parsed_message.body = std::move(message_json.value()[kOfferMessageBody]);
if (parsed_message.body.isNull()) {
OSP_LOG_WARN << "Invalid message offer body";
@@ -180,7 +219,6 @@ void ReceiverSession::OnOffer(Message* message) {
SelectStream(preferences_.video_codecs, offer.value().video_streams);
}
- cast_mode_ = offer.value().cast_mode;
auto receivers =
TrySpawningReceivers(selected_audio_stream, selected_video_stream);
if (receivers) {
@@ -188,9 +226,9 @@ void ReceiverSession::OnOffer(Message* message) {
ConstructAnswer(message, selected_audio_stream, selected_video_stream);
client_->OnNegotiated(this, std::move(receivers.value()));
- message->body = answer.ToAnswerMessage();
+ message->body = CreateAnswerMessage(answer);
} else {
- message->body = CreateInvalidAnswer(receivers.error());
+ message->body = CreateInvalidAnswerMessage(receivers.error());
}
SendMessage(message);
@@ -266,20 +304,20 @@ Answer ReceiverSession::ConstructAnswer(
absl::optional<Constraints> constraints;
if (preferences_.constraints) {
- constraints = *preferences_.constraints;
+ constraints = absl::optional<Constraints>(*preferences_.constraints);
}
absl::optional<DisplayDescription> display;
if (preferences_.display_description) {
- display = *preferences_.display_description;
+ display =
+ absl::optional<DisplayDescription>(*preferences_.display_description);
}
- return Answer{cast_mode_,
- environment_->GetBoundLocalEndpoint().port,
+ return Answer{environment_->GetBoundLocalEndpoint().port,
std::move(stream_indexes),
std::move(stream_ssrcs),
- constraints,
- display,
+ std::move(constraints),
+ std::move(display),
std::vector<int>{}, // receiver_rtcp_event_log
std::vector<int>{}, // receiver_rtcp_dscp
supports_wifi_status_reporting_};