diff --git a/adb/transport.cpp b/adb/transport.cpp index 332e0f83a818f107d04ffb25b3d210c118b38ada..239403a83f19ac40a7b270babfc19b92479eb919 100644 --- a/adb/transport.cpp +++ b/adb/transport.cpp @@ -220,25 +220,34 @@ void ReconnectHandler::Run() { } D("attempting to reconnect %s", attempt.transport->serial.c_str()); - if (!attempt.transport->Reconnect()) { - D("attempting to reconnect %s failed.", attempt.transport->serial.c_str()); - if (attempt.attempts_left == 0) { - D("transport %s exceeded the number of retry attempts. giving up on it.", - attempt.transport->serial.c_str()); - remove_transport(attempt.transport); + switch (attempt.transport->Reconnect()) { + case ReconnectResult::Retry: { + D("attempting to reconnect %s failed.", attempt.transport->serial.c_str()); + if (attempt.attempts_left == 0) { + D("transport %s exceeded the number of retry attempts. giving up on it.", + attempt.transport->serial.c_str()); + remove_transport(attempt.transport); + continue; + } + + std::lock_guard<std::mutex> lock(reconnect_mutex_); + reconnect_queue_.emplace(ReconnectAttempt{ + attempt.transport, + std::chrono::steady_clock::now() + ReconnectHandler::kDefaultTimeout, + attempt.attempts_left - 1}); continue; } - std::lock_guard<std::mutex> lock(reconnect_mutex_); - reconnect_queue_.emplace(ReconnectAttempt{ - attempt.transport, - std::chrono::steady_clock::now() + ReconnectHandler::kDefaultTimeout, - attempt.attempts_left - 1}); - continue; - } + case ReconnectResult::Success: + D("reconnection to %s succeeded.", attempt.transport->serial.c_str()); + register_transport(attempt.transport); + continue; - D("reconnection to %s succeeded.", attempt.transport->serial.c_str()); - register_transport(attempt.transport); + case ReconnectResult::Abort: + D("cancelling reconnection attempt to %s.", attempt.transport->serial.c_str()); + remove_transport(attempt.transport); + continue; + } } } @@ -1128,7 +1137,7 @@ void atransport::SetConnectionEstablished(bool success) { connection_waitable_->SetConnectionEstablished(success); } -bool atransport::Reconnect() { +ReconnectResult atransport::Reconnect() { return reconnect_(this); } diff --git a/adb/transport.h b/adb/transport.h index f362f241ea87c70224f040677056a5db2acf4c3a..f854ce5c2f8743534632a9282d987992014b07b0 100644 --- a/adb/transport.h +++ b/adb/transport.h @@ -193,6 +193,12 @@ class ConnectionWaitable { DISALLOW_COPY_AND_ASSIGN(ConnectionWaitable); }; +enum class ReconnectResult { + Retry, + Success, + Abort, +}; + class atransport { public: // TODO(danalbert): We expose waaaaaaay too much stuff because this was @@ -200,7 +206,7 @@ class atransport { // class in one go is a very large change. Given how bad our testing is, // it's better to do this piece by piece. - using ReconnectCallback = std::function<bool(atransport*)>; + using ReconnectCallback = std::function<ReconnectResult(atransport*)>; atransport(ReconnectCallback reconnect, ConnectionState state) : id(NextTransportId()), @@ -215,7 +221,7 @@ class atransport { max_payload = MAX_PAYLOAD; } atransport(ConnectionState state = kCsOffline) - : atransport([](atransport*) { return false; }, state) {} + : atransport([](atransport*) { return ReconnectResult::Abort; }, state) {} virtual ~atransport(); int Write(apacket* p); @@ -295,9 +301,8 @@ class atransport { // Gets a shared reference to the ConnectionWaitable. std::shared_ptr<ConnectionWaitable> connection_waitable() { return connection_waitable_; } - // Attempts to reconnect with the underlying Connection. Returns true if the - // reconnection attempt succeeded. - bool Reconnect(); + // Attempts to reconnect with the underlying Connection. + ReconnectResult Reconnect(); private: std::atomic<bool> kicked_; diff --git a/adb/transport_local.cpp b/adb/transport_local.cpp index 143125289655a631961c3bad6ff37a2f035bd62d..4477aef4c27f22e20a05fa58eb5b898a706e3154 100644 --- a/adb/transport_local.cpp +++ b/adb/transport_local.cpp @@ -115,14 +115,15 @@ void connect_device(const std::string& address, std::string* response) { std::tie(fd, port, serial) = tcp_connect(address, &response); if (fd == -1) { D("reconnect failed: %s", response.c_str()); - return false; + return ReconnectResult::Retry; } // This invokes the part of register_socket_transport() that needs to be // invoked if the atransport* has already been setup. This eventually // calls atransport->SetConnection() with a newly created Connection* // that will in turn send the CNXN packet. - return init_socket_transport(t, std::move(fd), port, 0) >= 0; + return init_socket_transport(t, std::move(fd), port, 0) >= 0 ? ReconnectResult::Success + : ReconnectResult::Retry; }; int error; @@ -164,7 +165,7 @@ int local_connect_arbitrary_ports(int console_port, int adb_port, std::string* e disable_tcp_nagle(fd.get()); std::string serial = getEmulatorSerialString(console_port); if (register_socket_transport(std::move(fd), std::move(serial), adb_port, 1, - [](atransport*) { return false; })) { + [](atransport*) { return ReconnectResult::Abort; })) { return 0; } } @@ -267,7 +268,7 @@ static void server_socket_thread(int port) { disable_tcp_nagle(fd.get()); std::string serial = android::base::StringPrintf("host-%d", fd.get()); register_socket_transport(std::move(fd), std::move(serial), port, 1, - [](atransport*) { return false; }); + [](atransport*) { return ReconnectResult::Abort; }); } } D("transport: server_socket_thread() exiting"); @@ -364,7 +365,7 @@ static void qemu_socket_thread(int port) { std::string serial = android::base::StringPrintf("host-%d", fd.get()); WriteFdExactly(fd.get(), _start_req, strlen(_start_req)); register_socket_transport(std::move(fd), std::move(serial), port, 1, - [](atransport*) { return false; }); + [](atransport*) { return ReconnectResult::Abort; }); } /* Prepare for accepting of the next ADB host connection. */