15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <stdio.h> 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <termios.h> 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/at_exit.h" 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/command_line.h" 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/run_loop.h" 115e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)#include "base/strings/stringprintf.h" 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/threading/thread.h" 132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "net/url_request/url_fetcher.h" 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/url_request/url_request_context_getter.h" 157dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "remoting/base/url_request_context.h" 162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "remoting/host/service_urls.h" 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "remoting/host/setup/host_starter.h" 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "remoting/host/setup/oauth_helper.h" 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "remoting/host/setup/pin_validator.h" 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// A simple command-line app that registers and starts a host. 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using remoting::HostStarter; 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// True if the host was started successfully. 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool g_started = false; 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The main message loop. 29868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)base::MessageLoop* g_message_loop = NULL; 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Lets us hide the PIN that a user types. 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SetEcho(bool echo) { 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) termios term; 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) tcgetattr(STDIN_FILENO, &term); 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (echo) { 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) term.c_lflag |= ECHO; 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) term.c_lflag &= ~ECHO; 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) tcsetattr(STDIN_FILENO, TCSANOW, &term); 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Reads a newline-terminated string from stdin. 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::string ReadString(bool no_echo) { 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (no_echo) 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SetEcho(false); 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const int kMaxLen = 1024; 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string str(kMaxLen, 0); 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) char* result = fgets(&str[0], kMaxLen, stdin); 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (no_echo) { 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) printf("\n"); 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SetEcho(true); 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!result) 55c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return std::string(); 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t newline_index = str.find('\n'); 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (newline_index != std::string::npos) 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) str[newline_index] = '\0'; 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) str.resize(strlen(&str[0])); 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return str; 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Called when the HostStarter has finished. 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void OnDone(HostStarter::Result result) { 65c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (base::MessageLoop::current() != g_message_loop) { 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) g_message_loop->PostTask(FROM_HERE, base::Bind(&OnDone, result)); 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) switch (result) { 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case HostStarter::START_COMPLETE: 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) g_started = true; 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case HostStarter::NETWORK_ERROR: 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) fprintf(stderr, "Couldn't start host: network error.\n"); 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case HostStarter::OAUTH_ERROR: 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) fprintf(stderr, "Couldn't start host: OAuth error.\n"); 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case HostStarter::START_ERROR: 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) fprintf(stderr, "Couldn't start host.\n"); 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) g_message_loop->QuitNow(); 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int main(int argc, char** argv) { 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // google_apis::GetOAuth2ClientID/Secret need a static CommandLine. 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CommandLine::Init(argc, argv); 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const CommandLine* command_line = CommandLine::ForCurrentProcess(); 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string host_name = command_line->GetSwitchValueASCII("name"); 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string host_pin = command_line->GetSwitchValueASCII("pin"); 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string auth_code = command_line->GetSwitchValueASCII("code"); 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string redirect_url = command_line->GetSwitchValueASCII("redirect-url"); 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (host_name.empty()) { 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) fprintf(stderr, 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "Usage: %s --name=<hostname> [--code=<auth-code>] [--pin=<PIN>] " 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "[--redirect-url=<redirectURL>]\n", 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) argv[0]); 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 1; 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (host_pin.empty()) { 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) while (true) { 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) fprintf(stdout, "Enter a six-digit PIN: "); 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) fflush(stdout); 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) host_pin = ReadString(true); 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!remoting::IsPinValid(host_pin)) { 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) fprintf(stdout, 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "Please use a PIN consisting of at least six digits.\n"); 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) fflush(stdout); 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) continue; 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string host_pin_confirm; 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) fprintf(stdout, "Enter the same PIN again: "); 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) fflush(stdout); 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) host_pin_confirm = ReadString(true); 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (host_pin != host_pin_confirm) { 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) fprintf(stdout, "You entered different PINs.\n"); 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) fflush(stdout); 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) continue; 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!remoting::IsPinValid(host_pin)) { 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) fprintf(stderr, "Please use a PIN consisting of at least six digits.\n"); 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 1; 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (auth_code.empty()) { 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) fprintf(stdout, "Enter an authorization code: "); 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) fflush(stdout); 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) auth_code = ReadString(true); 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // This object instance is required by Chrome code (for example, 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // FilePath, LazyInstance, MessageLoop). 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::AtExitManager exit_manager; 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Provide message loops and threads for the URLRequestContextGetter. 145c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) base::MessageLoop message_loop; 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) g_message_loop = &message_loop; 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Thread io_thread("IO thread"); 148c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) base::Thread::Options io_thread_options(base::MessageLoop::TYPE_IO, 0); 1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) io_thread.StartWithOptions(io_thread_options); 1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_refptr<net::URLRequestContextGetter> url_request_context_getter( 1523551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) new remoting::URLRequestContextGetter(io_thread.message_loop_proxy())); 1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 154a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) net::URLFetcher::SetIgnoreCertificateRequests(true); 1552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Start the host. 157868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) scoped_ptr<HostStarter> host_starter(HostStarter::Create( 158868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) remoting::ServiceUrls::GetInstance()->directory_hosts_url(), 159868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) url_request_context_getter.get())); 1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (redirect_url.empty()) { 1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) redirect_url = remoting::GetDefaultOauthRedirectUrl(); 1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) host_starter->StartHost(host_name, host_pin, true, auth_code, redirect_url, 1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Bind(&OnDone)); 1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Run the message loop until the StartHost completion callback. 1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::RunLoop run_loop; 1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) run_loop.Run(); 1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) g_message_loop = NULL; 1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Destroy the HostStarter and URLRequestContextGetter before stopping the 1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // IO thread. 1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) host_starter.reset(); 1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) url_request_context_getter = NULL; 1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) io_thread.Stop(); 1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return g_started ? 0 : 1; 1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 181