• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
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 /*
17  * JDWP TCP socket network code.
18  */
19 #include "jdwp/JdwpPriv.h"
20 #include "jdwp/JdwpHandler.h"
21 #include "Bits.h"
22 
23 #include <stdlib.h>
24 #include <unistd.h>
25 #include <stdio.h>
26 #include <string.h>
27 #include <errno.h>
28 #include <sys/types.h>
29 #include <sys/socket.h>
30 #include <netinet/in.h>
31 #include <netinet/tcp.h>
32 #include <arpa/inet.h>
33 #include <netdb.h>
34 
35 #define kBasePort           8000
36 #define kMaxPort            8040
37 
38 #define kInputBufferSize    8192
39 
40 #define kMagicHandshake     "JDWP-Handshake"
41 #define kMagicHandshakeLen  (sizeof(kMagicHandshake)-1)
42 
43 // fwd
44 static void netShutdown(JdwpNetState* state);
45 static void netFree(JdwpNetState* state);
46 
47 
48 /*
49  * JDWP network state.
50  *
51  * We only talk to one debugger at a time.
52  */
53 struct JdwpNetState : public JdwpNetStateBase {
54     short   listenPort;
55     int     listenSock;         /* listen for connection from debugger */
56     int     wakePipe[2];        /* break out of select */
57 
58     struct in_addr remoteAddr;
59     unsigned short remotePort;
60 
61     bool    awaitingHandshake;  /* waiting for "JDWP-Handshake" */
62 
63     /* pending data from the network; would be more efficient as circular buf */
64     unsigned char  inputBuffer[kInputBufferSize];
65     int     inputCount;
66 
JdwpNetStateJdwpNetState67     JdwpNetState()
68     {
69         listenPort  = 0;
70         listenSock  = -1;
71         wakePipe[0] = -1;
72         wakePipe[1] = -1;
73 
74         awaitingHandshake = false;
75 
76         inputCount = 0;
77     }
78 };
79 
80 static JdwpNetState* netStartup(short port);
81 
82 /*
83  * Set up some stuff for transport=dt_socket.
84  */
prepareSocket(JdwpState * state,const JdwpStartupParams * pParams)85 static bool prepareSocket(JdwpState* state, const JdwpStartupParams* pParams)
86 {
87     unsigned short port;
88 
89     if (pParams->server) {
90         if (pParams->port != 0) {
91             /* try only the specified port */
92             port = pParams->port;
93             state->netState = netStartup(port);
94         } else {
95             /* scan through a range of ports, binding to the first available */
96             for (port = kBasePort; port <= kMaxPort; port++) {
97                 state->netState = netStartup(port);
98                 if (state->netState != NULL)
99                     break;
100             }
101         }
102         if (state->netState == NULL) {
103             ALOGE("JDWP net startup failed (req port=%d)", pParams->port);
104             return false;
105         }
106     } else {
107         port = pParams->port;   // used in a debug msg later
108         state->netState = netStartup(-1);
109     }
110 
111     if (pParams->suspend)
112         ALOGI("JDWP will wait for debugger on port %d", port);
113     else
114         ALOGD("JDWP will %s on port %d",
115             pParams->server ? "listen" : "connect", port);
116 
117     return true;
118 }
119 
120 
121 /*
122  * Are we still waiting for the handshake string?
123  */
awaitingHandshake(JdwpState * state)124 static bool awaitingHandshake(JdwpState* state)
125 {
126     return state->netState->awaitingHandshake;
127 }
128 
129 /*
130  * Initialize JDWP stuff.
131  *
132  * Allocates a new state structure.  If "port" is non-negative, this also
133  * tries to bind to a listen port.  If "port" is less than zero, we assume
134  * we're preparing for an outbound connection, and return without binding
135  * to anything.
136  *
137  * This may be called several times if we're probing for a port.
138  *
139  * Returns 0 on success.
140  */
netStartup(short port)141 static JdwpNetState* netStartup(short port)
142 {
143     int one = 1;
144     JdwpNetState* netState = new JdwpNetState;
145 
146     if (port < 0)
147         return netState;
148 
149     assert(port != 0);
150 
151     netState->listenSock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
152     if (netState->listenSock < 0) {
153         ALOGE("Socket create failed: %s", strerror(errno));
154         goto fail;
155     }
156 
157     /* allow immediate re-use */
158     if (setsockopt(netState->listenSock, SOL_SOCKET, SO_REUSEADDR, &one,
159             sizeof(one)) < 0)
160     {
161         ALOGE("setsockopt(SO_REUSEADDR) failed: %s", strerror(errno));
162         goto fail;
163     }
164 
165     union {
166         struct sockaddr_in  addrInet;
167         struct sockaddr     addrPlain;
168     } addr;
169     addr.addrInet.sin_family = AF_INET;
170     addr.addrInet.sin_port = htons(port);
171     inet_aton("127.0.0.1", &addr.addrInet.sin_addr);
172 
173     if (bind(netState->listenSock, &addr.addrPlain, sizeof(addr)) != 0) {
174         ALOGV("attempt to bind to port %u failed: %s", port, strerror(errno));
175         goto fail;
176     }
177 
178     netState->listenPort = port;
179     LOGVV("+++ bound to port %d", netState->listenPort);
180 
181     if (listen(netState->listenSock, 5) != 0) {
182         ALOGE("Listen failed: %s", strerror(errno));
183         goto fail;
184     }
185 
186     return netState;
187 
188 fail:
189     netShutdown(netState);
190     netFree(netState);
191     return NULL;
192 }
193 
194 /*
195  * Shut down JDWP listener.  Don't free state.
196  *
197  * Note that "netState" may be partially initialized if "startup" failed.
198  *
199  * This may be called from a non-JDWP thread as part of shutting the
200  * JDWP thread down.
201  *
202  * (This is currently called several times during startup as we probe
203  * for an open port.)
204  */
netShutdown(JdwpNetState * netState)205 static void netShutdown(JdwpNetState* netState)
206 {
207     if (netState == NULL)
208         return;
209 
210     int listenSock = netState->listenSock;
211     int clientSock = netState->clientSock;
212 
213     /* clear these out so it doesn't wake up and try to reuse them */
214     netState->listenSock = netState->clientSock = -1;
215 
216     /* "shutdown" dislodges blocking read() and accept() calls */
217     if (listenSock >= 0) {
218         shutdown(listenSock, SHUT_RDWR);
219         close(listenSock);
220     }
221     if (clientSock >= 0) {
222         shutdown(clientSock, SHUT_RDWR);
223         close(clientSock);
224     }
225 
226     /* if we might be sitting in select, kick us loose */
227     if (netState->wakePipe[1] >= 0) {
228         ALOGV("+++ writing to wakePipe");
229         (void) write(netState->wakePipe[1], "", 1);
230     }
231 }
netShutdownExtern(JdwpState * state)232 static void netShutdownExtern(JdwpState* state)
233 {
234     netShutdown(state->netState);
235 }
236 
237 /*
238  * Free JDWP state.
239  *
240  * Call this after shutting the network down with netShutdown().
241  */
netFree(JdwpNetState * netState)242 static void netFree(JdwpNetState* netState)
243 {
244     if (netState == NULL)
245         return;
246     assert(netState->listenSock == -1);
247     assert(netState->clientSock == -1);
248 
249     if (netState->wakePipe[0] >= 0) {
250         close(netState->wakePipe[0]);
251         netState->wakePipe[0] = -1;
252     }
253     if (netState->wakePipe[1] >= 0) {
254         close(netState->wakePipe[1]);
255         netState->wakePipe[1] = -1;
256     }
257 
258     delete netState;
259 }
netFreeExtern(JdwpState * state)260 static void netFreeExtern(JdwpState* state)
261 {
262     netFree(state->netState);
263 }
264 
265 /*
266  * Returns "true" if we're connected to a debugger.
267  */
isConnected(JdwpState * state)268 static bool isConnected(JdwpState* state)
269 {
270     return (state->netState != NULL &&
271             state->netState->clientSock >= 0);
272 }
273 
274 /*
275  * Returns "true" if the fd is ready, "false" if not.
276  */
277 #if 0
278 static bool isFdReadable(int sock)
279 {
280     fd_set readfds;
281     struct timeval tv;
282     int count;
283 
284     FD_ZERO(&readfds);
285     FD_SET(sock, &readfds);
286 
287     tv.tv_sec = 0;
288     tv.tv_usec = 0;
289     count = select(sock+1, &readfds, NULL, NULL, &tv);
290     if (count <= 0)
291         return false;
292 
293     if (FD_ISSET(sock, &readfds))   /* make sure it's our fd */
294         return true;
295 
296     ALOGE("WEIRD: odd behavior in select (count=%d)", count);
297     return false;
298 }
299 #endif
300 
301 #if 0
302 /*
303  * Check to see if we have a pending connection from the debugger.
304  *
305  * Returns true on success (meaning a connection is available).
306  */
307 static bool checkConnection(JdwpState* state)
308 {
309     JdwpNetState* netState = state->netState;
310 
311     assert(netState->listenSock >= 0);
312     /* not expecting to be called when debugger is actively connected */
313     assert(netState->clientSock < 0);
314 
315     if (!isFdReadable(netState->listenSock))
316         return false;
317     return true;
318 }
319 #endif
320 
321 /*
322  * Disable the TCP Nagle algorithm, which delays transmission of outbound
323  * packets until the previous transmissions have been acked.  JDWP does a
324  * lot of back-and-forth with small packets, so this may help.
325  */
setNoDelay(int fd)326 static int setNoDelay(int fd)
327 {
328     int cc, on = 1;
329 
330     cc = setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &on, sizeof(on));
331     assert(cc == 0);
332     return cc;
333 }
334 
335 /*
336  * Accept a connection.  This will block waiting for somebody to show up.
337  * If that's not desirable, use checkConnection() to make sure something
338  * is pending.
339  */
acceptConnection(JdwpState * state)340 static bool acceptConnection(JdwpState* state)
341 {
342     JdwpNetState* netState = state->netState;
343     union {
344         struct sockaddr_in  addrInet;
345         struct sockaddr     addrPlain;
346     } addr;
347     socklen_t addrlen;
348     int sock;
349 
350     if (netState->listenSock < 0)
351         return false;       /* you're not listening! */
352 
353     assert(netState->clientSock < 0);      /* must not already be talking */
354 
355     addrlen = sizeof(addr);
356     do {
357         sock = accept(netState->listenSock, &addr.addrPlain, &addrlen);
358         if (sock < 0 && errno != EINTR) {
359             // When we call shutdown() on the socket, accept() returns with
360             // EINVAL.  Don't gripe about it.
361             if (errno == EINVAL)
362                 LOGVV("accept failed: %s", strerror(errno));
363             else
364                 ALOGE("accept failed: %s", strerror(errno));
365             return false;
366         }
367     } while (sock < 0);
368 
369     netState->remoteAddr = addr.addrInet.sin_addr;
370     netState->remotePort = ntohs(addr.addrInet.sin_port);
371     ALOGV("+++ accepted connection from %s:%u",
372         inet_ntoa(netState->remoteAddr), netState->remotePort);
373 
374     netState->clientSock = sock;
375     netState->awaitingHandshake = true;
376     netState->inputCount = 0;
377 
378     ALOGV("Setting TCP_NODELAY on accepted socket");
379     setNoDelay(netState->clientSock);
380 
381     if (pipe(netState->wakePipe) < 0) {
382         ALOGE("pipe failed");
383         return false;
384     }
385 
386     return true;
387 }
388 
389 /*
390  * Create a connection to a waiting debugger.
391  */
establishConnection(JdwpState * state)392 static bool establishConnection(JdwpState* state)
393 {
394     union {
395         struct sockaddr_in  addrInet;
396         struct sockaddr     addrPlain;
397     } addr;
398     struct hostent* pEntry;
399     int h_errno;
400 
401     assert(state != NULL && state->netState != NULL);
402     assert(!state->params.server);
403     assert(state->params.host[0] != '\0');
404     assert(state->params.port != 0);
405 
406     /*
407      * Start by resolving the host name.
408      */
409 //#undef HAVE_GETHOSTBYNAME_R
410 //#warning "forcing non-R"
411 #ifdef HAVE_GETHOSTBYNAME_R
412     struct hostent he;
413     char auxBuf[128];
414     int cc = gethostbyname_r(state->params.host, &he, auxBuf, sizeof(auxBuf),
415             &pEntry, &h_errno);
416     if (cc != 0) {
417         ALOGW("gethostbyname_r('%s') failed: %s",
418             state->params.host, strerror(errno));
419         return false;
420     }
421 
422 #else
423     h_errno = 0;
424     pEntry = gethostbyname(state->params.host);
425     if (pEntry == NULL) {
426         ALOGW("gethostbyname('%s') failed: %s",
427             state->params.host, strerror(h_errno));
428         return false;
429     }
430 #endif
431 
432     /* copy it out ASAP to minimize risk of multithreaded annoyances */
433     memcpy(&addr.addrInet.sin_addr, pEntry->h_addr, pEntry->h_length);
434     addr.addrInet.sin_family = pEntry->h_addrtype;
435 
436     addr.addrInet.sin_port = htons(state->params.port);
437 
438     ALOGI("Connecting out to '%s' %d",
439         inet_ntoa(addr.addrInet.sin_addr), ntohs(addr.addrInet.sin_port));
440 
441     /*
442      * Create a socket.
443      */
444     JdwpNetState* netState;
445     netState = state->netState;
446     netState->clientSock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
447     if (netState->clientSock < 0) {
448         ALOGE("Unable to create socket: %s", strerror(errno));
449         return false;
450     }
451 
452     /*
453      * Try to connect.
454      */
455     if (connect(netState->clientSock, &addr.addrPlain, sizeof(addr)) != 0) {
456         ALOGE("Unable to connect to %s:%d: %s",
457             inet_ntoa(addr.addrInet.sin_addr), ntohs(addr.addrInet.sin_port),
458             strerror(errno));
459         close(netState->clientSock);
460         netState->clientSock = -1;
461         return false;
462     }
463 
464     ALOGI("Connection established to %s (%s:%d)",
465         state->params.host, inet_ntoa(addr.addrInet.sin_addr),
466         ntohs(addr.addrInet.sin_port));
467     netState->awaitingHandshake = true;
468     netState->inputCount = 0;
469 
470     setNoDelay(netState->clientSock);
471 
472     if (pipe(netState->wakePipe) < 0) {
473         ALOGE("pipe failed");
474         return false;
475     }
476 
477     return true;
478 }
479 
480 /*
481  * Close the connection to the debugger.
482  *
483  * Reset the state so we're ready to receive a new connection.
484  */
closeConnection(JdwpState * state)485 static void closeConnection(JdwpState* state)
486 {
487     JdwpNetState* netState;
488 
489     assert(state != NULL && state->netState != NULL);
490 
491     netState = state->netState;
492     if (netState->clientSock < 0)
493         return;
494 
495     ALOGV("+++ closed connection to %s:%u",
496         inet_ntoa(netState->remoteAddr), netState->remotePort);
497 
498     close(netState->clientSock);
499     netState->clientSock = -1;
500 
501     return;
502 }
503 
504 /*
505  * Figure out if we have a full packet in the buffer.
506  */
haveFullPacket(JdwpNetState * netState)507 static bool haveFullPacket(JdwpNetState* netState)
508 {
509     long length;
510 
511     if (netState->awaitingHandshake)
512         return (netState->inputCount >= (int) kMagicHandshakeLen);
513 
514     if (netState->inputCount < 4)
515         return false;
516 
517     length = get4BE(netState->inputBuffer);
518     return (netState->inputCount >= length);
519 }
520 
521 /*
522  * Consume bytes from the buffer.
523  *
524  * This would be more efficient with a circular buffer.  However, we're
525  * usually only going to find one packet, which is trivial to handle.
526  */
consumeBytes(JdwpNetState * netState,int count)527 static void consumeBytes(JdwpNetState* netState, int count)
528 {
529     assert(count > 0);
530     assert(count <= netState->inputCount);
531 
532     if (count == netState->inputCount) {
533         netState->inputCount = 0;
534         return;
535     }
536 
537     memmove(netState->inputBuffer, netState->inputBuffer + count,
538         netState->inputCount - count);
539     netState->inputCount -= count;
540 }
541 
542 /*
543  * Dump the contents of a packet to stdout.
544  */
545 #if 0
546 static void dumpPacket(const unsigned char* packetBuf)
547 {
548     const unsigned char* buf = packetBuf;
549     u4 length, id;
550     u1 flags, cmdSet, cmd;
551     u2 error;
552     bool reply;
553     int dataLen;
554 
555     cmd = cmdSet = 0xcc;
556 
557     length = read4BE(&buf);
558     id = read4BE(&buf);
559     flags = read1(&buf);
560     if ((flags & kJDWPFlagReply) != 0) {
561         reply = true;
562         error = read2BE(&buf);
563     } else {
564         reply = false;
565         cmdSet = read1(&buf);
566         cmd = read1(&buf);
567     }
568 
569     dataLen = length - (buf - packetBuf);
570 
571     ALOGV("--- %s: dataLen=%u id=0x%08x flags=0x%02x cmd=%d/%d",
572         reply ? "reply" : "req",
573         dataLen, id, flags, cmdSet, cmd);
574     if (dataLen > 0)
575         dvmPrintHexDumpDbg(buf, dataLen, LOG_TAG);
576 }
577 #endif
578 
579 /*
580  * Handle a packet.  Returns "false" if we encounter a connection-fatal error.
581  */
handlePacket(JdwpState * state)582 static bool handlePacket(JdwpState* state)
583 {
584     JdwpNetState* netState = state->netState;
585     const unsigned char* buf = netState->inputBuffer;
586     JdwpReqHeader hdr;
587     u4 length, id;
588     u1 flags, cmdSet, cmd;
589     u2 error;
590     bool reply;
591     int dataLen;
592 
593     cmd = cmdSet = 0;       // shut up gcc
594 
595     /*dumpPacket(netState->inputBuffer);*/
596 
597     length = read4BE(&buf);
598     id = read4BE(&buf);
599     flags = read1(&buf);
600     if ((flags & kJDWPFlagReply) != 0) {
601         reply = true;
602         error = read2BE(&buf);
603     } else {
604         reply = false;
605         cmdSet = read1(&buf);
606         cmd = read1(&buf);
607     }
608 
609     assert((int) length <= netState->inputCount);
610     dataLen = length - (buf - netState->inputBuffer);
611 
612     if (!reply) {
613         ExpandBuf* pReply = expandBufAlloc();
614 
615         hdr.length = length;
616         hdr.id = id;
617         hdr.cmdSet = cmdSet;
618         hdr.cmd = cmd;
619         dvmJdwpProcessRequest(state, &hdr, buf, dataLen, pReply);
620         if (expandBufGetLength(pReply) > 0) {
621             ssize_t cc = netState->writePacket(pReply);
622 
623             if (cc != (ssize_t) expandBufGetLength(pReply)) {
624                 ALOGE("Failed sending reply to debugger: %s", strerror(errno));
625                 expandBufFree(pReply);
626                 return false;
627             }
628         } else {
629             ALOGW("No reply created for set=%d cmd=%d", cmdSet, cmd);
630         }
631         expandBufFree(pReply);
632     } else {
633         ALOGV("reply?!");
634         assert(false);
635     }
636 
637     ALOGV("----------");
638 
639     consumeBytes(netState, length);
640     return true;
641 }
642 
643 /*
644  * Process incoming data.  If no data is available, this will block until
645  * some arrives.
646  *
647  * If we get a full packet, handle it.
648  *
649  * To take some of the mystery out of life, we want to reject incoming
650  * connections if we already have a debugger attached.  If we don't, the
651  * debugger will just mysteriously hang until it times out.  We could just
652  * close the listen socket, but there's a good chance we won't be able to
653  * bind to the same port again, which would confuse utilities.
654  *
655  * Returns "false" on error (indicating that the connection has been severed),
656  * "true" if things are still okay.
657  */
processIncoming(JdwpState * state)658 static bool processIncoming(JdwpState* state)
659 {
660     JdwpNetState* netState = state->netState;
661     int readCount;
662 
663     assert(netState->clientSock >= 0);
664 
665     if (!haveFullPacket(netState)) {
666         /* read some more, looping until we have data */
667         errno = 0;
668         while (1) {
669             int selCount;
670             fd_set readfds;
671             int maxfd;
672             int fd;
673 
674             maxfd = netState->listenSock;
675             if (netState->clientSock > maxfd)
676                 maxfd = netState->clientSock;
677             if (netState->wakePipe[0] > maxfd)
678                 maxfd = netState->wakePipe[0];
679 
680             if (maxfd < 0) {
681                 ALOGV("+++ all fds are closed");
682                 return false;
683             }
684 
685             FD_ZERO(&readfds);
686 
687             /* configure fds; note these may get zapped by another thread */
688             fd = netState->listenSock;
689             if (fd >= 0)
690                 FD_SET(fd, &readfds);
691             fd = netState->clientSock;
692             if (fd >= 0)
693                 FD_SET(fd, &readfds);
694             fd = netState->wakePipe[0];
695             if (fd >= 0) {
696                 FD_SET(fd, &readfds);
697             } else {
698                 ALOGI("NOTE: entering select w/o wakepipe");
699             }
700 
701             /*
702              * Select blocks until it sees activity on the file descriptors.
703              * Closing the local file descriptor does not count as activity,
704              * so we can't rely on that to wake us up (it works for read()
705              * and accept(), but not select()).
706              *
707              * We can do one of three things: (1) send a signal and catch
708              * EINTR, (2) open an additional fd ("wakePipe") and write to
709              * it when it's time to exit, or (3) time out periodically and
710              * re-issue the select.  We're currently using #2, as it's more
711              * reliable than #1 and generally better than #3.  Wastes two fds.
712              */
713             selCount = select(maxfd+1, &readfds, NULL, NULL, NULL);
714             if (selCount < 0) {
715                 if (errno == EINTR)
716                     continue;
717                 ALOGE("select failed: %s", strerror(errno));
718                 goto fail;
719             }
720 
721             if (netState->wakePipe[0] >= 0 &&
722                 FD_ISSET(netState->wakePipe[0], &readfds))
723             {
724                 if (netState->listenSock >= 0)
725                     ALOGE("Exit wake set, but not exiting?");
726                 else
727                     ALOGD("Got wake-up signal, bailing out of select");
728                 goto fail;
729             }
730             if (netState->listenSock >= 0 &&
731                 FD_ISSET(netState->listenSock, &readfds))
732             {
733                 ALOGI("Ignoring second debugger -- accepting and dropping");
734                 union {
735                     struct sockaddr_in   addrInet;
736                     struct sockaddr      addrPlain;
737                 } addr;
738                 socklen_t addrlen;
739                 int tmpSock;
740                 tmpSock = accept(netState->listenSock, &addr.addrPlain,
741                                 &addrlen);
742                 if (tmpSock < 0)
743                     ALOGI("Weird -- accept failed");
744                 else
745                     close(tmpSock);
746             }
747             if (netState->clientSock >= 0 &&
748                 FD_ISSET(netState->clientSock, &readfds))
749             {
750                 readCount = read(netState->clientSock,
751                                 netState->inputBuffer + netState->inputCount,
752                     sizeof(netState->inputBuffer) - netState->inputCount);
753                 if (readCount < 0) {
754                     /* read failed */
755                     if (errno != EINTR)
756                         goto fail;
757                     ALOGD("+++ EINTR hit");
758                     return true;
759                 } else if (readCount == 0) {
760                     /* EOF hit -- far end went away */
761                     ALOGD("+++ peer disconnected");
762                     goto fail;
763                 } else
764                     break;
765             }
766         }
767 
768         netState->inputCount += readCount;
769         if (!haveFullPacket(netState))
770             return true;        /* still not there yet */
771     }
772 
773     /*
774      * Special-case the initial handshake.  For some bizarre reason we're
775      * expected to emulate bad tty settings by echoing the request back
776      * exactly as it was sent.  Note the handshake is always initiated by
777      * the debugger, no matter who connects to whom.
778      *
779      * Other than this one case, the protocol [claims to be] stateless.
780      */
781     if (netState->awaitingHandshake) {
782         int cc;
783 
784         if (memcmp(netState->inputBuffer,
785                 kMagicHandshake, kMagicHandshakeLen) != 0)
786         {
787             ALOGE("ERROR: bad handshake '%.14s'", netState->inputBuffer);
788             goto fail;
789         }
790 
791         errno = 0;
792         cc = write(netState->clientSock, netState->inputBuffer,
793                 kMagicHandshakeLen);
794         if (cc != kMagicHandshakeLen) {
795             ALOGE("Failed writing handshake bytes: %s (%d of %d)",
796                 strerror(errno), cc, (int) kMagicHandshakeLen);
797             goto fail;
798         }
799 
800         consumeBytes(netState, kMagicHandshakeLen);
801         netState->awaitingHandshake = false;
802         ALOGV("+++ handshake complete");
803         return true;
804     }
805 
806     /*
807      * Handle this packet.
808      */
809     return handlePacket(state);
810 
811 fail:
812     closeConnection(state);
813     return false;
814 }
815 
816 /*
817  * Send a request.
818  *
819  * The entire packet must be sent with a single write() call to avoid
820  * threading issues.
821  *
822  * Returns "true" if it was sent successfully.
823  */
sendRequest(JdwpState * state,ExpandBuf * pReq)824 static bool sendRequest(JdwpState* state, ExpandBuf* pReq)
825 {
826     JdwpNetState* netState = state->netState;
827 
828     /*dumpPacket(expandBufGetBuffer(pReq));*/
829     if (netState->clientSock < 0) {
830         /* can happen with some DDMS events */
831         ALOGV("NOT sending request -- no debugger is attached");
832         return false;
833     }
834 
835     errno = 0;
836     ssize_t cc = netState->writePacket(pReq);
837 
838     if (cc != (ssize_t) expandBufGetLength(pReq)) {
839         ALOGE("Failed sending req to debugger: %s (%d of %d)",
840             strerror(errno), (int) cc, (int) expandBufGetLength(pReq));
841         return false;
842     }
843 
844     return true;
845 }
846 
847 /*
848  * Send a request that was split into multiple buffers.
849  *
850  * The entire packet must be sent with a single writev() call to avoid
851  * threading issues.
852  *
853  * Returns "true" if it was sent successfully.
854  */
sendBufferedRequest(JdwpState * state,const struct iovec * iov,int iovcnt)855 static bool sendBufferedRequest(JdwpState* state, const struct iovec* iov,
856     int iovcnt)
857 {
858     JdwpNetState* netState = state->netState;
859 
860     if (netState->clientSock < 0) {
861         /* can happen with some DDMS events */
862         ALOGV("NOT sending request -- no debugger is attached");
863         return false;
864     }
865 
866     size_t expected = 0;
867     int i;
868     for (i = 0; i < iovcnt; i++)
869         expected += iov[i].iov_len;
870 
871     ssize_t actual = netState->writeBufferedPacket(iov, iovcnt);
872 
873     if ((size_t)actual != expected) {
874         ALOGE("Failed sending b-req to debugger: %s (%d of %zu)",
875             strerror(errno), (int) actual, expected);
876         return false;
877     }
878 
879     return true;
880 }
881 
882 
883 /*
884  * Our functions.
885  *
886  * We can't generally share the implementations with other transports,
887  * even if they're also socket-based, because our JdwpNetState will be
888  * different from theirs.
889  */
890 static const JdwpTransport socketTransport = {
891     prepareSocket,
892     acceptConnection,
893     establishConnection,
894     closeConnection,
895     netShutdownExtern,
896     netFreeExtern,
897     isConnected,
898     awaitingHandshake,
899     processIncoming,
900     sendRequest,
901     sendBufferedRequest,
902 };
903 
904 /*
905  * Return our set.
906  */
dvmJdwpSocketTransport()907 const JdwpTransport* dvmJdwpSocketTransport()
908 {
909     return &socketTransport;
910 }
911