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