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