Skip to content

Commit 63abfc8

Browse files
joedow-42Chromium LUCI CQ
authored andcommitted
Implement IceConfigFetcherCloud
This CL implements the IceConfigFetcherCloud class, adds tests for it, and wires it up in remoting_me2me_host. I've also updated some of the code in IceConfig to remove a test-only helper which wasn't useful and exposed one of the helpers as a class method so parsing can be moved to the use-case specific files instead of IceConfig having to know about every proto. Lastly I've also added a variant of the IceConfigFetcher for Corp, I'll implement that in a follow-up. Bug: 325448647 Change-Id: If957095a6d67977d08a61b02ec3d78a5686cef32 Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/5924563 Reviewed-by: Yuwei Huang <yuweih@chromium.org> Commit-Queue: Joe Downing <joedow@chromium.org> Cr-Commit-Position: refs/heads/main@{#1367807}
1 parent ea3861a commit 63abfc8

10 files changed

+562
-114
lines changed

remoting/host/remoting_me2me_host.cc

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,8 @@
115115
#include "remoting/protocol/channel_authenticator.h"
116116
#include "remoting/protocol/chromium_port_allocator_factory.h"
117117
#include "remoting/protocol/host_authentication_config.h"
118+
#include "remoting/protocol/ice_config_fetcher_cloud.h"
119+
#include "remoting/protocol/ice_config_fetcher_corp.h"
118120
#include "remoting/protocol/ice_config_fetcher_default.h"
119121
#include "remoting/protocol/jingle_session_manager.h"
120122
#include "remoting/protocol/me2me_host_authenticator_factory.h"
@@ -1819,9 +1821,21 @@ void HostProcess::StartHost() {
18191821

18201822
InitializeSignaling();
18211823

1822-
// TODO: joedow - Create Cloud/Corp/Me2Me fetchers based on host config hint.
1823-
auto ice_config_fetcher = std::make_unique<protocol::IceConfigFetcherDefault>(
1824-
context_->url_loader_factory(), oauth_token_getter_.get());
1824+
// Create the appropriate API service client (corp, cloud, or me2me) for the
1825+
// IceConfigFetcher.
1826+
std::unique_ptr<protocol::IceConfigFetcher> ice_config_fetcher;
1827+
if (is_cloud_host_) {
1828+
ice_config_fetcher = std::make_unique<protocol::IceConfigFetcherCloud>(
1829+
context_->url_loader_factory(), oauth_token_getter_.get());
1830+
// TODO: joedow - Implement IceConfigFetcherCorp.
1831+
// } else if (is_corp_host_) {
1832+
// ice_config_fetcher = std::make_unique<protocol::IceConfigFetcherCorp>(
1833+
// context_->url_loader_factory(), oauth_token_getter_.get());
1834+
} else {
1835+
ice_config_fetcher = std::make_unique<protocol::IceConfigFetcherDefault>(
1836+
context_->url_loader_factory(), oauth_token_getter_.get());
1837+
}
1838+
18251839
scoped_refptr<protocol::TransportContext> transport_context =
18261840
new protocol::TransportContext(
18271841
std::make_unique<protocol::ChromiumPortAllocatorFactory>(),

remoting/protocol/BUILD.gn

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,10 @@ static_library("protocol") {
9999
"ice_config.cc",
100100
"ice_config.h",
101101
"ice_config_fetcher.h",
102+
"ice_config_fetcher_cloud.cc",
103+
"ice_config_fetcher_cloud.h",
104+
"ice_config_fetcher_corp.cc",
105+
"ice_config_fetcher_corp.h",
102106
"ice_config_fetcher_default.cc",
103107
"ice_config_fetcher_default.h",
104108
"ice_connection_to_host.cc",
@@ -249,6 +253,7 @@ static_library("protocol") {
249253
"//remoting/base:session_policies",
250254
"//remoting/codec:decoder",
251255
"//remoting/proto:internal_structs",
256+
"//remoting/proto/google/internal/remoting/cloud/v1alpha:messages",
252257
"//remoting/proto/remoting/v1:network_traversal_proto",
253258
"//remoting/signaling",
254259
"//services/network/public/cpp:cpp",
@@ -397,6 +402,7 @@ source_set("unit_tests") {
397402
"data_channel_manager_unittest.cc",
398403
"fractional_input_filter_unittest.cc",
399404
"frame_stats_unittest.cc",
405+
"ice_config_fetcher_cloud_unittest.cc",
400406
"ice_config_fetcher_default_unittest.cc",
401407
"ice_config_unittest.cc",
402408
"ice_transport_unittest.cc",
@@ -446,6 +452,7 @@ source_set("unit_tests") {
446452
"//remoting/base:test_support",
447453
"//remoting/codec:encoder",
448454
"//remoting/proto:internal_structs",
455+
"//remoting/proto/google/internal/remoting/cloud/v1alpha:messages",
449456
"//remoting/proto/remoting/v1:network_traversal_proto",
450457
"//remoting/signaling:test_support",
451458
"//services/network/public/cpp:cpp",

remoting/protocol/ice_config.cc

Lines changed: 72 additions & 90 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
#include "base/logging.h"
1212
#include "base/notreached.h"
1313
#include "base/strings/string_number_conversions.h"
14+
#include "base/strings/string_split.h"
1415
#include "base/strings/string_util.h"
1516
#include "base/values.h"
1617
#include "net/base/url_util.h"
@@ -34,69 +35,6 @@ bool ParseLifetime(const std::string& string, base::TimeDelta* result) {
3435
return true;
3536
}
3637

37-
// Parses url in form of <stun|turn|turns>:<host>[:<port>][?transport=<udp|tcp>]
38-
// and adds an entry to the |config|.
39-
bool AddServerToConfig(std::string url,
40-
const std::string& username,
41-
const std::string& password,
42-
IceConfig* config) {
43-
cricket::ProtocolType turn_transport_type = cricket::PROTO_LAST;
44-
45-
const char kTcpTransportSuffix[] = "?transport=tcp";
46-
const char kUdpTransportSuffix[] = "?transport=udp";
47-
if (base::EndsWith(url, kTcpTransportSuffix,
48-
base::CompareCase::INSENSITIVE_ASCII)) {
49-
turn_transport_type = cricket::PROTO_TCP;
50-
url.resize(url.size() - strlen(kTcpTransportSuffix));
51-
} else if (base::EndsWith(url, kUdpTransportSuffix,
52-
base::CompareCase::INSENSITIVE_ASCII)) {
53-
turn_transport_type = cricket::PROTO_UDP;
54-
url.resize(url.size() - strlen(kUdpTransportSuffix));
55-
}
56-
57-
size_t colon_pos = url.find(':');
58-
if (colon_pos == std::string::npos) {
59-
return false;
60-
}
61-
62-
std::string protocol = url.substr(0, colon_pos);
63-
64-
std::string host;
65-
int port;
66-
if (!net::ParseHostAndPort(url.substr(colon_pos + 1), &host, &port)) {
67-
return false;
68-
}
69-
70-
if (protocol == "stun") {
71-
if (port == -1) {
72-
port = kDefaultStunTurnPort;
73-
}
74-
config->stun_servers.emplace_back(host, port);
75-
} else if (protocol == "turn") {
76-
if (port == -1) {
77-
port = kDefaultStunTurnPort;
78-
}
79-
if (turn_transport_type == cricket::PROTO_LAST) {
80-
turn_transport_type = cricket::PROTO_UDP;
81-
}
82-
config->turn_servers.emplace_back(host, port, username, password,
83-
turn_transport_type, false);
84-
} else if (protocol == "turns") {
85-
if (port == -1) {
86-
port = kDefaultTurnsPort;
87-
}
88-
if (turn_transport_type == cricket::PROTO_LAST) {
89-
turn_transport_type = cricket::PROTO_TCP;
90-
}
91-
config->turn_servers.emplace_back(host, port, username, password,
92-
turn_transport_type, true);
93-
} else {
94-
return false;
95-
}
96-
97-
return true;
98-
}
99-
10038
// Returns the smallest specified value, or 0 if neither is specified.
10139
// A value is "specified" if it is greater than 0.
10240
int MinimumSpecified(int value1, int value2) {
@@ -120,6 +58,11 @@ IceConfig::~IceConfig() = default;
12058

12159
// static
12260
IceConfig IceConfig::Parse(const base::Value::Dict& dictionary) {
61+
const base::Value::Dict* data = dictionary.FindDict("data");
62+
if (data) {
63+
return Parse(*data);
64+
}
65+
12366
const base::Value::List* ice_servers_list = dictionary.FindList("iceServers");
12467
if (!ice_servers_list) {
12568
return IceConfig();
@@ -185,7 +128,7 @@ IceConfig IceConfig::Parse(const base::Value::Dict& dictionary) {
185128
errors_found = true;
186129
continue;
187130
}
188-
if (!AddServerToConfig(*url_str, username, password, &ice_config)) {
131+
if (!ice_config.AddServer(*url_str, username, password)) {
189132
LOG(ERROR) << "Invalid ICE server URL: " << *url_str;
190133
}
191134
}
@@ -210,30 +153,6 @@ IceConfig IceConfig::Parse(const base::Value::Dict& dictionary) {
210153
return ice_config;
211154
}
212155

213-
// static
214-
IceConfig IceConfig::Parse(const std::string& config_json) {
215-
std::optional<base::Value> json = base::JSONReader::Read(config_json);
216-
if (!json) {
217-
return IceConfig();
218-
}
219-
220-
base::Value::Dict* dictionary = json->GetIfDict();
221-
if (!dictionary) {
222-
return IceConfig();
223-
}
224-
225-
// Handle the case when the config is wrapped in 'data', i.e. as {'data': {
226-
// 'iceServers': {...} }}.
227-
if (!dictionary->Find("iceServers")) {
228-
base::Value::Dict* data_dictionary = dictionary->FindDict("data");
229-
if (data_dictionary) {
230-
return Parse(*data_dictionary);
231-
}
232-
}
233-
234-
return Parse(*dictionary);
235-
}
236-
237156
// static
238157
IceConfig IceConfig::Parse(const apis::v1::GetIceConfigResponse& config) {
239158
IceConfig ice_config;
@@ -255,8 +174,7 @@ IceConfig IceConfig::Parse(const apis::v1::GetIceConfigResponse& config) {
255174
MinimumSpecified(ice_config.max_bitrate_kbps, server.max_rate_kbps());
256175

257176
for (const auto& url : server.urls()) {
258-
if (!AddServerToConfig(url, server.username(), server.credential(),
259-
&ice_config)) {
177+
if (!ice_config.AddServer(url, server.username(), server.credential())) {
260178
LOG(ERROR) << "Invalid ICE server URL: " << url;
261179
}
262180
}
@@ -271,4 +189,68 @@ IceConfig IceConfig::Parse(const apis::v1::GetIceConfigResponse& config) {
271189
return ice_config;
272190
}
273191

192+
bool IceConfig::AddStunServer(std::string_view url) {
193+
CHECK(url.starts_with("stun:"));
194+
return AddServer(url, /*username=*/"", /*password=*/"");
195+
}
196+
197+
bool IceConfig::AddServer(std::string_view url,
198+
const std::string& username,
199+
const std::string& password) {
200+
cricket::ProtocolType turn_transport_type = cricket::PROTO_LAST;
201+
202+
const char kTcpTransportSuffix[] = "?transport=tcp";
203+
const char kUdpTransportSuffix[] = "?transport=udp";
204+
if (base::EndsWith(url, kTcpTransportSuffix,
205+
base::CompareCase::INSENSITIVE_ASCII)) {
206+
turn_transport_type = cricket::PROTO_TCP;
207+
url.remove_suffix(strlen(kTcpTransportSuffix));
208+
} else if (base::EndsWith(url, kUdpTransportSuffix,
209+
base::CompareCase::INSENSITIVE_ASCII)) {
210+
turn_transport_type = cricket::PROTO_UDP;
211+
url.remove_suffix(strlen(kUdpTransportSuffix));
212+
}
213+
214+
auto parts = base::SplitStringOnce(url, ':');
215+
if (!parts) {
216+
return false;
217+
}
218+
219+
auto [protocol, host_and_port] = *parts;
220+
std::string host;
221+
int port;
222+
if (!net::ParseHostAndPort(host_and_port, &host, &port)) {
223+
return false;
224+
}
225+
226+
if (protocol == "stun") {
227+
if (port == -1) {
228+
port = kDefaultStunTurnPort;
229+
}
230+
stun_servers.emplace_back(host, port);
231+
} else if (protocol == "turn") {
232+
if (port == -1) {
233+
port = kDefaultStunTurnPort;
234+
}
235+
if (turn_transport_type == cricket::PROTO_LAST) {
236+
turn_transport_type = cricket::PROTO_UDP;
237+
}
238+
turn_servers.emplace_back(host, port, username, password,
239+
turn_transport_type, false);
240+
} else if (protocol == "turns") {
241+
if (port == -1) {
242+
port = kDefaultTurnsPort;
243+
}
244+
if (turn_transport_type == cricket::PROTO_LAST) {
245+
turn_transport_type = cricket::PROTO_TCP;
246+
}
247+
turn_servers.emplace_back(host, port, username, password,
248+
turn_transport_type, true);
249+
} else {
250+
return false;
251+
}
252+
253+
return true;
254+
}
255+
274256
} // namespace remoting::protocol

remoting/protocol/ice_config.h

Lines changed: 17 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,9 @@
55
#ifndef REMOTING_PROTOCOL_ICE_CONFIG_H_
66
#define REMOTING_PROTOCOL_ICE_CONFIG_H_
77

8+
#include <optional>
89
#include <string>
10+
#include <string_view>
911
#include <vector>
1012

1113
#include "base/time/time.h"
@@ -15,11 +17,9 @@
1517

1618
namespace remoting {
1719

18-
namespace apis {
19-
namespace v1 {
20+
namespace apis::v1 {
2021
class GetIceConfigResponse;
21-
} // namespace v1
22-
} // namespace apis
22+
} // namespace apis::v1
2323

2424
namespace protocol {
2525

@@ -33,9 +33,19 @@ struct IceConfig {
3333
// Parses JSON representation of the config. Returns null config if parsing
3434
// fails.
3535
static IceConfig Parse(const base::Value::Dict& dictionary);
36-
static IceConfig Parse(const std::string& config_json);
3736
static IceConfig Parse(const apis::v1::GetIceConfigResponse& config);
3837

38+
// Parses a |url| in the form of stun:<host>[:<port>][?transport=<udp|tcp>]
39+
// and adds an entry to this instance.
40+
bool AddStunServer(std::string_view url);
41+
42+
// Parses a |url| in the form of
43+
// <stun|turn|turns>:<host>[:<port>][?transport=<udp|tcp>]
44+
// and adds an entry to this instance.
45+
bool AddServer(std::string_view url,
46+
const std::string& username,
47+
const std::string& password);
48+
3949
// Time when the config will stop being valid and need to be refreshed.
4050
base::Time expiration_time;
4151

@@ -44,8 +54,8 @@ struct IceConfig {
4454
// Standard TURN servers
4555
std::vector<cricket::RelayServerConfig> turn_servers;
4656

47-
// If greater than 0, the max bandwidth used for relayed connections should
48-
// be set to this value.
57+
// If greater than 0, the max bandwidth used for relayed connections should be
58+
// set to this value.
4959
int max_bitrate_kbps = 0;
5060
};
5161

0 commit comments

Comments
 (0)