• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2020 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include "host/frontend/webrtc/libcommon/utils.h"
18 
19 #include <functional>
20 
21 #include <json/json.h>
22 
23 #include "common/libs/utils/json.h"
24 
25 namespace cuttlefish {
26 namespace webrtc_streaming {
27 
28 namespace {
29 
30 template <typename T>
ToArray(const std::vector<T> & vec,std::function<Json::Value (const T &)> to_json)31 Json::Value ToArray(const std::vector<T>& vec,
32                     std::function<Json::Value(const T&)> to_json) {
33   Json::Value arr(Json::ValueType::arrayValue);
34   for (const auto& t : vec) {
35     arr.append(to_json(t));
36   }
37   return arr;
38 }
39 
40 }  // namespace
41 
42 Result<std::unique_ptr<webrtc::SessionDescriptionInterface>>
ParseSessionDescription(const std::string & type,const Json::Value & message,webrtc::SdpType sdp_type)43 ParseSessionDescription(const std::string& type, const Json::Value& message,
44                         webrtc::SdpType sdp_type) {
45   auto remote_desc_str = CF_EXPECT(GetValue<std::string>(message, {"sdp"}),
46                                    "Failed to get 'sdp' property");
47   auto remote_desc =
48       webrtc::CreateSessionDescription(sdp_type, remote_desc_str);
49   CF_EXPECT(remote_desc.get(), "Failed to parse sdp.");
50   return remote_desc;
51 }
52 
ParseIceCandidate(const std::string & type,const Json::Value & message)53 Result<std::unique_ptr<webrtc::IceCandidateInterface>> ParseIceCandidate(
54     const std::string& type, const Json::Value& message) {
55   auto mid = CF_EXPECT(GetValue<std::string>(message, {"candidate", "sdpMid"}));
56   auto candidate_sdp =
57       CF_EXPECT(GetValue<std::string>(message, {"candidate", "candidate"}));
58   auto line_index =
59       CF_EXPECT(GetValue<int>(message, {"candidate", "sdpMLineIndex"}));
60 
61   auto candidate =
62       std::unique_ptr<webrtc::IceCandidateInterface>(webrtc::CreateIceCandidate(
63           mid, line_index, candidate_sdp, nullptr /*error*/));
64   CF_EXPECT(candidate.get(), "Failed to parse ICE candidate");
65   return candidate;
66 }
67 
ParseError(const std::string & type,const Json::Value & message)68 Result<std::string> ParseError(const std::string& type,
69                                const Json::Value& message) {
70   return CF_EXPECT(GetValue<std::string>(message, {"error"}));
71 }
72 
73 Result<std::vector<webrtc::PeerConnectionInterface::IceServer>>
ParseIceServersMessage(const Json::Value & message)74 ParseIceServersMessage(const Json::Value& message) {
75   std::vector<webrtc::PeerConnectionInterface::IceServer> ret;
76   if (!message.isMember("ice_servers") || !message["ice_servers"].isArray()) {
77     // The ice_servers field is optional in some messages
78     LOG(VERBOSE)
79         << "ice_servers field not present in json object or not an array";
80     return ret;
81   }
82   auto& servers = message["ice_servers"];
83   for (const auto& server : servers) {
84     webrtc::PeerConnectionInterface::IceServer ice_server;
85     CF_EXPECT(server.isMember("urls") && server["urls"].isArray(),
86               "ICE server specification missing urls field or not an array: "
87                   << server.toStyledString());
88     auto urls = server["urls"];
89     for (int url_idx = 0; url_idx < urls.size(); url_idx++) {
90       auto url = urls[url_idx];
91       CF_EXPECT(url.isString(), "Non string 'urls' field in ice server: "
92                                     << url.toStyledString());
93       ice_server.urls.push_back(url.asString());
94     }
95     if (server.isMember("credential") && server["credential"].isString()) {
96       ice_server.password = server["credential"].asString();
97     }
98     if (server.isMember("username") && server["username"].isString()) {
99       ice_server.username = server["username"].asString();
100     }
101     ret.push_back(ice_server);
102   }
103   return ret;
104 }
105 
GenerateIceServersMessage(const std::vector<webrtc::PeerConnectionInterface::IceServer> & ice_servers)106 Json::Value GenerateIceServersMessage(
107     const std::vector<webrtc::PeerConnectionInterface::IceServer>&
108         ice_servers) {
109   return ToArray<webrtc::PeerConnectionInterface::IceServer>(
110       ice_servers,
111       [](const webrtc::PeerConnectionInterface::IceServer& ice_server) {
112         Json::Value server;
113         server["urls"] = ToArray<std::string>(
114             ice_server.urls,
115             [](const std::string& url) { return Json::Value(url); });
116         server["credential"] = ice_server.password;
117         server["username"] = ice_server.username;
118         return server;
119       });
120 }
121 
122 }  // namespace webrtc_streaming
123 }  // namespace cuttlefish
124