Ejemplo n.º 1
0
/*
 * Handle a packet.  Returns "false" if we encounter a connection-fatal error.
 */
static bool handlePacket(JdwpState* state)
{
    JdwpNetState* netState = state->netState;
    const unsigned char* buf = netState->inputBuffer;
    JdwpReqHeader hdr;
    u4 length, id;
    u1 flags, cmdSet, cmd;
    //u2 error;
    bool reply;
    int dataLen;

    cmd = cmdSet = 0;       // shut up gcc

    /*dumpPacket(netState->inputBuffer);*/

    length = read4BE(&buf);
    id = read4BE(&buf);
    flags = read1(&buf);
    if ((flags & kJDWPFlagReply) != 0) {
        reply = true;
        /*error =*/ read2BE(&buf);
    } else {
        reply = false;
        cmdSet = read1(&buf);
        cmd = read1(&buf);
    }

    assert((int) length <= netState->inputCount);
    dataLen = length - (buf - netState->inputBuffer);

    if (!reply) {
        ExpandBuf* pReply = expandBufAlloc();

        hdr.length = length;
        hdr.id = id;
        hdr.cmdSet = cmdSet;
        hdr.cmd = cmd;
        dvmJdwpProcessRequest(state, &hdr, buf, dataLen, pReply);
        if (expandBufGetLength(pReply) > 0) {
            ssize_t cc = netState->writePacket(pReply);

            if (cc != (ssize_t) expandBufGetLength(pReply)) {
                ALOGE("Failed sending reply to debugger: %s", strerror(errno));
                expandBufFree(pReply);
                return false;
            }
        } else {
            ALOGW("No reply created for set=%d cmd=%d", cmdSet, cmd);
        }
        expandBufFree(pReply);
    } else {
        ALOGV("reply?!");
        assert(false);
    }

    ALOGV("----------");

    consumeBytes(netState, length);
    return true;
}
Ejemplo n.º 2
0
/*
 * Handle incoming data.  If we have a full packet in the buffer, process it.
 */
static bool handleIncoming(Peer* pWritePeer, Peer* pReadPeer)
{
    if (haveFullPacket(pReadPeer)) {
        if (pReadPeer->awaitingHandshake) {
            printf("Handshake [%c]: %.14s\n",
                pReadPeer->label[0], pReadPeer->inputBuffer);
            if (write(pWritePeer->sock, pReadPeer->inputBuffer,
                    kMagicHandshakeLen) != kMagicHandshakeLen)
            {
                fprintf(stderr,
                    "+++ [%c] handshake write failed\n", pReadPeer->label[0]);
                goto fail;
            }
            consumeBytes(pReadPeer, kMagicHandshakeLen);
            pReadPeer->awaitingHandshake = false;
        } else {
            if (!handlePacket(pWritePeer, pReadPeer))
                goto fail;
        }
    } else {
        /*printf("*** %c not full yet\n", pReadPeer->label[0]);*/
    }

    return true;

fail:
    return false;
}
Ejemplo n.º 3
0
/*
 * Handle a packet.  Returns "false" if we encounter a connection-fatal error.
 */
static bool handlePacket(Peer* pDst, Peer* pSrc)
{
    const unsigned char* buf = pSrc->inputBuffer;
    u4 length;
    u1 flags;
    int cc;

    length = get4BE(buf+0);
    flags = get1(buf+9);

    assert((int) length <= pSrc->inputCount);

    dumpPacket(buf, pSrc->label, pDst->label);

    cc = write(pDst->sock, buf, length);
    if (cc != (int) length) {
        fprintf(stderr, "Failed sending packet: %s\n", strerror(errno));
        return false;
    }
    /*printf("*** wrote %d bytes from %c to %c\n",
        cc, pSrc->label[0], pDst->label[0]);*/

    consumeBytes(pSrc, length);
    return true;
}
Ejemplo n.º 4
0
/**
 * @brief Reads Null from `Reader`.
 * @param reader The JSONReader.
 * @return Null.
 */
static Null *readNull(JSONReader *reader) {

	consumeBytes(reader, "null");

	Null *null = $$(Null, null);

	return retain(null);
}
Ejemplo n.º 5
0
/**
 * @brief Reads a Boole from `reader`.
 * @param reader The JSONReader.
 * @return The Boole.
 */
static _Bool *readBoole(JSONReader *reader) {

	Boole *boolean = NULL;

	switch (*reader->b) {
		case 't':
			consumeBytes(reader, "true");
			boolean = $$(Boole, True);
			break;
		case 'f':
			consumeBytes(reader, "false");
			boolean = $$(Boole, False);
			break;
		default:
			assert(false);
	}

	return retain(boolean);
}
Ejemplo n.º 6
0
/*
 * Process incoming data.  If no data is available, this will block until
 * some arrives.
 *
 * If we get a full packet, handle it.
 *
 * To take some of the mystery out of life, we want to reject incoming
 * connections if we already have a debugger attached.  If we don't, the
 * debugger will just mysteriously hang until it times out.  We could just
 * close the listen socket, but there's a good chance we won't be able to
 * bind to the same port again, which would confuse utilities.
 *
 * Returns "false" on error (indicating that the connection has been severed),
 * "true" if things are still okay.
 */
static bool processIncoming(JdwpState* state)
{
    JdwpNetState* netState = state->netState;
    int readCount;

    assert(netState->clientSock >= 0);

    if (!haveFullPacket(netState)) {
        /* read some more, looping until we have data */
        errno = 0;
        while (1) {
            int selCount;
            fd_set readfds;
            int maxfd;
            int fd;

            maxfd = netState->listenSock;
            if (netState->clientSock > maxfd)
                maxfd = netState->clientSock;
            if (netState->wakePipe[0] > maxfd)
                maxfd = netState->wakePipe[0];

            if (maxfd < 0) {
                ALOGV("+++ all fds are closed");
                return false;
            }

            FD_ZERO(&readfds);

            /* configure fds; note these may get zapped by another thread */
            fd = netState->listenSock;
            if (fd >= 0)
                FD_SET(fd, &readfds);
            fd = netState->clientSock;
            if (fd >= 0)
                FD_SET(fd, &readfds);
            fd = netState->wakePipe[0];
            if (fd >= 0) {
                FD_SET(fd, &readfds);
            } else {
                ALOGI("NOTE: entering select w/o wakepipe");
            }

            /*
             * Select blocks until it sees activity on the file descriptors.
             * Closing the local file descriptor does not count as activity,
             * so we can't rely on that to wake us up (it works for read()
             * and accept(), but not select()).
             *
             * We can do one of three things: (1) send a signal and catch
             * EINTR, (2) open an additional fd ("wakePipe") and write to
             * it when it's time to exit, or (3) time out periodically and
             * re-issue the select.  We're currently using #2, as it's more
             * reliable than #1 and generally better than #3.  Wastes two fds.
             */
            selCount = select(maxfd+1, &readfds, NULL, NULL, NULL);
            if (selCount < 0) {
                if (errno == EINTR)
                    continue;
                ALOGE("select failed: %s", strerror(errno));
                goto fail;
            }

            if (netState->wakePipe[0] >= 0 &&
                FD_ISSET(netState->wakePipe[0], &readfds))
            {
                if (netState->listenSock >= 0)
                    ALOGE("Exit wake set, but not exiting?");
                else
                    ALOGD("Got wake-up signal, bailing out of select");
                goto fail;
            }
            if (netState->listenSock >= 0 &&
                FD_ISSET(netState->listenSock, &readfds))
            {
                ALOGI("Ignoring second debugger -- accepting and dropping");
                union {
                    struct sockaddr_in   addrInet;
                    struct sockaddr      addrPlain;
                } addr;
                socklen_t addrlen;
                int tmpSock;
                tmpSock = accept(netState->listenSock, &addr.addrPlain,
                                &addrlen);
                if (tmpSock < 0)
                    ALOGI("Weird -- accept failed");
                else
                    close(tmpSock);
            }
            if (netState->clientSock >= 0 &&
                FD_ISSET(netState->clientSock, &readfds))
            {
                readCount = read(netState->clientSock,
                                netState->inputBuffer + netState->inputCount,
                    sizeof(netState->inputBuffer) - netState->inputCount);
                if (readCount < 0) {
                    /* read failed */
                    if (errno != EINTR)
                        goto fail;
                    ALOGD("+++ EINTR hit");
                    return true;
                } else if (readCount == 0) {
                    /* EOF hit -- far end went away */
                    ALOGD("+++ peer disconnected");
                    goto fail;
                } else
                    break;
            }
        }

        netState->inputCount += readCount;
        if (!haveFullPacket(netState))
            return true;        /* still not there yet */
    }

    /*
     * Special-case the initial handshake.  For some bizarre reason we're
     * expected to emulate bad tty settings by echoing the request back
     * exactly as it was sent.  Note the handshake is always initiated by
     * the debugger, no matter who connects to whom.
     *
     * Other than this one case, the protocol [claims to be] stateless.
     */
    if (netState->awaitingHandshake) {
        int cc;

        if (memcmp(netState->inputBuffer,
                kMagicHandshake, kMagicHandshakeLen) != 0)
        {
            ALOGE("ERROR: bad handshake '%.14s'", netState->inputBuffer);
            goto fail;
        }

        errno = 0;
        cc = write(netState->clientSock, netState->inputBuffer,
                kMagicHandshakeLen);
        if (cc != kMagicHandshakeLen) {
            ALOGE("Failed writing handshake bytes: %s (%d of %d)",
                strerror(errno), cc, (int) kMagicHandshakeLen);
            goto fail;
        }

        consumeBytes(netState, kMagicHandshakeLen);
        netState->awaitingHandshake = false;
        ALOGV("+++ handshake complete");
        return true;
    }

    /*
     * Handle this packet.
     */
    return handlePacket(state);

fail:
    closeConnection(state);
    return false;
}
Ejemplo n.º 7
0
/*
 * Handle a packet.  Returns "false" if we encounter a connection-fatal error.
 */
static bool handlePacket(JdwpState* state)
{
    JdwpNetState* netState = state->netState;
    const unsigned char* buf = netState->inputBuffer;
    JdwpReqHeader hdr;
    u4 length, id;
    u1 flags, cmdSet, cmd;
    u2 error;
    bool reply;
    int dataLen;

    cmd = cmdSet = 0;       // shut up gcc

    /*dumpPacket(netState->inputBuffer);*/

    length = read4BE(&buf);
    id = read4BE(&buf);
    flags = read1(&buf);
    if ((flags & kJDWPFlagReply) != 0) {
        reply = true;
        error = read2BE(&buf);
    } else {
        reply = false;
        cmdSet = read1(&buf);
        cmd = read1(&buf);
    }

    assert((int) length <= netState->inputCount);
    dataLen = length - (buf - netState->inputBuffer);

    if (!reply) {
        ExpandBuf* pReply = expandBufAlloc();

        hdr.length = length;
        hdr.id = id;
        hdr.cmdSet = cmdSet;
        hdr.cmd = cmd;
        dvmJdwpProcessRequest(state, &hdr, buf, dataLen, pReply);
        if (expandBufGetLength(pReply) > 0) {
            int cc;

            /*
             * TODO: we currently assume the write() will complete in one
             * go, which may not be safe for a network socket.  We may need
             * to mutex this against sendRequest().
             */
            cc = write(netState->clientSock, expandBufGetBuffer(pReply),
                    expandBufGetLength(pReply));
            if (cc != (int) expandBufGetLength(pReply)) {
                LOGE("Failed sending reply to debugger: %s\n", strerror(errno));
                expandBufFree(pReply);
                return false;
            }
        } else {
            LOGW("No reply created for set=%d cmd=%d\n", cmdSet, cmd);
        }
        expandBufFree(pReply);
    } else {
        LOGV("reply?!\n");
        assert(false);
    }

    LOGV("----------\n");

    consumeBytes(netState, length);
    return true;
}