blob: 6feff42172c402ae2469188f31e8493538afdce4 [file] [log] [blame]
// 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/mirroring/service/receiver_response.h"
#include "base/base64.h"
#include "base/json/json_reader.h"
#include "base/json/json_writer.h"
#include "base/logging.h"
#include "base/strings/string_util.h"
#include "components/mirroring/service/value_util.h"
namespace mirroring {
namespace {
// Get the response type from the type string value in the JSON message.
ResponseType GetResponseType(const std::string& type) {
if (type == "ANSWER")
return ResponseType::ANSWER;
if (type == "STATUS_RESPONSE")
return ResponseType::STATUS_RESPONSE;
if (type == "CAPABILITIES_RESPONSE")
return ResponseType::CAPABILITIES_RESPONSE;
if (type == "RPC")
return ResponseType::RPC;
return ResponseType::UNKNOWN;
}
} // namespace
Answer::Answer()
: udp_port(-1), supports_get_status(false), cast_mode("mirroring") {}
Answer::~Answer() {}
Answer::Answer(const Answer& answer) = default;
bool Answer::Parse(const base::Value& raw_value) {
return (raw_value.is_dict() && GetInt(raw_value, "udpPort", &udp_port) &&
GetIntArray(raw_value, "ssrcs", &ssrcs) &&
GetIntArray(raw_value, "sendIndexes", &send_indexes) &&
GetString(raw_value, "IV", &iv) &&
GetBool(raw_value, "receiverGetStatus", &supports_get_status) &&
GetString(raw_value, "castMode", &cast_mode));
}
// ----------------------------------------------------------------------------
ReceiverStatus::ReceiverStatus() : wifi_snr(0) {}
ReceiverStatus::~ReceiverStatus() {}
ReceiverStatus::ReceiverStatus(const ReceiverStatus& status) = default;
bool ReceiverStatus::Parse(const base::Value& raw_value) {
return (raw_value.is_dict() && GetDouble(raw_value, "wifiSnr", &wifi_snr) &&
GetIntArray(raw_value, "wifiSpeed", &wifi_speed));
}
// ----------------------------------------------------------------------------
ReceiverKeySystem::ReceiverKeySystem() {}
ReceiverKeySystem::~ReceiverKeySystem() {}
ReceiverKeySystem::ReceiverKeySystem(
const ReceiverKeySystem& receiver_key_system) = default;
bool ReceiverKeySystem::Parse(const base::Value& raw_value) {
return (raw_value.is_dict() && GetString(raw_value, "keySystemName", &name) &&
GetStringArray(raw_value, "initDataTypes", &init_data_types) &&
GetStringArray(raw_value, "codecs", &codecs) &&
GetStringArray(raw_value, "secureCodecs", &secure_codecs) &&
GetStringArray(raw_value, "audioRobustness", &audio_robustness) &&
GetStringArray(raw_value, "videoRobustness", &video_robustness) &&
GetString(raw_value, "persistentLicenseSessionSupport",
&persistent_license_session_support) &&
GetString(raw_value, "persistentReleaseMessageSessionSupport",
&persistent_release_message_session_support) &&
GetString(raw_value, "persistentStateSupport",
&persistent_state_support) &&
GetString(raw_value, "distinctiveIdentifierSupport",
&distinctive_identifier_support));
}
// ----------------------------------------------------------------------------
ReceiverCapability::ReceiverCapability() {}
ReceiverCapability::~ReceiverCapability() {}
ReceiverCapability::ReceiverCapability(const ReceiverCapability& capabilities) =
default;
bool ReceiverCapability::Parse(const base::Value& raw_value) {
if (!raw_value.is_dict() ||
!GetStringArray(raw_value, "mediaCaps", &media_caps))
return false;
auto* found = raw_value.FindKey("keySystems");
if (!found)
return true;
for (const auto& key_system_value : found->GetList()) {
ReceiverKeySystem key_system;
if (!key_system.Parse(key_system_value))
return false;
key_systems.emplace_back(key_system);
}
return true;
}
// ----------------------------------------------------------------------------
ReceiverError::ReceiverError() : code(-1) {}
ReceiverError::~ReceiverError() {}
bool ReceiverError::Parse(const base::Value& raw_value) {
if (!raw_value.is_dict() || !GetInt(raw_value, "code", &code) ||
!GetString(raw_value, "description", &description))
return false;
auto* found = raw_value.FindKey("details");
return found && base::JSONWriter::Write(*found, &details);
}
// ----------------------------------------------------------------------------
ReceiverResponse::ReceiverResponse()
: type(ResponseType::UNKNOWN), session_id(-1), sequence_number(-1) {}
ReceiverResponse::~ReceiverResponse() {}
ReceiverResponse::ReceiverResponse(ReceiverResponse&& receiver_response) =
default;
ReceiverResponse& ReceiverResponse::operator=(
ReceiverResponse&& receiver_response) = default;
bool ReceiverResponse::Parse(const std::string& message_data) {
std::unique_ptr<base::Value> raw_value = base::JSONReader::Read(message_data);
if (!raw_value || !raw_value->is_dict() ||
!GetInt(*raw_value, "sessionId", &session_id) ||
!GetInt(*raw_value, "seqNum", &sequence_number) ||
!GetString(*raw_value, "result", &result))
return false;
if (result == "error") {
auto* found = raw_value->FindKey("error");
if (found) {
error = std::make_unique<ReceiverError>();
if (!error->Parse(*found))
return false;
}
}
std::string message_type;
if (!GetString(*raw_value, "type", &message_type))
return false;
// Convert |message_type| to uppercase.
message_type = base::ToUpperASCII(message_type);
type = GetResponseType(message_type);
if (type == ResponseType::UNKNOWN) {
DVLOG(2) << "Unknown response message type= " << message_type;
return false;
}
auto* found = raw_value->FindKey("answer");
if (found && !found->is_none()) {
answer = std::make_unique<Answer>();
if (!answer->Parse(*found))
return false;
}
found = raw_value->FindKey("status");
if (found && !found->is_none()) {
status = std::make_unique<ReceiverStatus>();
if (!status->Parse(*found))
return false;
}
found = raw_value->FindKey("capabilities");
if (found && !found->is_none()) {
capabilities = std::make_unique<ReceiverCapability>();
if (!capabilities->Parse(*found))
return false;
}
found = raw_value->FindKey("rpc");
if (found && !found->is_none()) {
// Decode the base64-encoded string.
if (!found->is_string() || !base::Base64Decode(found->GetString(), &rpc))
return false;
}
return true;
}
} // namespace mirroring