Use actual VNDK list for non-VNDK-enforcing devices
am: 8a9a8eeb85
Change-Id: I2677acd9dbd266873fb12d20674e298cc9d1444c
diff --git a/adb/adb.cpp b/adb/adb.cpp
index 0e38897..ee3503b 100644
--- a/adb/adb.cpp
+++ b/adb/adb.cpp
@@ -474,13 +474,14 @@
asocket* s = find_local_socket(p->msg.arg1, p->msg.arg0);
if (s) {
unsigned rid = p->msg.arg0;
- p->len = p->msg.data_length;
- if (s->enqueue(s, p) == 0) {
+ // TODO: Convert apacket::data to a type that we can move out of.
+ std::string copy(p->data, p->data + p->msg.data_length);
+
+ if (s->enqueue(s, std::move(copy)) == 0) {
D("Enqueue the socket");
send_ready(s->id, rid, t);
}
- return;
}
}
break;
diff --git a/adb/adb.h b/adb/adb.h
index b5d6bcb..c9c635a 100644
--- a/adb/adb.h
+++ b/adb/adb.h
@@ -73,11 +73,6 @@
};
struct apacket {
- apacket* next;
-
- size_t len;
- char* ptr;
-
amessage msg;
char data[MAX_PAYLOAD];
};
diff --git a/adb/jdwp_service.cpp b/adb/jdwp_service.cpp
index f0dff06..0a8a85a 100644
--- a/adb/jdwp_service.cpp
+++ b/adb/jdwp_service.cpp
@@ -470,10 +470,9 @@
free(s);
}
-static int jdwp_socket_enqueue(asocket* s, apacket* p) {
+static int jdwp_socket_enqueue(asocket* s, std::string) {
/* you can't write to this asocket */
D("LS(%d): JDWP socket received data?", s->id);
- put_apacket(p);
s->peer->close(s->peer);
return -1;
}
@@ -486,9 +485,11 @@
* on the second one, close the connection
*/
if (!jdwp->pass) {
- apacket* p = get_apacket();
- p->len = jdwp_process_list((char*)p->data, s->get_max_payload());
- peer->enqueue(peer, p);
+ std::string data;
+ data.resize(s->get_max_payload());
+ size_t len = jdwp_process_list(&data[0], data.size());
+ data.resize(len);
+ peer->enqueue(peer, std::move(data));
jdwp->pass = true;
} else {
peer->close(peer);
@@ -524,17 +525,14 @@
static std::vector<std::unique_ptr<JdwpTracker>> _jdwp_trackers;
static void jdwp_process_list_updated(void) {
- char buffer[1024];
- int len = jdwp_process_list_msg(buffer, sizeof(buffer));
+ std::string data;
+ data.resize(1024);
+ data.resize(jdwp_process_list_msg(&data[0], data.size()));
for (auto& t : _jdwp_trackers) {
- apacket* p = get_apacket();
- memcpy(p->data, buffer, len);
- p->len = len;
-
if (t->peer) {
// The tracker might not have been connected yet.
- t->peer->enqueue(t->peer, p);
+ t->peer->enqueue(t->peer, data);
}
}
}
@@ -560,17 +558,17 @@
JdwpTracker* t = (JdwpTracker*)s;
if (t->need_initial) {
- apacket* p = get_apacket();
+ std::string data;
+ data.resize(s->get_max_payload());
+ data.resize(jdwp_process_list_msg(&data[0], data.size()));
t->need_initial = false;
- p->len = jdwp_process_list_msg((char*)p->data, s->get_max_payload());
- s->peer->enqueue(s->peer, p);
+ s->peer->enqueue(s->peer, std::move(data));
}
}
-static int jdwp_tracker_enqueue(asocket* s, apacket* p) {
+static int jdwp_tracker_enqueue(asocket* s, std::string) {
/* you can't write to this socket */
D("LS(%d): JDWP tracker received data?", s->id);
- put_apacket(p);
s->peer->close(s->peer);
return -1;
}
diff --git a/adb/range.h b/adb/range.h
new file mode 100644
index 0000000..7a0b822
--- /dev/null
+++ b/adb/range.h
@@ -0,0 +1,65 @@
+#pragma once
+
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <string>
+
+#include <android-base/logging.h>
+
+struct Range {
+ explicit Range(std::string data) : data_(std::move(data)) {}
+
+ Range(const Range& copy) = delete;
+ Range& operator=(const Range& copy) = delete;
+
+ Range(Range&& move) = default;
+ Range& operator=(Range&& move) = default;
+
+ bool empty() const {
+ return size() == 0;
+ }
+
+ size_t size() const {
+ return data_.size() - begin_offset_ - end_offset_;
+ };
+
+ void drop_front(size_t n) {
+ CHECK_GE(size(), n);
+ begin_offset_ += n;
+ }
+
+ void drop_end(size_t n) {
+ CHECK_GE(size(), n);
+ end_offset_ += n;
+ }
+
+ char* data() {
+ return &data_[0] + begin_offset_;
+ }
+
+ std::string::iterator begin() {
+ return data_.begin() + begin_offset_;
+ }
+
+ std::string::iterator end() {
+ return data_.end() - end_offset_;
+ }
+
+ std::string data_;
+ size_t begin_offset_ = 0;
+ size_t end_offset_ = 0;
+};
diff --git a/adb/socket.h b/adb/socket.h
index 64d05a9..a1b52b3 100644
--- a/adb/socket.h
+++ b/adb/socket.h
@@ -19,9 +19,12 @@
#include <stddef.h>
+#include <deque>
#include <memory>
+#include <string>
#include "fdevent.h"
+#include "range.h"
struct apacket;
class atransport;
@@ -31,12 +34,6 @@
* remote asocket is bound to the protocol engine.
*/
struct asocket {
- /* chain pointers for the local/remote list of
- * asockets that this asocket lives in
- */
- asocket* next;
- asocket* prev;
-
/* the unique identifier for this asocket
*/
unsigned id;
@@ -65,9 +62,10 @@
fdevent fde;
int fd;
- // queue of apackets waiting to be written
- apacket* pkt_first;
- apacket* pkt_last;
+ // queue of data waiting to be written
+ std::deque<Range> packet_queue;
+
+ std::string smart_socket_data;
/* enqueue is called by our peer when it has data
* for us. It should return 0 if we can accept more
@@ -75,7 +73,7 @@
* peer->ready() when we once again are ready to
* receive data.
*/
- int (*enqueue)(asocket* s, apacket* pkt);
+ int (*enqueue)(asocket* s, std::string data);
/* ready is called by the peer when it is ready for
* us to send data via enqueue again
diff --git a/adb/socket_test.cpp b/adb/socket_test.cpp
index f7c66db..04ad6f3 100644
--- a/adb/socket_test.cpp
+++ b/adb/socket_test.cpp
@@ -114,10 +114,10 @@
ASSERT_TRUE(s != nullptr);
arg->bytes_written = 0;
while (true) {
- apacket* p = get_apacket();
- p->len = sizeof(p->data);
- arg->bytes_written += p->len;
- int ret = s->enqueue(s, p);
+ std::string data;
+ data.resize(MAX_PAYLOAD);
+ arg->bytes_written += data.size();
+ int ret = s->enqueue(s, std::move(data));
if (ret == 1) {
// The writer has one packet waiting to send.
break;
diff --git a/adb/sockets.cpp b/adb/sockets.cpp
index c53fbb4..e9c45b7 100644
--- a/adb/sockets.cpp
+++ b/adb/sockets.cpp
@@ -37,32 +37,28 @@
#include "adb.h"
#include "adb_io.h"
+#include "range.h"
#include "transport.h"
static std::recursive_mutex& local_socket_list_lock = *new std::recursive_mutex();
static unsigned local_socket_next_id = 1;
-static asocket local_socket_list = {
- .next = &local_socket_list, .prev = &local_socket_list,
-};
+static auto& local_socket_list = *new std::vector<asocket*>();
/* the the list of currently closing local sockets.
** these have no peer anymore, but still packets to
** write to their fd.
*/
-static asocket local_socket_closing_list = {
- .next = &local_socket_closing_list, .prev = &local_socket_closing_list,
-};
+static auto& local_socket_closing_list = *new std::vector<asocket*>();
// Parse the global list of sockets to find one with id |local_id|.
// If |peer_id| is not 0, also check that it is connected to a peer
// with id |peer_id|. Returns an asocket handle on success, NULL on failure.
asocket* find_local_socket(unsigned local_id, unsigned peer_id) {
- asocket* s;
- asocket* result = NULL;
+ asocket* result = nullptr;
std::lock_guard<std::recursive_mutex> lock(local_socket_list_lock);
- for (s = local_socket_list.next; s != &local_socket_list; s = s->next) {
+ for (asocket* s : local_socket_list) {
if (s->id != local_id) {
continue;
}
@@ -75,13 +71,6 @@
return result;
}
-static void insert_local_socket(asocket* s, asocket* list) {
- s->next = list;
- s->prev = s->next->prev;
- s->prev->next = s;
- s->next->prev = s;
-}
-
void install_local_socket(asocket* s) {
std::lock_guard<std::recursive_mutex> lock(local_socket_list_lock);
@@ -92,29 +81,24 @@
fatal("local socket id overflow");
}
- insert_local_socket(s, &local_socket_list);
+ local_socket_list.push_back(s);
}
void remove_socket(asocket* s) {
std::lock_guard<std::recursive_mutex> lock(local_socket_list_lock);
- if (s->prev && s->next) {
- s->prev->next = s->next;
- s->next->prev = s->prev;
- s->next = 0;
- s->prev = 0;
- s->id = 0;
+ for (auto list : { &local_socket_list, &local_socket_closing_list }) {
+ list->erase(std::remove_if(list->begin(), list->end(), [s](asocket* x) { return x == s; }),
+ list->end());
}
}
void close_all_sockets(atransport* t) {
- asocket* s;
-
/* this is a little gross, but since s->close() *will* modify
** the list out from under you, your options are limited.
*/
std::lock_guard<std::recursive_mutex> lock(local_socket_list_lock);
restart:
- for (s = local_socket_list.next; s != &local_socket_list; s = s->next) {
+ for (asocket* s : local_socket_list) {
if (s->transport == t || (s->peer && s->peer->transport == t)) {
s->close(s);
goto restart;
@@ -122,55 +106,47 @@
}
}
-static int local_socket_enqueue(asocket* s, apacket* p) {
- D("LS(%d): enqueue %zu", s->id, p->len);
+static int local_socket_enqueue(asocket* s, std::string data) {
+ D("LS(%d): enqueue %zu", s->id, data.size());
- p->ptr = p->data;
+ Range r(std::move(data));
/* if there is already data queue'd, we will receive
** events when it's time to write. just add this to
** the tail
*/
- if (s->pkt_first) {
+ if (!s->packet_queue.empty()) {
goto enqueue;
}
/* write as much as we can, until we
** would block or there is an error/eof
*/
- while (p->len > 0) {
- int r = adb_write(s->fd, p->ptr, p->len);
- if (r > 0) {
- p->len -= r;
- p->ptr += r;
+ while (!r.empty()) {
+ int rc = adb_write(s->fd, r.data(), r.size());
+ if (rc > 0) {
+ r.drop_front(rc);
continue;
}
- if ((r == 0) || (errno != EAGAIN)) {
+
+ if (rc == 0 || errno != EAGAIN) {
D("LS(%d): not ready, errno=%d: %s", s->id, errno, strerror(errno));
- put_apacket(p);
s->has_write_error = true;
s->close(s);
return 1; /* not ready (error) */
} else {
+ // errno == EAGAIN
break;
}
}
- if (p->len == 0) {
- put_apacket(p);
+ if (r.empty()) {
return 0; /* ready for more data */
}
enqueue:
- p->next = 0;
- if (s->pkt_first) {
- s->pkt_last->next = p;
- } else {
- s->pkt_first = p;
- }
- s->pkt_last = p;
-
/* make sure we are notified when we can drain the queue */
+ s->packet_queue.push_back(std::move(r));
fdevent_add(&s->fde, FDE_WRITE);
return 1; /* not ready (backlog) */
@@ -184,7 +160,6 @@
// be sure to hold the socket list lock when calling this
static void local_socket_destroy(asocket* s) {
- apacket *p, *n;
int exit_on_close = s->exit_on_close;
D("LS(%d): destroying fde.fd=%d", s->id, s->fde.fd);
@@ -194,12 +169,6 @@
*/
fdevent_remove(&s->fde);
- /* dispose of any unwritten data */
- for (p = s->pkt_first; p; p = n) {
- D("LS(%d): discarding %zu bytes", s->id, p->len);
- n = p->next;
- put_apacket(p);
- }
remove_socket(s);
free(s);
@@ -229,7 +198,7 @@
/* If we are already closing, or if there are no
** pending packets, destroy immediately
*/
- if (s->closing || s->has_write_error || s->pkt_first == NULL) {
+ if (s->closing || s->has_write_error || s->packet_queue.empty()) {
int id = s->id;
local_socket_destroy(s);
D("LS(%d): closed", id);
@@ -243,7 +212,7 @@
fdevent_del(&s->fde, FDE_READ);
remove_socket(s);
D("LS(%d): put on socket_closing_list fd=%d", s->id, s->fd);
- insert_local_socket(s, &local_socket_closing_list);
+ local_socket_closing_list.push_back(s);
CHECK_EQ(FDE_WRITE, s->fde.state & FDE_WRITE);
}
@@ -255,35 +224,30 @@
** in order to simplify the code.
*/
if (ev & FDE_WRITE) {
- apacket* p;
- while ((p = s->pkt_first) != nullptr) {
- while (p->len > 0) {
- int r = adb_write(fd, p->ptr, p->len);
- if (r == -1) {
+ while (!s->packet_queue.empty()) {
+ Range& r = s->packet_queue.front();
+ while (!r.empty()) {
+ int rc = adb_write(fd, r.data(), r.size());
+ if (rc == -1) {
/* returning here is ok because FDE_READ will
** be processed in the next iteration loop
*/
if (errno == EAGAIN) {
return;
}
- } else if (r > 0) {
- p->ptr += r;
- p->len -= r;
+ } else if (rc > 0) {
+ r.drop_front(rc);
continue;
}
- D(" closing after write because r=%d and errno is %d", r, errno);
+ D(" closing after write because rc=%d and errno is %d", rc, errno);
s->has_write_error = true;
s->close(s);
return;
}
- if (p->len == 0) {
- s->pkt_first = p->next;
- if (s->pkt_first == 0) {
- s->pkt_last = 0;
- }
- put_apacket(p);
+ if (r.empty()) {
+ s->packet_queue.pop_front();
}
}
@@ -305,9 +269,10 @@
}
if (ev & FDE_READ) {
- apacket* p = get_apacket();
- char* x = p->data;
const size_t max_payload = s->get_max_payload();
+ std::string data;
+ data.resize(max_payload);
+ char* x = &data[0];
size_t avail = max_payload;
int r = 0;
int is_eof = 0;
@@ -332,16 +297,15 @@
}
D("LS(%d): fd=%d post avail loop. r=%d is_eof=%d forced_eof=%d", s->id, s->fd, r, is_eof,
s->fde.force_eof);
- if ((avail == max_payload) || (s->peer == 0)) {
- put_apacket(p);
- } else {
- p->len = max_payload - avail;
+
+ if (avail != max_payload && s->peer) {
+ data.resize(max_payload - avail);
// s->peer->enqueue() may call s->close() and free s,
// so save variables for debug printing below.
unsigned saved_id = s->id;
int saved_fd = s->fd;
- r = s->peer->enqueue(s->peer, p);
+ r = s->peer->enqueue(s->peer, std::move(data));
D("LS(%u): fd=%d post peer->enqueue(). r=%d", saved_id, saved_fd, r);
if (r < 0) {
@@ -445,12 +409,22 @@
}
#endif /* ADB_HOST */
-static int remote_socket_enqueue(asocket* s, apacket* p) {
+static int remote_socket_enqueue(asocket* s, std::string data) {
D("entered remote_socket_enqueue RS(%d) WRITE fd=%d peer.fd=%d", s->id, s->fd, s->peer->fd);
+ apacket* p = get_apacket();
+
p->msg.command = A_WRTE;
p->msg.arg0 = s->peer->id;
p->msg.arg1 = s->id;
- p->msg.data_length = p->len;
+ p->msg.data_length = data.size();
+
+ if (data.size() > sizeof(p->data)) {
+ put_apacket(p);
+ return -1;
+ }
+
+ // TODO: Convert apacket::data to a type that we can move into.
+ memcpy(p->data, data.data(), data.size());
send_packet(p, s->transport);
return 1;
}
@@ -550,7 +524,7 @@
s->close(s);
}
-static unsigned unhex(char* s, int len) {
+static unsigned unhex(const char* s, int len) {
unsigned n = 0, c;
while (len-- > 0) {
@@ -654,8 +628,7 @@
#endif // ADB_HOST
-static int smart_socket_enqueue(asocket* s, apacket* p) {
- unsigned len;
+static int smart_socket_enqueue(asocket* s, std::string data) {
#if ADB_HOST
char* service = nullptr;
char* serial = nullptr;
@@ -663,49 +636,38 @@
TransportType type = kTransportAny;
#endif
- D("SS(%d): enqueue %zu", s->id, p->len);
+ D("SS(%d): enqueue %zu", s->id, data.size());
- if (s->pkt_first == 0) {
- s->pkt_first = p;
- s->pkt_last = p;
+ if (s->smart_socket_data.empty()) {
+ s->smart_socket_data = std::move(data);
} else {
- if ((s->pkt_first->len + p->len) > s->get_max_payload()) {
- D("SS(%d): overflow", s->id);
- put_apacket(p);
- goto fail;
- }
-
- memcpy(s->pkt_first->data + s->pkt_first->len, p->data, p->len);
- s->pkt_first->len += p->len;
- put_apacket(p);
-
- p = s->pkt_first;
+ std::copy(data.begin(), data.end(), std::back_inserter(s->smart_socket_data));
}
/* don't bother if we can't decode the length */
- if (p->len < 4) {
+ if (s->smart_socket_data.size() < 4) {
return 0;
}
- len = unhex(p->data, 4);
- if ((len < 1) || (len > MAX_PAYLOAD)) {
- D("SS(%d): bad size (%d)", s->id, len);
+ uint32_t len = unhex(s->smart_socket_data.data(), 4);
+ if (len == 0 || len > MAX_PAYLOAD) {
+ D("SS(%d): bad size (%u)", s->id, len);
goto fail;
}
- D("SS(%d): len is %d", s->id, len);
+ D("SS(%d): len is %u", s->id, len);
/* can't do anything until we have the full header */
- if ((len + 4) > p->len) {
- D("SS(%d): waiting for %zu more bytes", s->id, len + 4 - p->len);
+ if ((len + 4) > s->smart_socket_data.size()) {
+ D("SS(%d): waiting for %zu more bytes", s->id, len + 4 - s->smart_socket_data.size());
return 0;
}
- p->data[len + 4] = 0;
+ s->smart_socket_data[len + 4] = 0;
- D("SS(%d): '%s'", s->id, (char*)(p->data + 4));
+ D("SS(%d): '%s'", s->id, (char*)(s->smart_socket_data.data() + 4));
#if ADB_HOST
- service = (char*)p->data + 4;
+ service = &s->smart_socket_data[4];
if (!strncmp(service, "host-serial:", strlen("host-serial:"))) {
char* serial_end;
service += strlen("host-serial:");
@@ -753,7 +715,7 @@
}
if (!strncmp(service, "transport", strlen("transport"))) {
D("SS(%d): okay transport", s->id);
- p->len = 0;
+ s->smart_socket_data.clear();
return 0;
}
@@ -824,7 +786,7 @@
/* give him our transport and upref it */
s->peer->transport = s->transport;
- connect_to_remote(s->peer, (char*)(p->data + 4));
+ connect_to_remote(s->peer, s->smart_socket_data.data() + 4);
s->peer = 0;
s->close(s);
return 1;
@@ -844,9 +806,6 @@
static void smart_socket_close(asocket* s) {
D("SS(%d): closed", s->id);
- if (s->pkt_first) {
- put_apacket(s->pkt_first);
- }
if (s->peer) {
s->peer->peer = 0;
s->peer->close(s->peer);
diff --git a/adb/transport.cpp b/adb/transport.cpp
index 5acaaec..3b0669c 100644
--- a/adb/transport.cpp
+++ b/adb/transport.cpp
@@ -72,6 +72,11 @@
return false;
}
+ if (packet->msg.data_length > sizeof(packet->data)) {
+ D("remote local: read overflow (data length = %" PRIu32 ")", packet->msg.data_length);
+ return false;
+ }
+
if (!ReadFdExactly(fd_.get(), &packet->data, packet->msg.data_length)) {
D("remote local: terminated (data)");
return false;
@@ -409,21 +414,22 @@
free(tracker);
}
-static int device_tracker_enqueue(asocket* socket, apacket* p) {
+static int device_tracker_enqueue(asocket* socket, std::string) {
/* you can't read from a device tracker, close immediately */
- put_apacket(p);
device_tracker_close(socket);
return -1;
}
static int device_tracker_send(device_tracker* tracker, const std::string& string) {
- apacket* p = get_apacket();
asocket* peer = tracker->socket.peer;
- snprintf(reinterpret_cast<char*>(p->data), 5, "%04x", static_cast<int>(string.size()));
- memcpy(&p->data[4], string.data(), string.size());
- p->len = 4 + string.size();
- return peer->enqueue(peer, p);
+ std::string data;
+ data.resize(4 + string.size());
+ char buf[5];
+ snprintf(buf, sizeof(buf), "%04x", static_cast<int>(string.size()));
+ memcpy(&data[0], buf, 4);
+ memcpy(&data[4], string.data(), string.size());
+ return peer->enqueue(peer, std::move(data));
}
static void device_tracker_ready(asocket* socket) {
diff --git a/adb/transport_usb.cpp b/adb/transport_usb.cpp
index 73e8e15..a108699 100644
--- a/adb/transport_usb.cpp
+++ b/adb/transport_usb.cpp
@@ -61,6 +61,10 @@
static int UsbReadPayload(usb_handle* h, apacket* p) {
D("UsbReadPayload(%d)", p->msg.data_length);
+ if (p->msg.data_length > sizeof(p->data)) {
+ return -1;
+ }
+
#if CHECK_PACKET_OVERFLOW
size_t usb_packet_size = usb_get_max_packet_size(h);
CHECK_EQ(0ULL, sizeof(p->data) % usb_packet_size);
@@ -116,6 +120,11 @@
}
if (p->msg.data_length) {
+ if (p->msg.data_length > sizeof(p->data)) {
+ PLOG(ERROR) << "remote usb: read overflow (data length = " << p->msg.data_length << ")";
+ return -1;
+ }
+
if (usb_read(usb, p->data, p->msg.data_length)) {
PLOG(ERROR) << "remote usb: terminated (data)";
return -1;