xref: /aosp_15_r20/external/openscreen/cast/streaming/receiver_message.cc (revision 3f982cf4871df8771c9d4abe6e9a6f8d829b2736)
1*3f982cf4SFabien Sanglard // Copyright 2020 The Chromium Authors. All rights reserved.
2*3f982cf4SFabien Sanglard // Use of this source code is governed by a BSD-style license that can be
3*3f982cf4SFabien Sanglard // found in the LICENSE file.
4*3f982cf4SFabien Sanglard 
5*3f982cf4SFabien Sanglard #include "cast/streaming/receiver_message.h"
6*3f982cf4SFabien Sanglard 
7*3f982cf4SFabien Sanglard #include <utility>
8*3f982cf4SFabien Sanglard 
9*3f982cf4SFabien Sanglard #include "absl/strings/ascii.h"
10*3f982cf4SFabien Sanglard #include "absl/types/optional.h"
11*3f982cf4SFabien Sanglard #include "cast/streaming/message_fields.h"
12*3f982cf4SFabien Sanglard #include "json/reader.h"
13*3f982cf4SFabien Sanglard #include "json/writer.h"
14*3f982cf4SFabien Sanglard #include "platform/base/error.h"
15*3f982cf4SFabien Sanglard #include "util/base64.h"
16*3f982cf4SFabien Sanglard #include "util/enum_name_table.h"
17*3f982cf4SFabien Sanglard #include "util/json/json_helpers.h"
18*3f982cf4SFabien Sanglard #include "util/json/json_serialization.h"
19*3f982cf4SFabien Sanglard 
20*3f982cf4SFabien Sanglard namespace openscreen {
21*3f982cf4SFabien Sanglard namespace cast {
22*3f982cf4SFabien Sanglard 
23*3f982cf4SFabien Sanglard namespace {
24*3f982cf4SFabien Sanglard 
25*3f982cf4SFabien Sanglard EnumNameTable<ReceiverMessage::Type, 5> kMessageTypeNames{
26*3f982cf4SFabien Sanglard     {{kMessageTypeAnswer, ReceiverMessage::Type::kAnswer},
27*3f982cf4SFabien Sanglard      {"CAPABILITIES_RESPONSE", ReceiverMessage::Type::kCapabilitiesResponse},
28*3f982cf4SFabien Sanglard      {"RPC", ReceiverMessage::Type::kRpc}}};
29*3f982cf4SFabien Sanglard 
30*3f982cf4SFabien Sanglard EnumNameTable<MediaCapability, 10> kMediaCapabilityNames{
31*3f982cf4SFabien Sanglard     {{"audio", MediaCapability::kAudio},
32*3f982cf4SFabien Sanglard      {"aac", MediaCapability::kAac},
33*3f982cf4SFabien Sanglard      {"opus", MediaCapability::kOpus},
34*3f982cf4SFabien Sanglard      {"video", MediaCapability::kVideo},
35*3f982cf4SFabien Sanglard      {"4k", MediaCapability::k4k},
36*3f982cf4SFabien Sanglard      {"h264", MediaCapability::kH264},
37*3f982cf4SFabien Sanglard      {"vp8", MediaCapability::kVp8},
38*3f982cf4SFabien Sanglard      {"vp9", MediaCapability::kVp9},
39*3f982cf4SFabien Sanglard      {"hevc", MediaCapability::kHevc},
40*3f982cf4SFabien Sanglard      {"av1", MediaCapability::kAv1}}};
41*3f982cf4SFabien Sanglard 
GetMessageType(const Json::Value & root)42*3f982cf4SFabien Sanglard ReceiverMessage::Type GetMessageType(const Json::Value& root) {
43*3f982cf4SFabien Sanglard   std::string type;
44*3f982cf4SFabien Sanglard   if (!json::TryParseString(root[kMessageType], &type)) {
45*3f982cf4SFabien Sanglard     return ReceiverMessage::Type::kUnknown;
46*3f982cf4SFabien Sanglard   }
47*3f982cf4SFabien Sanglard 
48*3f982cf4SFabien Sanglard   absl::AsciiStrToUpper(&type);
49*3f982cf4SFabien Sanglard   ErrorOr<ReceiverMessage::Type> parsed = GetEnum(kMessageTypeNames, type);
50*3f982cf4SFabien Sanglard 
51*3f982cf4SFabien Sanglard   return parsed.value(ReceiverMessage::Type::kUnknown);
52*3f982cf4SFabien Sanglard }
53*3f982cf4SFabien Sanglard 
TryParseCapability(const Json::Value & value,MediaCapability * out)54*3f982cf4SFabien Sanglard bool TryParseCapability(const Json::Value& value, MediaCapability* out) {
55*3f982cf4SFabien Sanglard   std::string c;
56*3f982cf4SFabien Sanglard   if (!json::TryParseString(value, &c)) {
57*3f982cf4SFabien Sanglard     return false;
58*3f982cf4SFabien Sanglard   }
59*3f982cf4SFabien Sanglard 
60*3f982cf4SFabien Sanglard   const ErrorOr<MediaCapability> capability = GetEnum(kMediaCapabilityNames, c);
61*3f982cf4SFabien Sanglard   if (capability.is_error()) {
62*3f982cf4SFabien Sanglard     return false;
63*3f982cf4SFabien Sanglard   }
64*3f982cf4SFabien Sanglard 
65*3f982cf4SFabien Sanglard   *out = capability.value();
66*3f982cf4SFabien Sanglard   return true;
67*3f982cf4SFabien Sanglard }
68*3f982cf4SFabien Sanglard 
69*3f982cf4SFabien Sanglard }  // namespace
70*3f982cf4SFabien Sanglard 
71*3f982cf4SFabien Sanglard // static
Parse(const Json::Value & value)72*3f982cf4SFabien Sanglard ErrorOr<ReceiverError> ReceiverError::Parse(const Json::Value& value) {
73*3f982cf4SFabien Sanglard   if (!value) {
74*3f982cf4SFabien Sanglard     return Error(Error::Code::kParameterInvalid,
75*3f982cf4SFabien Sanglard                  "Empty JSON in receiver error parsing");
76*3f982cf4SFabien Sanglard   }
77*3f982cf4SFabien Sanglard 
78*3f982cf4SFabien Sanglard   int code;
79*3f982cf4SFabien Sanglard   std::string description;
80*3f982cf4SFabien Sanglard   if (!json::TryParseInt(value[kErrorCode], &code) ||
81*3f982cf4SFabien Sanglard       !json::TryParseString(value[kErrorDescription], &description)) {
82*3f982cf4SFabien Sanglard     return Error::Code::kJsonParseError;
83*3f982cf4SFabien Sanglard   }
84*3f982cf4SFabien Sanglard   return ReceiverError{code, description};
85*3f982cf4SFabien Sanglard }
86*3f982cf4SFabien Sanglard 
ToJson() const87*3f982cf4SFabien Sanglard Json::Value ReceiverError::ToJson() const {
88*3f982cf4SFabien Sanglard   Json::Value root;
89*3f982cf4SFabien Sanglard   root[kErrorCode] = code;
90*3f982cf4SFabien Sanglard   root[kErrorDescription] = description;
91*3f982cf4SFabien Sanglard   return root;
92*3f982cf4SFabien Sanglard }
93*3f982cf4SFabien Sanglard 
94*3f982cf4SFabien Sanglard // static
Parse(const Json::Value & value)95*3f982cf4SFabien Sanglard ErrorOr<ReceiverCapability> ReceiverCapability::Parse(
96*3f982cf4SFabien Sanglard     const Json::Value& value) {
97*3f982cf4SFabien Sanglard   if (!value) {
98*3f982cf4SFabien Sanglard     return Error(Error::Code::kParameterInvalid,
99*3f982cf4SFabien Sanglard                  "Empty JSON in capabilities parsing");
100*3f982cf4SFabien Sanglard   }
101*3f982cf4SFabien Sanglard 
102*3f982cf4SFabien Sanglard   int remoting_version;
103*3f982cf4SFabien Sanglard   if (!json::TryParseInt(value["remoting"], &remoting_version)) {
104*3f982cf4SFabien Sanglard     remoting_version = ReceiverCapability::kRemotingVersionUnknown;
105*3f982cf4SFabien Sanglard   }
106*3f982cf4SFabien Sanglard 
107*3f982cf4SFabien Sanglard   std::vector<MediaCapability> capabilities;
108*3f982cf4SFabien Sanglard   if (!json::TryParseArray<MediaCapability>(
109*3f982cf4SFabien Sanglard           value["mediaCaps"], TryParseCapability, &capabilities)) {
110*3f982cf4SFabien Sanglard     return Error(Error::Code::kJsonParseError,
111*3f982cf4SFabien Sanglard                  "Failed to parse media capabilities");
112*3f982cf4SFabien Sanglard   }
113*3f982cf4SFabien Sanglard 
114*3f982cf4SFabien Sanglard   return ReceiverCapability{remoting_version, std::move(capabilities)};
115*3f982cf4SFabien Sanglard }
116*3f982cf4SFabien Sanglard 
ToJson() const117*3f982cf4SFabien Sanglard Json::Value ReceiverCapability::ToJson() const {
118*3f982cf4SFabien Sanglard   Json::Value root;
119*3f982cf4SFabien Sanglard   root["remoting"] = remoting_version;
120*3f982cf4SFabien Sanglard   Json::Value capabilities(Json::ValueType::arrayValue);
121*3f982cf4SFabien Sanglard   for (const auto& capability : media_capabilities) {
122*3f982cf4SFabien Sanglard     capabilities.append(GetEnumName(kMediaCapabilityNames, capability).value());
123*3f982cf4SFabien Sanglard   }
124*3f982cf4SFabien Sanglard   root["mediaCaps"] = std::move(capabilities);
125*3f982cf4SFabien Sanglard   return root;
126*3f982cf4SFabien Sanglard }
127*3f982cf4SFabien Sanglard 
128*3f982cf4SFabien Sanglard // static
Parse(const Json::Value & value)129*3f982cf4SFabien Sanglard ErrorOr<ReceiverMessage> ReceiverMessage::Parse(const Json::Value& value) {
130*3f982cf4SFabien Sanglard   ReceiverMessage message;
131*3f982cf4SFabien Sanglard   if (!value) {
132*3f982cf4SFabien Sanglard     return Error(Error::Code::kJsonParseError, "Invalid message body");
133*3f982cf4SFabien Sanglard   }
134*3f982cf4SFabien Sanglard 
135*3f982cf4SFabien Sanglard   std::string result;
136*3f982cf4SFabien Sanglard   if (!json::TryParseString(value[kResult], &result)) {
137*3f982cf4SFabien Sanglard     result = kResultError;
138*3f982cf4SFabien Sanglard   }
139*3f982cf4SFabien Sanglard 
140*3f982cf4SFabien Sanglard   message.type = GetMessageType(value);
141*3f982cf4SFabien Sanglard   message.valid =
142*3f982cf4SFabien Sanglard       (result == kResultOk || message.type == ReceiverMessage::Type::kRpc);
143*3f982cf4SFabien Sanglard   if (!message.valid) {
144*3f982cf4SFabien Sanglard     ErrorOr<ReceiverError> error =
145*3f982cf4SFabien Sanglard         ReceiverError::Parse(value[kErrorMessageBody]);
146*3f982cf4SFabien Sanglard     if (error.is_value()) {
147*3f982cf4SFabien Sanglard       message.body = std::move(error.value());
148*3f982cf4SFabien Sanglard     }
149*3f982cf4SFabien Sanglard     return message;
150*3f982cf4SFabien Sanglard   }
151*3f982cf4SFabien Sanglard 
152*3f982cf4SFabien Sanglard   switch (message.type) {
153*3f982cf4SFabien Sanglard     case Type::kAnswer: {
154*3f982cf4SFabien Sanglard       Answer answer;
155*3f982cf4SFabien Sanglard       if (openscreen::cast::Answer::TryParse(value[kAnswerMessageBody],
156*3f982cf4SFabien Sanglard                                              &answer)) {
157*3f982cf4SFabien Sanglard         message.body = std::move(answer);
158*3f982cf4SFabien Sanglard         message.valid = true;
159*3f982cf4SFabien Sanglard       }
160*3f982cf4SFabien Sanglard     } break;
161*3f982cf4SFabien Sanglard 
162*3f982cf4SFabien Sanglard     case Type::kCapabilitiesResponse: {
163*3f982cf4SFabien Sanglard       ErrorOr<ReceiverCapability> capability =
164*3f982cf4SFabien Sanglard           ReceiverCapability::Parse(value[kCapabilitiesMessageBody]);
165*3f982cf4SFabien Sanglard       if (capability.is_value()) {
166*3f982cf4SFabien Sanglard         message.body = std::move(capability.value());
167*3f982cf4SFabien Sanglard         message.valid = true;
168*3f982cf4SFabien Sanglard       }
169*3f982cf4SFabien Sanglard     } break;
170*3f982cf4SFabien Sanglard 
171*3f982cf4SFabien Sanglard     case Type::kRpc: {
172*3f982cf4SFabien Sanglard       std::string encoded_rpc;
173*3f982cf4SFabien Sanglard       std::vector<uint8_t> rpc;
174*3f982cf4SFabien Sanglard       if (json::TryParseString(value[kRpcMessageBody], &encoded_rpc) &&
175*3f982cf4SFabien Sanglard           base64::Decode(encoded_rpc, &rpc)) {
176*3f982cf4SFabien Sanglard         message.body = std::move(rpc);
177*3f982cf4SFabien Sanglard         message.valid = true;
178*3f982cf4SFabien Sanglard       }
179*3f982cf4SFabien Sanglard     } break;
180*3f982cf4SFabien Sanglard 
181*3f982cf4SFabien Sanglard     default:
182*3f982cf4SFabien Sanglard       break;
183*3f982cf4SFabien Sanglard   }
184*3f982cf4SFabien Sanglard 
185*3f982cf4SFabien Sanglard   if (message.type != ReceiverMessage::Type::kRpc &&
186*3f982cf4SFabien Sanglard       !json::TryParseInt(value[kSequenceNumber], &(message.sequence_number))) {
187*3f982cf4SFabien Sanglard     message.sequence_number = -1;
188*3f982cf4SFabien Sanglard     message.valid = false;
189*3f982cf4SFabien Sanglard   }
190*3f982cf4SFabien Sanglard 
191*3f982cf4SFabien Sanglard   return message;
192*3f982cf4SFabien Sanglard }
193*3f982cf4SFabien Sanglard 
ToJson() const194*3f982cf4SFabien Sanglard ErrorOr<Json::Value> ReceiverMessage::ToJson() const {
195*3f982cf4SFabien Sanglard   OSP_CHECK(type != ReceiverMessage::Type::kUnknown)
196*3f982cf4SFabien Sanglard       << "Trying to send an unknown message is a developer error";
197*3f982cf4SFabien Sanglard 
198*3f982cf4SFabien Sanglard   Json::Value root;
199*3f982cf4SFabien Sanglard   root[kMessageType] = GetEnumName(kMessageTypeNames, type).value();
200*3f982cf4SFabien Sanglard   if (sequence_number >= 0) {
201*3f982cf4SFabien Sanglard     root[kSequenceNumber] = sequence_number;
202*3f982cf4SFabien Sanglard   }
203*3f982cf4SFabien Sanglard 
204*3f982cf4SFabien Sanglard   switch (type) {
205*3f982cf4SFabien Sanglard     case ReceiverMessage::Type::kAnswer:
206*3f982cf4SFabien Sanglard       if (valid) {
207*3f982cf4SFabien Sanglard         root[kResult] = kResultOk;
208*3f982cf4SFabien Sanglard         root[kAnswerMessageBody] = absl::get<Answer>(body).ToJson();
209*3f982cf4SFabien Sanglard       } else {
210*3f982cf4SFabien Sanglard         root[kResult] = kResultError;
211*3f982cf4SFabien Sanglard         root[kErrorMessageBody] = absl::get<ReceiverError>(body).ToJson();
212*3f982cf4SFabien Sanglard       }
213*3f982cf4SFabien Sanglard       break;
214*3f982cf4SFabien Sanglard 
215*3f982cf4SFabien Sanglard     case ReceiverMessage::Type::kCapabilitiesResponse:
216*3f982cf4SFabien Sanglard       if (valid) {
217*3f982cf4SFabien Sanglard         root[kResult] = kResultOk;
218*3f982cf4SFabien Sanglard         root[kCapabilitiesMessageBody] =
219*3f982cf4SFabien Sanglard             absl::get<ReceiverCapability>(body).ToJson();
220*3f982cf4SFabien Sanglard       } else {
221*3f982cf4SFabien Sanglard         root[kResult] = kResultError;
222*3f982cf4SFabien Sanglard         root[kErrorMessageBody] = absl::get<ReceiverError>(body).ToJson();
223*3f982cf4SFabien Sanglard       }
224*3f982cf4SFabien Sanglard       break;
225*3f982cf4SFabien Sanglard 
226*3f982cf4SFabien Sanglard     // NOTE: RPC messages do NOT have a result field.
227*3f982cf4SFabien Sanglard     case ReceiverMessage::Type::kRpc:
228*3f982cf4SFabien Sanglard       root[kRpcMessageBody] =
229*3f982cf4SFabien Sanglard           base64::Encode(absl::get<std::vector<uint8_t>>(body));
230*3f982cf4SFabien Sanglard       break;
231*3f982cf4SFabien Sanglard 
232*3f982cf4SFabien Sanglard     default:
233*3f982cf4SFabien Sanglard       OSP_NOTREACHED();
234*3f982cf4SFabien Sanglard   }
235*3f982cf4SFabien Sanglard 
236*3f982cf4SFabien Sanglard   return root;
237*3f982cf4SFabien Sanglard }
238*3f982cf4SFabien Sanglard 
239*3f982cf4SFabien Sanglard }  // namespace cast
240*3f982cf4SFabien Sanglard }  // namespace openscreen
241