xref: /aosp_15_r20/external/openscreen/cast/common/channel/message_util.cc (revision 3f982cf4871df8771c9d4abe6e9a6f8d829b2736)
1*3f982cf4SFabien Sanglard // Copyright 2019 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/common/channel/message_util.h"
6*3f982cf4SFabien Sanglard 
7*3f982cf4SFabien Sanglard #include <sstream>
8*3f982cf4SFabien Sanglard #include <utility>
9*3f982cf4SFabien Sanglard 
10*3f982cf4SFabien Sanglard #include "cast/common/channel/virtual_connection.h"
11*3f982cf4SFabien Sanglard #include "util/json/json_serialization.h"
12*3f982cf4SFabien Sanglard #include "util/json/json_value.h"
13*3f982cf4SFabien Sanglard #include "util/osp_logging.h"
14*3f982cf4SFabien Sanglard 
15*3f982cf4SFabien Sanglard #if defined(__APPLE__) || defined(__MACH__)
16*3f982cf4SFabien Sanglard #include <TargetConditionals.h>
17*3f982cf4SFabien Sanglard #endif
18*3f982cf4SFabien Sanglard 
19*3f982cf4SFabien Sanglard namespace openscreen {
20*3f982cf4SFabien Sanglard namespace cast {
21*3f982cf4SFabien Sanglard namespace {
22*3f982cf4SFabien Sanglard 
23*3f982cf4SFabien Sanglard using ::cast::channel::CastMessage;
24*3f982cf4SFabien Sanglard 
25*3f982cf4SFabien Sanglard // The value used for "sdkType" in a virtual CONNECT request. Historically, this
26*3f982cf4SFabien Sanglard // value was used in Chrome's C++ impl even though "2" refers to the Media
27*3f982cf4SFabien Sanglard // Router Extension.
28*3f982cf4SFabien Sanglard constexpr int kVirtualConnectSdkType = 2;
29*3f982cf4SFabien Sanglard 
30*3f982cf4SFabien Sanglard // The value used for "connectionType" in a virtual CONNECT request. This value
31*3f982cf4SFabien Sanglard // stands for CONNECTION_TYPE_LOCAL.
32*3f982cf4SFabien Sanglard constexpr int kVirtualConnectTypeLocal = 1;
33*3f982cf4SFabien Sanglard 
34*3f982cf4SFabien Sanglard // The value to be set as the "platform" value in a virtual CONNECT request.
35*3f982cf4SFabien Sanglard // Source (in Chromium source tree):
36*3f982cf4SFabien Sanglard // src/third_party/metrics_proto/cast_logs.proto
37*3f982cf4SFabien Sanglard enum VirtualConnectPlatformValue {
38*3f982cf4SFabien Sanglard   kOtherPlatform = 0,
39*3f982cf4SFabien Sanglard   kAndroid = 1,
40*3f982cf4SFabien Sanglard   kIOS = 2,
41*3f982cf4SFabien Sanglard   kWindows = 3,
42*3f982cf4SFabien Sanglard   kMacOSX = 4,
43*3f982cf4SFabien Sanglard   kChromeOS = 5,
44*3f982cf4SFabien Sanglard   kLinux = 6,
45*3f982cf4SFabien Sanglard   kCastDevice = 7,
46*3f982cf4SFabien Sanglard };
47*3f982cf4SFabien Sanglard 
48*3f982cf4SFabien Sanglard #if defined(__APPLE__) || defined(__MACH__)
GetVirtualConnectPlatformMacFlavor()49*3f982cf4SFabien Sanglard constexpr VirtualConnectPlatformValue GetVirtualConnectPlatformMacFlavor() {
50*3f982cf4SFabien Sanglard #if defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE
51*3f982cf4SFabien Sanglard   return kIOS;
52*3f982cf4SFabien Sanglard #else
53*3f982cf4SFabien Sanglard   return kMacOSX;
54*3f982cf4SFabien Sanglard #endif
55*3f982cf4SFabien Sanglard }
56*3f982cf4SFabien Sanglard #endif
57*3f982cf4SFabien Sanglard 
GetVirtualConnectPlatform()58*3f982cf4SFabien Sanglard constexpr VirtualConnectPlatformValue GetVirtualConnectPlatform() {
59*3f982cf4SFabien Sanglard   // Based on //build/build_config.h in the Chromium project. The order of these
60*3f982cf4SFabien Sanglard   // matters!
61*3f982cf4SFabien Sanglard #if defined(__ANDROID__)
62*3f982cf4SFabien Sanglard   return kAndroid;
63*3f982cf4SFabien Sanglard #elif defined(__APPLE__) || defined(__MACH__)
64*3f982cf4SFabien Sanglard   return GetVirtualConnectPlatformMacFlavor();
65*3f982cf4SFabien Sanglard #elif defined(_WIN32) || defined(_WIN64)
66*3f982cf4SFabien Sanglard   return kWindows;
67*3f982cf4SFabien Sanglard #elif defined(OS_CHROMEOS)
68*3f982cf4SFabien Sanglard   // Note: OS_CHROMEOS is defined via the compiler's command line in Chromium
69*3f982cf4SFabien Sanglard   // embedder builds by Chromium's //build/config/linux:runtime_library config.
70*3f982cf4SFabien Sanglard   return kChromeOS;
71*3f982cf4SFabien Sanglard #elif defined(__linux__)
72*3f982cf4SFabien Sanglard   return kLinux;
73*3f982cf4SFabien Sanglard #else
74*3f982cf4SFabien Sanglard   return kOtherPlatform;
75*3f982cf4SFabien Sanglard #endif
76*3f982cf4SFabien Sanglard }
77*3f982cf4SFabien Sanglard 
MakeConnectionMessage(const std::string & source_id,const std::string & destination_id)78*3f982cf4SFabien Sanglard CastMessage MakeConnectionMessage(const std::string& source_id,
79*3f982cf4SFabien Sanglard                                   const std::string& destination_id) {
80*3f982cf4SFabien Sanglard   CastMessage connect_message;
81*3f982cf4SFabien Sanglard   connect_message.set_protocol_version(kDefaultOutgoingMessageVersion);
82*3f982cf4SFabien Sanglard   connect_message.set_source_id(source_id);
83*3f982cf4SFabien Sanglard   connect_message.set_destination_id(destination_id);
84*3f982cf4SFabien Sanglard   connect_message.set_namespace_(kConnectionNamespace);
85*3f982cf4SFabien Sanglard   return connect_message;
86*3f982cf4SFabien Sanglard }
87*3f982cf4SFabien Sanglard 
88*3f982cf4SFabien Sanglard }  // namespace
89*3f982cf4SFabien Sanglard 
ToString(AppAvailabilityResult availability)90*3f982cf4SFabien Sanglard std::string ToString(AppAvailabilityResult availability) {
91*3f982cf4SFabien Sanglard   switch (availability) {
92*3f982cf4SFabien Sanglard     case AppAvailabilityResult::kAvailable:
93*3f982cf4SFabien Sanglard       return "Available";
94*3f982cf4SFabien Sanglard     case AppAvailabilityResult::kUnavailable:
95*3f982cf4SFabien Sanglard       return "Unavailable";
96*3f982cf4SFabien Sanglard     case AppAvailabilityResult::kUnknown:
97*3f982cf4SFabien Sanglard       return "Unknown";
98*3f982cf4SFabien Sanglard     default:
99*3f982cf4SFabien Sanglard       OSP_NOTREACHED();
100*3f982cf4SFabien Sanglard   }
101*3f982cf4SFabien Sanglard }
102*3f982cf4SFabien Sanglard 
MakeSimpleUTF8Message(const std::string & namespace_,std::string payload)103*3f982cf4SFabien Sanglard CastMessage MakeSimpleUTF8Message(const std::string& namespace_,
104*3f982cf4SFabien Sanglard                                   std::string payload) {
105*3f982cf4SFabien Sanglard   CastMessage message;
106*3f982cf4SFabien Sanglard   message.set_protocol_version(kDefaultOutgoingMessageVersion);
107*3f982cf4SFabien Sanglard   message.set_namespace_(namespace_);
108*3f982cf4SFabien Sanglard   message.set_payload_type(::cast::channel::CastMessage_PayloadType_STRING);
109*3f982cf4SFabien Sanglard   message.set_payload_utf8(std::move(payload));
110*3f982cf4SFabien Sanglard   return message;
111*3f982cf4SFabien Sanglard }
112*3f982cf4SFabien Sanglard 
MakeConnectMessage(const std::string & source_id,const std::string & destination_id)113*3f982cf4SFabien Sanglard CastMessage MakeConnectMessage(const std::string& source_id,
114*3f982cf4SFabien Sanglard                                const std::string& destination_id) {
115*3f982cf4SFabien Sanglard   CastMessage connect_message =
116*3f982cf4SFabien Sanglard       MakeConnectionMessage(source_id, destination_id);
117*3f982cf4SFabien Sanglard   connect_message.set_payload_type(
118*3f982cf4SFabien Sanglard       ::cast::channel::CastMessage_PayloadType_STRING);
119*3f982cf4SFabien Sanglard 
120*3f982cf4SFabien Sanglard   // Historically, the CONNECT message was meant to come from a Chrome browser.
121*3f982cf4SFabien Sanglard   // However, this library could be embedded in any app. So, properties like
122*3f982cf4SFabien Sanglard   // user agent, application version, etc. are not known here.
123*3f982cf4SFabien Sanglard   static constexpr char kUnknownVersion[] = "Unknown (Open Screen)";
124*3f982cf4SFabien Sanglard 
125*3f982cf4SFabien Sanglard   Json::Value message(Json::objectValue);
126*3f982cf4SFabien Sanglard   message[kMessageKeyType] = CastMessageTypeToString(CastMessageType::kConnect);
127*3f982cf4SFabien Sanglard   for (int i = 0; i <= 3; ++i) {
128*3f982cf4SFabien Sanglard     message[kMessageKeyProtocolVersionList][i] =
129*3f982cf4SFabien Sanglard         ::cast::channel::CastMessage_ProtocolVersion_CASTV2_1_0 + i;
130*3f982cf4SFabien Sanglard   }
131*3f982cf4SFabien Sanglard   message[kMessageKeyUserAgent] = kUnknownVersion;
132*3f982cf4SFabien Sanglard   message[kMessageKeyConnType] =
133*3f982cf4SFabien Sanglard       static_cast<int>(VirtualConnection::Type::kStrong);
134*3f982cf4SFabien Sanglard   message[kMessageKeyOrigin] = Json::Value(Json::objectValue);
135*3f982cf4SFabien Sanglard 
136*3f982cf4SFabien Sanglard   Json::Value sender_info(Json::objectValue);
137*3f982cf4SFabien Sanglard   sender_info[kMessageKeySdkType] = kVirtualConnectSdkType;
138*3f982cf4SFabien Sanglard   sender_info[kMessageKeyVersion] = kUnknownVersion;
139*3f982cf4SFabien Sanglard   sender_info[kMessageKeyBrowserVersion] = kUnknownVersion;
140*3f982cf4SFabien Sanglard   sender_info[kMessageKeyPlatform] = GetVirtualConnectPlatform();
141*3f982cf4SFabien Sanglard   sender_info[kMessageKeyConnectionType] = kVirtualConnectTypeLocal;
142*3f982cf4SFabien Sanglard   message[kMessageKeySenderInfo] = std::move(sender_info);
143*3f982cf4SFabien Sanglard 
144*3f982cf4SFabien Sanglard   connect_message.set_payload_utf8(json::Stringify(std::move(message)).value());
145*3f982cf4SFabien Sanglard   return connect_message;
146*3f982cf4SFabien Sanglard }
147*3f982cf4SFabien Sanglard 
MakeCloseMessage(const std::string & source_id,const std::string & destination_id)148*3f982cf4SFabien Sanglard CastMessage MakeCloseMessage(const std::string& source_id,
149*3f982cf4SFabien Sanglard                              const std::string& destination_id) {
150*3f982cf4SFabien Sanglard   CastMessage close_message = MakeConnectionMessage(source_id, destination_id);
151*3f982cf4SFabien Sanglard   close_message.set_payload_type(
152*3f982cf4SFabien Sanglard       ::cast::channel::CastMessage_PayloadType_STRING);
153*3f982cf4SFabien Sanglard   close_message.set_payload_utf8(R"!({"type": "CLOSE"})!");
154*3f982cf4SFabien Sanglard   return close_message;
155*3f982cf4SFabien Sanglard }
156*3f982cf4SFabien Sanglard 
MakeUniqueSessionId(const char * prefix)157*3f982cf4SFabien Sanglard std::string MakeUniqueSessionId(const char* prefix) {
158*3f982cf4SFabien Sanglard   static int next_id = 10000;
159*3f982cf4SFabien Sanglard 
160*3f982cf4SFabien Sanglard   std::ostringstream oss;
161*3f982cf4SFabien Sanglard   oss << prefix << '-' << (next_id++);
162*3f982cf4SFabien Sanglard   return oss.str();
163*3f982cf4SFabien Sanglard }
164*3f982cf4SFabien Sanglard 
HasType(const Json::Value & object,CastMessageType type)165*3f982cf4SFabien Sanglard bool HasType(const Json::Value& object, CastMessageType type) {
166*3f982cf4SFabien Sanglard   OSP_DCHECK(object.isObject());
167*3f982cf4SFabien Sanglard   const Json::Value& value =
168*3f982cf4SFabien Sanglard       object.get(kMessageKeyType, Json::Value::nullSingleton());
169*3f982cf4SFabien Sanglard   return value.isString() && value.asString() == CastMessageTypeToString(type);
170*3f982cf4SFabien Sanglard }
171*3f982cf4SFabien Sanglard 
172*3f982cf4SFabien Sanglard }  // namespace cast
173*3f982cf4SFabien Sanglard }  // namespace openscreen
174