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