aboutsummaryrefslogtreecommitdiffstats
path: root/android
diff options
context:
space:
mode:
authorVladimir Chtchetkine <vchtchetkine@google.com>2012-04-30 15:18:15 -0700
committerVladimir Chtchetkine <vchtchetkine@google.com>2012-04-30 15:18:15 -0700
commit39a1158197072f846301a8263e2851e892962e64 (patch)
tree4e46cb3eefc05827396db83dcf8a3007a32b883a /android
parent7136b053b7fc7840ec64e01d1d19ab822e1f949a (diff)
downloadexternal_qemu-39a1158197072f846301a8263e2851e892962e64.zip
external_qemu-39a1158197072f846301a8263e2851e892962e64.tar.gz
external_qemu-39a1158197072f846301a8263e2851e892962e64.tar.bz2
Fix adb client protocol
There are cases when 'accept' message that guest adbd sends via qemu pipe to the emulator get broken into pieces: once 4 bytes are delivered, and then the remaining two. This breaks the protocol, as emulator assumes that all 6 bytes would be delivered in one chunk. This CL adjusts that by accumulating messages in a buffer, and analyzing them only when collected message length reaches certain point. Change-Id: Ice25625f65bbaa2b07677c3285bf75e7bf46fbb7
Diffstat (limited to 'android')
-rw-r--r--android/adb-qemud.c44
1 files changed, 35 insertions, 9 deletions
diff --git a/android/adb-qemud.c b/android/adb-qemud.c
index 1d2498e..9d82251 100644
--- a/android/adb-qemud.c
+++ b/android/adb-qemud.c
@@ -33,7 +33,8 @@
#define SERVICE_NAME "adb"
#define DEBUG_SERVICE_NAME "adb-debug"
-
+/* Maximum length of the message that can be received from the guest. */
+#define ADB_MAX_MSG_LEN 8
/* Enumerates ADB client state values. */
typedef enum AdbClientState {
/* Waiting on a connection from ADB host. */
@@ -58,6 +59,10 @@ struct AdbClient {
QemudClient* qemud_client;
/* Connection state. */
AdbClientState state;
+ /* Buffer, collecting accept / stop messages from client. */
+ char msg_buffer[ADB_MAX_MSG_LEN];
+ /* Current position in message buffer. */
+ int msg_cur;
};
/* ADB debugging client descriptor. */
@@ -183,17 +188,36 @@ _adb_client_recv(void* opaque, uint8_t* msg, int msglen, QemudClient* client)
D("ADB client %p(o=%p) received from guest %d bytes in %s",
adb_client, adb_client->opaque, msglen, QB(msg, msglen));
+ if (adb_client->state == ADBC_STATE_CONNECTED) {
+ /* Connection is fully established. Dispatch the message to the host. */
+ adb_server_on_guest_message(adb_client->opaque, msg, msglen);
+ return;
+ }
+
+ /*
+ * At this point we expect either "accept", or "start" messages. Depending
+ * on the state of the pipe (although small) these messages could be broken
+ * into pieces. So, simply checking msg for "accept", or "start" may not
+ * work. Lets collect them first in internal buffer, and then will see.
+ */
+
+ /* Make sure tha message doesn't overflow the buffer. */
+ if ((msglen + adb_client->msg_cur) > sizeof(adb_client->msg_buffer)) {
+ D("Unexpected message in ADB client.");
+ adb_client->msg_cur = 0;
+ return;
+ }
+ /* Append to current message. */
+ memcpy(adb_client->msg_buffer + adb_client->msg_cur, msg, msglen);
+ adb_client->msg_cur += msglen;
+
/* Properly dispatch the message, depending on the client state. */
switch (adb_client->state) {
- case ADBC_STATE_CONNECTED:
- /* Connection is fully established. Dispatch the message to the
- * host. */
- adb_server_on_guest_message(adb_client->opaque, msg, msglen);
- break;
-
case ADBC_STATE_WAIT_ON_HOST:
/* At this state the only message that is allowed is 'accept' */
- if (msglen == 6 && !memcmp(msg, "accept", 6)) {
+ if (adb_client->msg_cur == 6 &&
+ !memcmp(adb_client->msg_buffer, "accept", 6)) {
+ adb_client->msg_cur = 0;
/* Register ADB guest connection with the ADB server. */
adb_client->opaque =
adb_server_register_guest(adb_client, &_adb_client_routines);
@@ -210,7 +234,9 @@ _adb_client_recv(void* opaque, uint8_t* msg, int msglen, QemudClient* client)
case ADBC_STATE_HOST_CONNECTED:
/* At this state the only message that is allowed is 'start' */
- if (msglen == 5 && !memcmp(msg, "start", 5)) {
+ if (adb_client->msg_cur &&
+ !memcmp(adb_client->msg_buffer, "start", 5)) {
+ adb_client->msg_cur = 0;
adb_client->state = ADBC_STATE_CONNECTED;
adb_server_complete_connection(adb_client->opaque);
} else {