1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include <signal.h> 6 #include <stdlib.h> 7 8 #include <iostream> 9 #include <string> 10 11 #include "base/at_exit.h" 12 #include "base/bind.h" 13 #include "base/command_line.h" 14 #include "base/compiler_specific.h" 15 #include "base/logging.h" 16 #include "base/strings/string_piece.h" 17 #include "base/strings/stringprintf.h" 18 #include "base/threading/thread.h" 19 #include "tools/android/forwarder2/common.h" 20 #include "tools/android/forwarder2/daemon.h" 21 #include "tools/android/forwarder2/device_controller.h" 22 #include "tools/android/forwarder2/pipe_notifier.h" 23 24 namespace forwarder2 { 25 namespace { 26 27 // Leaky global instance, accessed from the signal handler. 28 forwarder2::PipeNotifier* g_notifier = NULL; 29 30 const int kBufSize = 256; 31 32 const char kUnixDomainSocketPath[] = "chrome_device_forwarder"; 33 const char kDaemonIdentifier[] = "chrome_device_forwarder_daemon"; 34 35 void KillHandler(int /* unused */) { 36 CHECK(g_notifier); 37 if (!g_notifier->Notify()) 38 exit(1); 39 } 40 41 // Lets the daemon fetch the exit notifier file descriptor. 42 int GetExitNotifierFD() { 43 DCHECK(g_notifier); 44 return g_notifier->receiver_fd(); 45 } 46 47 class ServerDelegate : public Daemon::ServerDelegate { 48 public: 49 ServerDelegate() : initialized_(false) {} 50 51 virtual ~ServerDelegate() { 52 if (!controller_thread_.get()) 53 return; 54 // The DeviceController instance, if any, is constructed on the controller 55 // thread. Make sure that it gets deleted on that same thread. Note that 56 // DeleteSoon() is not used here since it would imply reading |controller_| 57 // from the main thread while it's set on the internal thread. 58 controller_thread_->message_loop_proxy()->PostTask( 59 FROM_HERE, 60 base::Bind(&ServerDelegate::DeleteControllerOnInternalThread, 61 base::Unretained(this))); 62 } 63 64 void DeleteControllerOnInternalThread() { 65 DCHECK( 66 controller_thread_->message_loop_proxy()->RunsTasksOnCurrentThread()); 67 controller_.reset(); 68 } 69 70 // Daemon::ServerDelegate: 71 virtual void Init() OVERRIDE { 72 DCHECK(!g_notifier); 73 g_notifier = new forwarder2::PipeNotifier(); 74 signal(SIGTERM, KillHandler); 75 signal(SIGINT, KillHandler); 76 controller_thread_.reset(new base::Thread("controller_thread")); 77 controller_thread_->Start(); 78 } 79 80 virtual void OnClientConnected(scoped_ptr<Socket> client_socket) OVERRIDE { 81 if (initialized_) { 82 client_socket->WriteString("OK"); 83 return; 84 } 85 controller_thread_->message_loop()->PostTask( 86 FROM_HERE, 87 base::Bind(&ServerDelegate::StartController, base::Unretained(this), 88 GetExitNotifierFD(), base::Passed(&client_socket))); 89 initialized_ = true; 90 } 91 92 private: 93 void StartController(int exit_notifier_fd, scoped_ptr<Socket> client_socket) { 94 DCHECK(!controller_.get()); 95 scoped_ptr<DeviceController> controller( 96 DeviceController::Create(kUnixDomainSocketPath, exit_notifier_fd)); 97 if (!controller.get()) { 98 client_socket->WriteString( 99 base::StringPrintf("ERROR: Could not initialize device controller " 100 "with ADB socket path: %s", 101 kUnixDomainSocketPath)); 102 return; 103 } 104 controller_.swap(controller); 105 controller_->Start(); 106 client_socket->WriteString("OK"); 107 client_socket->Close(); 108 } 109 110 scoped_ptr<DeviceController> controller_; 111 scoped_ptr<base::Thread> controller_thread_; 112 bool initialized_; 113 }; 114 115 class ClientDelegate : public Daemon::ClientDelegate { 116 public: 117 ClientDelegate() : has_failed_(false) {} 118 119 bool has_failed() const { return has_failed_; } 120 121 // Daemon::ClientDelegate: 122 virtual void OnDaemonReady(Socket* daemon_socket) OVERRIDE { 123 char buf[kBufSize]; 124 const int bytes_read = daemon_socket->Read( 125 buf, sizeof(buf) - 1 /* leave space for null terminator */); 126 CHECK_GT(bytes_read, 0); 127 DCHECK(bytes_read < sizeof(buf)); 128 buf[bytes_read] = 0; 129 base::StringPiece msg(buf, bytes_read); 130 if (msg.starts_with("ERROR")) { 131 LOG(ERROR) << msg; 132 has_failed_ = true; 133 return; 134 } 135 } 136 137 private: 138 bool has_failed_; 139 }; 140 141 int RunDeviceForwarder(int argc, char** argv) { 142 CommandLine::Init(argc, argv); // Needed by logging. 143 const bool kill_server = CommandLine::ForCurrentProcess()->HasSwitch( 144 "kill-server"); 145 if ((kill_server && argc != 2) || (!kill_server && argc != 1)) { 146 std::cerr << "Usage: device_forwarder [--kill-server]" << std::endl; 147 return 1; 148 } 149 base::AtExitManager at_exit_manager; // Used by base::Thread. 150 ClientDelegate client_delegate; 151 ServerDelegate daemon_delegate; 152 const char kLogFilePath[] = ""; // Log to logcat. 153 Daemon daemon(kLogFilePath, kDaemonIdentifier, &client_delegate, 154 &daemon_delegate, &GetExitNotifierFD); 155 156 if (kill_server) 157 return !daemon.Kill(); 158 159 if (!daemon.SpawnIfNeeded()) 160 return 1; 161 return client_delegate.has_failed(); 162 } 163 164 } // namespace 165 } // namespace forwarder2 166 167 int main(int argc, char** argv) { 168 return forwarder2::RunDeviceForwarder(argc, argv); 169 } 170