Change next_proto member type.
[chromium-blink-merge.git] / tools / android / forwarder2 / device_forwarder_main.cc
blobbe99aeb501757fb1df03bb2f9aff3edaa7bbdc82
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.
5 #include <signal.h>
6 #include <stdlib.h>
8 #include <iostream>
9 #include <string>
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"
24 namespace forwarder2 {
25 namespace {
27 // Leaky global instance, accessed from the signal handler.
28 forwarder2::PipeNotifier* g_notifier = NULL;
30 const int kBufSize = 256;
32 const char kUnixDomainSocketPath[] = "chrome_device_forwarder";
33 const char kDaemonIdentifier[] = "chrome_device_forwarder_daemon";
35 void KillHandler(int /* unused */) {
36 CHECK(g_notifier);
37 if (!g_notifier->Notify())
38 exit(1);
41 // Lets the daemon fetch the exit notifier file descriptor.
42 int GetExitNotifierFD() {
43 DCHECK(g_notifier);
44 return g_notifier->receiver_fd();
47 class ServerDelegate : public Daemon::ServerDelegate {
48 public:
49 ServerDelegate() : initialized_(false) {}
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)));
64 void DeleteControllerOnInternalThread() {
65 DCHECK(
66 controller_thread_->message_loop_proxy()->RunsTasksOnCurrentThread());
67 controller_.reset();
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();
80 virtual void OnClientConnected(scoped_ptr<Socket> client_socket) override {
81 if (initialized_) {
82 client_socket->WriteString("OK");
83 return;
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;
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;
104 controller_.swap(controller);
105 controller_->Start();
106 client_socket->WriteString("OK");
107 client_socket->Close();
110 scoped_ptr<DeviceController> controller_;
111 scoped_ptr<base::Thread> controller_thread_;
112 bool initialized_;
115 class ClientDelegate : public Daemon::ClientDelegate {
116 public:
117 ClientDelegate() : has_failed_(false) {}
119 bool has_failed() const { return has_failed_; }
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(static_cast<unsigned int>(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;
137 private:
138 bool has_failed_;
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;
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);
156 if (kill_server)
157 return !daemon.Kill();
159 if (!daemon.SpawnIfNeeded())
160 return 1;
161 return client_delegate.has_failed();
164 } // namespace
165 } // namespace forwarder2
167 int main(int argc, char** argv) {
168 return forwarder2::RunDeviceForwarder(argc, argv);