blob: 3e2bc2a01ab6cc0ba6b84c103acfb71852b01de0 [file] [log] [blame]
[email protected]988dfc3c2012-01-04 01:10:111// Copyright (c) 2012 The Chromium Authors. All rights reserved.
[email protected]cb3b1f9312010-06-07 19:58:232// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4//
5// This is an application of a minimal host process in a Chromoting
6// system. It serves the purpose of gluing different pieces together
7// to make a functional host process for testing.
8//
9// It peforms the following functionality:
10// 1. Connect to the GTalk network and register the machine as a host.
11// 2. Accepts connection through libjingle.
12// 3. Receive mouse / keyboard events through libjingle.
13// 4. Sends screen capture through libjingle.
14
15#include <iostream>
16#include <string>
17
18#include "build/build_config.h"
19
[email protected]cb3b1f9312010-06-07 19:58:2320#include "base/at_exit.h"
[email protected]a2db97612011-05-17 21:07:4621#include "base/bind.h"
[email protected]717651a52011-05-10 01:34:0922#include "base/callback.h"
[email protected]76207352010-06-17 23:43:0023#include "base/command_line.h"
[email protected]76b90d312010-08-03 03:00:5024#include "base/environment.h"
[email protected]76207352010-06-17 23:43:0025#include "base/file_path.h"
26#include "base/logging.h"
[email protected]8f449bb2011-06-16 17:33:3927#include "base/message_loop.h"
[email protected]04b36142010-11-02 01:08:1928#include "base/path_service.h"
[email protected]d286b6732012-01-13 21:18:3229#include "base/string_number_conversions.h"
[email protected]672704f2012-01-07 01:07:1230#include "base/utf_string_conversions.h"
[email protected]34b99632011-01-01 01:01:0631#include "base/threading/thread.h"
[email protected]4b559b4d2011-04-14 17:37:1432#include "crypto/nss_util.h"
[email protected]8f1f2352012-01-07 03:09:2933#include "net/base/network_change_notifier.h"
[email protected]fc9bc0532011-05-25 20:11:2234#include "remoting/base/constants.h"
[email protected]cb3b1f9312010-06-07 19:58:2335#include "remoting/host/capturer_fake.h"
[email protected]2a4f9882010-06-15 00:20:3836#include "remoting/host/chromoting_host.h"
[email protected]92698ce2010-06-28 21:49:3037#include "remoting/host/chromoting_host_context.h"
[email protected]eff1b5d2012-05-12 02:02:1638#include "remoting/host/constants.h"
[email protected]1fdc9df2011-02-23 11:33:5939#include "remoting/host/desktop_environment.h"
[email protected]1e72daa2011-01-28 21:25:4240#include "remoting/host/event_executor.h"
[email protected]f6bca1f2011-05-03 20:07:4041#include "remoting/host/heartbeat_sender.h"
[email protected]b5a6afe2012-01-07 05:48:2042#include "remoting/host/host_key_pair.h"
[email protected]1f249e22011-11-29 20:19:5943#include "remoting/host/host_secret.h"
[email protected]856dec52011-12-01 04:25:2644#include "remoting/host/it2me_host_user_interface.h"
[email protected]76207352010-06-17 23:43:0045#include "remoting/host/json_host_config.h"
[email protected]8f1f2352012-01-07 03:09:2946#include "remoting/host/log_to_server.h"
[email protected]717651a52011-05-10 01:34:0947#include "remoting/host/register_support_host_request.h"
[email protected]8f1f2352012-01-07 03:09:2948#include "remoting/host/signaling_connector.h"
[email protected]988dfc3c2012-01-04 01:10:1149#include "remoting/jingle_glue/xmpp_signal_strategy.h"
[email protected]04b36142010-11-02 01:08:1950#include "remoting/proto/video.pb.h"
[email protected]b5a6afe2012-01-07 05:48:2051#include "remoting/protocol/it2me_host_authenticator_factory.h"
[email protected]21109572012-01-10 00:19:5352#include "remoting/protocol/me2me_host_authenticator_factory.h"
[email protected]cb3b1f9312010-06-07 19:58:2353
[email protected]a13283cc2012-04-05 00:21:2254#if defined(TOOLKIT_GTK)
[email protected]7b398be32011-02-19 00:32:4455#include "ui/gfx/gtk_util.h"
[email protected]badf5cf2011-10-29 03:44:4456#elif defined(OS_MACOSX)
57#include "base/mac/scoped_nsautorelease_pool.h"
58#elif defined(OS_WIN)
[email protected]0bec77c2011-06-14 22:16:5059// TODO(garykac) Make simple host into a proper GUI app on Windows so that we
60// have an hModule for the dialog resource.
61HMODULE g_hModule = NULL;
62#endif
63
[email protected]f901a072010-11-23 22:18:1264using remoting::protocol::CandidateSessionConfig;
65using remoting::protocol::ChannelConfig;
[email protected]f901a072010-11-23 22:18:1266
[email protected]672704f2012-01-07 01:07:1267namespace {
68
69const FilePath::CharType kDefaultConfigPath[] =
70 FILE_PATH_LITERAL(".ChromotingConfig.json");
71
72const char kHomeDrive[] = "HOMEDRIVE";
73const char kHomePath[] = "HOMEPATH";
[email protected]76207352010-06-17 23:43:0074
[email protected]f901a072010-11-23 22:18:1275const char kFakeSwitchName[] = "fake";
[email protected]970fb672011-06-20 20:54:4776const char kIT2MeSwitchName[] = "it2me";
[email protected]f901a072010-11-23 22:18:1277const char kConfigSwitchName[] = "config";
78const char kVideoSwitchName[] = "video";
[email protected]d286b6732012-01-13 21:18:3279const char kDisableNatTraversalSwitchName[] = "disable-nat-traversal";
80const char kMinPortSwitchName[] = "min-port";
81const char kMaxPortSwitchName[] = "max-port";
[email protected]f901a072010-11-23 22:18:1282
83const char kVideoSwitchValueVerbatim[] = "verbatim";
84const char kVideoSwitchValueZip[] = "zip";
85const char kVideoSwitchValueVp8[] = "vp8";
86const char kVideoSwitchValueVp8Rtp[] = "vp8rtp";
87
[email protected]672704f2012-01-07 01:07:1288} // namespace
89
90namespace remoting {
91
[email protected]ac31b782012-04-17 22:30:5492class SimpleHost : public HeartbeatSender::Listener {
[email protected]717651a52011-05-10 01:34:0993 public:
94 SimpleHost()
[email protected]672704f2012-01-07 01:07:1295 : message_loop_(MessageLoop::TYPE_UI),
[email protected]cec4d7a2012-04-17 05:26:2996 context_(message_loop_.message_loop_proxy()),
[email protected]672704f2012-01-07 01:07:1297 fake_(false),
[email protected]eff1b5d2012-05-12 02:02:1698 is_it2me_(false),
99 shutting_down_(false),
100 exit_code_(kSuccessExitCode) {
[email protected]672704f2012-01-07 01:07:12101 context_.Start();
[email protected]8f1f2352012-01-07 03:09:29102 network_change_notifier_.reset(net::NetworkChangeNotifier::Create());
[email protected]717651a52011-05-10 01:34:09103 }
104
[email protected]ac31b782012-04-17 22:30:54105 // Overridden from HeartbeatSender::Listener
106 virtual void OnUnknownHostIdError() OVERRIDE {
107 LOG(ERROR) << "Host ID not found.";
[email protected]eff1b5d2012-05-12 02:02:16108 Shutdown(kInvalidHostIdExitCode);
[email protected]ac31b782012-04-17 22:30:54109 }
110
[email protected]717651a52011-05-10 01:34:09111 int Run() {
[email protected]717651a52011-05-10 01:34:09112 FilePath config_path = GetConfigPath();
[email protected]30224c162012-04-07 19:20:06113 JsonHostConfig config(config_path);
114 if (!config.Read()) {
[email protected]717651a52011-05-10 01:34:09115 LOG(ERROR) << "Failed to read configuration file "
116 << config_path.value();
[email protected]717651a52011-05-10 01:34:09117 return 1;
118 }
119
[email protected]30224c162012-04-07 19:20:06120 if (!config.GetString(kHostIdConfigPath, &host_id_)) {
[email protected]b5a6afe2012-01-07 05:48:20121 LOG(ERROR) << "host_id is not defined in the config.";
122 return 1;
123 }
124
125 if (!key_pair_.Load(config)) {
126 return 1;
127 }
128
[email protected]26d4acc2012-01-24 18:24:26129 std::string host_secret_hash_string;
[email protected]30224c162012-04-07 19:20:06130 if (!config.GetString(kHostSecretHashConfigPath,
131 &host_secret_hash_string)) {
[email protected]26d4acc2012-01-24 18:24:26132 host_secret_hash_string = "plain:";
133 }
134
135 if (!host_secret_hash_.Parse(host_secret_hash_string)) {
136 LOG(ERROR) << "Invalid host_secret_hash.";
137 return false;
138 }
139
[email protected]988dfc3c2012-01-04 01:10:11140 // Use an XMPP connection to the Talk network for session signalling.
[email protected]30224c162012-04-07 19:20:06141 if (!config.GetString(kXmppLoginConfigPath, &xmpp_login_) ||
142 !config.GetString(kXmppAuthTokenConfigPath, &xmpp_auth_token_)) {
[email protected]988dfc3c2012-01-04 01:10:11143 LOG(ERROR) << "XMPP credentials are not defined in the config.";
144 return 1;
[email protected]1be2ddb2011-05-11 01:36:36145 }
[email protected]30224c162012-04-07 19:20:06146 if (!config.GetString(kXmppAuthServiceConfigPath, &xmpp_auth_service_)) {
[email protected]988dfc3c2012-01-04 01:10:11147 // For the simple host, we assume we always use the ClientLogin token for
148 // chromiumsync because we do not have an HTTP stack with which we can
149 // easily request an OAuth2 access token even if we had a RefreshToken for
150 // the account.
[email protected]672704f2012-01-07 01:07:12151 xmpp_auth_service_ = kChromotingTokenDefaultServiceName;
[email protected]988dfc3c2012-01-04 01:10:11152 }
153
[email protected]672704f2012-01-07 01:07:12154 context_.network_message_loop()->PostTask(FROM_HERE, base::Bind(
155 &SimpleHost::StartHost, base::Unretained(this)));
[email protected]988dfc3c2012-01-04 01:10:11156
[email protected]672704f2012-01-07 01:07:12157 message_loop_.MessageLoop::Run();
[email protected]7677f4e2011-08-03 19:22:03158
[email protected]eff1b5d2012-05-12 02:02:16159 return exit_code_;
[email protected]717651a52011-05-10 01:34:09160 }
161
162 void set_config_path(const FilePath& config_path) {
163 config_path_ = config_path;
164 }
165 void set_fake(bool fake) { fake_ = fake; }
[email protected]970fb672011-06-20 20:54:47166 void set_is_it2me(bool is_it2me) { is_it2me_ = is_it2me; }
[email protected]717651a52011-05-10 01:34:09167 void set_protocol_config(CandidateSessionConfig* protocol_config) {
168 protocol_config_.reset(protocol_config);
169 }
170
[email protected]d286b6732012-01-13 21:18:32171 NetworkSettings* network_settings() { return &network_settings_; }
172
[email protected]717651a52011-05-10 01:34:09173 private:
[email protected]672704f2012-01-07 01:07:12174 static void SetIT2MeAccessCode(scoped_refptr<ChromotingHost> host,
[email protected]b5a6afe2012-01-07 05:48:20175 HostKeyPair* key_pair,
[email protected]672704f2012-01-07 01:07:12176 bool successful,
177 const std::string& support_id,
178 const base::TimeDelta& lifetime) {
[email protected]7677f4e2011-08-03 19:22:03179 if (successful) {
[email protected]672704f2012-01-07 01:07:12180 std::string host_secret = GenerateSupportHostSecret();
[email protected]1f249e22011-11-29 20:19:59181 std::string access_code = support_id + host_secret;
[email protected]7677f4e2011-08-03 19:22:03182 std::cout << "Support id: " << access_code << std::endl;
183
[email protected]b5a6afe2012-01-07 05:48:20184 scoped_ptr<protocol::AuthenticatorFactory> factory(
185 new protocol::It2MeHostAuthenticatorFactory(
[email protected]eda59e22012-01-11 06:19:21186 key_pair->GenerateCertificate(), *key_pair->private_key(),
[email protected]b5a6afe2012-01-07 05:48:20187 access_code));
188 host->SetAuthenticatorFactory(factory.Pass());
[email protected]7677f4e2011-08-03 19:22:03189 } else {
190 LOG(ERROR) << "If you haven't done so recently, try running"
191 << " remoting/tools/register_host.py.";
192 }
193 }
194
[email protected]717651a52011-05-10 01:34:09195 FilePath GetConfigPath() {
196 if (!config_path_.empty())
197 return config_path_;
198
[email protected]672704f2012-01-07 01:07:12199 scoped_ptr<base::Environment> env(base::Environment::Create());
200
[email protected]717651a52011-05-10 01:34:09201#if defined(OS_WIN)
[email protected]672704f2012-01-07 01:07:12202 std::string home_drive;
203 env->GetVar(kHomeDrive, &home_drive);
204 std::string home_path;
205 env->GetVar(kHomePath, &home_path);
206 return FilePath(UTF8ToWide(home_drive))
207 .Append(UTF8ToWide(home_path))
208 .Append(kDefaultConfigPath);
[email protected]717651a52011-05-10 01:34:09209#else
[email protected]672704f2012-01-07 01:07:12210 std::string home_path;
211 env->GetVar(base::env_vars::kHome, &home_path);
[email protected]717651a52011-05-10 01:34:09212 return FilePath(home_path).Append(kDefaultConfigPath);
[email protected]672704f2012-01-07 01:07:12213#endif
[email protected]717651a52011-05-10 01:34:09214 }
215
[email protected]672704f2012-01-07 01:07:12216 void StartHost() {
217 signal_strategy_.reset(
218 new XmppSignalStrategy(context_.jingle_thread(), xmpp_login_,
219 xmpp_auth_token_, xmpp_auth_service_));
[email protected]eff1b5d2012-05-12 02:02:16220 signaling_connector_.reset(new SignalingConnector(
221 signal_strategy_.get(),
222 base::Bind(&SimpleHost::OnAuthFailed, base::Unretained(this))));
[email protected]672704f2012-01-07 01:07:12223
224 if (fake_) {
[email protected]c2b374402012-03-12 19:23:07225 scoped_ptr<Capturer> capturer(new CapturerFake());
[email protected]6d17db92012-05-11 17:03:14226 scoped_ptr<EventExecutor> event_executor =
[email protected]98f99a02012-05-16 18:03:32227 EventExecutor::Create(context_.desktop_message_loop(),
228 context_.ui_message_loop(),
229 capturer.get());
[email protected]c2b374402012-03-12 19:23:07230 desktop_environment_ = DesktopEnvironment::CreateFake(
231 &context_, capturer.Pass(), event_executor.Pass());
[email protected]672704f2012-01-07 01:07:12232 } else {
[email protected]c2b374402012-03-12 19:23:07233 desktop_environment_ = DesktopEnvironment::Create(&context_);
[email protected]672704f2012-01-07 01:07:12234 }
235
[email protected]b5a6afe2012-01-07 05:48:20236 host_ = new ChromotingHost(&context_, signal_strategy_.get(),
[email protected]d286b6732012-01-13 21:18:32237 desktop_environment_.get(), network_settings_);
[email protected]672704f2012-01-07 01:07:12238
[email protected]be93be842012-01-21 00:25:57239 ServerLogEntry::Mode mode =
240 is_it2me_ ? ServerLogEntry::IT2ME : ServerLogEntry::ME2ME;
241 log_to_server_.reset(new LogToServer(host_, mode, signal_strategy_.get()));
[email protected]672704f2012-01-07 01:07:12242
243 if (is_it2me_) {
[email protected]c3041a12012-05-11 23:01:45244 it2me_host_user_interface_.reset(new It2MeHostUserInterface(&context_));
245 it2me_host_user_interface_->Start(
246 host_,
247 base::Bind(&ChromotingHost::Shutdown, host_, base::Closure()));
[email protected]672704f2012-01-07 01:07:12248 }
249
250 if (protocol_config_.get()) {
251 host_->set_protocol_config(protocol_config_.release());
252 }
253
254 if (is_it2me_) {
[email protected]b5a6afe2012-01-07 05:48:20255 register_request_.reset(new RegisterSupportHostRequest(
256 signal_strategy_.get(), &key_pair_,
257 base::Bind(&SimpleHost::SetIT2MeAccessCode, host_, &key_pair_)));
[email protected]672704f2012-01-07 01:07:12258 } else {
[email protected]ac31b782012-04-17 22:30:54259 heartbeat_sender_.reset(new HeartbeatSender(
260 this, host_id_, signal_strategy_.get(), &key_pair_));
[email protected]672704f2012-01-07 01:07:12261 }
262
[email protected]672704f2012-01-07 01:07:12263 host_->Start();
264
[email protected]21109572012-01-10 00:19:53265 // Create a Me2Me authenticator factory.
[email protected]b5a6afe2012-01-07 05:48:20266 if (!is_it2me_) {
267 scoped_ptr<protocol::AuthenticatorFactory> factory(
[email protected]21109572012-01-10 00:19:53268 new protocol::Me2MeHostAuthenticatorFactory(
[email protected]aee88cf2012-05-22 05:56:34269 key_pair_.GenerateCertificate(), *key_pair_.private_key(),
270 host_secret_hash_));
[email protected]b5a6afe2012-01-07 05:48:20271 host_->SetAuthenticatorFactory(factory.Pass());
272 }
[email protected]672704f2012-01-07 01:07:12273 }
274
[email protected]eff1b5d2012-05-12 02:02:16275 void OnAuthFailed() {
276 Shutdown(kInvalidOauthCredentialsExitCode);
277 }
278
279 void Shutdown(int exit_code) {
280 DCHECK(context_.network_message_loop()->BelongsToCurrentThread());
281
282 if (shutting_down_)
283 return;
284
285 shutting_down_ = true;
286 exit_code_ = exit_code;
287 host_->Shutdown(base::Bind(
288 &SimpleHost::OnShutdownFinished, base::Unretained(this)));
289 }
290
291 void OnShutdownFinished() {
292 DCHECK(context_.network_message_loop()->BelongsToCurrentThread());
293
294 // Destroy networking objects while we are on the network thread.
295 host_ = NULL;
296 log_to_server_.reset();
297 heartbeat_sender_.reset();
298 signaling_connector_.reset();
299 signal_strategy_.reset();
300
[email protected]ac31b782012-04-17 22:30:54301 message_loop_.PostTask(FROM_HERE, MessageLoop::QuitClosure());
302 }
303
[email protected]672704f2012-01-07 01:07:12304 MessageLoop message_loop_;
[email protected]672704f2012-01-07 01:07:12305 ChromotingHostContext context_;
[email protected]8f1f2352012-01-07 03:09:29306 scoped_ptr<net::NetworkChangeNotifier> network_change_notifier_;
[email protected]672704f2012-01-07 01:07:12307
[email protected]717651a52011-05-10 01:34:09308 FilePath config_path_;
309 bool fake_;
[email protected]970fb672011-06-20 20:54:47310 bool is_it2me_;
[email protected]d286b6732012-01-13 21:18:32311 NetworkSettings network_settings_;
[email protected]717651a52011-05-10 01:34:09312 scoped_ptr<CandidateSessionConfig> protocol_config_;
[email protected]7677f4e2011-08-03 19:22:03313
[email protected]b5a6afe2012-01-07 05:48:20314 std::string host_id_;
315 HostKeyPair key_pair_;
[email protected]26d4acc2012-01-24 18:24:26316 protocol::SharedSecretHash host_secret_hash_;
[email protected]672704f2012-01-07 01:07:12317 std::string xmpp_login_;
318 std::string xmpp_auth_token_;
319 std::string xmpp_auth_service_;
320
[email protected]6d2c32ce2012-04-18 05:54:40321 scoped_ptr<XmppSignalStrategy> signal_strategy_;
[email protected]8f1f2352012-01-07 03:09:29322 scoped_ptr<SignalingConnector> signaling_connector_;
[email protected]672704f2012-01-07 01:07:12323 scoped_ptr<DesktopEnvironment> desktop_environment_;
324 scoped_ptr<LogToServer> log_to_server_;
325 scoped_ptr<It2MeHostUserInterface> it2me_host_user_interface_;
326 scoped_ptr<RegisterSupportHostRequest> register_request_;
327 scoped_ptr<HeartbeatSender> heartbeat_sender_;
328
[email protected]7677f4e2011-08-03 19:22:03329 scoped_refptr<ChromotingHost> host_;
[email protected]eff1b5d2012-05-12 02:02:16330
331 bool shutting_down_;
332 int exit_code_;
[email protected]717651a52011-05-10 01:34:09333};
[email protected]76207352010-06-17 23:43:00334
[email protected]672704f2012-01-07 01:07:12335} // namespace remoting
336
[email protected]cb3b1f9312010-06-07 19:58:23337int main(int argc, char** argv) {
[email protected]badf5cf2011-10-29 03:44:44338#if defined(OS_MACOSX)
339 // Needed so we don't leak objects when threads are created.
[email protected]c2818d42010-10-18 02:47:39340 base::mac::ScopedNSAutoreleasePool pool;
[email protected]badf5cf2011-10-29 03:44:44341#endif
[email protected]7de8b182010-06-23 15:38:29342
[email protected]76207352010-06-17 23:43:00343 CommandLine::Init(argc, argv);
344 const CommandLine* cmd_line = CommandLine::ForCurrentProcess();
345
[email protected]cb3b1f9312010-06-07 19:58:23346 base::AtExitManager exit_manager;
[email protected]4b559b4d2011-04-14 17:37:14347 crypto::EnsureNSPRInit();
[email protected]81565e952010-06-30 22:51:06348
[email protected]a13283cc2012-04-05 00:21:22349#if defined(TOOLKIT_GTK)
[email protected]717651a52011-05-10 01:34:09350 gfx::GtkInitFromCommandLine(*cmd_line);
[email protected]a13283cc2012-04-05 00:21:22351#endif // TOOLKIT_GTK
[email protected]7edc7162011-05-10 00:45:03352
[email protected]672704f2012-01-07 01:07:12353 remoting::SimpleHost simple_host;
[email protected]717651a52011-05-10 01:34:09354
355 if (cmd_line->HasSwitch(kConfigSwitchName)) {
356 simple_host.set_config_path(
357 cmd_line->GetSwitchValuePath(kConfigSwitchName));
[email protected]7edc7162011-05-10 00:45:03358 }
[email protected]717651a52011-05-10 01:34:09359 simple_host.set_fake(cmd_line->HasSwitch(kFakeSwitchName));
[email protected]970fb672011-06-20 20:54:47360 simple_host.set_is_it2me(cmd_line->HasSwitch(kIT2MeSwitchName));
[email protected]f901a072010-11-23 22:18:12361
362 if (cmd_line->HasSwitch(kVideoSwitchName)) {
[email protected]672704f2012-01-07 01:07:12363 std::string video_codec = cmd_line->GetSwitchValueASCII(kVideoSwitchName);
[email protected]f901a072010-11-23 22:18:12364 scoped_ptr<CandidateSessionConfig> config(
365 CandidateSessionConfig::CreateDefault());
366 config->mutable_video_configs()->clear();
367
368 ChannelConfig::TransportType transport = ChannelConfig::TRANSPORT_STREAM;
369 ChannelConfig::Codec codec;
370 if (video_codec == kVideoSwitchValueVerbatim) {
371 codec = ChannelConfig::CODEC_VERBATIM;
372 } else if (video_codec == kVideoSwitchValueZip) {
373 codec = ChannelConfig::CODEC_ZIP;
374 } else if (video_codec == kVideoSwitchValueVp8) {
375 codec = ChannelConfig::CODEC_VP8;
376 } else if (video_codec == kVideoSwitchValueVp8Rtp) {
377 transport = ChannelConfig::TRANSPORT_SRTP;
378 codec = ChannelConfig::CODEC_VP8;
379 } else {
380 LOG(ERROR) << "Unknown video codec: " << video_codec;
[email protected]f901a072010-11-23 22:18:12381 return 1;
382 }
383 config->mutable_video_configs()->push_back(ChannelConfig(
384 transport, remoting::protocol::kDefaultStreamVersion, codec));
[email protected]717651a52011-05-10 01:34:09385 simple_host.set_protocol_config(config.release());
[email protected]c3ba9b32010-11-17 05:24:30386 }
[email protected]76207352010-06-17 23:43:00387
[email protected]804d072862012-03-02 01:07:39388 simple_host.network_settings()->nat_traversal_mode =
389 cmd_line->HasSwitch(kDisableNatTraversalSwitchName) ?
[email protected]40a6002482012-04-30 22:08:36390 remoting::NetworkSettings::NAT_TRAVERSAL_DISABLED :
391 remoting::NetworkSettings::NAT_TRAVERSAL_ENABLED;
[email protected]d286b6732012-01-13 21:18:32392
393 if (cmd_line->HasSwitch(kMinPortSwitchName)) {
394 std::string min_port_str =
395 cmd_line->GetSwitchValueASCII(kMinPortSwitchName);
396 int min_port = 0;
397 if (!base::StringToInt(min_port_str, &min_port) ||
398 min_port < 0 || min_port > 65535) {
399 LOG(ERROR) << "Invalid min-port value: " << min_port
400 << ". Expected integer in range [0, 65535].";
401 return 1;
402 }
403 simple_host.network_settings()->min_port = min_port;
404 }
405
406 if (cmd_line->HasSwitch(kMaxPortSwitchName)) {
407 std::string max_port_str =
408 cmd_line->GetSwitchValueASCII(kMaxPortSwitchName);
409 int max_port = 0;
410 if (!base::StringToInt(max_port_str, &max_port) ||
411 max_port < 0 || max_port > 65535) {
412 LOG(ERROR) << "Invalid max-port value: " << max_port
413 << ". Expected integer in range [0, 65535].";
414 return 1;
415 }
416 simple_host.network_settings()->max_port = max_port;
417 }
418
[email protected]717651a52011-05-10 01:34:09419 return simple_host.Run();
[email protected]cb3b1f9312010-06-07 19:58:23420}