• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2020 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "cast/streaming/sender_message.h"
6 
7 #include <utility>
8 
9 #include "absl/strings/ascii.h"
10 #include "cast/streaming/message_fields.h"
11 #include "util/base64.h"
12 #include "util/enum_name_table.h"
13 #include "util/json/json_helpers.h"
14 #include "util/json/json_serialization.h"
15 
16 namespace openscreen {
17 namespace cast {
18 
19 namespace {
20 
21 EnumNameTable<SenderMessage::Type, 4> kMessageTypeNames{
22     {{kMessageTypeOffer, SenderMessage::Type::kOffer},
23      {"GET_STATUS", SenderMessage::Type::kGetStatus},
24      {"GET_CAPABILITIES", SenderMessage::Type::kGetCapabilities},
25      {"RPC", SenderMessage::Type::kRpc}}};
26 
GetMessageType(const Json::Value & root)27 SenderMessage::Type GetMessageType(const Json::Value& root) {
28   std::string type;
29   if (!json::ParseAndValidateString(root[kMessageType], &type)) {
30     return SenderMessage::Type::kUnknown;
31   }
32 
33   absl::AsciiStrToUpper(&type);
34   ErrorOr<SenderMessage::Type> parsed = GetEnum(kMessageTypeNames, type);
35 
36   return parsed.value(SenderMessage::Type::kUnknown);
37 }
38 
39 }  // namespace
40 
41 // static
Parse(const Json::Value & value)42 ErrorOr<SenderMessage> SenderMessage::Parse(const Json::Value& value) {
43   if (!value) {
44     return Error(Error::Code::kParameterInvalid, "Empty JSON");
45   }
46 
47   SenderMessage message;
48   message.type = GetMessageType(value);
49   if (!json::ParseAndValidateInt(value[kSequenceNumber],
50                                  &(message.sequence_number))) {
51     message.sequence_number = -1;
52   }
53 
54   if (message.type == SenderMessage::Type::kOffer) {
55     ErrorOr<Offer> offer = Offer::Parse(value[kOfferMessageBody]);
56     if (offer.is_value()) {
57       message.body = std::move(offer.value());
58       message.valid = true;
59     }
60   } else if (message.type == SenderMessage::Type::kRpc) {
61     std::string rpc_body;
62     if (json::ParseAndValidateString(value[kRpcMessageBody], &rpc_body) &&
63         base64::Decode(rpc_body, &rpc_body)) {
64       message.body = rpc_body;
65       message.valid = true;
66     }
67   } else if (message.type == SenderMessage::Type::kGetStatus ||
68              message.type == SenderMessage::Type::kGetCapabilities) {
69     // These types of messages just don't have a body.
70     message.valid = true;
71   }
72 
73   return message;
74 }
75 
ToJson() const76 ErrorOr<Json::Value> SenderMessage::ToJson() const {
77   OSP_CHECK(type != SenderMessage::Type::kUnknown)
78       << "Trying to send an unknown message is a developer error";
79 
80   Json::Value root;
81   ErrorOr<const char*> message_type = GetEnumName(kMessageTypeNames, type);
82   root[kMessageType] = message_type.value();
83   if (sequence_number >= 0) {
84     root[kSequenceNumber] = sequence_number;
85   }
86 
87   switch (type) {
88     case SenderMessage::Type::kOffer:
89       root[kOfferMessageBody] = absl::get<Offer>(body).ToJson().value();
90       break;
91 
92     case SenderMessage::Type::kRpc:
93       root[kRpcMessageBody] = base64::Encode(absl::get<std::string>(body));
94       break;
95 
96     case SenderMessage::Type::kGetCapabilities:  // fallthrough
97     case SenderMessage::Type::kGetStatus:
98       break;
99 
100     default:
101       OSP_NOTREACHED();
102   }
103   return root;
104 }
105 
106 }  // namespace cast
107 }  // namespace openscreen
108