Loading adb/Android.mk +1 −1 Original line number Diff line number Diff line Loading @@ -16,6 +16,7 @@ adb_version := $(shell git -C $(LOCAL_PATH) rev-parse --short=12 HEAD 2>/dev/nul ADB_COMMON_CFLAGS := \ -Wall -Wextra -Werror \ -Wno-unused-parameter \ -Wno-missing-field-initializers \ -DADB_REVISION='"$(adb_version)"' \ # libadb Loading Loading @@ -45,7 +46,6 @@ LIBADB_TEST_SRCS := \ LIBADB_CFLAGS := \ $(ADB_COMMON_CFLAGS) \ -Wno-missing-field-initializers \ -fvisibility=hidden \ LIBADB_darwin_SRC_FILES := \ Loading adb/adb.h +62 −49 Original line number Diff line number Diff line Loading @@ -20,6 +20,8 @@ #include <limits.h> #include <sys/types.h> #include <base/macros.h> #include "adb_trace.h" #include "fdevent.h" Loading @@ -43,7 +45,7 @@ // Increment this when we want to force users to start a new adb server. #define ADB_SERVER_VERSION 32 struct atransport; class atransport; struct usb_handle; struct amessage { Loading Loading @@ -152,15 +154,14 @@ struct adisconnect }; /* a transport object models the connection to a remote device or emulator ** there is one transport per connected device/emulator. a "local transport" ** connects through TCP (for the emulator), while a "usb transport" through ** USB (for real devices) ** ** note that kTransportHost doesn't really correspond to a real transport ** object, it's a special value used to indicate that a client wants to ** connect to a service implemented within the ADB server itself. */ // A transport object models the connection to a remote device or emulator there // is one transport per connected device/emulator. A "local transport" connects // through TCP (for the emulator), while a "usb transport" through USB (for real // devices). // // Note that kTransportHost doesn't really correspond to a real transport // object, it's a special value used to indicate that a client wants to connect // to a service implemented within the ADB server itself. enum TransportType { kTransportUsb, kTransportLocal, Loading @@ -182,47 +183,59 @@ enum ConnectionState { kCsUnauthorized, }; struct atransport { atransport *next; atransport *prev; class atransport { public: // TODO(danalbert): We expose waaaaaaay too much stuff because this was // historically just a struct, but making the whole thing a more idiomatic // class in one go is a very large change. Given how bad our testing is, // it's better to do this piece by piece. int (*read_from_remote)(apacket *p, atransport *t); int (*write_to_remote)(apacket *p, atransport *t); void (*close)(atransport *t); void (*kick)(atransport *t); atransport() { auth_fde = {}; transport_fde = {}; } int fd; int transport_socket; virtual ~atransport() {} int (*read_from_remote)(apacket* p, atransport* t) = nullptr; int (*write_to_remote)(apacket* p, atransport* t) = nullptr; void (*close)(atransport* t) = nullptr; void (*kick)(atransport* t) = nullptr; int fd = -1; int transport_socket = -1; fdevent transport_fde; int ref_count; unsigned sync_token; int connection_state; int online; TransportType type; /* usb handle or socket fd as needed */ usb_handle *usb; int sfd; /* used to identify transports for clients */ char *serial; char *product; char *model; char *device; char *devpath; int adb_port; // Use for emulators (local transport) /* a list of adisconnect callbacks called when the transport is kicked */ int kicked; adisconnect disconnects; void *key; unsigned char token[TOKEN_SIZE]; int ref_count = 0; uint32_t sync_token = 0; ConnectionState connection_state = kCsOffline; bool online = false; TransportType type = kTransportAny; // USB handle or socket fd as needed. usb_handle* usb = nullptr; int sfd = -1; // Used to identify transports for clients. char* serial = nullptr; char* product = nullptr; char* model = nullptr; char* device = nullptr; char* devpath = nullptr; int adb_port = -1; // Use for emulators (local transport) bool kicked = false; // A list of adisconnect callbacks called when the transport is kicked. adisconnect disconnects = {}; void* key = nullptr; unsigned char token[TOKEN_SIZE] = {}; fdevent auth_fde; unsigned failed_auth_attempts; size_t failed_auth_attempts = 0; const char* connection_state_name() const; private: DISALLOW_COPY_AND_ASSIGN(atransport); }; Loading adb/transport.cpp +60 −94 Original line number Diff line number Diff line Loading @@ -26,6 +26,8 @@ #include <string.h> #include <unistd.h> #include <list> #include <base/stringprintf.h> #include "adb.h" Loading @@ -33,15 +35,8 @@ static void transport_unref(atransport *t); static atransport transport_list = { .next = &transport_list, .prev = &transport_list, }; static atransport pending_list = { .next = &pending_list, .prev = &pending_list, }; static std::list<atransport*> transport_list; static std::list<atransport*> pending_list; ADB_MUTEX_DEFINE( transport_lock ); Loading Loading @@ -553,8 +548,7 @@ static void transport_registration_func(int _fd, unsigned ev, void *data) adb_close(t->fd); adb_mutex_lock(&transport_lock); t->next->prev = t->prev; t->prev->next = t->next; transport_list.remove(t); adb_mutex_unlock(&transport_lock); run_transport_disconnects(t); Loading @@ -570,8 +564,7 @@ static void transport_registration_func(int _fd, unsigned ev, void *data) if (t->devpath) free(t->devpath); memset(t,0xee,sizeof(atransport)); free(t); delete t; update_transports(); return; Loading Loading @@ -608,14 +601,8 @@ static void transport_registration_func(int _fd, unsigned ev, void *data) } adb_mutex_lock(&transport_lock); /* remove from pending list */ t->next->prev = t->prev; t->prev->next = t->next; /* put us on the master device list */ t->next = &transport_list; t->prev = transport_list.prev; t->next->prev = t; t->prev->next = t; pending_list.remove(t); transport_list.push_front(t); adb_mutex_unlock(&transport_lock); t->disconnects.next = t->disconnects.prev = &t->disconnects; Loading Loading @@ -740,7 +727,6 @@ static int qual_match(const char *to_test, atransport* acquire_one_transport(ConnectionState state, TransportType type, const char* serial, std::string* error_out) { atransport *t; atransport *result = NULL; int ambiguous = 0; Loading @@ -748,7 +734,7 @@ retry: if (error_out) *error_out = android::base::StringPrintf("device '%s' not found", serial); adb_mutex_lock(&transport_lock); for (t = transport_list.next; t != &transport_list; t = t->next) { for (auto t : transport_list) { if (t->connection_state == kCsNoPerm) { if (error_out) *error_out = "insufficient permissions for device"; continue; Loading Loading @@ -866,7 +852,8 @@ static void append_transport_info(std::string* result, const char* key, } } static void append_transport(atransport* t, std::string* result, bool long_listing) { static void append_transport(const atransport* t, std::string* result, bool long_listing) { const char* serial = t->serial; if (!serial || !serial[0]) { serial = "(no serial number)"; Loading @@ -890,7 +877,7 @@ static void append_transport(atransport* t, std::string* result, bool long_listi std::string list_transports(bool long_listing) { std::string result; adb_mutex_lock(&transport_lock); for (atransport* t = transport_list.next; t != &transport_list; t = t->next) { for (const auto t : transport_list) { append_transport(t, &result, long_listing); } adb_mutex_unlock(&transport_lock); Loading @@ -898,10 +885,9 @@ std::string list_transports(bool long_listing) { } /* hack for osx */ void close_usb_devices() { void close_usb_devices() { adb_mutex_lock(&transport_lock); for (atransport* t = transport_list.next; t != &transport_list; t = t->next) { for (auto t : transport_list) { if (!t->kicked) { t->kicked = 1; t->kick(t); Loading @@ -911,47 +897,39 @@ void close_usb_devices() } #endif // ADB_HOST int register_socket_transport(int s, const char *serial, int port, int local) { atransport *t = reinterpret_cast<atransport*>(calloc(1, sizeof(atransport))); if (t == nullptr) { return -1; } atransport *n; char buff[32]; int register_socket_transport(int s, const char *serial, int port, int local) { atransport* t = new atransport(); if (!serial) { snprintf(buff, sizeof buff, "T-%p", t); serial = buff; char buf[32]; snprintf(buf, sizeof(buf), "T-%p", t); serial = buf; } D("transport: %s init'ing for socket %d, on port %d\n", serial, s, port); if (init_socket_transport(t, s, port, local) < 0) { free(t); delete t; return -1; } adb_mutex_lock(&transport_lock); for (n = pending_list.next; n != &pending_list; n = n->next) { if (n->serial && !strcmp(serial, n->serial)) { for (auto transport : pending_list) { if (transport->serial && strcmp(serial, transport->serial) == 0) { adb_mutex_unlock(&transport_lock); free(t); delete t; return -1; } } for (n = transport_list.next; n != &transport_list; n = n->next) { if (n->serial && !strcmp(serial, n->serial)) { for (auto transport : transport_list) { if (transport->serial && strcmp(serial, transport->serial) == 0) { adb_mutex_unlock(&transport_lock); free(t); delete t; return -1; } } t->next = &pending_list; t->prev = pending_list.prev; t->next->prev = t; t->prev->next = t; pending_list.push_front(t); t->serial = strdup(serial); adb_mutex_unlock(&transport_lock); Loading @@ -960,52 +938,47 @@ int register_socket_transport(int s, const char *serial, int port, int local) } #if ADB_HOST atransport *find_transport(const char *serial) { atransport *t; atransport *find_transport(const char *serial) { atransport* result = nullptr; adb_mutex_lock(&transport_lock); for(t = transport_list.next; t != &transport_list; t = t->next) { if (t->serial && !strcmp(serial, t->serial)) { for (auto t : transport_list) { if (t->serial && strcmp(serial, t->serial) == 0) { result = t; break; } } adb_mutex_unlock(&transport_lock); if (t != &transport_list) return t; else return 0; return result; } void unregister_transport(atransport *t) { adb_mutex_lock(&transport_lock); t->next->prev = t->prev; t->prev->next = t->next; transport_list.remove(t); adb_mutex_unlock(&transport_lock); kick_transport(t); transport_unref(t); } // unregisters all non-emulator TCP transports void unregister_all_tcp_transports() { atransport *t, *next; // Unregisters all non-emulator TCP transports. void unregister_all_tcp_transports() { adb_mutex_lock(&transport_lock); for (t = transport_list.next; t != &transport_list; t = next) { next = t->next; for (auto it = transport_list.begin(); it != transport_list.end(); ) { atransport* t = *it; if (t->type == kTransportLocal && t->adb_port == 0) { t->next->prev = t->prev; t->prev->next = next; // we cannot call kick_transport when holding transport_lock if (!t->kicked) { // We cannot call kick_transport when holding transport_lock. if (!t->kicked) { t->kicked = 1; t->kick(t); } transport_unref_locked(t); it = transport_list.erase(it); } else { ++it; } } Loading @@ -1014,25 +987,23 @@ void unregister_all_tcp_transports() #endif void register_usb_transport(usb_handle *usb, const char *serial, const char *devpath, unsigned writeable) { atransport *t = reinterpret_cast<atransport*>(calloc(1, sizeof(atransport))); if (t == nullptr) fatal("cannot allocate USB atransport"); void register_usb_transport(usb_handle* usb, const char* serial, const char* devpath, unsigned writeable) { atransport* t = new atransport(); D("transport: %p init'ing for usb_handle %p (sn='%s')\n", t, usb, serial ? serial : ""); init_usb_transport(t, usb, (writeable ? kCsOffline : kCsNoPerm)); if(serial) { t->serial = strdup(serial); } if (devpath) { t->devpath = strdup(devpath); } adb_mutex_lock(&transport_lock); t->next = &pending_list; t->prev = pending_list.prev; t->next->prev = t; t->prev->next = t; pending_list.push_front(t); adb_mutex_unlock(&transport_lock); register_transport(t); Loading @@ -1041,14 +1012,9 @@ void register_usb_transport(usb_handle *usb, const char *serial, const char *dev // This should only be used for transports with connection_state == kCsNoPerm. void unregister_usb_transport(usb_handle *usb) { adb_mutex_lock(&transport_lock); for (atransport* t = transport_list.next; t != &transport_list; t = t->next) { if (t->usb == usb && t->connection_state == kCsNoPerm) { t->next->prev = t->prev; t->prev->next = t->next; break; } } transport_list.remove_if([usb](atransport* t) { return t->usb == usb && t->connection_state == kCsNoPerm; }); adb_mutex_unlock(&transport_lock); } Loading adb/transport_test.cpp +58 −7 Original line number Diff line number Diff line Loading @@ -20,34 +20,85 @@ #include "adb.h" class TestTransport : public atransport { public: bool operator==(const atransport& rhs) const { EXPECT_EQ(read_from_remote, rhs.read_from_remote); EXPECT_EQ(write_to_remote, rhs.write_to_remote); EXPECT_EQ(close, rhs.close); EXPECT_EQ(kick, rhs.kick); EXPECT_EQ(fd, rhs.fd); EXPECT_EQ(transport_socket, rhs.transport_socket); EXPECT_EQ( 0, memcmp(&transport_fde, &rhs.transport_fde, sizeof(fdevent))); EXPECT_EQ(ref_count, rhs.ref_count); EXPECT_EQ(sync_token, rhs.sync_token); EXPECT_EQ(connection_state, rhs.connection_state); EXPECT_EQ(online, rhs.online); EXPECT_EQ(type, rhs.type); EXPECT_EQ(usb, rhs.usb); EXPECT_EQ(sfd, rhs.sfd); EXPECT_EQ(serial, rhs.serial); EXPECT_EQ(product, rhs.product); EXPECT_EQ(model, rhs.model); EXPECT_EQ(device, rhs.device); EXPECT_EQ(devpath, rhs.devpath); EXPECT_EQ(adb_port, rhs.adb_port); EXPECT_EQ(kicked, rhs.kicked); EXPECT_EQ( 0, memcmp(&disconnects, &rhs.disconnects, sizeof(adisconnect))); EXPECT_EQ(key, rhs.key); EXPECT_EQ(0, memcmp(token, rhs.token, TOKEN_SIZE)); EXPECT_EQ(0, memcmp(&auth_fde, &rhs.auth_fde, sizeof(fdevent))); EXPECT_EQ(failed_auth_attempts, rhs.failed_auth_attempts); return true; } }; TEST(transport, kick_transport) { atransport t = {}; TestTransport t; // Mutate some member so we can test that the function is run. t.kick = [](atransport* trans) { trans->fd = 42; }; atransport expected = t; TestTransport expected; expected.kick = t.kick; expected.fd = 42; expected.kicked = 1; kick_transport(&t); ASSERT_EQ(42, t.fd); ASSERT_EQ(1, t.kicked); ASSERT_EQ(0, memcmp(&expected, &t, sizeof(atransport))); ASSERT_EQ(expected, t); } TEST(transport, kick_transport_already_kicked) { // Ensure that the transport is not modified if the transport has already been // kicked. atransport t = {}; TestTransport t; t.kicked = 1; t.kick = [](atransport*) { FAIL() << "Kick should not have been called"; }; atransport expected = t; TestTransport expected; expected.kicked = 1; expected.kick = t.kick; kick_transport(&t); ASSERT_EQ(0, memcmp(&expected, &t, sizeof(atransport))); ASSERT_EQ(expected, t); } // Disabled because the function currently segfaults for a zeroed atransport. I // want to make sure I understand how this is working at all before I try fixing // that. TEST(transport, DISABLED_run_transport_disconnects_zeroed_atransport) { atransport t = {}; atransport t; run_transport_disconnects(&t); } Loading
adb/Android.mk +1 −1 Original line number Diff line number Diff line Loading @@ -16,6 +16,7 @@ adb_version := $(shell git -C $(LOCAL_PATH) rev-parse --short=12 HEAD 2>/dev/nul ADB_COMMON_CFLAGS := \ -Wall -Wextra -Werror \ -Wno-unused-parameter \ -Wno-missing-field-initializers \ -DADB_REVISION='"$(adb_version)"' \ # libadb Loading Loading @@ -45,7 +46,6 @@ LIBADB_TEST_SRCS := \ LIBADB_CFLAGS := \ $(ADB_COMMON_CFLAGS) \ -Wno-missing-field-initializers \ -fvisibility=hidden \ LIBADB_darwin_SRC_FILES := \ Loading
adb/adb.h +62 −49 Original line number Diff line number Diff line Loading @@ -20,6 +20,8 @@ #include <limits.h> #include <sys/types.h> #include <base/macros.h> #include "adb_trace.h" #include "fdevent.h" Loading @@ -43,7 +45,7 @@ // Increment this when we want to force users to start a new adb server. #define ADB_SERVER_VERSION 32 struct atransport; class atransport; struct usb_handle; struct amessage { Loading Loading @@ -152,15 +154,14 @@ struct adisconnect }; /* a transport object models the connection to a remote device or emulator ** there is one transport per connected device/emulator. a "local transport" ** connects through TCP (for the emulator), while a "usb transport" through ** USB (for real devices) ** ** note that kTransportHost doesn't really correspond to a real transport ** object, it's a special value used to indicate that a client wants to ** connect to a service implemented within the ADB server itself. */ // A transport object models the connection to a remote device or emulator there // is one transport per connected device/emulator. A "local transport" connects // through TCP (for the emulator), while a "usb transport" through USB (for real // devices). // // Note that kTransportHost doesn't really correspond to a real transport // object, it's a special value used to indicate that a client wants to connect // to a service implemented within the ADB server itself. enum TransportType { kTransportUsb, kTransportLocal, Loading @@ -182,47 +183,59 @@ enum ConnectionState { kCsUnauthorized, }; struct atransport { atransport *next; atransport *prev; class atransport { public: // TODO(danalbert): We expose waaaaaaay too much stuff because this was // historically just a struct, but making the whole thing a more idiomatic // class in one go is a very large change. Given how bad our testing is, // it's better to do this piece by piece. int (*read_from_remote)(apacket *p, atransport *t); int (*write_to_remote)(apacket *p, atransport *t); void (*close)(atransport *t); void (*kick)(atransport *t); atransport() { auth_fde = {}; transport_fde = {}; } int fd; int transport_socket; virtual ~atransport() {} int (*read_from_remote)(apacket* p, atransport* t) = nullptr; int (*write_to_remote)(apacket* p, atransport* t) = nullptr; void (*close)(atransport* t) = nullptr; void (*kick)(atransport* t) = nullptr; int fd = -1; int transport_socket = -1; fdevent transport_fde; int ref_count; unsigned sync_token; int connection_state; int online; TransportType type; /* usb handle or socket fd as needed */ usb_handle *usb; int sfd; /* used to identify transports for clients */ char *serial; char *product; char *model; char *device; char *devpath; int adb_port; // Use for emulators (local transport) /* a list of adisconnect callbacks called when the transport is kicked */ int kicked; adisconnect disconnects; void *key; unsigned char token[TOKEN_SIZE]; int ref_count = 0; uint32_t sync_token = 0; ConnectionState connection_state = kCsOffline; bool online = false; TransportType type = kTransportAny; // USB handle or socket fd as needed. usb_handle* usb = nullptr; int sfd = -1; // Used to identify transports for clients. char* serial = nullptr; char* product = nullptr; char* model = nullptr; char* device = nullptr; char* devpath = nullptr; int adb_port = -1; // Use for emulators (local transport) bool kicked = false; // A list of adisconnect callbacks called when the transport is kicked. adisconnect disconnects = {}; void* key = nullptr; unsigned char token[TOKEN_SIZE] = {}; fdevent auth_fde; unsigned failed_auth_attempts; size_t failed_auth_attempts = 0; const char* connection_state_name() const; private: DISALLOW_COPY_AND_ASSIGN(atransport); }; Loading
adb/transport.cpp +60 −94 Original line number Diff line number Diff line Loading @@ -26,6 +26,8 @@ #include <string.h> #include <unistd.h> #include <list> #include <base/stringprintf.h> #include "adb.h" Loading @@ -33,15 +35,8 @@ static void transport_unref(atransport *t); static atransport transport_list = { .next = &transport_list, .prev = &transport_list, }; static atransport pending_list = { .next = &pending_list, .prev = &pending_list, }; static std::list<atransport*> transport_list; static std::list<atransport*> pending_list; ADB_MUTEX_DEFINE( transport_lock ); Loading Loading @@ -553,8 +548,7 @@ static void transport_registration_func(int _fd, unsigned ev, void *data) adb_close(t->fd); adb_mutex_lock(&transport_lock); t->next->prev = t->prev; t->prev->next = t->next; transport_list.remove(t); adb_mutex_unlock(&transport_lock); run_transport_disconnects(t); Loading @@ -570,8 +564,7 @@ static void transport_registration_func(int _fd, unsigned ev, void *data) if (t->devpath) free(t->devpath); memset(t,0xee,sizeof(atransport)); free(t); delete t; update_transports(); return; Loading Loading @@ -608,14 +601,8 @@ static void transport_registration_func(int _fd, unsigned ev, void *data) } adb_mutex_lock(&transport_lock); /* remove from pending list */ t->next->prev = t->prev; t->prev->next = t->next; /* put us on the master device list */ t->next = &transport_list; t->prev = transport_list.prev; t->next->prev = t; t->prev->next = t; pending_list.remove(t); transport_list.push_front(t); adb_mutex_unlock(&transport_lock); t->disconnects.next = t->disconnects.prev = &t->disconnects; Loading Loading @@ -740,7 +727,6 @@ static int qual_match(const char *to_test, atransport* acquire_one_transport(ConnectionState state, TransportType type, const char* serial, std::string* error_out) { atransport *t; atransport *result = NULL; int ambiguous = 0; Loading @@ -748,7 +734,7 @@ retry: if (error_out) *error_out = android::base::StringPrintf("device '%s' not found", serial); adb_mutex_lock(&transport_lock); for (t = transport_list.next; t != &transport_list; t = t->next) { for (auto t : transport_list) { if (t->connection_state == kCsNoPerm) { if (error_out) *error_out = "insufficient permissions for device"; continue; Loading Loading @@ -866,7 +852,8 @@ static void append_transport_info(std::string* result, const char* key, } } static void append_transport(atransport* t, std::string* result, bool long_listing) { static void append_transport(const atransport* t, std::string* result, bool long_listing) { const char* serial = t->serial; if (!serial || !serial[0]) { serial = "(no serial number)"; Loading @@ -890,7 +877,7 @@ static void append_transport(atransport* t, std::string* result, bool long_listi std::string list_transports(bool long_listing) { std::string result; adb_mutex_lock(&transport_lock); for (atransport* t = transport_list.next; t != &transport_list; t = t->next) { for (const auto t : transport_list) { append_transport(t, &result, long_listing); } adb_mutex_unlock(&transport_lock); Loading @@ -898,10 +885,9 @@ std::string list_transports(bool long_listing) { } /* hack for osx */ void close_usb_devices() { void close_usb_devices() { adb_mutex_lock(&transport_lock); for (atransport* t = transport_list.next; t != &transport_list; t = t->next) { for (auto t : transport_list) { if (!t->kicked) { t->kicked = 1; t->kick(t); Loading @@ -911,47 +897,39 @@ void close_usb_devices() } #endif // ADB_HOST int register_socket_transport(int s, const char *serial, int port, int local) { atransport *t = reinterpret_cast<atransport*>(calloc(1, sizeof(atransport))); if (t == nullptr) { return -1; } atransport *n; char buff[32]; int register_socket_transport(int s, const char *serial, int port, int local) { atransport* t = new atransport(); if (!serial) { snprintf(buff, sizeof buff, "T-%p", t); serial = buff; char buf[32]; snprintf(buf, sizeof(buf), "T-%p", t); serial = buf; } D("transport: %s init'ing for socket %d, on port %d\n", serial, s, port); if (init_socket_transport(t, s, port, local) < 0) { free(t); delete t; return -1; } adb_mutex_lock(&transport_lock); for (n = pending_list.next; n != &pending_list; n = n->next) { if (n->serial && !strcmp(serial, n->serial)) { for (auto transport : pending_list) { if (transport->serial && strcmp(serial, transport->serial) == 0) { adb_mutex_unlock(&transport_lock); free(t); delete t; return -1; } } for (n = transport_list.next; n != &transport_list; n = n->next) { if (n->serial && !strcmp(serial, n->serial)) { for (auto transport : transport_list) { if (transport->serial && strcmp(serial, transport->serial) == 0) { adb_mutex_unlock(&transport_lock); free(t); delete t; return -1; } } t->next = &pending_list; t->prev = pending_list.prev; t->next->prev = t; t->prev->next = t; pending_list.push_front(t); t->serial = strdup(serial); adb_mutex_unlock(&transport_lock); Loading @@ -960,52 +938,47 @@ int register_socket_transport(int s, const char *serial, int port, int local) } #if ADB_HOST atransport *find_transport(const char *serial) { atransport *t; atransport *find_transport(const char *serial) { atransport* result = nullptr; adb_mutex_lock(&transport_lock); for(t = transport_list.next; t != &transport_list; t = t->next) { if (t->serial && !strcmp(serial, t->serial)) { for (auto t : transport_list) { if (t->serial && strcmp(serial, t->serial) == 0) { result = t; break; } } adb_mutex_unlock(&transport_lock); if (t != &transport_list) return t; else return 0; return result; } void unregister_transport(atransport *t) { adb_mutex_lock(&transport_lock); t->next->prev = t->prev; t->prev->next = t->next; transport_list.remove(t); adb_mutex_unlock(&transport_lock); kick_transport(t); transport_unref(t); } // unregisters all non-emulator TCP transports void unregister_all_tcp_transports() { atransport *t, *next; // Unregisters all non-emulator TCP transports. void unregister_all_tcp_transports() { adb_mutex_lock(&transport_lock); for (t = transport_list.next; t != &transport_list; t = next) { next = t->next; for (auto it = transport_list.begin(); it != transport_list.end(); ) { atransport* t = *it; if (t->type == kTransportLocal && t->adb_port == 0) { t->next->prev = t->prev; t->prev->next = next; // we cannot call kick_transport when holding transport_lock if (!t->kicked) { // We cannot call kick_transport when holding transport_lock. if (!t->kicked) { t->kicked = 1; t->kick(t); } transport_unref_locked(t); it = transport_list.erase(it); } else { ++it; } } Loading @@ -1014,25 +987,23 @@ void unregister_all_tcp_transports() #endif void register_usb_transport(usb_handle *usb, const char *serial, const char *devpath, unsigned writeable) { atransport *t = reinterpret_cast<atransport*>(calloc(1, sizeof(atransport))); if (t == nullptr) fatal("cannot allocate USB atransport"); void register_usb_transport(usb_handle* usb, const char* serial, const char* devpath, unsigned writeable) { atransport* t = new atransport(); D("transport: %p init'ing for usb_handle %p (sn='%s')\n", t, usb, serial ? serial : ""); init_usb_transport(t, usb, (writeable ? kCsOffline : kCsNoPerm)); if(serial) { t->serial = strdup(serial); } if (devpath) { t->devpath = strdup(devpath); } adb_mutex_lock(&transport_lock); t->next = &pending_list; t->prev = pending_list.prev; t->next->prev = t; t->prev->next = t; pending_list.push_front(t); adb_mutex_unlock(&transport_lock); register_transport(t); Loading @@ -1041,14 +1012,9 @@ void register_usb_transport(usb_handle *usb, const char *serial, const char *dev // This should only be used for transports with connection_state == kCsNoPerm. void unregister_usb_transport(usb_handle *usb) { adb_mutex_lock(&transport_lock); for (atransport* t = transport_list.next; t != &transport_list; t = t->next) { if (t->usb == usb && t->connection_state == kCsNoPerm) { t->next->prev = t->prev; t->prev->next = t->next; break; } } transport_list.remove_if([usb](atransport* t) { return t->usb == usb && t->connection_state == kCsNoPerm; }); adb_mutex_unlock(&transport_lock); } Loading
adb/transport_test.cpp +58 −7 Original line number Diff line number Diff line Loading @@ -20,34 +20,85 @@ #include "adb.h" class TestTransport : public atransport { public: bool operator==(const atransport& rhs) const { EXPECT_EQ(read_from_remote, rhs.read_from_remote); EXPECT_EQ(write_to_remote, rhs.write_to_remote); EXPECT_EQ(close, rhs.close); EXPECT_EQ(kick, rhs.kick); EXPECT_EQ(fd, rhs.fd); EXPECT_EQ(transport_socket, rhs.transport_socket); EXPECT_EQ( 0, memcmp(&transport_fde, &rhs.transport_fde, sizeof(fdevent))); EXPECT_EQ(ref_count, rhs.ref_count); EXPECT_EQ(sync_token, rhs.sync_token); EXPECT_EQ(connection_state, rhs.connection_state); EXPECT_EQ(online, rhs.online); EXPECT_EQ(type, rhs.type); EXPECT_EQ(usb, rhs.usb); EXPECT_EQ(sfd, rhs.sfd); EXPECT_EQ(serial, rhs.serial); EXPECT_EQ(product, rhs.product); EXPECT_EQ(model, rhs.model); EXPECT_EQ(device, rhs.device); EXPECT_EQ(devpath, rhs.devpath); EXPECT_EQ(adb_port, rhs.adb_port); EXPECT_EQ(kicked, rhs.kicked); EXPECT_EQ( 0, memcmp(&disconnects, &rhs.disconnects, sizeof(adisconnect))); EXPECT_EQ(key, rhs.key); EXPECT_EQ(0, memcmp(token, rhs.token, TOKEN_SIZE)); EXPECT_EQ(0, memcmp(&auth_fde, &rhs.auth_fde, sizeof(fdevent))); EXPECT_EQ(failed_auth_attempts, rhs.failed_auth_attempts); return true; } }; TEST(transport, kick_transport) { atransport t = {}; TestTransport t; // Mutate some member so we can test that the function is run. t.kick = [](atransport* trans) { trans->fd = 42; }; atransport expected = t; TestTransport expected; expected.kick = t.kick; expected.fd = 42; expected.kicked = 1; kick_transport(&t); ASSERT_EQ(42, t.fd); ASSERT_EQ(1, t.kicked); ASSERT_EQ(0, memcmp(&expected, &t, sizeof(atransport))); ASSERT_EQ(expected, t); } TEST(transport, kick_transport_already_kicked) { // Ensure that the transport is not modified if the transport has already been // kicked. atransport t = {}; TestTransport t; t.kicked = 1; t.kick = [](atransport*) { FAIL() << "Kick should not have been called"; }; atransport expected = t; TestTransport expected; expected.kicked = 1; expected.kick = t.kick; kick_transport(&t); ASSERT_EQ(0, memcmp(&expected, &t, sizeof(atransport))); ASSERT_EQ(expected, t); } // Disabled because the function currently segfaults for a zeroed atransport. I // want to make sure I understand how this is working at all before I try fixing // that. TEST(transport, DISABLED_run_transport_disconnects_zeroed_atransport) { atransport t = {}; atransport t; run_transport_disconnects(&t); }