diff --git a/fastboot/fastboot.cpp b/fastboot/fastboot.cpp index 517253078..5dac3f5ff 100644 --- a/fastboot/fastboot.cpp +++ b/fastboot/fastboot.cpp @@ -342,30 +342,49 @@ struct NetworkSerial { int port; }; -static Result ParseNetworkSerial(const std::string& serial) { - const auto serial_parsed = android::base::Tokenize(serial, ":"); - const auto parsed_segments_count = serial_parsed.size(); - if (parsed_segments_count != 2 && parsed_segments_count != 3) { - return Error() << "invalid network address: " << serial << ". Expected format:\n" - << ":
: (tcp:localhost:5554)"; - } +class ParseNetworkAddressError { + public: + enum Type { WRONG_PREFIX = 1, WRONG_ADDRESS = 2 }; + ParseNetworkAddressError(Type&& type) : type_(std::forward(type)) {} + + Type value() const { return type_; } + operator Type() const { return value(); } + std::string print() const { return ""; } + + private: + Type type_; +}; + +static Result ParseNetworkSerial( + const std::string& serial) { Socket::Protocol protocol; - if (serial_parsed[0] == "tcp") { + const char* net_address = nullptr; + int port = 0; + + if (android::base::StartsWith(serial, "tcp:")) { protocol = Socket::Protocol::kTcp; - } else if (serial_parsed[0] == "udp") { + net_address = serial.c_str() + strlen("tcp:"); + port = tcp::kDefaultPort; + } else if (android::base::StartsWith(serial, "udp:")) { protocol = Socket::Protocol::kUdp; + net_address = serial.c_str() + strlen("udp:"); + port = udp::kDefaultPort; } else { - return Error() << "invalid network address: " << serial << ". Expected format:\n" - << ":
: (tcp:localhost:5554)"; + return Error(ParseNetworkAddressError::Type::WRONG_PREFIX) + << "protocol prefix ('tcp:' or 'udp:') is missed: " << serial << ". " + << "Expected address format:\n" + << ":
: (tcp:localhost:5554)"; } - int port = 5554; - if (parsed_segments_count == 3) { - android::base::ParseInt(serial_parsed[2], &port, 5554); + std::string error; + std::string host; + if (!android::base::ParseNetAddress(net_address, &host, &port, nullptr, &error)) { + return Error(ParseNetworkAddressError::Type::WRONG_ADDRESS) + << "invalid network address '" << net_address << "': " << error; } - return NetworkSerial{protocol, serial_parsed[1], port}; + return NetworkSerial{protocol, host, port}; } // Opens a new Transport connected to the particular device. @@ -380,7 +399,8 @@ static Result ParseNetworkSerial(const std::string& serial) { // object, and the caller should not attempt to delete the returned Transport. static Transport* open_device(const char* local_serial, bool wait_for_device = true, bool announce = true) { - const Result network_serial = ParseNetworkSerial(local_serial); + const Result network_serial = + ParseNetworkSerial(local_serial); Transport* transport = nullptr; while (true) { @@ -397,8 +417,12 @@ static Transport* open_device(const char* local_serial, bool wait_for_device = t if (transport == nullptr && announce) { LOG(ERROR) << "error: " << error; } - } else { + } else if (network_serial.error().code() == ParseNetworkAddressError::Type::WRONG_PREFIX) { + // WRONG_PREFIX is special because it happens when user wants to communicate with USB + // device transport = usb_open(match_fastboot(local_serial)); + } else { + Expect(network_serial); } if (transport != nullptr) { @@ -413,7 +437,7 @@ static Transport* open_device(const char* local_serial, bool wait_for_device = t announce = false; LOG(ERROR) << "< waiting for " << local_serial << ">"; } - std::this_thread::sleep_for(std::chrono::milliseconds(1)); + std::this_thread::sleep_for(std::chrono::seconds(1)); } } @@ -476,7 +500,7 @@ static Transport* open_device() { announce = false; LOG(ERROR) << "< waiting for any device >"; } - std::this_thread::sleep_for(std::chrono::milliseconds(1)); + std::this_thread::sleep_for(std::chrono::seconds(1)); } } @@ -487,7 +511,7 @@ static int Connect(int argc, char* argv[]) { } const char* local_serial = *argv; - EXPECT(ParseNetworkSerial(local_serial)); + Expect(ParseNetworkSerial(local_serial)); const Transport* transport = open_device(local_serial, false); if (transport == nullptr) { @@ -506,7 +530,7 @@ static int Connect(int argc, char* argv[]) { } static int Disconnect(const char* local_serial) { - EXPECT(ParseNetworkSerial(local_serial)); + Expect(ParseNetworkSerial(local_serial)); ConnectedDevicesStorage storage; { @@ -1557,7 +1581,7 @@ void reboot_to_userspace_fastboot() { delete old_transport; // Give the current connection time to close. - std::this_thread::sleep_for(std::chrono::milliseconds(1000)); + std::this_thread::sleep_for(std::chrono::seconds(1)); fb->set_transport(open_device()); diff --git a/fastboot/util.h b/fastboot/util.h index bc0147367..8a79e1303 100644 --- a/fastboot/util.h +++ b/fastboot/util.h @@ -18,8 +18,16 @@ using android::base::Error; using android::base::Result; using android::base::ResultError; -#define EXPECT(result) \ - (result.ok() ? result.value() : (LOG(FATAL) << result.error().message(), result.value())) +template +inline T Expect(Result r) { + if (r.ok()) { + return r.value(); + } + + LOG(FATAL) << r.error().message(); + + return r.value(); +} using SparsePtr = std::unique_ptr;