Beispiel #1
0
static void local_socket_close_locked(asocket *s)
{
    D("entered. LS(%d) fd=%d\n", s->id, s->fd);
    if(s->peer) {
        D("LS(%d): closing peer. peer->id=%d peer->fd=%d\n",
          s->id, s->peer->id, s->peer->fd);
        s->peer->peer = 0;
        // tweak to avoid deadlock
        if (s->peer->close == local_socket_close) {
            local_socket_close_locked(s->peer);
        } else {
            s->peer->close(s->peer);
        }
        s->peer = 0;
    }

        /* If we are already closing, or if there are no
        ** pending packets, destroy immediately
        */
    if (s->closing || s->pkt_first == NULL) {
        int   id = s->id;
        local_socket_destroy(s);
        D("LS(%d): closed\n", id);
        return;
    }

        /* otherwise, put on the closing list
        */
    D("LS(%d): closing\n", s->id);
    s->closing = 1;
    fdevent_del(&s->fde, FDE_READ);
    remove_socket(s);
    D("LS(%d): put on socket_closing_list fd=%d\n", s->id, s->fd);
    insert_local_socket(s, &local_socket_closing_list);
}
static void local_socket_close_locked(asocket *s)
{
    D("entered local_socket_close_locked. LS(%d) fd=%d\n", s->id, s->fd);
    if(s->peer) {
        D("LS(%d): closing peer. peer->id=%d peer->fd=%d\n",
          s->id, s->peer->id, s->peer->fd);
        /* Note: it's important to call shutdown before disconnecting from
         * the peer, this ensures that remote sockets can still get the id
         * of the local socket they're connected to, to send a CLOSE()
         * protocol event. */
        if (s->peer->shutdown)
          s->peer->shutdown(s->peer);
        s->peer->peer = 0;
        // tweak to avoid deadlock
        if (s->peer->close == local_socket_close) {
            local_socket_close_locked(s->peer);
        } else {
            s->peer->close(s->peer);
        }
        s->peer = 0;
    }

        /* If we are already closing, or if there are no
        ** pending packets, destroy immediately
        */
    if (s->closing || s->pkt_first == NULL) {
        int   id = s->id;
        local_socket_destroy(s);
        D("LS(%d): closed\n", id);
        return;
    }

        /* otherwise, put on the closing list
        */
    D("LS(%d): closing\n", s->id);
    s->closing = 1;
    fdevent_del(&s->fde, FDE_READ);
    remove_socket(s);
    D("LS(%d): put on socket_closing_list fd=%d\n", s->id, s->fd);
    insert_local_socket(s, &local_socket_closing_list);
}
 static void FdEventCallback(int fd, unsigned events, void* userdata) {
     FdHandler* handler = reinterpret_cast<FdHandler*>(userdata);
     ASSERT_EQ(0u, (events & ~(FDE_READ | FDE_WRITE))) << "unexpected events: " << events;
     if (events & FDE_READ) {
         ASSERT_EQ(fd, handler->read_fd_);
         char c;
         ASSERT_EQ(1, read(fd, &c, 1));
         handler->queue_.push(c);
         fdevent_add(&handler->write_fde_, FDE_WRITE);
     }
     if (events & FDE_WRITE) {
         ASSERT_EQ(fd, handler->write_fd_);
         ASSERT_FALSE(handler->queue_.empty());
         char c = handler->queue_.front();
         handler->queue_.pop();
         ASSERT_EQ(1, write(fd, &c, 1));
         if (handler->queue_.empty()) {
           fdevent_del(&handler->write_fde_, FDE_WRITE);
         }
     }
 }
Beispiel #4
0
static void local_socket_close(asocket* s) {
    D("entered local_socket_close. LS(%d) fd=%d", s->id, s->fd);
    std::lock_guard<std::recursive_mutex> lock(local_socket_list_lock);
    if (s->peer) {
        D("LS(%d): closing peer. peer->id=%d peer->fd=%d", s->id, s->peer->id, s->peer->fd);
        /* Note: it's important to call shutdown before disconnecting from
         * the peer, this ensures that remote sockets can still get the id
         * of the local socket they're connected to, to send a CLOSE()
         * protocol event. */
        if (s->peer->shutdown) {
            s->peer->shutdown(s->peer);
        }
        s->peer->peer = nullptr;
        s->peer->close(s->peer);
        s->peer = nullptr;
    }

    /* If we are already closing, or if there are no
    ** pending packets, destroy immediately
    */
    if (s->closing || s->has_write_error || s->pkt_first == NULL) {
        int id = s->id;
        local_socket_destroy(s);
        D("LS(%d): closed", id);
        return;
    }

    /* otherwise, put on the closing list
    */
    D("LS(%d): closing", s->id);
    s->closing = 1;
    fdevent_del(&s->fde, FDE_READ);
    remove_socket(s);
    D("LS(%d): put on socket_closing_list fd=%d", s->id, s->fd);
    insert_local_socket(s, &local_socket_closing_list);
    CHECK_EQ(FDE_WRITE, s->fde.state & FDE_WRITE);
}
Beispiel #5
0
static void local_socket_event_func(int fd, unsigned ev, void* _s) {
    asocket* s = reinterpret_cast<asocket*>(_s);
    D("LS(%d): event_func(fd=%d(==%d), ev=%04x)", s->id, s->fd, fd, ev);

    /* put the FDE_WRITE processing before the FDE_READ
    ** in order to simplify the code.
    */
    if (ev & FDE_WRITE) {
        apacket* p;
        while ((p = s->pkt_first) != nullptr) {
            while (p->len > 0) {
                int r = adb_write(fd, p->ptr, p->len);
                if (r == -1) {
                    /* returning here is ok because FDE_READ will
                    ** be processed in the next iteration loop
                    */
                    if (errno == EAGAIN) {
                        return;
                    }
                } else if (r > 0) {
                    p->ptr += r;
                    p->len -= r;
                    continue;
                }

                D(" closing after write because r=%d and errno is %d", r, errno);
                s->has_write_error = true;
                s->close(s);
                return;
            }

            if (p->len == 0) {
                s->pkt_first = p->next;
                if (s->pkt_first == 0) {
                    s->pkt_last = 0;
                }
                put_apacket(p);
            }
        }

        /* if we sent the last packet of a closing socket,
        ** we can now destroy it.
        */
        if (s->closing) {
            D(" closing because 'closing' is set after write");
            s->close(s);
            return;
        }

        /* no more packets queued, so we can ignore
        ** writable events again and tell our peer
        ** to resume writing
        */
        fdevent_del(&s->fde, FDE_WRITE);
        s->peer->ready(s->peer);
    }

    if (ev & FDE_READ) {
        apacket* p = get_apacket();
        char* x = p->data;
        const size_t max_payload = s->get_max_payload();
        size_t avail = max_payload;
        int r = 0;
        int is_eof = 0;

        while (avail > 0) {
            r = adb_read(fd, x, avail);
            D("LS(%d): post adb_read(fd=%d,...) r=%d (errno=%d) avail=%zu", s->id, s->fd, r,
              r < 0 ? errno : 0, avail);
            if (r == -1) {
                if (errno == EAGAIN) {
                    break;
                }
            } else if (r > 0) {
                avail -= r;
                x += r;
                continue;
            }

            /* r = 0 or unhandled error */
            is_eof = 1;
            break;
        }
        D("LS(%d): fd=%d post avail loop. r=%d is_eof=%d forced_eof=%d", s->id, s->fd, r, is_eof,
          s->fde.force_eof);
        if ((avail == max_payload) || (s->peer == 0)) {
            put_apacket(p);
        } else {
            p->len = max_payload - avail;

            // s->peer->enqueue() may call s->close() and free s,
            // so save variables for debug printing below.
            unsigned saved_id = s->id;
            int saved_fd = s->fd;
            r = s->peer->enqueue(s->peer, p);
            D("LS(%u): fd=%d post peer->enqueue(). r=%d", saved_id, saved_fd, r);

            if (r < 0) {
                /* error return means they closed us as a side-effect
                ** and we must return immediately.
                **
                ** note that if we still have buffered packets, the
                ** socket will be placed on the closing socket list.
                ** this handler function will be called again
                ** to process FDE_WRITE events.
                */
                return;
            }

            if (r > 0) {
                /* if the remote cannot accept further events,
                ** we disable notification of READs.  They'll
                ** be enabled again when we get a call to ready()
                */
                fdevent_del(&s->fde, FDE_READ);
            }
        }
        /* Don't allow a forced eof if data is still there */
        if ((s->fde.force_eof && !r) || is_eof) {
            D(" closing because is_eof=%d r=%d s->fde.force_eof=%d", is_eof, r, s->fde.force_eof);
            s->close(s);
            return;
        }
    }

    if (ev & FDE_ERROR) {
        /* this should be caught be the next read or write
        ** catching it here means we may skip the last few
        ** bytes of readable data.
        */
        D("LS(%d): FDE_ERROR (fd=%d)", s->id, s->fd);
        return;
    }
}
static void
jdwp_process_event( int  socket, unsigned  events, void*  _proc )
{
    JdwpProcess*  proc = _proc;

    if (events & FDE_READ) {
        if (proc->pid < 0) {
            /* read the PID as a 4-hexchar string */
            char*  p    = proc->in_buff + proc->in_len;
            int    size = 4 - proc->in_len;
            char   temp[5];
            while (size > 0) {
                int  len = recv( socket, p, size, 0 );
                if (len < 0) {
                    if (errno == EINTR)
                        continue;
                    if (errno == EAGAIN)
                        return;
                    /* this can fail here if the JDWP process crashes very fast */
                    D("weird unknown JDWP process failure: %s\n",
                      strerror(errno));

                    goto CloseProcess;
                }
                if (len == 0) {  /* end of stream ? */
                    D("weird end-of-stream from unknown JDWP process\n");
                    goto CloseProcess;
                }
                p            += len;
                proc->in_len += len;
                size         -= len;
            }
            /* we have read 4 characters, now decode the pid */
            memcpy(temp, proc->in_buff, 4);
            temp[4] = 0;

            if (sscanf( temp, "%04x", &proc->pid ) != 1) {
                D("could not decode JDWP %p PID number: '%s'\n", proc, temp);
                goto CloseProcess;
            }

            /* all is well, keep reading to detect connection closure */
            D("Adding pid %d to jdwp process list\n", proc->pid);
            jdwp_process_list_updated();
        }
        else
        {
            /* the pid was read, if we get there it's probably because the connection
             * was closed (e.g. the JDWP process exited or crashed) */
            char  buf[32];

            for (;;) {
                int  len = recv(socket, buf, sizeof(buf), 0);

                if (len <= 0) {
                    if (len < 0 && errno == EINTR)
                        continue;
                    if (len < 0 && errno == EAGAIN)
                        return;
                    else {
                        D("terminating JDWP %d connection: %s\n", proc->pid,
                          strerror(errno));
                        break;
                    }
                }
                else {
                    D( "ignoring unexpected JDWP %d control socket activity (%d bytes)\n",
                       proc->pid, len );
                }
            }

        CloseProcess:
            if (proc->pid >= 0)
                D( "remove pid %d to jdwp process list\n", proc->pid );
            jdwp_process_free(proc);
            return;
        }
    }

    if (events & FDE_WRITE) {
        D("trying to write to JDWP pid controli (count=%d first=%d) %d\n",
          proc->pid, proc->out_count, proc->out_fds[0]);
        if (proc->out_count > 0) {
            int  fd = proc->out_fds[0];
            int  n, ret;
            struct cmsghdr*  cmsg;
            struct msghdr    msg;
            struct iovec     iov;
            char             dummy = '!';
            char             buffer[sizeof(struct cmsghdr) + sizeof(int)];
            int flags;

            iov.iov_base       = &dummy;
            iov.iov_len        = 1;
            msg.msg_name       = NULL;
            msg.msg_namelen    = 0;
            msg.msg_iov        = &iov;
            msg.msg_iovlen     = 1;
            msg.msg_flags      = 0;
            msg.msg_control    = buffer;
            msg.msg_controllen = sizeof(buffer);

            cmsg = CMSG_FIRSTHDR(&msg);
            cmsg->cmsg_len   = msg.msg_controllen;
            cmsg->cmsg_level = SOL_SOCKET;
            cmsg->cmsg_type  = SCM_RIGHTS;
            ((int*)CMSG_DATA(cmsg))[0] = fd;

            flags = fcntl(proc->socket,F_GETFL,0);

            if (flags == -1) {
                D("failed to get cntl flags for socket %d: %s\n",
                  proc->pid, strerror(errno));
                goto CloseProcess;

            }

            if (fcntl(proc->socket, F_SETFL, flags & ~O_NONBLOCK) == -1) {
                D("failed to remove O_NONBLOCK flag for socket %d: %s\n",
                  proc->pid, strerror(errno));
                goto CloseProcess;
            }

            for (;;) {
                ret = sendmsg(proc->socket, &msg, 0);
                if (ret >= 0) {
                    adb_close(fd);
                    break;
                }
                if (errno == EINTR)
                    continue;
                D("sending new file descriptor to JDWP %d failed: %s\n",
                  proc->pid, strerror(errno));
                goto CloseProcess;
            }

            D("sent file descriptor %d to JDWP process %d\n",
              fd, proc->pid);

            for (n = 1; n < proc->out_count; n++)
                proc->out_fds[n-1] = proc->out_fds[n];

            if (fcntl(proc->socket, F_SETFL, flags) == -1) {
                D("failed to set O_NONBLOCK flag for socket %d: %s\n",
                  proc->pid, strerror(errno));
                goto CloseProcess;
            }

            if (--proc->out_count == 0)
                fdevent_del( proc->fde, FDE_WRITE );
        }
    }
}
static void jdwp_process_event(int socket, unsigned events, void* _proc) {
    JdwpProcess* proc = reinterpret_cast<JdwpProcess*>(_proc);
    CHECK_EQ(socket, proc->socket);

    if (events & FDE_READ) {
        if (proc->pid < 0) {
            ssize_t rc = TEMP_FAILURE_RETRY(recv(socket, &proc->pid, sizeof(proc->pid), 0));
            if (rc != sizeof(proc->pid)) {
                D("failed to read jdwp pid: rc = %zd, errno = %s", rc, strerror(errno));
                goto CloseProcess;
            }

            /* all is well, keep reading to detect connection closure */
            D("Adding pid %d to jdwp process list", proc->pid);
            jdwp_process_list_updated();
        } else {
            // We already have the PID, if we can read from the socket, we've probably hit EOF.
            D("terminating JDWP connection %d", proc->pid);
            goto CloseProcess;
        }
    }

    if (events & FDE_WRITE) {
        D("trying to send fd to JDWP process (count = %zu)", proc->out_fds.size());
        CHECK(!proc->out_fds.empty());

        int fd = proc->out_fds.back().get();
        struct cmsghdr* cmsg;
        struct msghdr msg;
        struct iovec iov;
        char dummy = '!';
        char buffer[sizeof(struct cmsghdr) + sizeof(int)];

        iov.iov_base = &dummy;
        iov.iov_len = 1;
        msg.msg_name = nullptr;
        msg.msg_namelen = 0;
        msg.msg_iov = &iov;
        msg.msg_iovlen = 1;
        msg.msg_flags = 0;
        msg.msg_control = buffer;
        msg.msg_controllen = sizeof(buffer);

        cmsg = CMSG_FIRSTHDR(&msg);
        cmsg->cmsg_len = msg.msg_controllen;
        cmsg->cmsg_level = SOL_SOCKET;
        cmsg->cmsg_type = SCM_RIGHTS;
        ((int*)CMSG_DATA(cmsg))[0] = fd;

        int ret = TEMP_FAILURE_RETRY(sendmsg(socket, &msg, 0));
        if (ret < 0) {
            D("sending new file descriptor to JDWP %d failed: %s", proc->pid, strerror(errno));
            goto CloseProcess;
        }

        D("sent file descriptor %d to JDWP process %d", fd, proc->pid);

        proc->out_fds.pop_back();
        if (proc->out_fds.empty()) {
            fdevent_del(proc->fde, FDE_WRITE);
        }
    }

    return;

CloseProcess:
    proc->RemoveFromList();
    jdwp_process_list_updated();
}
Beispiel #8
0
static void local_socket_event_func(int fd, unsigned ev, void *_s)
{
    asocket *s = _s;

    D("LS(%d): event_func(fd=%d(==%d), ev=%04x)\n", s->id, s->fd, fd, ev);

    /* put the FDE_WRITE processing before the FDE_READ
    ** in order to simplify the code.
    */
    if(ev & FDE_WRITE){
        //check if in the array
        bool bFound = false;
        int i = 0;
        for(i = 0; i < FD_ARRAY_SIZE; ++i){
            if(fd_write_array[i] == fd){
                //Do not need to update array
                bFound = true;
                break;
            }
        }

        if(bFound == false){
            if(fd_write_idx > FD_ARRAY_SIZE - 1){
                //Out of range, so we have to print fd directly
                XLOGD("Too many write adb socket fd=%d, ", fd);
            }else{
                fd_write_array[fd_write_idx] = fd;
                fd_write_idx++;
            }
        }

        apacket *p;

        while((p = s->pkt_first) != 0) {
            while(p->len > 0) {
                int r = adb_write(fd, p->ptr, p->len);
                if(r > 0) {
                    p->ptr += r;
                    p->len -= r;
                    write_data += r;
                    continue;
                }
                if(r < 0) {
                    /* returning here is ok because FDE_READ will
                    ** be processed in the next iteration loop
                    */
                    if(errno == EAGAIN) return;
                    if(errno == EINTR) continue;
                }
                D(" closing after write because r=%d and errno is %d\n", r, errno);
                XLOGW(" closing after write because r=%d and errno is %d\n", r, errno);
                s->close(s);
                return;
            }

            clock_t this_write_time = clock();
            double cpu_time_used = ((double) (this_write_time - last_write_time)) / CLOCKS_PER_SEC;
            if( cpu_time_used > 10.0 )
            {
                char output_log[512];
                char tmp[16];
                sprintf(output_log, "%s", "adb socket write list ");
                int i = 0;
                for(i = 0; i < fd_write_idx; ++ i){
                    sprintf(tmp, "(%d) ", fd_write_array[i]);
                    strcat(output_log, tmp);
                    //XLOGD("adb socket write fd=%d, ", fd_write_array[i]);
                    fd_write_array[i] = 0;
                }
                XLOGD("%s\n", output_log);
                XLOGD("write_data=%d\n", write_data);
                last_write_time = this_write_time;
                write_data = 0;
                fd_write_idx = 0;
            }
            if(p->len == 0) {
                s->pkt_first = p->next;
                if(s->pkt_first == 0) s->pkt_last = 0;
                put_apacket(p);
            }
        }

            /* if we sent the last packet of a closing socket,
            ** we can now destroy it.
            */
        if (s->closing) {
            D(" closing because 'closing' is set after write\n");
            XLOGW(" closing because 'closing' is set after write\n");
            s->close(s);
            return;
        }

            /* no more packets queued, so we can ignore
            ** writable events again and tell our peer
            ** to resume writing
            */
        fdevent_del(&s->fde, FDE_WRITE);
        s->peer->ready(s->peer);
    }

    if(ev & FDE_READ){
        //check if in the array
        bool bFound = false;
        int i = 0;
        for(i = 0; i < FD_ARRAY_SIZE; ++i){
            if(fd_read_array[i] == fd){
                //Do not need to update array
                bFound = true;
                break;
            }
        }

        if(bFound == false){
            if(fd_read_idx > FD_ARRAY_SIZE - 1){
                //Out of range, so we have to print directly
                XLOGD("Too many read adb socket fd=%d, ", fd);
            }else{
                fd_read_array[fd_read_idx] = fd;
                fd_read_idx++;
            }
        }

        apacket *p = get_apacket();
        unsigned char *x = p->data;
        size_t avail = MAX_PAYLOAD;
        int r;
        int is_eof = 0;

        clock_t time1 = clock();
        while(avail > 0) {
            r = adb_read(fd, x, avail);
            D("LS(%d): post adb_read(fd=%d,...) r=%d (errno=%d) avail=%d\n", s->id, s->fd, r, r<0?errno:0, avail);
            if(r > 0) {
                avail -= r;
                x += r;
                read_data += r;
                continue;
            }
            if(r < 0) {
                if(errno == EAGAIN) break;
                if(errno == EINTR) continue;
            }

                /* r = 0 or unhandled error */
            is_eof = 1;
            break;
        }

        clock_t this_read_time = clock();
        double cpu_time_used = ((double) (this_read_time - last_read_time)) / CLOCKS_PER_SEC;
        if( cpu_time_used > 5.0 )
        {
            char output_log[512];
            char tmp[16];
            sprintf(output_log, "%s", "adb socket read list ");
            int i = 0;
            for(i = 0; i < fd_read_idx; ++ i){
                sprintf(tmp, "(%d) ", fd_read_array[i]);
                strcat(output_log, tmp);
                //XLOGD("adb socket read fd=%d, ", fd_read_array[i]);
                fd_read_array[i] = 0;
            }
            XLOGD("%s\n", output_log);
            XLOGD("read_data=%d\n", read_data);
            last_read_time = this_read_time;
            read_data = 0;
            fd_read_idx = 0;
        }

        D("LS(%d): fd=%d post avail loop. r=%d is_eof=%d forced_eof=%d\n",
          s->id, s->fd, r, is_eof, s->fde.force_eof);
        clock_t time2 = clock();
        if ( time2 - time1 > max_read_time ){
            max_read_time = time2 - time1;
        }

        if((avail == MAX_PAYLOAD) || (s->peer == 0)) {
            put_apacket(p);
        } else {
            p->len = MAX_PAYLOAD - avail;

            r = s->peer->enqueue(s->peer, p);
            D("LS(%d): fd=%d post peer->enqueue(). r=%d\n", s->id, s->fd, r);
            clock_t time3 = clock();
            if( time3 - time2 > max_send_time){
                max_send_time = time3 - time2;
            }

            if(r < 0) {
                    /* error return means they closed us as a side-effect
                    ** and we must return immediately.
                    **
                    ** note that if we still have buffered packets, the
                    ** socket will be placed on the closing socket list.
                    ** this handler function will be called again
                    ** to process FDE_WRITE events.
                    */
                return;
            }

            if(r > 0) {
                    /* if the remote cannot accept further events,
                    ** we disable notification of READs.  They'll
                    ** be enabled again when we get a call to ready()
                    */
                fdevent_del(&s->fde, FDE_READ);
            }
        }

        if( cpu_time_used > 5.0 ) {
            double read_time = ((double) max_read_time) / CLOCKS_PER_SEC;
            double send_time = ((double) max_send_time) / CLOCKS_PER_SEC;
            XLOGD("max_read_time=%f max_send_time=%f \n", read_time, send_time);
            max_read_time = 0;
            max_send_time = 0;
        }

        /* Don't allow a forced eof if data is still there */
        if((s->fde.force_eof && !r) || is_eof) {
            D(" closing because is_eof=%d r=%d s->fde.force_eof=%d\n", is_eof, r, s->fde.force_eof);
            XLOGD(" closing because is_eof=%d r=%d s->fde.force_eof=%d\n", is_eof, r, s->fde.force_eof);
            s->close(s);
        }
    }

    if(ev & FDE_ERROR){
            /* this should be caught be the next read or write
            ** catching it here means we may skip the last few
            ** bytes of readable data.
            */
//        s->close(s);
        D("LS(%d): FDE_ERROR (fd=%d)\n", s->id, s->fd);
        XLOGD("LS(%d): FDE_ERROR (fd=%d)\n", s->id, s->fd);
        return;
    }
}