Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(105)

Side by Side Diff: tools/android/forwarder2/device_controller.cc

Issue 19478003: Remove Thread wrapper class in forwarder2. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Rebase Created 7 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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 "tools/android/forwarder2/device_controller.h" 5 #include "tools/android/forwarder2/device_controller.h"
6 6
7 #include <errno.h> 7 #include <errno.h>
8 #include <stdlib.h> 8 #include <stdlib.h>
9 9
10 #include "base/bind.h"
11 #include "base/bind_helpers.h"
10 #include "base/logging.h" 12 #include "base/logging.h"
11 #include "base/memory/scoped_ptr.h" 13 #include "base/memory/scoped_ptr.h"
12 #include "base/safe_strerror_posix.h" 14 #include "base/message_loop/message_loop_proxy.h"
15 #include "base/single_thread_task_runner.h"
13 #include "tools/android/forwarder2/command.h" 16 #include "tools/android/forwarder2/command.h"
14 #include "tools/android/forwarder2/device_listener.h" 17 #include "tools/android/forwarder2/device_listener.h"
15 #include "tools/android/forwarder2/socket.h" 18 #include "tools/android/forwarder2/socket.h"
16 19
17 namespace forwarder2 { 20 namespace forwarder2 {
18 21
19 DeviceController::DeviceController(int exit_notifier_fd) 22 DeviceController::DeviceController(int exit_notifier_fd)
20 : exit_notifier_fd_(exit_notifier_fd) { 23 : exit_notifier_fd_(exit_notifier_fd),
24 listeners_deletion_thread_(base::MessageLoopProxy::current()) {
21 kickstart_adb_socket_.AddEventFd(exit_notifier_fd); 25 kickstart_adb_socket_.AddEventFd(exit_notifier_fd);
22 } 26 }
23 27
24 DeviceController::~DeviceController() { 28 DeviceController::~DeviceController() {}
25 KillAllListeners();
26 CleanUpDeadListeners();
27 CHECK_EQ(0, listeners_.size());
28 }
29
30 void DeviceController::CleanUpDeadListeners() {
31 // Clean up dead listeners.
32 for (ListenersMap::iterator it(&listeners_); !it.IsAtEnd(); it.Advance()) {
33 if (!it.GetCurrentValue()->is_alive())
34 // Remove deletes the listener.
35 listeners_.Remove(it.GetCurrentKey());
36 }
37 }
38
39 void DeviceController::KillAllListeners() {
40 for (ListenersMap::iterator it(&listeners_); !it.IsAtEnd(); it.Advance())
41 it.GetCurrentValue()->ForceExit();
42 for (ListenersMap::iterator it(&listeners_); !it.IsAtEnd(); it.Advance()) {
43 it.GetCurrentValue()->Join();
44 CHECK(!it.GetCurrentValue()->is_alive());
45 }
46 }
47 29
48 bool DeviceController::Init(const std::string& adb_unix_socket) { 30 bool DeviceController::Init(const std::string& adb_unix_socket) {
49 if (!kickstart_adb_socket_.BindUnix(adb_unix_socket)) { 31 if (!kickstart_adb_socket_.BindUnix(adb_unix_socket)) {
50 LOG(ERROR) << "Could not BindAndListen DeviceController socket on port " 32 PLOG(ERROR) << "Could not BindAndListen DeviceController socket on port "
51 << adb_unix_socket << ": " << safe_strerror(errno); 33 << adb_unix_socket << ": ";
52 return false; 34 return false;
53 } 35 }
54 LOG(INFO) << "Listening on Unix Domain Socket " << adb_unix_socket; 36 LOG(INFO) << "Listening on Unix Domain Socket " << adb_unix_socket;
55 return true; 37 return true;
56 } 38 }
57 39
58 void DeviceController::Start() { 40 void DeviceController::Start() {
59 while (true) { 41 AcceptClientSoon();
60 CleanUpDeadListeners(); 42 }
61 scoped_ptr<Socket> socket(new Socket); 43
62 if (!kickstart_adb_socket_.Accept(socket.get())) { 44 void DeviceController::AcceptClientSoon() {
digit1 2013/07/18 20:08:39 nit: I think AcceptHostCommandSoon() / AcceptHostC
Philippe 2013/07/22 15:16:14 Indeed.
63 if (!kickstart_adb_socket_.DidReceiveEvent()) { 45 base::MessageLoopProxy::current()->PostTask(
64 LOG(ERROR) << "Could not Accept DeviceController socket: " 46 FROM_HERE,
65 << safe_strerror(errno); 47 base::Bind(&DeviceController::AcceptClientInternal,
66 } else { 48 base::Unretained(this)));
67 LOG(INFO) << "Received exit notification"; 49 }
50
51 void DeviceController::AcceptClientInternal() {
52 scoped_ptr<Socket> socket(new Socket);
53 if (!kickstart_adb_socket_.Accept(socket.get())) {
54 if (!kickstart_adb_socket_.DidReceiveEvent()) {
55 PLOG(ERROR) << "Could not Accept DeviceController socket";
56 } else {
57 LOG(INFO) << "Received exit notification";
58 }
59 return;
60 }
61 base::ScopedClosureRunner accept_next_client(
62 base::Bind(&DeviceController::AcceptClientSoon, base::Unretained(this)));
63 // So that |socket| doesn't block on read if it has notifications.
64 socket->AddEventFd(exit_notifier_fd_);
65 int port;
66 command::Type command;
67 if (!ReadCommand(socket.get(), &port, &command)) {
68 LOG(ERROR) << "Invalid command received.";
69 return;
70 }
71 DeviceListener* listener = listeners_.Lookup(port);
72 switch (command) {
73 case command::LISTEN: {
74 if (listener != NULL) {
75 LOG(WARNING) << "Already forwarding port " << port
76 << ". Attempting to restart the listener.\n";
77 // Remove deletes the listener object.
78 listeners_.Remove(port);
68 } 79 }
80 scoped_ptr<DeviceListener> new_listener(
81 DeviceListener::Create(
82 socket.Pass(), port, base::Bind(&DeviceController::DeleteListener,
83 base::Unretained(this))));
84 if (!new_listener)
85 return;
86 new_listener->Start();
87 // |port| can be zero, to allow dynamically allocated port, so instead, we
88 // call DeviceListener::listener_port() to retrieve the currently
89 // allocated port to this new listener, which has been set by the
90 // BindListenerSocket() method in case of success.
91 const int listener_port = new_listener->listener_port();
92 // |new_listener| is now owned by listeners_ map.
93 listeners_.AddWithID(new_listener.release(), listener_port);
94 LOG(INFO) << "Forwarding device port " << listener_port << " to host.";
69 break; 95 break;
70 } 96 }
71 // So that |socket| doesn't block on read if it has notifications. 97 case command::DATA_CONNECTION:
72 socket->AddEventFd(exit_notifier_fd_); 98 if (listener == NULL) {
73 int port; 99 LOG(ERROR) << "Data Connection command received, but "
74 command::Type command; 100 << "listener has not been set up yet for port " << port;
75 if (!ReadCommand(socket.get(), &port, &command)) { 101 // After this point it is assumed that, once we close our Adb Data
76 LOG(ERROR) << "Invalid command received."; 102 // socket, the Adb forwarder command will propagate the closing of
77 continue; 103 // sockets all the way to the host side.
78 }
79 DeviceListener* listener = listeners_.Lookup(port);
80 switch (command) {
81 case command::LISTEN: {
82 if (listener != NULL) {
83 LOG(WARNING) << "Already forwarding port " << port
84 << ". Attempting to restart the listener.\n";
85 listener->ForceExit();
86 listener->Join();
87 CHECK(!listener->is_alive());
88 // Remove deletes the listener object.
89 listeners_.Remove(port);
90 }
91 scoped_ptr<DeviceListener> new_listener(
92 new DeviceListener(socket.Pass(), port));
93 if (!new_listener->BindListenerSocket())
94 continue;
95 new_listener->Start();
96 // |port| can be zero, to allow dynamically allocated port, so instead,
97 // we call DeviceListener::listener_port() to retrieve the currently
98 // allocated port to this new listener, which has been set by the
99 // BindListenerSocket() method in case of success.
100 const int listener_port = new_listener->listener_port();
101 // |new_listener| is now owned by listeners_ map.
102 listeners_.AddWithID(new_listener.release(), listener_port);
103 LOG(INFO) << "Forwarding device port " << listener_port << " to host.";
104 break; 104 break;
105 } 105 }
106 case command::DATA_CONNECTION: 106 listener->SetAdbDataSocket(socket.Pass());
digit1 2013/07/18 20:08:39 Since you changed the interaction between DeviceCo
Philippe 2013/07/22 15:16:14 I believe it should not be too risky as it is curr
107 if (listener == NULL) { 107 break;
108 LOG(ERROR) << "Data Connection command received, but " 108 case command::UNMAP_PORT:
digit1 2013/07/18 20:08:39 nit: This should really be called UNLISTEN :-) Le
Philippe 2013/07/22 15:16:14 Yeah indeed :) I made the change in this CL since
109 << "listener has not been set up yet for port " << port; 109 if (!listener) {
110 // After this point it is assumed that, once we close our Adb Data 110 SendCommand(command::UNMAP_PORT_ERROR, port, socket.get());
111 // socket, the Adb forwarder command will propagate the closing of
112 // sockets all the way to the host side.
113 continue;
114 } else if (!listener->SetAdbDataSocket(socket.Pass())) {
115 LOG(ERROR) << "Could not set Adb Data Socket for port: " << port;
116 // Same assumption as above, but in this case the socket is closed
117 // inside SetAdbDataSocket.
118 continue;
119 }
120 break; 111 break;
121 case command::UNMAP_PORT: 112 }
122 if (!listener) { 113 listeners_.Remove(port);
123 SendCommand(command::UNMAP_PORT_ERROR, port, socket.get()); 114 SendCommand(command::UNMAP_PORT_SUCCESS, port, socket.get());
124 break; 115 break;
125 } 116 default:
126 listener->ForceExit(); 117 // TODO(felipeg): add a KillAllListeners command.
127 listener->Join(); 118 LOG(ERROR) << "Invalid command received. Port: " << port
128 CHECK(!listener->is_alive()); 119 << " Command: " << command;
129 listeners_.Remove(port);
130 SendCommand(command::UNMAP_PORT_SUCCESS, port, socket.get());
131 break;
132 default:
133 // TODO(felipeg): add a KillAllListeners command.
134 LOG(ERROR) << "Invalid command received. Port: " << port
135 << " Command: " << command;
136 }
137 } 120 }
138 KillAllListeners(); 121 }
139 CleanUpDeadListeners(); 122
123 void DeviceController::DeleteListener(int listener_port) {
124 if (!listeners_deletion_thread_->RunsTasksOnCurrentThread()) {
125 listeners_deletion_thread_->PostTask(
126 FROM_HERE,
127 base::Bind(&DeviceController::DeleteListenerOnTaskRunner,
128 base::Unretained(this), listener_port));
129 return;
130 }
131 DeleteListenerOnTaskRunner(listener_port);
132 }
133
134 void DeviceController::DeleteListenerOnTaskRunner(int listener_port) {
135 DCHECK(listeners_deletion_thread_->RunsTasksOnCurrentThread());
136 if (listeners_.Lookup(listener_port))
137 listeners_.Remove(listener_port);
140 } 138 }
141 139
142 } // namespace forwarder 140 } // namespace forwarder
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698