blob: e0effb8dcd2feee4c159c6d403a3024b5e51bd5d (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
|
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "tools/android/forwarder2/device_controller.h"
#include <errno.h>
#include <stdlib.h>
#include "base/logging.h"
#include "base/memory/scoped_ptr.h"
#include "base/safe_strerror_posix.h"
#include "tools/android/forwarder2/command.h"
#include "tools/android/forwarder2/device_listener.h"
#include "tools/android/forwarder2/socket.h"
namespace forwarder2 {
DeviceController::DeviceController(int exit_notifier_fd)
: exit_notifier_fd_(exit_notifier_fd) {
kickstart_adb_socket_.set_exit_notifier_fd(exit_notifier_fd);
}
DeviceController::~DeviceController() {
KillAllListeners();
CleanUpDeadListeners();
CHECK_EQ(0, listeners_.size());
}
void DeviceController::CleanUpDeadListeners() {
// Clean up dead listeners.
for (ListenersMap::iterator it(&listeners_); !it.IsAtEnd(); it.Advance()) {
if (!it.GetCurrentValue()->is_alive())
// Remove deletes the listener.
listeners_.Remove(it.GetCurrentKey());
}
}
void DeviceController::KillAllListeners() {
for (ListenersMap::iterator it(&listeners_); !it.IsAtEnd(); it.Advance())
it.GetCurrentValue()->ForceExit();
for (ListenersMap::iterator it(&listeners_); !it.IsAtEnd(); it.Advance()) {
it.GetCurrentValue()->Join();
CHECK(!it.GetCurrentValue()->is_alive());
}
}
bool DeviceController::Start(const std::string& adb_unix_socket) {
if (!kickstart_adb_socket_.BindUnix(adb_unix_socket,
true /* abstract */)) {
LOG(ERROR) << "Could not BindAndListen DeviceController socket on port: "
<< adb_unix_socket;
return false;
}
while (true) {
CleanUpDeadListeners();
scoped_ptr<Socket> socket(new Socket);
if (!kickstart_adb_socket_.Accept(socket.get())) {
LOG(ERROR) << "Could not Accept DeviceController socket: "
<< safe_strerror(errno);
break;
}
// So that |socket| doesn't block on read if it has notifications.
socket->set_exit_notifier_fd(exit_notifier_fd_);
int port;
command::Type command;
if (!ReadCommand(socket.get(), &port, &command)) {
LOG(ERROR) << "Invalid command received.";
socket->Close();
continue;
}
DeviceListener* listener = listeners_.Lookup(port);
switch (command) {
case command::LISTEN: {
if (listener != NULL) {
LOG(WARNING) << "Already forwarding port " << port
<< ". Attempting to restart the listener.\n";
listener->ForceExit();
listener->Join();
CHECK(!listener->is_alive());
// Remove deletes the listener object.
listeners_.Remove(port);
}
// Listener object will be deleted by the CleanUpDeadListeners method.
DeviceListener* new_listener = new DeviceListener(socket.Pass(), port);
listeners_.AddWithID(new_listener, port);
new_listener->Start();
break;
}
case command::DATA_CONNECTION:
if (listener == NULL) {
LOG(ERROR) << "Data Connection command received, but "
<< "listener has not been set up yet for port " << port;
// After this point it is assumed that, once we close our Adb Data
// socket, the Adb forwarder command will propagate the closing of
// sockets all the way to the host side.
socket->Close();
continue;
} else if (!listener->SetAdbDataSocket(socket.Pass())) {
LOG(ERROR) << "Could not set Adb Data Socket for port: " << port;
// Same assumption as above, but in this case the socket is closed
// inside SetAdbDataSocket.
continue;
}
break;
default:
// TODO(felipeg): add a KillAllListeners command.
LOG(ERROR) << "Invalid command received. Port: " << port
<< " Command: " << command;
socket->Close();
continue;
break;
}
}
KillAllListeners();
CleanUpDeadListeners();
kickstart_adb_socket_.Close();
}
} // namespace forwarder
|