| 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> |
| 6 #include <stdlib.h> | 7 #include <stdlib.h> |
| 7 | 8 |
| 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"; | |
| 33 const char kDaemonIdentifier[] = "chrome_device_forwarder_daemon"; | 32 const char kDaemonIdentifier[] = "chrome_device_forwarder_daemon"; |
| 34 | 33 |
| 34 const char kKillServerCommand[] = "kill-server"; |
| 35 const char kStartCommand[] = "start"; |
| 36 |
| 35 void KillHandler(int /* unused */) { | 37 void KillHandler(int /* unused */) { |
| 36 CHECK(g_notifier); | 38 CHECK(g_notifier); |
| 37 if (!g_notifier->Notify()) | 39 if (!g_notifier->Notify()) |
| 38 exit(1); | 40 exit(1); |
| 39 } | 41 } |
| 40 | 42 |
| 41 // Lets the daemon fetch the exit notifier file descriptor. | 43 // Lets the daemon fetch the exit notifier file descriptor. |
| 42 int GetExitNotifierFD() { | 44 int GetExitNotifierFD() { |
| 43 DCHECK(g_notifier); | 45 DCHECK(g_notifier); |
| 44 return g_notifier->receiver_fd(); | 46 return g_notifier->receiver_fd(); |
| 45 } | 47 } |
| 46 | 48 |
| 47 class ServerDelegate : public Daemon::ServerDelegate { | 49 class ServerDelegate : public Daemon::ServerDelegate { |
| 48 public: | 50 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 if (initialized_) { | 62 char buf[kBufSize]; |
| 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_) { |
| 63 client_socket->WriteString("OK"); | 72 client_socket->WriteString("OK"); |
| 64 return; | 73 return; |
| 65 } | 74 } |
| 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; |
| 66 controller_thread_->message_loop()->PostTask( | 83 controller_thread_->message_loop()->PostTask( |
| 67 FROM_HERE, | 84 FROM_HERE, |
| 68 base::Bind(&ServerDelegate::StartController, GetExitNotifierFD(), | 85 base::Bind(&ServerDelegate::StartController, adb_socket_path, |
| 69 base::Passed(&client_socket))); | 86 GetExitNotifierFD(), base::Passed(&client_socket))); |
| 70 initialized_ = true; | |
| 71 } | 87 } |
| 72 | 88 |
| 73 virtual void OnServerExited() OVERRIDE {} | 89 virtual void OnServerExited() OVERRIDE {} |
| 74 | 90 |
| 75 private: | 91 private: |
| 76 static void StartController(int exit_notifier_fd, | 92 static void StartController(const std::string& adb_socket_path, |
| 93 int exit_notifier_fd, |
| 77 scoped_ptr<Socket> client_socket) { | 94 scoped_ptr<Socket> client_socket) { |
| 78 forwarder2::DeviceController controller(exit_notifier_fd); | 95 forwarder2::DeviceController controller(exit_notifier_fd); |
| 79 if (!controller.Init(kUnixDomainSocketPath)) { | 96 if (!controller.Init(adb_socket_path)) { |
| 80 client_socket->WriteString( | 97 client_socket->WriteString( |
| 81 base::StringPrintf("ERROR: Could not initialize device controller " | 98 base::StringPrintf("ERROR: Could not initialize device controller " |
| 82 "with ADB socket path: %s", | 99 "with ADB socket path: %s", |
| 83 kUnixDomainSocketPath)); | 100 adb_socket_path.c_str())); |
| 84 return; | 101 return; |
| 85 } | 102 } |
| 86 client_socket->WriteString("OK"); | 103 client_socket->WriteString("OK"); |
| 87 client_socket->Close(); | 104 client_socket->Close(); |
| 88 // Note that the following call is blocking which explains why the device | 105 // Note that the following call is blocking which explains why the device |
| 89 // controller has to live on a separate thread (so that the daemon command | 106 // controller has to live on a separate thread (so that the daemon command |
| 90 // server is not blocked). | 107 // server is not blocked). |
| 91 controller.Start(); | 108 controller.Start(); |
| 92 } | 109 } |
| 93 | 110 |
| 94 base::AtExitManager at_exit_manager_; // Used by base::Thread. | 111 base::AtExitManager at_exit_manager_; // Used by base::Thread. |
| 95 scoped_ptr<base::Thread> controller_thread_; | 112 scoped_ptr<base::Thread> controller_thread_; |
| 96 bool initialized_; | 113 std::string adb_socket_path_; |
| 97 }; | 114 }; |
| 98 | 115 |
| 99 class ClientDelegate : public Daemon::ClientDelegate { | 116 class ClientDelegate : public Daemon::ClientDelegate { |
| 100 public: | 117 public: |
| 101 ClientDelegate() : has_failed_(false) {} | 118 ClientDelegate(const std::string& adb_socket) |
| 119 : adb_socket_(adb_socket), |
| 120 has_failed_(false) { |
| 121 } |
| 102 | 122 |
| 103 bool has_failed() const { return has_failed_; } | 123 bool has_failed() const { return has_failed_; } |
| 104 | 124 |
| 105 // Daemon::ClientDelegate: | 125 // Daemon::ClientDelegate: |
| 106 virtual void OnDaemonReady(Socket* daemon_socket) OVERRIDE { | 126 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())); |
| 107 char buf[kBufSize]; | 130 char buf[kBufSize]; |
| 108 const int bytes_read = daemon_socket->Read( | 131 const int bytes_read = daemon_socket->Read( |
| 109 buf, sizeof(buf) - 1 /* leave space for null terminator */); | 132 buf, sizeof(buf) - 1 /* leave space for null terminator */); |
| 110 CHECK_GT(bytes_read, 0); | 133 CHECK_GT(bytes_read, 0); |
| 111 DCHECK(bytes_read < sizeof(buf)); | 134 DCHECK(bytes_read < sizeof(buf)); |
| 112 buf[bytes_read] = 0; | 135 buf[bytes_read] = 0; |
| 113 base::StringPiece msg(buf, bytes_read); | 136 base::StringPiece msg(buf, bytes_read); |
| 114 if (msg.starts_with("ERROR")) { | 137 if (msg.starts_with("ERROR")) { |
| 115 LOG(ERROR) << msg; | 138 LOG(ERROR) << msg; |
| 116 has_failed_ = true; | 139 has_failed_ = true; |
| 117 return; | 140 return; |
| 118 } | 141 } |
| 119 } | 142 } |
| 120 | 143 |
| 121 private: | 144 private: |
| 145 const std::string adb_socket_; |
| 122 bool has_failed_; | 146 bool has_failed_; |
| 123 }; | 147 }; |
| 124 | 148 |
| 125 int RunDeviceForwarder(int argc, char** argv) { | 149 int RunDeviceForwarder(int argc, char** argv) { |
| 126 CommandLine::Init(argc, argv); // Needed by logging. | 150 if (argc != 2) { |
| 127 const bool kill_server = CommandLine::ForCurrentProcess()->HasSwitch( | 151 fprintf(stderr, |
| 128 "kill-server"); | 152 "Usage: %s kill-server|<adb_socket>\n" |
| 129 if ((kill_server && argc != 2) || (!kill_server && argc != 1)) { | 153 " <adb_socket> is the abstract Unix Domain Socket path " |
| 130 std::cerr << "Usage: device_forwarder [--kill-server]" << std::endl; | 154 "where Adb is configured to forward from.\n", argv[0]); |
| 131 return 1; | 155 return 1; |
| 132 } | 156 } |
| 133 ClientDelegate client_delegate; | 157 CommandLine::Init(argc, argv); // Needed by logging. |
| 158 const char* const command = |
| 159 !strcmp(argv[1], kKillServerCommand) ? kKillServerCommand : kStartCommand; |
| 160 ClientDelegate client_delegate(argv[1]); |
| 134 ServerDelegate daemon_delegate; | 161 ServerDelegate daemon_delegate; |
| 135 const char kLogFilePath[] = ""; // Log to logcat. | 162 const char kLogFilePath[] = ""; // Log to logcat. |
| 136 Daemon daemon(kLogFilePath, kDaemonIdentifier, &client_delegate, | 163 Daemon daemon(kLogFilePath, kDaemonIdentifier, &client_delegate, |
| 137 &daemon_delegate, &GetExitNotifierFD); | 164 &daemon_delegate, &GetExitNotifierFD); |
| 138 | 165 |
| 139 if (kill_server) | 166 if (command == kKillServerCommand) |
| 140 return !daemon.Kill(); | 167 return !daemon.Kill(); |
| 141 | 168 |
| 169 DCHECK(command == kStartCommand); |
| 142 if (!daemon.SpawnIfNeeded()) | 170 if (!daemon.SpawnIfNeeded()) |
| 143 return 1; | 171 return 1; |
| 144 return client_delegate.has_failed(); | 172 return client_delegate.has_failed(); |
| 145 } | 173 } |
| 146 | 174 |
| 147 } // namespace | 175 } // namespace |
| 148 } // namespace forwarder2 | 176 } // namespace forwarder2 |
| 149 | 177 |
| 150 int main(int argc, char** argv) { | 178 int main(int argc, char** argv) { |
| 151 return forwarder2::RunDeviceForwarder(argc, argv); | 179 return forwarder2::RunDeviceForwarder(argc, argv); |
| 152 } | 180 } |
| OLD | NEW |