JdwpSocket.cpp revision 062bf509a77fce9dfcb7e7b2e401cf2a124d83d5
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 : 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
67    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
80static JdwpNetState* netStartup(short port);
81
82/*
83 * Set up some stuff for transport=dt_socket.
84 */
85static 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            LOGE("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        LOGI("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 */
124static 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 */
141static 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        LOGE("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        LOGE("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        LOGE("Listen failed: %s", strerror(errno));
183        goto fail;
184    }
185
186    return netState;
187
188fail:
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 */
205static 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}
232static 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 */
242static 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}
260static void netFreeExtern(JdwpState* state)
261{
262    netFree(state->netState);
263}
264
265/*
266 * Returns "true" if we're connected to a debugger.
267 */
268static 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
278static 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    LOGE("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 */
307static 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 */
326static 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 */
340static 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                LOGE("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        LOGE("pipe failed");
383        return false;
384    }
385
386    return true;
387}
388
389/*
390 * Create a connection to a waiting debugger.
391 */
392static 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        LOGW("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        LOGW("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    LOGI("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        LOGE("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        LOGE("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    LOGI("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        LOGE("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 */
485static 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 */
507static 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 */
527static 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
546static 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 */
582static 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                LOGE("Failed sending reply to debugger: %s", strerror(errno));
625                expandBufFree(pReply);
626                return false;
627            }
628        } else {
629            LOGW("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 */
658static 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                LOGI("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                LOGE("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                    LOGE("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                LOGI("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                    LOGI("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            LOGE("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            LOGE("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
811fail:
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 */
824static 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        LOGE("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 */
855static 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        LOGE("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 */
890static 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 */
907const JdwpTransport* dvmJdwpSocketTransport()
908{
909    return &socketTransport;
910}
911