Loading adb/socket.h +9 −0 Original line number Original line Diff line number Diff line Loading @@ -114,4 +114,13 @@ asocket *create_remote_socket(unsigned id, atransport *t); void connect_to_remote(asocket *s, const char *destination); void connect_to_remote(asocket *s, const char *destination); void connect_to_smartsocket(asocket *s); void connect_to_smartsocket(asocket *s); // Internal functions that are only made available here for testing purposes. namespace internal { #if ADB_HOST char* skip_host_serial(const char* service); #endif } // namespace internal #endif // __ADB_SOCKET_H #endif // __ADB_SOCKET_H adb/socket_test.cpp +46 −0 Original line number Original line Diff line number Diff line Loading @@ -270,3 +270,49 @@ TEST_F(LocalSocketTest, close_socket_in_CLOSE_WAIT_state) { } } #endif // defined(__linux__) #endif // defined(__linux__) #if ADB_HOST // Checks that skip_host_serial(serial) returns a pointer to the part of |serial| which matches // |expected|, otherwise logs the failure to gtest. void VerifySkipHostSerial(const std::string& serial, const char* expected) { const char* result = internal::skip_host_serial(serial.c_str()); if (expected == nullptr) { EXPECT_EQ(nullptr, result); } else { EXPECT_STREQ(expected, result); } } // Check [tcp:|udp:]<serial>[:<port>]:<command> format. TEST(socket_test, test_skip_host_serial) { for (const std::string& protocol : {"", "tcp:", "udp:"}) { VerifySkipHostSerial(protocol, nullptr); VerifySkipHostSerial(protocol + "foo", nullptr); VerifySkipHostSerial(protocol + "foo:bar", ":bar"); VerifySkipHostSerial(protocol + "foo:bar:baz", ":bar:baz"); VerifySkipHostSerial(protocol + "foo:123:bar", ":bar"); VerifySkipHostSerial(protocol + "foo:123:456", ":456"); VerifySkipHostSerial(protocol + "foo:123:bar:baz", ":bar:baz"); // Don't register a port unless it's all numbers and ends with ':'. VerifySkipHostSerial(protocol + "foo:123", ":123"); VerifySkipHostSerial(protocol + "foo:123bar:baz", ":123bar:baz"); } } // Check <prefix>:<serial>:<command> format. TEST(socket_test, test_skip_host_serial_prefix) { for (const std::string& prefix : {"usb:", "product:", "model:", "device:"}) { VerifySkipHostSerial(prefix, nullptr); VerifySkipHostSerial(prefix + "foo", nullptr); VerifySkipHostSerial(prefix + "foo:bar", ":bar"); VerifySkipHostSerial(prefix + "foo:bar:baz", ":bar:baz"); VerifySkipHostSerial(prefix + "foo:123:bar", ":123:bar"); } } #endif // ADB_HOST adb/sockets.cpp +33 −29 Original line number Original line Diff line number Diff line Loading @@ -26,6 +26,8 @@ #include <unistd.h> #include <unistd.h> #include <algorithm> #include <algorithm> #include <string> #include <vector> #if !ADB_HOST #if !ADB_HOST #include "cutils/properties.h" #include "cutils/properties.h" Loading Loading @@ -623,43 +625,43 @@ static unsigned unhex(unsigned char *s, int len) #if ADB_HOST #if ADB_HOST #define PREFIX(str) { str, sizeof(str) - 1 } namespace internal { static const struct prefix_struct { const char *str; // Returns the position in |service| following the target serial parameter. Serial format can be const size_t len; // any of: } prefixes[] = { // * [tcp:|udp:]<serial>[:<port>]:<command> PREFIX("usb:"), // * <prefix>:<serial>:<command> PREFIX("product:"), // Where <port> must be a base-10 number and <prefix> may be any of {usb,product,model,device}. PREFIX("model:"), // PREFIX("device:"), // The returned pointer will point to the ':' just before <command>, or nullptr if not found. }; char* skip_host_serial(const char* service) { static const int num_prefixes = (sizeof(prefixes) / sizeof(prefixes[0])); static const std::vector<std::string>& prefixes = *(new std::vector<std::string>{"usb:", "product:", "model:", "device:"}); /* skip_host_serial return the position in a string for (const std::string& prefix : prefixes) { skipping over the 'serial' parameter in the ADB protocol, if (!strncmp(service, prefix.c_str(), prefix.length())) { where parameter string may be a host:port string containing return strchr(service + prefix.length(), ':'); the protocol delimiter (colon). */ } static char *skip_host_serial(char *service) { } char *first_colon, *serial_end; int i; for (i = 0; i < num_prefixes; i++) { // For fastboot compatibility, ignore protocol prefixes. if (!strncmp(service, prefixes[i].str, prefixes[i].len)) if (!strncmp(service, "tcp:", 4) || !strncmp(service, "udp:", 4)) { return strchr(service + prefixes[i].len, ':'); service += 4; } } first_colon = strchr(service, ':'); char* first_colon = strchr(service, ':'); if (!first_colon) { if (!first_colon) { /* No colon in service string. */ // No colon in service string. return NULL; return nullptr; } } serial_end = first_colon; char* serial_end = first_colon; if (isdigit(serial_end[1])) { if (isdigit(serial_end[1])) { serial_end++; serial_end++; while ((*serial_end) && isdigit(*serial_end)) { while (*serial_end && isdigit(*serial_end)) { serial_end++; serial_end++; } } if ((*serial_end) != ':') { if (*serial_end != ':') { // Something other than numbers was found, reset the end. // Something other than numbers was found, reset the end. serial_end = first_colon; serial_end = first_colon; } } Loading @@ -667,6 +669,8 @@ static char *skip_host_serial(char *service) { return serial_end; return serial_end; } } } // namespace internal #endif // ADB_HOST #endif // ADB_HOST static int smart_socket_enqueue(asocket *s, apacket *p) static int smart_socket_enqueue(asocket *s, apacket *p) Loading Loading @@ -725,7 +729,7 @@ static int smart_socket_enqueue(asocket *s, apacket *p) service += strlen("host-serial:"); service += strlen("host-serial:"); // serial number should follow "host:" and could be a host:port string. // serial number should follow "host:" and could be a host:port string. serial_end = skip_host_serial(service); serial_end = internal::skip_host_serial(service); if (serial_end) { if (serial_end) { *serial_end = 0; // terminate string *serial_end = 0; // terminate string serial = service; serial = service; Loading adb/transport.cpp +39 −5 Original line number Original line Diff line number Diff line Loading @@ -30,6 +30,7 @@ #include <list> #include <list> #include <android-base/logging.h> #include <android-base/logging.h> #include <android-base/parsenetaddress.h> #include <android-base/stringprintf.h> #include <android-base/stringprintf.h> #include <android-base/strings.h> #include <android-base/strings.h> Loading Loading @@ -679,11 +680,7 @@ atransport* acquire_one_transport(TransportType type, const char* serial, // Check for matching serial number. // Check for matching serial number. if (serial) { if (serial) { if ((t->serial && !strcmp(serial, t->serial)) || if (t->MatchesTarget(serial)) { (t->devpath && !strcmp(serial, t->devpath)) || qual_match(serial, "product:", t->product, false) || qual_match(serial, "model:", t->model, true) || qual_match(serial, "device:", t->device, false)) { if (result) { if (result) { *error_out = "more than one device"; *error_out = "more than one device"; if (is_ambiguous) *is_ambiguous = true; if (is_ambiguous) *is_ambiguous = true; Loading Loading @@ -837,6 +834,43 @@ void atransport::RunDisconnects() { disconnects_.clear(); disconnects_.clear(); } } bool atransport::MatchesTarget(const std::string& target) const { if (serial) { if (target == serial) { return true; } else if (type == kTransportLocal) { // Local transports can match [tcp:|udp:]<hostname>[:port]. const char* local_target_ptr = target.c_str(); // For fastboot compatibility, ignore protocol prefixes. if (android::base::StartsWith(target, "tcp:") || android::base::StartsWith(target, "udp:")) { local_target_ptr += 4; } // Parse our |serial| and the given |target| to check if the hostnames and ports match. std::string serial_host, error; int serial_port = -1; if (android::base::ParseNetAddress(serial, &serial_host, &serial_port, nullptr, &error)) { // |target| may omit the port to default to ours. std::string target_host; int target_port = serial_port; if (android::base::ParseNetAddress(local_target_ptr, &target_host, &target_port, nullptr, &error) && serial_host == target_host && serial_port == target_port) { return true; } } } } return (devpath && target == devpath) || qual_match(target.c_str(), "product:", product, false) || qual_match(target.c_str(), "model:", model, true) || qual_match(target.c_str(), "device:", device, false); } #if ADB_HOST #if ADB_HOST static void append_transport_info(std::string* result, const char* key, static void append_transport_info(std::string* result, const char* key, Loading adb/transport.h +15 −0 Original line number Original line Diff line number Diff line Loading @@ -107,6 +107,21 @@ public: void RemoveDisconnect(adisconnect* disconnect); void RemoveDisconnect(adisconnect* disconnect); void RunDisconnects(); void RunDisconnects(); // Returns true if |target| matches this transport. A matching |target| can be any of: // * <serial> // * <devpath> // * product:<product> // * model:<model> // * device:<device> // // If this is a local transport, serial will also match [tcp:|udp:]<hostname>[:port] targets. // For example, serial "100.100.100.100:5555" would match any of: // * 100.100.100.100 // * tcp:100.100.100.100 // * udp:100.100.100.100:5555 // This is to make it easier to use the same network target for both fastboot and adb. bool MatchesTarget(const std::string& target) const; private: private: // A set of features transmitted in the banner with the initial connection. // A set of features transmitted in the banner with the initial connection. // This is stored in the banner as 'features=feature0,feature1,etc'. // This is stored in the banner as 'features=feature0,feature1,etc'. Loading Loading
adb/socket.h +9 −0 Original line number Original line Diff line number Diff line Loading @@ -114,4 +114,13 @@ asocket *create_remote_socket(unsigned id, atransport *t); void connect_to_remote(asocket *s, const char *destination); void connect_to_remote(asocket *s, const char *destination); void connect_to_smartsocket(asocket *s); void connect_to_smartsocket(asocket *s); // Internal functions that are only made available here for testing purposes. namespace internal { #if ADB_HOST char* skip_host_serial(const char* service); #endif } // namespace internal #endif // __ADB_SOCKET_H #endif // __ADB_SOCKET_H
adb/socket_test.cpp +46 −0 Original line number Original line Diff line number Diff line Loading @@ -270,3 +270,49 @@ TEST_F(LocalSocketTest, close_socket_in_CLOSE_WAIT_state) { } } #endif // defined(__linux__) #endif // defined(__linux__) #if ADB_HOST // Checks that skip_host_serial(serial) returns a pointer to the part of |serial| which matches // |expected|, otherwise logs the failure to gtest. void VerifySkipHostSerial(const std::string& serial, const char* expected) { const char* result = internal::skip_host_serial(serial.c_str()); if (expected == nullptr) { EXPECT_EQ(nullptr, result); } else { EXPECT_STREQ(expected, result); } } // Check [tcp:|udp:]<serial>[:<port>]:<command> format. TEST(socket_test, test_skip_host_serial) { for (const std::string& protocol : {"", "tcp:", "udp:"}) { VerifySkipHostSerial(protocol, nullptr); VerifySkipHostSerial(protocol + "foo", nullptr); VerifySkipHostSerial(protocol + "foo:bar", ":bar"); VerifySkipHostSerial(protocol + "foo:bar:baz", ":bar:baz"); VerifySkipHostSerial(protocol + "foo:123:bar", ":bar"); VerifySkipHostSerial(protocol + "foo:123:456", ":456"); VerifySkipHostSerial(protocol + "foo:123:bar:baz", ":bar:baz"); // Don't register a port unless it's all numbers and ends with ':'. VerifySkipHostSerial(protocol + "foo:123", ":123"); VerifySkipHostSerial(protocol + "foo:123bar:baz", ":123bar:baz"); } } // Check <prefix>:<serial>:<command> format. TEST(socket_test, test_skip_host_serial_prefix) { for (const std::string& prefix : {"usb:", "product:", "model:", "device:"}) { VerifySkipHostSerial(prefix, nullptr); VerifySkipHostSerial(prefix + "foo", nullptr); VerifySkipHostSerial(prefix + "foo:bar", ":bar"); VerifySkipHostSerial(prefix + "foo:bar:baz", ":bar:baz"); VerifySkipHostSerial(prefix + "foo:123:bar", ":123:bar"); } } #endif // ADB_HOST
adb/sockets.cpp +33 −29 Original line number Original line Diff line number Diff line Loading @@ -26,6 +26,8 @@ #include <unistd.h> #include <unistd.h> #include <algorithm> #include <algorithm> #include <string> #include <vector> #if !ADB_HOST #if !ADB_HOST #include "cutils/properties.h" #include "cutils/properties.h" Loading Loading @@ -623,43 +625,43 @@ static unsigned unhex(unsigned char *s, int len) #if ADB_HOST #if ADB_HOST #define PREFIX(str) { str, sizeof(str) - 1 } namespace internal { static const struct prefix_struct { const char *str; // Returns the position in |service| following the target serial parameter. Serial format can be const size_t len; // any of: } prefixes[] = { // * [tcp:|udp:]<serial>[:<port>]:<command> PREFIX("usb:"), // * <prefix>:<serial>:<command> PREFIX("product:"), // Where <port> must be a base-10 number and <prefix> may be any of {usb,product,model,device}. PREFIX("model:"), // PREFIX("device:"), // The returned pointer will point to the ':' just before <command>, or nullptr if not found. }; char* skip_host_serial(const char* service) { static const int num_prefixes = (sizeof(prefixes) / sizeof(prefixes[0])); static const std::vector<std::string>& prefixes = *(new std::vector<std::string>{"usb:", "product:", "model:", "device:"}); /* skip_host_serial return the position in a string for (const std::string& prefix : prefixes) { skipping over the 'serial' parameter in the ADB protocol, if (!strncmp(service, prefix.c_str(), prefix.length())) { where parameter string may be a host:port string containing return strchr(service + prefix.length(), ':'); the protocol delimiter (colon). */ } static char *skip_host_serial(char *service) { } char *first_colon, *serial_end; int i; for (i = 0; i < num_prefixes; i++) { // For fastboot compatibility, ignore protocol prefixes. if (!strncmp(service, prefixes[i].str, prefixes[i].len)) if (!strncmp(service, "tcp:", 4) || !strncmp(service, "udp:", 4)) { return strchr(service + prefixes[i].len, ':'); service += 4; } } first_colon = strchr(service, ':'); char* first_colon = strchr(service, ':'); if (!first_colon) { if (!first_colon) { /* No colon in service string. */ // No colon in service string. return NULL; return nullptr; } } serial_end = first_colon; char* serial_end = first_colon; if (isdigit(serial_end[1])) { if (isdigit(serial_end[1])) { serial_end++; serial_end++; while ((*serial_end) && isdigit(*serial_end)) { while (*serial_end && isdigit(*serial_end)) { serial_end++; serial_end++; } } if ((*serial_end) != ':') { if (*serial_end != ':') { // Something other than numbers was found, reset the end. // Something other than numbers was found, reset the end. serial_end = first_colon; serial_end = first_colon; } } Loading @@ -667,6 +669,8 @@ static char *skip_host_serial(char *service) { return serial_end; return serial_end; } } } // namespace internal #endif // ADB_HOST #endif // ADB_HOST static int smart_socket_enqueue(asocket *s, apacket *p) static int smart_socket_enqueue(asocket *s, apacket *p) Loading Loading @@ -725,7 +729,7 @@ static int smart_socket_enqueue(asocket *s, apacket *p) service += strlen("host-serial:"); service += strlen("host-serial:"); // serial number should follow "host:" and could be a host:port string. // serial number should follow "host:" and could be a host:port string. serial_end = skip_host_serial(service); serial_end = internal::skip_host_serial(service); if (serial_end) { if (serial_end) { *serial_end = 0; // terminate string *serial_end = 0; // terminate string serial = service; serial = service; Loading
adb/transport.cpp +39 −5 Original line number Original line Diff line number Diff line Loading @@ -30,6 +30,7 @@ #include <list> #include <list> #include <android-base/logging.h> #include <android-base/logging.h> #include <android-base/parsenetaddress.h> #include <android-base/stringprintf.h> #include <android-base/stringprintf.h> #include <android-base/strings.h> #include <android-base/strings.h> Loading Loading @@ -679,11 +680,7 @@ atransport* acquire_one_transport(TransportType type, const char* serial, // Check for matching serial number. // Check for matching serial number. if (serial) { if (serial) { if ((t->serial && !strcmp(serial, t->serial)) || if (t->MatchesTarget(serial)) { (t->devpath && !strcmp(serial, t->devpath)) || qual_match(serial, "product:", t->product, false) || qual_match(serial, "model:", t->model, true) || qual_match(serial, "device:", t->device, false)) { if (result) { if (result) { *error_out = "more than one device"; *error_out = "more than one device"; if (is_ambiguous) *is_ambiguous = true; if (is_ambiguous) *is_ambiguous = true; Loading Loading @@ -837,6 +834,43 @@ void atransport::RunDisconnects() { disconnects_.clear(); disconnects_.clear(); } } bool atransport::MatchesTarget(const std::string& target) const { if (serial) { if (target == serial) { return true; } else if (type == kTransportLocal) { // Local transports can match [tcp:|udp:]<hostname>[:port]. const char* local_target_ptr = target.c_str(); // For fastboot compatibility, ignore protocol prefixes. if (android::base::StartsWith(target, "tcp:") || android::base::StartsWith(target, "udp:")) { local_target_ptr += 4; } // Parse our |serial| and the given |target| to check if the hostnames and ports match. std::string serial_host, error; int serial_port = -1; if (android::base::ParseNetAddress(serial, &serial_host, &serial_port, nullptr, &error)) { // |target| may omit the port to default to ours. std::string target_host; int target_port = serial_port; if (android::base::ParseNetAddress(local_target_ptr, &target_host, &target_port, nullptr, &error) && serial_host == target_host && serial_port == target_port) { return true; } } } } return (devpath && target == devpath) || qual_match(target.c_str(), "product:", product, false) || qual_match(target.c_str(), "model:", model, true) || qual_match(target.c_str(), "device:", device, false); } #if ADB_HOST #if ADB_HOST static void append_transport_info(std::string* result, const char* key, static void append_transport_info(std::string* result, const char* key, Loading
adb/transport.h +15 −0 Original line number Original line Diff line number Diff line Loading @@ -107,6 +107,21 @@ public: void RemoveDisconnect(adisconnect* disconnect); void RemoveDisconnect(adisconnect* disconnect); void RunDisconnects(); void RunDisconnects(); // Returns true if |target| matches this transport. A matching |target| can be any of: // * <serial> // * <devpath> // * product:<product> // * model:<model> // * device:<device> // // If this is a local transport, serial will also match [tcp:|udp:]<hostname>[:port] targets. // For example, serial "100.100.100.100:5555" would match any of: // * 100.100.100.100 // * tcp:100.100.100.100 // * udp:100.100.100.100:5555 // This is to make it easier to use the same network target for both fastboot and adb. bool MatchesTarget(const std::string& target) const; private: private: // A set of features transmitted in the banner with the initial connection. // A set of features transmitted in the banner with the initial connection. // This is stored in the banner as 'features=feature0,feature1,etc'. // This is stored in the banner as 'features=feature0,feature1,etc'. Loading