blob: 9a57baa1b786be428e88ee076a7fc0f3df569b8e [file] [log] [blame]
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001/*
2 * Copyright (C) 2008 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16#include "jdwp/JdwpPriv.h"
17#include "jdwp/JdwpHandler.h"
18#include <sys/socket.h>
19#include <sys/un.h>
20#include <errno.h>
21#include <unistd.h>
22
23/* the JDWP <-> ADB transport protocol is explained in details
24 * in //device/tools/adb/jdwp_service.c, here's a summary.
25 *
26 * 1/ when the JDWP thread starts, it tries to connect to a Unix
27 * domain stream socket (@jdwp-control) that is opened by the
28 * ADB daemon.
29 *
30 * 2/ it then sends the current process PID as a string of 4 hexadecimal
31 * chars (no terminating zero)
32 *
33 * 3/ then, it uses recvmsg to receive file descriptors from the
34 * daemon. each incoming file descriptor is a pass-through to
35 * a given JDWP debugger, that can be used to read the usual
36 * JDWP-handshake, etc...
37 *
38 */
39
40#define kInputBufferSize 8192
41
42#define kMagicHandshake "JDWP-Handshake"
43#define kMagicHandshakeLen (sizeof(kMagicHandshake)-1)
44
45#define kJdwpControlName "\0jdwp-control"
46#define kJdwpControlNameLen (sizeof(kJdwpControlName)-1)
47
48struct JdwpNetState {
49 int controlSock;
50 int clientSock;
51 bool awaitingHandshake;
Andy McFadden201a6b52009-06-02 14:15:22 -070052 bool shuttingDown;
The Android Open Source Projectf6c38712009-03-03 19:28:47 -080053 int wakeFds[2];
54
55 int inputCount;
56 unsigned char inputBuffer[kInputBufferSize];
57
58 socklen_t controlAddrLen;
59 union {
60 struct sockaddr_un controlAddrUn;
61 struct sockaddr controlAddrPlain;
62 } controlAddr;
63};
64
65static void
66adbStateFree( JdwpNetState* netState )
67{
68 if (netState == NULL)
69 return;
70
71 if (netState->clientSock >= 0) {
72 shutdown(netState->clientSock, SHUT_RDWR);
73 close(netState->clientSock);
74 }
75 if (netState->controlSock >= 0) {
76 shutdown(netState->controlSock, SHUT_RDWR);
77 close(netState->controlSock);
78 }
79 if (netState->wakeFds[0] >= 0) {
80 close(netState->wakeFds[0]);
81 netState->wakeFds[0] = -1;
82 }
83 if (netState->wakeFds[1] >= 0) {
84 close(netState->wakeFds[1]);
85 netState->wakeFds[1] = -1;
86 }
87
88 free(netState);
89}
90
91
Carl Shapiro1e1433e2011-04-20 16:51:38 -070092static JdwpNetState* adbStateAlloc()
The Android Open Source Projectf6c38712009-03-03 19:28:47 -080093{
Carl Shapirofc75f3e2010-12-07 11:43:38 -080094 JdwpNetState* netState = (JdwpNetState*) calloc(sizeof(*netState),1);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -080095
96 netState->controlSock = -1;
97 netState->clientSock = -1;
98
99 netState->controlAddr.controlAddrUn.sun_family = AF_UNIX;
100 netState->controlAddrLen =
101 sizeof(netState->controlAddr.controlAddrUn.sun_family) +
102 kJdwpControlNameLen;
Carl Shapirode750892010-06-08 16:37:12 -0700103
104 memcpy(netState->controlAddr.controlAddrUn.sun_path,
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800105 kJdwpControlName, kJdwpControlNameLen);
Carl Shapirode750892010-06-08 16:37:12 -0700106
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800107 netState->wakeFds[0] = -1;
108 netState->wakeFds[1] = -1;
Carl Shapirode750892010-06-08 16:37:12 -0700109
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800110 return netState;
111}
112
113
114/*
115 * Do initial prep work, e.g. binding to ports and opening files. This
116 * runs in the main thread, before the JDWP thread starts, so it shouldn't
117 * do anything that might block forever.
118 */
119static bool startup(struct JdwpState* state, const JdwpStartupParams* pParams)
120{
121 JdwpNetState* netState;
122
123 LOGV("ADB transport startup\n");
Carl Shapirode750892010-06-08 16:37:12 -0700124
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800125 state->netState = netState = adbStateAlloc();
126 if (netState == NULL)
127 return false;
128
129 return true;
130}
131
Andy McFadden305efe62009-05-28 14:55:57 -0700132/*
133 * Receive a file descriptor from ADB. The fd can be used to communicate
134 * directly with a debugger or DDMS.
135 *
Andy McFadden6196d152009-06-03 15:53:27 -0700136 * Returns the file descriptor on success. On failure, returns -1 and
137 * closes netState->controlSock.
Andy McFadden305efe62009-05-28 14:55:57 -0700138 */
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800139static int receiveClientFd(JdwpNetState* netState)
140{
141 struct msghdr msg;
142 struct cmsghdr* cmsg;
143 struct iovec iov;
144 char dummy = '!';
145 union {
146 struct cmsghdr cm;
147 char buffer[CMSG_SPACE(sizeof(int))];
148 } cm_un;
149 int ret;
150
151 iov.iov_base = &dummy;
152 iov.iov_len = 1;
153 msg.msg_name = NULL;
154 msg.msg_namelen = 0;
155 msg.msg_iov = &iov;
156 msg.msg_iovlen = 1;
157 msg.msg_flags = 0;
158 msg.msg_control = cm_un.buffer;
159 msg.msg_controllen = sizeof(cm_un.buffer);
Carl Shapirode750892010-06-08 16:37:12 -0700160
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800161 cmsg = CMSG_FIRSTHDR(&msg);
162 cmsg->cmsg_len = msg.msg_controllen;
163 cmsg->cmsg_level = SOL_SOCKET;
164 cmsg->cmsg_type = SCM_RIGHTS;
Carl Shapirod5c36b92011-04-15 18:38:06 -0700165 ((int*)(void*)CMSG_DATA(cmsg))[0] = -1;
Carl Shapirode750892010-06-08 16:37:12 -0700166
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800167 do {
168 ret = recvmsg(netState->controlSock, &msg, 0);
169 } while (ret < 0 && errno == EINTR);
170
Andy McFadden6196d152009-06-03 15:53:27 -0700171 if (ret <= 0) {
172 if (ret < 0) {
173 LOGW("receiving file descriptor from ADB failed (socket %d): %s\n",
174 netState->controlSock, strerror(errno));
175 } else {
Andy McFadden43eb5012010-02-01 16:56:53 -0800176 LOGD("adbd disconnected\n");
Andy McFadden6196d152009-06-03 15:53:27 -0700177 }
Andy McFadden305efe62009-05-28 14:55:57 -0700178 close(netState->controlSock);
179 netState->controlSock = -1;
Andy McFadden6196d152009-06-03 15:53:27 -0700180 return -1;
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800181 }
182
Carl Shapirod5c36b92011-04-15 18:38:06 -0700183 return ((int*)(void*)CMSG_DATA(cmsg))[0];
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800184}
185
186/*
187 * Block forever, waiting for a debugger to connect to us. Called from the
188 * JDWP thread.
189 *
190 * This needs to un-block and return "false" if the VM is shutting down. It
191 * should return "true" when it successfully accepts a connection.
192 */
193static bool acceptConnection(struct JdwpState* state)
194{
195 JdwpNetState* netState = state->netState;
Andy McFadden305efe62009-05-28 14:55:57 -0700196 int retryCount = 0;
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800197
198 /* first, ensure that we get a connection to the ADB daemon */
Carl Shapirode750892010-06-08 16:37:12 -0700199
Andy McFadden305efe62009-05-28 14:55:57 -0700200retry:
Andy McFadden201a6b52009-06-02 14:15:22 -0700201 if (netState->shuttingDown)
202 return false;
203
204 if (netState->controlSock < 0) {
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800205 int sleep_ms = 500;
206 const int sleep_max_ms = 2*1000;
207 char buff[5];
208
209 netState->controlSock = socket(PF_UNIX, SOCK_STREAM, 0);
210 if (netState->controlSock < 0) {
211 LOGE("Could not create ADB control socket:%s\n",
212 strerror(errno));
213 return false;
214 }
215
216 if (pipe(netState->wakeFds) < 0) {
217 LOGE("pipe failed");
218 return false;
219 }
220
221 snprintf(buff, sizeof(buff), "%04x", getpid());
222 buff[4] = 0;
223
224 for (;;) {
Andy McFadden305efe62009-05-28 14:55:57 -0700225 /*
226 * If adbd isn't running, because USB debugging was disabled or
227 * perhaps the system is restarting it for "adb root", the
228 * connect() will fail. We loop here forever waiting for it
229 * to come back.
230 *
231 * Waking up and polling every couple of seconds is generally a
232 * bad thing to do, but we only do this if the application is
233 * debuggable *and* adbd isn't running. Still, for the sake
234 * of battery life, we should consider timing out and giving
235 * up after a few minutes in case somebody ships an app with
236 * the debuggable flag set.
237 */
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800238 int ret = connect(netState->controlSock,
239 &netState->controlAddr.controlAddrPlain,
240 netState->controlAddrLen);
241 if (!ret) {
242 /* now try to send our pid to the ADB daemon */
243 do {
244 ret = send( netState->controlSock, buff, 4, 0 );
245 } while (ret < 0 && errno == EINTR);
246
247 if (ret >= 0) {
248 LOGV("PID sent as '%.*s' to ADB\n", 4, buff);
249 break;
250 }
251
252 LOGE("Weird, can't send JDWP process pid to ADB: %s\n",
253 strerror(errno));
254 return false;
255 }
256 LOGV("Can't connect to ADB control socket:%s\n",
257 strerror(errno));
258
259 usleep( sleep_ms*1000 );
260
261 sleep_ms += (sleep_ms >> 1);
262 if (sleep_ms > sleep_max_ms)
263 sleep_ms = sleep_max_ms;
264 }
265 }
266
267 LOGV("trying to receive file descriptor from ADB\n");
268 /* now we can receive a client file descriptor */
269 netState->clientSock = receiveClientFd(netState);
Andy McFadden201a6b52009-06-02 14:15:22 -0700270 if (netState->shuttingDown)
271 return false; // suppress logs and additional activity
272
Andy McFadden6196d152009-06-03 15:53:27 -0700273 if (netState->clientSock < 0) {
Andy McFadden305efe62009-05-28 14:55:57 -0700274 if (++retryCount > 5) {
Andy McFadden6196d152009-06-03 15:53:27 -0700275 LOGE("adb connection max retries exceeded\n");
Andy McFadden305efe62009-05-28 14:55:57 -0700276 return false;
277 }
278 goto retry;
279 } else {
280 LOGV("received file descriptor %d from ADB\n", netState->clientSock);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800281 netState->awaitingHandshake = 1;
282 netState->inputCount = 0;
Andy McFadden305efe62009-05-28 14:55:57 -0700283 return true;
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800284 }
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800285}
286
287/*
288 * Connect out to a debugger (for server=n). Not required.
289 */
290static bool establishConnection(struct JdwpState* state)
291{
292 return false;
293}
294
295/*
296 * Close a connection from a debugger (which may have already dropped us).
297 * Only called from the JDWP thread.
298 */
299static void closeConnection(struct JdwpState* state)
300{
301 JdwpNetState* netState;
302
303 assert(state != NULL && state->netState != NULL);
304
305 netState = state->netState;
306 if (netState->clientSock < 0)
307 return;
308
309 LOGV("+++ closed JDWP <-> ADB connection\n");
310
311 close(netState->clientSock);
312 netState->clientSock = -1;
313}
314
315/*
316 * Close all network stuff, including the socket we use to listen for
317 * new connections.
318 *
319 * May be called from a non-JDWP thread, e.g. when the VM is shutting down.
320 */
321static void adbStateShutdown(struct JdwpNetState* netState)
322{
323 int controlSock;
324 int clientSock;
325
326 if (netState == NULL)
327 return;
328
Andy McFadden201a6b52009-06-02 14:15:22 -0700329 netState->shuttingDown = true;
330
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800331 clientSock = netState->clientSock;
332 if (clientSock >= 0) {
333 shutdown(clientSock, SHUT_RDWR);
334 netState->clientSock = -1;
335 }
336
337 controlSock = netState->controlSock;
338 if (controlSock >= 0) {
339 shutdown(controlSock, SHUT_RDWR);
340 netState->controlSock = -1;
341 }
Carl Shapirode750892010-06-08 16:37:12 -0700342
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800343 if (netState->wakeFds[1] >= 0) {
344 LOGV("+++ writing to wakePipe\n");
Carl Shapiro1e1433e2011-04-20 16:51:38 -0700345 write(netState->wakeFds[1], "", 1);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800346 }
347}
348
349static void netShutdown(JdwpState* state)
350{
351 adbStateShutdown(state->netState);
352}
353
354/*
355 * Free up anything we put in state->netState. This is called after
356 * "netShutdown", after the JDWP thread has stopped.
357 */
358static void netFree(struct JdwpState* state)
359{
360 JdwpNetState* netState = state->netState;
361
362 adbStateFree(netState);
363}
364
365/*
366 * Is a debugger connected to us?
367 */
368static bool isConnected(struct JdwpState* state)
369{
370 return (state->netState != NULL &&
371 state->netState->clientSock >= 0);
372}
373
374/*
375 * Are we still waiting for the JDWP handshake?
376 */
377static bool awaitingHandshake(struct JdwpState* state)
378{
379 return state->netState->awaitingHandshake;
380}
381
382/*
383 * Figure out if we have a full packet in the buffer.
384 */
385static bool haveFullPacket(JdwpNetState* netState)
386{
387 long length;
388
389 if (netState->awaitingHandshake)
390 return (netState->inputCount >= (int) kMagicHandshakeLen);
391
392 if (netState->inputCount < 4)
393 return false;
394
395 length = get4BE(netState->inputBuffer);
396 return (netState->inputCount >= length);
397}
398
399/*
400 * Consume bytes from the buffer.
401 *
402 * This would be more efficient with a circular buffer. However, we're
403 * usually only going to find one packet, which is trivial to handle.
404 */
405static void consumeBytes(JdwpNetState* netState, int count)
406{
407 assert(count > 0);
408 assert(count <= netState->inputCount);
409
410 if (count == netState->inputCount) {
411 netState->inputCount = 0;
412 return;
413 }
414
415 memmove(netState->inputBuffer, netState->inputBuffer + count,
416 netState->inputCount - count);
417 netState->inputCount -= count;
418}
419
420/*
421 * Handle a packet. Returns "false" if we encounter a connection-fatal error.
422 */
423static bool handlePacket(JdwpState* state)
424{
425 JdwpNetState* netState = state->netState;
426 const unsigned char* buf = netState->inputBuffer;
427 JdwpReqHeader hdr;
428 u4 length, id;
429 u1 flags, cmdSet, cmd;
430 u2 error;
431 bool reply;
432 int dataLen;
433
434 cmd = cmdSet = 0; // shut up gcc
435
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800436 length = read4BE(&buf);
437 id = read4BE(&buf);
438 flags = read1(&buf);
439 if ((flags & kJDWPFlagReply) != 0) {
440 reply = true;
441 error = read2BE(&buf);
442 } else {
443 reply = false;
444 cmdSet = read1(&buf);
445 cmd = read1(&buf);
446 }
447
448 assert((int) length <= netState->inputCount);
449 dataLen = length - (buf - netState->inputBuffer);
450
451 if (!reply) {
452 ExpandBuf* pReply = expandBufAlloc();
453
454 hdr.length = length;
455 hdr.id = id;
456 hdr.cmdSet = cmdSet;
457 hdr.cmd = cmd;
458 dvmJdwpProcessRequest(state, &hdr, buf, dataLen, pReply);
459 if (expandBufGetLength(pReply) > 0) {
460 int cc;
461
462 /*
463 * TODO: we currently assume the write() will complete in one
464 * go, which may not be safe for a network socket. We may need
465 * to mutex this against sendRequest().
466 */
467 cc = write(netState->clientSock, expandBufGetBuffer(pReply),
468 expandBufGetLength(pReply));
469 if (cc != (int) expandBufGetLength(pReply)) {
470 LOGE("Failed sending reply to debugger: %s\n", strerror(errno));
471 expandBufFree(pReply);
472 return false;
473 }
474 } else {
475 LOGW("No reply created for set=%d cmd=%d\n", cmdSet, cmd);
476 }
477 expandBufFree(pReply);
478 } else {
479 LOGV("reply?!\n");
480 assert(false);
481 }
482
483 LOGV("----------\n");
484
485 consumeBytes(netState, length);
486 return true;
487}
488
489/*
490 * Process incoming data. If no data is available, this will block until
491 * some arrives.
492 *
493 * If we get a full packet, handle it.
494 *
495 * To take some of the mystery out of life, we want to reject incoming
496 * connections if we already have a debugger attached. If we don't, the
497 * debugger will just mysteriously hang until it times out. We could just
498 * close the listen socket, but there's a good chance we won't be able to
499 * bind to the same port again, which would confuse utilities.
500 *
501 * Returns "false" on error (indicating that the connection has been severed),
502 * "true" if things are still okay.
503 */
504static bool processIncoming(JdwpState* state)
505{
506 JdwpNetState* netState = state->netState;
507 int readCount;
508
509 assert(netState->clientSock >= 0);
510
511 if (!haveFullPacket(netState)) {
512 /* read some more, looping until we have data */
513 errno = 0;
514 while (1) {
515 int selCount;
516 fd_set readfds;
517 int maxfd = -1;
518 int fd;
519
520 FD_ZERO(&readfds);
521
522 /* configure fds; note these may get zapped by another thread */
523 fd = netState->controlSock;
524 if (fd >= 0) {
525 FD_SET(fd, &readfds);
526 if (maxfd < fd)
527 maxfd = fd;
528 }
529 fd = netState->clientSock;
530 if (fd >= 0) {
531 FD_SET(fd, &readfds);
532 if (maxfd < fd)
533 maxfd = fd;
534 }
535 fd = netState->wakeFds[0];
536 if (fd >= 0) {
537 FD_SET(fd, &readfds);
538 if (maxfd < fd)
539 maxfd = fd;
540 } else {
541 LOGI("NOTE: entering select w/o wakepipe\n");
542 }
543
544 if (maxfd < 0) {
545 LOGV("+++ all fds are closed\n");
546 return false;
547 }
548
549 /*
550 * Select blocks until it sees activity on the file descriptors.
551 * Closing the local file descriptor does not count as activity,
552 * so we can't rely on that to wake us up (it works for read()
553 * and accept(), but not select()).
554 *
555 * We can do one of three things: (1) send a signal and catch
556 * EINTR, (2) open an additional fd ("wakePipe") and write to
557 * it when it's time to exit, or (3) time out periodically and
558 * re-issue the select. We're currently using #2, as it's more
559 * reliable than #1 and generally better than #3. Wastes two fds.
560 */
561 selCount = select(maxfd+1, &readfds, NULL, NULL, NULL);
562 if (selCount < 0) {
563 if (errno == EINTR)
564 continue;
565 LOGE("select failed: %s\n", strerror(errno));
566 goto fail;
567 }
568
569 if (netState->wakeFds[0] >= 0 &&
570 FD_ISSET(netState->wakeFds[0], &readfds))
571 {
572 LOGD("Got wake-up signal, bailing out of select\n");
573 goto fail;
574 }
575 if (netState->controlSock >= 0 &&
576 FD_ISSET(netState->controlSock, &readfds))
577 {
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800578 int sock = receiveClientFd(netState);
Andy McFadden6196d152009-06-03 15:53:27 -0700579 if (sock >= 0) {
580 LOGI("Ignoring second debugger -- accepting and dropping\n");
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800581 close(sock);
Andy McFadden6196d152009-06-03 15:53:27 -0700582 } else {
583 assert(netState->controlSock < 0);
584 /*
585 * Remote side most likely went away, so our next read
586 * on netState->clientSock will fail and throw us out
587 * of the loop.
588 */
589 }
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800590 }
591 if (netState->clientSock >= 0 &&
592 FD_ISSET(netState->clientSock, &readfds))
593 {
594 readCount = read(netState->clientSock,
595 netState->inputBuffer + netState->inputCount,
596 sizeof(netState->inputBuffer) - netState->inputCount);
597 if (readCount < 0) {
598 /* read failed */
599 if (errno != EINTR)
600 goto fail;
601 LOGD("+++ EINTR hit\n");
602 return true;
603 } else if (readCount == 0) {
604 /* EOF hit -- far end went away */
Andy McFadden305efe62009-05-28 14:55:57 -0700605 LOGV("+++ peer disconnected\n");
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800606 goto fail;
607 } else
608 break;
609 }
610 }
611
612 netState->inputCount += readCount;
613 if (!haveFullPacket(netState))
614 return true; /* still not there yet */
615 }
616
617 /*
618 * Special-case the initial handshake. For some bizarre reason we're
619 * expected to emulate bad tty settings by echoing the request back
620 * exactly as it was sent. Note the handshake is always initiated by
621 * the debugger, no matter who connects to whom.
622 *
623 * Other than this one case, the protocol [claims to be] stateless.
624 */
625 if (netState->awaitingHandshake) {
626 int cc;
627
628 if (memcmp(netState->inputBuffer,
629 kMagicHandshake, kMagicHandshakeLen) != 0)
630 {
631 LOGE("ERROR: bad handshake '%.14s'\n", netState->inputBuffer);
632 goto fail;
633 }
634
635 errno = 0;
636 cc = write(netState->clientSock, netState->inputBuffer,
637 kMagicHandshakeLen);
638 if (cc != kMagicHandshakeLen) {
639 LOGE("Failed writing handshake bytes: %s (%d of %d)\n",
640 strerror(errno), cc, (int) kMagicHandshakeLen);
641 goto fail;
642 }
643
644 consumeBytes(netState, kMagicHandshakeLen);
645 netState->awaitingHandshake = false;
646 LOGV("+++ handshake complete\n");
647 return true;
648 }
649
650 /*
651 * Handle this packet.
652 */
653 return handlePacket(state);
654
655fail:
656 closeConnection(state);
657 return false;
658}
659
660/*
661 * Send a request.
662 *
663 * The entire packet must be sent with a single write() call to avoid
664 * threading issues.
665 *
666 * Returns "true" if it was sent successfully.
667 */
668static bool sendRequest(JdwpState* state, ExpandBuf* pReq)
669{
670 JdwpNetState* netState = state->netState;
671 int cc;
672
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800673 if (netState->clientSock < 0) {
674 /* can happen with some DDMS events */
675 LOGV("NOT sending request -- no debugger is attached\n");
676 return false;
677 }
678
679 /*
680 * TODO: we currently assume the write() will complete in one
681 * go, which may not be safe for a network socket. We may need
682 * to mutex this against handlePacket().
683 */
684 errno = 0;
685 cc = write(netState->clientSock, expandBufGetBuffer(pReq),
686 expandBufGetLength(pReq));
687 if (cc != (int) expandBufGetLength(pReq)) {
688 LOGE("Failed sending req to debugger: %s (%d of %d)\n",
689 strerror(errno), cc, (int) expandBufGetLength(pReq));
690 return false;
691 }
692
693 return true;
694}
695
Andy McFadden5442d462009-12-17 16:21:36 -0800696/*
Andy McFadden01718122010-01-22 16:36:30 -0800697 * Send a request that was split into multiple buffers.
Andy McFadden5442d462009-12-17 16:21:36 -0800698 *
699 * The entire packet must be sent with a single writev() call to avoid
700 * threading issues.
701 *
702 * Returns "true" if it was sent successfully.
703 */
Andy McFadden01718122010-01-22 16:36:30 -0800704static bool sendBufferedRequest(JdwpState* state, const struct iovec* iov,
705 int iovcnt)
Andy McFadden5442d462009-12-17 16:21:36 -0800706{
707 JdwpNetState* netState = state->netState;
708
Andy McFadden5442d462009-12-17 16:21:36 -0800709 if (netState->clientSock < 0) {
710 /* can happen with some DDMS events */
711 LOGV("NOT sending request -- no debugger is attached\n");
712 return false;
713 }
714
Andy McFadden01718122010-01-22 16:36:30 -0800715 size_t expected = 0;
716 int i;
717 for (i = 0; i < iovcnt; i++)
718 expected += iov[i].iov_len;
Andy McFadden5442d462009-12-17 16:21:36 -0800719
720 /*
721 * TODO: we currently assume the writev() will complete in one
722 * go, which may not be safe for a network socket. We may need
723 * to mutex this against handlePacket().
724 */
725 ssize_t actual;
726 actual = writev(netState->clientSock, iov, iovcnt);
Andy McFadden01718122010-01-22 16:36:30 -0800727 if ((size_t)actual != expected) {
Andy McFadden5442d462009-12-17 16:21:36 -0800728 LOGE("Failed sending b-req to debugger: %s (%d of %zu)\n",
Andy McFadden01718122010-01-22 16:36:30 -0800729 strerror(errno), (int) actual, expected);
Andy McFadden5442d462009-12-17 16:21:36 -0800730 return false;
731 }
732
733 return true;
734}
735
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800736
737/*
738 * Our functions.
739 */
740static const JdwpTransport socketTransport = {
741 startup,
742 acceptConnection,
743 establishConnection,
744 closeConnection,
745 netShutdown,
746 netFree,
747 isConnected,
748 awaitingHandshake,
749 processIncoming,
Andy McFadden5442d462009-12-17 16:21:36 -0800750 sendRequest,
751 sendBufferedRequest
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800752};
753
754/*
755 * Return our set.
756 */
Carl Shapiro1e1433e2011-04-20 16:51:38 -0700757const JdwpTransport* dvmJdwpAndroidAdbTransport()
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800758{
759 return &socketTransport;
760}