| 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 <errno.h> | 5 #include <errno.h> |
| 6 #include <signal.h> | 6 #include <signal.h> |
| 7 #include <stdio.h> | |
| 8 #include <stdlib.h> | |
| 9 #include <unistd.h> | 7 #include <unistd.h> |
| 10 | 8 |
| 9 #include <cstdio> |
| 10 #include <cstring> |
| 11 #include <string> |
| 11 #include <vector> | 12 #include <vector> |
| 12 #include <string> | |
| 13 | 13 |
| 14 #include "base/command_line.h" | 14 #include "base/command_line.h" |
| 15 #include "base/compiler_specific.h" |
| 15 #include "base/file_path.h" | 16 #include "base/file_path.h" |
| 16 #include "base/file_util.h" | 17 #include "base/file_util.h" |
| 17 #include "base/logging.h" | 18 #include "base/logging.h" |
| 18 #include "base/memory/scoped_vector.h" | 19 #include "base/memory/scoped_vector.h" |
| 19 #include "base/posix/eintr_wrapper.h" | 20 #include "base/posix/eintr_wrapper.h" |
| 20 #include "base/safe_strerror_posix.h" | 21 #include "base/safe_strerror_posix.h" |
| 21 #include "base/string_number_conversions.h" | 22 #include "base/string_number_conversions.h" |
| 22 #include "base/string_piece.h" | 23 #include "base/string_piece.h" |
| 23 #include "base/string_split.h" | 24 #include "base/string_split.h" |
| 24 #include "base/string_util.h" | 25 #include "base/string_util.h" |
| 25 #include "base/stringprintf.h" | 26 #include "base/stringprintf.h" |
| 26 #include "tools/android/forwarder2/common.h" | 27 #include "tools/android/forwarder2/common.h" |
| 27 #include "tools/android/forwarder2/daemon.h" | 28 #include "tools/android/forwarder2/daemon.h" |
| 28 #include "tools/android/forwarder2/host_controller.h" | 29 #include "tools/android/forwarder2/host_controller.h" |
| 29 #include "tools/android/forwarder2/pipe_notifier.h" | 30 #include "tools/android/forwarder2/pipe_notifier.h" |
| 30 #include "tools/android/forwarder2/socket.h" | 31 #include "tools/android/forwarder2/socket.h" |
| 31 | 32 |
| 32 using base::StringToInt; | |
| 33 | |
| 34 namespace forwarder2 { | 33 namespace forwarder2 { |
| 35 namespace { | 34 namespace { |
| 36 | 35 |
| 36 const char kLogFilePath[] = "/tmp/host_forwarder_log"; |
| 37 const char kPIDFilePath[] = "/tmp/host_forwarder_pid"; | 37 const char kPIDFilePath[] = "/tmp/host_forwarder_pid"; |
| 38 const char kCommandSocketPath[] = "host_forwarder_command_socket"; | 38 const char kDaemonIdentifier[] = "chrome_host_forwarder_daemon"; |
| 39 const char kWelcomeMessage[] = "forwarder2"; | 39 |
| 40 const char kKillServerCommand[] = "kill-server"; |
| 41 const char kForwardCommand[] = "forward"; |
| 42 |
| 40 const int kBufSize = 256; | 43 const int kBufSize = 256; |
| 41 | 44 |
| 42 // Need to be global to be able to accessed from the signal handler. | 45 // Needs to be global to be able to be accessed from the signal handler. |
| 43 PipeNotifier* g_notifier; | 46 PipeNotifier* g_notifier = NULL; |
| 47 |
| 48 // Lets the daemon fetch the exit notifier file descriptor. |
| 49 int GetExitNotifierFD() { |
| 50 DCHECK(g_notifier); |
| 51 return g_notifier->receiver_fd(); |
| 52 } |
| 44 | 53 |
| 45 void KillHandler(int signal_number) { | 54 void KillHandler(int signal_number) { |
| 55 char buf[kBufSize]; |
| 46 if (signal_number != SIGTERM && signal_number != SIGINT) { | 56 if (signal_number != SIGTERM && signal_number != SIGINT) { |
| 47 char buf[kBufSize]; | |
| 48 snprintf(buf, sizeof(buf), "Ignoring unexpected signal %d.", signal_number); | 57 snprintf(buf, sizeof(buf), "Ignoring unexpected signal %d.", signal_number); |
| 49 SIGNAL_SAFE_LOG(WARNING, buf); | 58 SIGNAL_SAFE_LOG(WARNING, buf); |
| 50 return; | 59 return; |
| 51 } | 60 } |
| 61 snprintf(buf, sizeof(buf), "Received signal %d.", signal_number); |
| 62 SIGNAL_SAFE_LOG(WARNING, buf); |
| 52 static int s_kill_handler_count = 0; | 63 static int s_kill_handler_count = 0; |
| 53 CHECK(g_notifier); | 64 CHECK(g_notifier); |
| 54 // If for some reason the forwarder get stuck in any socket waiting forever, | 65 // If for some reason the forwarder get stuck in any socket waiting forever, |
| 55 // we can send a SIGKILL or SIGINT three times to force it die | 66 // we can send a SIGKILL or SIGINT three times to force it die |
| 56 // (non-nicely). This is useful when debugging. | 67 // (non-nicely). This is useful when debugging. |
| 57 ++s_kill_handler_count; | 68 ++s_kill_handler_count; |
| 58 if (!g_notifier->Notify() || s_kill_handler_count > 2) | 69 if (!g_notifier->Notify() || s_kill_handler_count > 2) |
| 59 exit(1); | 70 exit(1); |
| 60 } | 71 } |
| 61 | 72 |
| 62 enum { | |
| 63 kConnectSingleTry = 1, | |
| 64 kConnectNoIdleTime = 0, | |
| 65 }; | |
| 66 | |
| 67 scoped_ptr<Socket> ConnectToDaemon(int tries_count, int idle_time_msec) { | |
| 68 for (int i = 0; i < tries_count; ++i) { | |
| 69 scoped_ptr<Socket> socket(new Socket()); | |
| 70 if (!socket->ConnectUnix(kCommandSocketPath, true)) { | |
| 71 if (idle_time_msec) | |
| 72 usleep(idle_time_msec * 1000); | |
| 73 continue; | |
| 74 } | |
| 75 char buf[sizeof(kWelcomeMessage)]; | |
| 76 memset(buf, 0, sizeof(buf)); | |
| 77 if (socket->Read(buf, sizeof(buf)) < 0) { | |
| 78 perror("read"); | |
| 79 continue; | |
| 80 } | |
| 81 if (strcmp(buf, kWelcomeMessage)) { | |
| 82 LOG(ERROR) << "Unexpected message read from daemon: " << buf; | |
| 83 break; | |
| 84 } | |
| 85 return socket.Pass(); | |
| 86 } | |
| 87 return scoped_ptr<Socket>(NULL); | |
| 88 } | |
| 89 | |
| 90 // Format of |command|: | 73 // Format of |command|: |
| 91 // <ADB port>:<Device port>[:<Forward to port>:<Forward to address>]. | 74 // <ADB port>:<Device port>[:<Forward to port>:<Forward to address>]. |
| 92 bool ParseForwardCommand(const std::string& command, | 75 bool ParseForwardCommand(const std::string& command, |
| 93 int* adb_port, | 76 int* adb_port, |
| 94 int* device_port, | 77 int* device_port, |
| 95 std::string* forward_to_host, | 78 std::string* forward_to_host, |
| 96 int* forward_to_port) { | 79 int* forward_to_port) { |
| 97 std::vector<std::string> command_pieces; | 80 std::vector<std::string> command_pieces; |
| 98 base::SplitString(command, ':', &command_pieces); | 81 base::SplitString(command, ':', &command_pieces); |
| 99 | 82 |
| 100 if (command_pieces.size() < 2 || | 83 if (command_pieces.size() < 2 || |
| 101 !StringToInt(command_pieces[0], adb_port) || | 84 !base::StringToInt(command_pieces[0], adb_port) || |
| 102 !StringToInt(command_pieces[1], device_port)) | 85 !base::StringToInt(command_pieces[1], device_port)) |
| 103 return false; | 86 return false; |
| 104 | 87 |
| 105 if (command_pieces.size() > 2) { | 88 if (command_pieces.size() > 2) { |
| 106 if (!StringToInt(command_pieces[2], forward_to_port)) | 89 if (!base::StringToInt(command_pieces[2], forward_to_port)) |
| 107 return false; | 90 return false; |
| 108 if (command_pieces.size() > 3) | 91 if (command_pieces.size() > 3) |
| 109 *forward_to_host = command_pieces[3]; | 92 *forward_to_host = command_pieces[3]; |
| 110 } else { | 93 } else { |
| 111 *forward_to_port = *device_port; | 94 *forward_to_port = *device_port; |
| 112 } | 95 } |
| 113 return true; | 96 return true; |
| 114 } | 97 } |
| 115 | 98 |
| 116 bool IsForwardCommandValid(const std::string& command) { | 99 bool IsForwardCommandValid(const std::string& command) { |
| 117 int adb_port, device_port, forward_to_port; | 100 int adb_port, device_port, forward_to_port; |
| 118 std::string forward_to_host; | 101 std::string forward_to_host; |
| 119 std::vector<std::string> command_pieces; | 102 std::vector<std::string> command_pieces; |
| 120 return ParseForwardCommand( | 103 return ParseForwardCommand( |
| 121 command, &adb_port, &device_port, &forward_to_host, &forward_to_port); | 104 command, &adb_port, &device_port, &forward_to_host, &forward_to_port); |
| 122 } | 105 } |
| 123 | 106 |
| 124 bool DaemonHandler() { | 107 class ServerDelegate : public Daemon::ServerDelegate { |
| 125 LOG(INFO) << "Starting host process daemon (pid=" << getpid() << ")"; | 108 public: |
| 126 DCHECK(!g_notifier); | 109 ServerDelegate() : has_failed_(false) {} |
| 127 g_notifier = new PipeNotifier(); | |
| 128 | 110 |
| 129 const int notifier_fd = g_notifier->receiver_fd(); | 111 bool has_failed() const { return has_failed_; } |
| 130 Socket command_socket; | 112 |
| 131 if (!command_socket.BindUnix(kCommandSocketPath, true)) { | 113 // Daemon::ServerDelegate: |
| 132 LOG(ERROR) << "Could not bind Unix Domain Socket"; | 114 virtual void Init() OVERRIDE { |
| 133 return false; | 115 LOG(INFO) << "Starting host process daemon (pid=" << getpid() << ")"; |
| 116 DCHECK(!g_notifier); |
| 117 g_notifier = new PipeNotifier(); |
| 118 signal(SIGTERM, KillHandler); |
| 119 signal(SIGINT, KillHandler); |
| 134 } | 120 } |
| 135 command_socket.set_exit_notifier_fd(notifier_fd); | |
| 136 | 121 |
| 137 signal(SIGTERM, KillHandler); | 122 virtual void OnClientConnected(scoped_ptr<Socket> client_socket) OVERRIDE { |
| 138 signal(SIGINT, KillHandler); | |
| 139 | |
| 140 ScopedVector<HostController> controllers; | |
| 141 int failed_count = 0; | |
| 142 | |
| 143 for (;;) { | |
| 144 Socket client_socket; | |
| 145 if (!command_socket.Accept(&client_socket)) { | |
| 146 if (command_socket.exited()) | |
| 147 return true; | |
| 148 PError("Accept()"); | |
| 149 return false; | |
| 150 } | |
| 151 if (!client_socket.Write(kWelcomeMessage, sizeof(kWelcomeMessage))) { | |
| 152 PError("Write()"); | |
| 153 continue; | |
| 154 } | |
| 155 char buf[kBufSize]; | 123 char buf[kBufSize]; |
| 156 const int bytes_read = client_socket.Read(buf, sizeof(buf)); | 124 const int bytes_read = client_socket->Read(buf, sizeof(buf)); |
| 157 if (bytes_read <= 0) { | 125 if (bytes_read <= 0) { |
| 158 if (client_socket.exited()) | 126 if (client_socket->exited()) |
| 159 break; | 127 return; |
| 160 PError("Read()"); | 128 PError("Read()"); |
| 161 ++failed_count; | 129 has_failed_ = true; |
| 130 return; |
| 162 } | 131 } |
| 163 const std::string command(buf, bytes_read); | 132 const std::string command(buf, bytes_read); |
| 164 int adb_port = 0; | 133 int adb_port = 0; |
| 165 int device_port = 0; | 134 int device_port = 0; |
| 166 std::string forward_to_host; | 135 std::string forward_to_host; |
| 167 int forward_to_port = 0; | 136 int forward_to_port = 0; |
| 168 const bool succeeded = ParseForwardCommand( | 137 const bool succeeded = ParseForwardCommand( |
| 169 command, &adb_port, &device_port, &forward_to_host, &forward_to_port); | 138 command, &adb_port, &device_port, &forward_to_host, &forward_to_port); |
| 170 if (!succeeded) { | 139 if (!succeeded) { |
| 171 ++failed_count; | 140 has_failed_ = true; |
| 172 client_socket.WriteString( | 141 client_socket->WriteString( |
| 173 base::StringPrintf("ERROR: Could not parse forward command '%s'", | 142 base::StringPrintf("ERROR: Could not parse forward command '%s'", |
| 174 command.c_str())); | 143 command.c_str())); |
| 175 continue; | 144 return; |
| 176 } | 145 } |
| 177 scoped_ptr<HostController> host_controller( | 146 scoped_ptr<HostController> host_controller( |
| 178 new HostController(device_port, forward_to_host, forward_to_port, | 147 new HostController(device_port, forward_to_host, forward_to_port, |
| 179 adb_port, notifier_fd)); | 148 adb_port, GetExitNotifierFD())); |
| 180 if (!host_controller->Connect()) { | 149 if (!host_controller->Connect()) { |
| 181 ++failed_count; | 150 has_failed_ = true; |
| 182 client_socket.WriteString("ERROR: Connection to device failed."); | 151 client_socket->WriteString("ERROR: Connection to device failed."); |
| 183 continue; | 152 return; |
| 184 } | 153 } |
| 185 // Get the current allocated port. | 154 // Get the current allocated port. |
| 186 device_port = host_controller->device_port(); | 155 device_port = host_controller->device_port(); |
| 187 LOG(INFO) << "Forwarding device port " << device_port << " to host " | 156 LOG(INFO) << "Forwarding device port " << device_port << " to host " |
| 188 << forward_to_host << ":" << forward_to_port; | 157 << forward_to_host << ":" << forward_to_port; |
| 189 if (!client_socket.WriteString( | 158 if (!client_socket->WriteString( |
| 190 base::StringPrintf("%d:%d", device_port, forward_to_port))) { | 159 base::StringPrintf("%d:%d", device_port, forward_to_port))) { |
| 191 ++failed_count; | 160 has_failed_ = true; |
| 192 continue; | 161 return; |
| 193 } | 162 } |
| 194 host_controller->Start(); | 163 host_controller->Start(); |
| 195 controllers.push_back(host_controller.release()); | 164 controllers_.push_back(host_controller.release()); |
| 196 } | 165 } |
| 197 for (int i = 0; i < controllers.size(); ++i) | |
| 198 controllers[i]->Join(); | |
| 199 | 166 |
| 200 if (controllers.size() == 0) { | 167 virtual void OnServerExited() OVERRIDE { |
| 201 LOG(ERROR) << "No forwarder servers could be started. Exiting."; | 168 for (int i = 0; i < controllers_.size(); ++i) |
| 202 return false; | 169 controllers_[i]->Join(); |
| 170 if (controllers_.size() == 0) { |
| 171 LOG(ERROR) << "No forwarder servers could be started. Exiting."; |
| 172 has_failed_ = true; |
| 173 } |
| 203 } | 174 } |
| 204 return true; | 175 |
| 205 } | 176 private: |
| 177 ScopedVector<HostController> controllers_; |
| 178 bool has_failed_; |
| 179 |
| 180 DISALLOW_COPY_AND_ASSIGN(ServerDelegate); |
| 181 }; |
| 182 |
| 183 class ClientDelegate : public Daemon::ClientDelegate { |
| 184 public: |
| 185 ClientDelegate(const std::string& forward_command) |
| 186 : forward_command_(forward_command), |
| 187 has_failed_(false) { |
| 188 } |
| 189 |
| 190 bool has_failed() const { return has_failed_; } |
| 191 |
| 192 // Daemon::ClientDelegate: |
| 193 virtual void OnDaemonReady(Socket* daemon_socket) OVERRIDE { |
| 194 // Send the forward command to the daemon. |
| 195 CHECK(daemon_socket->WriteString(forward_command_)); |
| 196 char buf[kBufSize]; |
| 197 const int bytes_read = daemon_socket->Read( |
| 198 buf, sizeof(buf) - 1 /* leave space for null terminator */); |
| 199 CHECK_GT(bytes_read, 0); |
| 200 DCHECK(bytes_read < sizeof(buf)); |
| 201 buf[bytes_read] = 0; |
| 202 base::StringPiece msg(buf, bytes_read); |
| 203 if (msg.starts_with("ERROR")) { |
| 204 LOG(ERROR) << msg; |
| 205 has_failed_ = true; |
| 206 return; |
| 207 } |
| 208 printf("%s\n", buf); |
| 209 } |
| 210 |
| 211 private: |
| 212 const std::string forward_command_; |
| 213 bool has_failed_; |
| 214 }; |
| 206 | 215 |
| 207 void PrintUsage(const char* program_name) { | 216 void PrintUsage(const char* program_name) { |
| 208 LOG(ERROR) << program_name << " adb_port:from_port:to_port:to_host\n" | 217 LOG(ERROR) << program_name << " adb_port:from_port:to_port:to_host\n" |
| 209 "<adb port> is the TCP port Adb is configured to forward to."; | 218 "<adb port> is the TCP port Adb is configured to forward to."; |
| 210 } | 219 } |
| 211 | 220 |
| 212 int RunHostForwarder(int argc, char** argv) { | 221 int RunHostForwarder(int argc, char** argv) { |
| 213 if (!CommandLine::Init(argc, argv)) { | 222 if (!CommandLine::Init(argc, argv)) { |
| 214 LOG(ERROR) << "Could not initialize command line"; | 223 LOG(ERROR) << "Could not initialize command line"; |
| 215 return 1; | 224 return 1; |
| 216 } | 225 } |
| 217 const CommandLine& command_line = *CommandLine::ForCurrentProcess(); | 226 const CommandLine& command_line = *CommandLine::ForCurrentProcess(); |
| 218 std::string command; | 227 const char* command = NULL; |
| 219 int adb_port = 0; | 228 int adb_port = 0; |
| 220 if (argc != 2) { | 229 if (argc != 2) { |
| 221 PrintUsage(argv[0]); | 230 PrintUsage(argv[0]); |
| 222 return 1; | 231 return 1; |
| 223 } | 232 } |
| 224 if (!strcmp(argv[1], "kill-server")) { | 233 if (!strcmp(argv[1], kKillServerCommand)) { |
| 225 command = "kill-server"; | 234 command = kKillServerCommand; |
| 226 } else { | 235 } else { |
| 227 command = "forward"; | 236 command = kForwardCommand; |
| 228 if (!IsForwardCommandValid(argv[1])) { | 237 if (!IsForwardCommandValid(argv[1])) { |
| 229 PrintUsage(argv[0]); | 238 PrintUsage(argv[0]); |
| 230 return 1; | 239 return 1; |
| 231 } | 240 } |
| 232 } | 241 } |
| 233 | 242 |
| 234 Daemon daemon(kPIDFilePath); | 243 ClientDelegate client_delegate(argv[1]); |
| 244 ServerDelegate daemon_delegate; |
| 245 Daemon daemon( |
| 246 kLogFilePath, kPIDFilePath, kDaemonIdentifier, &client_delegate, |
| 247 &daemon_delegate, &GetExitNotifierFD); |
| 235 | 248 |
| 236 if (command == "kill-server") | 249 if (command == kKillServerCommand) |
| 237 return !daemon.Kill(); | 250 return !daemon.Kill(); |
| 238 | 251 |
| 239 bool is_daemon = false; | 252 DCHECK(command == kForwardCommand); |
| 240 scoped_ptr<Socket> daemon_socket = ConnectToDaemon( | 253 if (!daemon.SpawnIfNeeded()) |
| 241 kConnectSingleTry, kConnectNoIdleTime); | 254 return 1; |
| 242 if (!daemon_socket) { | |
| 243 if (!daemon.Spawn(&is_daemon)) | |
| 244 return 1; | |
| 245 } | |
| 246 | 255 |
| 247 if (is_daemon) | 256 return client_delegate.has_failed() || daemon_delegate.has_failed(); |
| 248 return !DaemonHandler(); | |
| 249 | |
| 250 if (!daemon_socket) { | |
| 251 const int kTries = 10; | |
| 252 const int kIdleTimeMsec = 10; | |
| 253 daemon_socket = ConnectToDaemon(kTries, kIdleTimeMsec); | |
| 254 if (!daemon_socket) { | |
| 255 LOG(ERROR) << "Could not connect to daemon."; | |
| 256 return 1; | |
| 257 } | |
| 258 } | |
| 259 | |
| 260 // Send the forward command to the daemon. | |
| 261 CHECK(daemon_socket->Write(argv[1], strlen(argv[1]))); | |
| 262 char buf[kBufSize]; | |
| 263 const int bytes_read = daemon_socket->Read( | |
| 264 buf, sizeof(buf) - 1 /* leave space for null terminator */); | |
| 265 CHECK_GT(bytes_read, 0); | |
| 266 DCHECK(bytes_read < sizeof(buf)); | |
| 267 buf[bytes_read] = 0; | |
| 268 base::StringPiece msg(buf, bytes_read); | |
| 269 if (msg.starts_with("ERROR")) { | |
| 270 LOG(ERROR) << msg; | |
| 271 return 1; | |
| 272 } | |
| 273 printf("%s\n", buf); | |
| 274 return 0; | |
| 275 } | 257 } |
| 276 | 258 |
| 277 } // namespace | 259 } // namespace |
| 278 } // namespace forwarder2 | 260 } // namespace forwarder2 |
| 279 | 261 |
| 280 int main(int argc, char** argv) { | 262 int main(int argc, char** argv) { |
| 281 return forwarder2::RunHostForwarder(argc, argv); | 263 return forwarder2::RunHostForwarder(argc, argv); |
| 282 } | 264 } |
| OLD | NEW |