Index: tools/android/forwarder2/host_forwarder_main.cc |
diff --git a/tools/android/forwarder2/host_forwarder_main.cc b/tools/android/forwarder2/host_forwarder_main.cc |
index d7f52d157e033815dc8f00aaab0809b68e51dde5..435cae43194dd449c8dcbce8c080e339fb73229d 100644 |
--- a/tools/android/forwarder2/host_forwarder_main.cc |
+++ b/tools/android/forwarder2/host_forwarder_main.cc |
@@ -4,14 +4,15 @@ |
#include <errno.h> |
#include <signal.h> |
-#include <stdio.h> |
-#include <stdlib.h> |
#include <unistd.h> |
-#include <vector> |
+#include <cstdio> |
+#include <cstring> |
#include <string> |
+#include <vector> |
#include "base/command_line.h" |
+#include "base/compiler_specific.h" |
#include "base/file_path.h" |
#include "base/file_util.h" |
#include "base/logging.h" |
@@ -29,26 +30,36 @@ |
#include "tools/android/forwarder2/pipe_notifier.h" |
#include "tools/android/forwarder2/socket.h" |
-using base::StringToInt; |
- |
namespace forwarder2 { |
namespace { |
+const char kLogFilePath[] = "/tmp/host_forwarder_log"; |
const char kPIDFilePath[] = "/tmp/host_forwarder_pid"; |
-const char kCommandSocketPath[] = "host_forwarder_command_socket"; |
-const char kWelcomeMessage[] = "forwarder2"; |
+const char kDaemonIdentifier[] = "chrome_host_forwarder_daemon"; |
+ |
+const char kKillServerCommand[] = "kill-server"; |
+const char kForwardCommand[] = "forward"; |
+ |
const int kBufSize = 256; |
-// Need to be global to be able to accessed from the signal handler. |
-PipeNotifier* g_notifier; |
+// Needs to be global to be able to be accessed from the signal handler. |
+PipeNotifier* g_notifier = NULL; |
+ |
+// Lets the daemon fetch the exit notifier file descriptor. |
+int GetExitNotifierFD() { |
+ DCHECK(g_notifier); |
+ return g_notifier->receiver_fd(); |
+} |
void KillHandler(int signal_number) { |
+ char buf[kBufSize]; |
if (signal_number != SIGTERM && signal_number != SIGINT) { |
- char buf[kBufSize]; |
snprintf(buf, sizeof(buf), "Ignoring unexpected signal %d.", signal_number); |
SIGNAL_SAFE_LOG(WARNING, buf); |
return; |
} |
+ snprintf(buf, sizeof(buf), "Received signal %d.", signal_number); |
+ SIGNAL_SAFE_LOG(WARNING, buf); |
static int s_kill_handler_count = 0; |
CHECK(g_notifier); |
// If for some reason the forwarder get stuck in any socket waiting forever, |
@@ -59,34 +70,6 @@ void KillHandler(int signal_number) { |
exit(1); |
} |
-enum { |
- kConnectSingleTry = 1, |
- kConnectNoIdleTime = 0, |
-}; |
- |
-scoped_ptr<Socket> ConnectToDaemon(int tries_count, int idle_time_msec) { |
- for (int i = 0; i < tries_count; ++i) { |
- scoped_ptr<Socket> socket(new Socket()); |
- if (!socket->ConnectUnix(kCommandSocketPath, true)) { |
- if (idle_time_msec) |
- usleep(idle_time_msec * 1000); |
- continue; |
- } |
- char buf[sizeof(kWelcomeMessage)]; |
- memset(buf, 0, sizeof(buf)); |
- if (socket->Read(buf, sizeof(buf)) < 0) { |
- perror("read"); |
- continue; |
- } |
- if (strcmp(buf, kWelcomeMessage)) { |
- LOG(ERROR) << "Unexpected message read from daemon: " << buf; |
- break; |
- } |
- return socket.Pass(); |
- } |
- return scoped_ptr<Socket>(NULL); |
-} |
- |
// Format of |command|: |
// <ADB port>:<Device port>[:<Forward to port>:<Forward to address>]. |
bool ParseForwardCommand(const std::string& command, |
@@ -98,12 +81,12 @@ bool ParseForwardCommand(const std::string& command, |
base::SplitString(command, ':', &command_pieces); |
if (command_pieces.size() < 2 || |
- !StringToInt(command_pieces[0], adb_port) || |
- !StringToInt(command_pieces[1], device_port)) |
+ !base::StringToInt(command_pieces[0], adb_port) || |
+ !base::StringToInt(command_pieces[1], device_port)) |
return false; |
if (command_pieces.size() > 2) { |
- if (!StringToInt(command_pieces[2], forward_to_port)) |
+ if (!base::StringToInt(command_pieces[2], forward_to_port)) |
return false; |
if (command_pieces.size() > 3) |
*forward_to_host = command_pieces[3]; |
@@ -121,44 +104,30 @@ bool IsForwardCommandValid(const std::string& command) { |
command, &adb_port, &device_port, &forward_to_host, &forward_to_port); |
} |
-bool DaemonHandler() { |
- LOG(INFO) << "Starting host process daemon (pid=" << getpid() << ")"; |
- DCHECK(!g_notifier); |
- g_notifier = new PipeNotifier(); |
- |
- const int notifier_fd = g_notifier->receiver_fd(); |
- Socket command_socket; |
- if (!command_socket.BindUnix(kCommandSocketPath, true)) { |
- LOG(ERROR) << "Could not bind Unix Domain Socket"; |
- return false; |
- } |
- command_socket.set_exit_notifier_fd(notifier_fd); |
+class ServerDelegate : public Daemon::ServerDelegate { |
+ public: |
+ ServerDelegate() : has_failed_(false) {} |
- signal(SIGTERM, KillHandler); |
- signal(SIGINT, KillHandler); |
+ bool has_failed() const { return has_failed_; } |
- ScopedVector<HostController> controllers; |
- int failed_count = 0; |
+ // Daemon::ServerDelegate: |
+ virtual void Init() OVERRIDE { |
+ LOG(INFO) << "Starting host process daemon (pid=" << getpid() << ")"; |
+ DCHECK(!g_notifier); |
+ g_notifier = new PipeNotifier(); |
+ signal(SIGTERM, KillHandler); |
+ signal(SIGINT, KillHandler); |
+ } |
- for (;;) { |
- Socket client_socket; |
- if (!command_socket.Accept(&client_socket)) { |
- if (command_socket.exited()) |
- return true; |
- PError("Accept()"); |
- return false; |
- } |
- if (!client_socket.Write(kWelcomeMessage, sizeof(kWelcomeMessage))) { |
- PError("Write()"); |
- continue; |
- } |
+ virtual void OnClientConnected(scoped_ptr<Socket> client_socket) OVERRIDE { |
char buf[kBufSize]; |
- const int bytes_read = client_socket.Read(buf, sizeof(buf)); |
+ const int bytes_read = client_socket->Read(buf, sizeof(buf)); |
if (bytes_read <= 0) { |
- if (client_socket.exited()) |
- break; |
+ if (client_socket->exited()) |
+ return; |
PError("Read()"); |
- ++failed_count; |
+ has_failed_ = true; |
+ return; |
} |
const std::string command(buf, bytes_read); |
int adb_port = 0; |
@@ -168,41 +137,81 @@ bool DaemonHandler() { |
const bool succeeded = ParseForwardCommand( |
command, &adb_port, &device_port, &forward_to_host, &forward_to_port); |
if (!succeeded) { |
- ++failed_count; |
- client_socket.WriteString( |
+ has_failed_ = true; |
+ client_socket->WriteString( |
base::StringPrintf("ERROR: Could not parse forward command '%s'", |
command.c_str())); |
- continue; |
+ return; |
} |
scoped_ptr<HostController> host_controller( |
new HostController(device_port, forward_to_host, forward_to_port, |
- adb_port, notifier_fd)); |
+ adb_port, GetExitNotifierFD())); |
if (!host_controller->Connect()) { |
- ++failed_count; |
- client_socket.WriteString("ERROR: Connection to device failed."); |
- continue; |
+ has_failed_ = true; |
+ client_socket->WriteString("ERROR: Connection to device failed."); |
+ return; |
} |
// Get the current allocated port. |
device_port = host_controller->device_port(); |
LOG(INFO) << "Forwarding device port " << device_port << " to host " |
<< forward_to_host << ":" << forward_to_port; |
- if (!client_socket.WriteString( |
+ if (!client_socket->WriteString( |
base::StringPrintf("%d:%d", device_port, forward_to_port))) { |
- ++failed_count; |
- continue; |
+ has_failed_ = true; |
+ return; |
} |
host_controller->Start(); |
- controllers.push_back(host_controller.release()); |
+ controllers_.push_back(host_controller.release()); |
} |
- for (int i = 0; i < controllers.size(); ++i) |
- controllers[i]->Join(); |
- if (controllers.size() == 0) { |
- LOG(ERROR) << "No forwarder servers could be started. Exiting."; |
- return false; |
+ virtual void OnServerExited() OVERRIDE { |
+ for (int i = 0; i < controllers_.size(); ++i) |
+ controllers_[i]->Join(); |
+ if (controllers_.size() == 0) { |
+ LOG(ERROR) << "No forwarder servers could be started. Exiting."; |
+ has_failed_ = true; |
+ } |
+ } |
+ |
+ private: |
+ ScopedVector<HostController> controllers_; |
+ bool has_failed_; |
+ |
+ DISALLOW_COPY_AND_ASSIGN(ServerDelegate); |
+}; |
+ |
+class ClientDelegate : public Daemon::ClientDelegate { |
+ public: |
+ ClientDelegate(const std::string& forward_command) |
+ : forward_command_(forward_command), |
+ has_failed_(false) { |
} |
- return true; |
-} |
+ |
+ bool has_failed() const { return has_failed_; } |
+ |
+ // Daemon::ClientDelegate: |
+ virtual void OnDaemonReady(Socket* daemon_socket) OVERRIDE { |
+ // Send the forward command to the daemon. |
+ CHECK(daemon_socket->WriteString(forward_command_)); |
+ char buf[kBufSize]; |
+ const int bytes_read = daemon_socket->Read( |
+ buf, sizeof(buf) - 1 /* leave space for null terminator */); |
+ CHECK_GT(bytes_read, 0); |
+ DCHECK(bytes_read < sizeof(buf)); |
+ buf[bytes_read] = 0; |
+ base::StringPiece msg(buf, bytes_read); |
+ if (msg.starts_with("ERROR")) { |
+ LOG(ERROR) << msg; |
+ has_failed_ = true; |
+ return; |
+ } |
+ printf("%s\n", buf); |
+ } |
+ |
+ private: |
+ const std::string forward_command_; |
+ bool has_failed_; |
+}; |
void PrintUsage(const char* program_name) { |
LOG(ERROR) << program_name << " adb_port:from_port:to_port:to_host\n" |
@@ -215,63 +224,36 @@ int RunHostForwarder(int argc, char** argv) { |
return 1; |
} |
const CommandLine& command_line = *CommandLine::ForCurrentProcess(); |
- std::string command; |
+ const char* command = NULL; |
int adb_port = 0; |
if (argc != 2) { |
PrintUsage(argv[0]); |
return 1; |
} |
- if (!strcmp(argv[1], "kill-server")) { |
- command = "kill-server"; |
+ if (!strcmp(argv[1], kKillServerCommand)) { |
+ command = kKillServerCommand; |
} else { |
- command = "forward"; |
+ command = kForwardCommand; |
if (!IsForwardCommandValid(argv[1])) { |
PrintUsage(argv[0]); |
return 1; |
} |
} |
- Daemon daemon(kPIDFilePath); |
+ ClientDelegate client_delegate(argv[1]); |
+ ServerDelegate daemon_delegate; |
+ Daemon daemon( |
+ kLogFilePath, kPIDFilePath, kDaemonIdentifier, &client_delegate, |
+ &daemon_delegate, &GetExitNotifierFD); |
- if (command == "kill-server") |
+ if (command == kKillServerCommand) |
return !daemon.Kill(); |
- bool is_daemon = false; |
- scoped_ptr<Socket> daemon_socket = ConnectToDaemon( |
- kConnectSingleTry, kConnectNoIdleTime); |
- if (!daemon_socket) { |
- if (!daemon.Spawn(&is_daemon)) |
- return 1; |
- } |
- |
- if (is_daemon) |
- return !DaemonHandler(); |
- |
- if (!daemon_socket) { |
- const int kTries = 10; |
- const int kIdleTimeMsec = 10; |
- daemon_socket = ConnectToDaemon(kTries, kIdleTimeMsec); |
- if (!daemon_socket) { |
- LOG(ERROR) << "Could not connect to daemon."; |
- return 1; |
- } |
- } |
- |
- // Send the forward command to the daemon. |
- CHECK(daemon_socket->Write(argv[1], strlen(argv[1]))); |
- char buf[kBufSize]; |
- const int bytes_read = daemon_socket->Read( |
- buf, sizeof(buf) - 1 /* leave space for null terminator */); |
- CHECK_GT(bytes_read, 0); |
- DCHECK(bytes_read < sizeof(buf)); |
- buf[bytes_read] = 0; |
- base::StringPiece msg(buf, bytes_read); |
- if (msg.starts_with("ERROR")) { |
- LOG(ERROR) << msg; |
+ DCHECK(command == kForwardCommand); |
+ if (!daemon.SpawnIfNeeded()) |
return 1; |
- } |
- printf("%s\n", buf); |
- return 0; |
+ |
+ return client_delegate.has_failed() || daemon_delegate.has_failed(); |
} |
} // namespace |