jdwp_service.c

来自「Android 一些工具」· C语言 代码 · 共 710 行 · 第 1/2 页

C
710
字号
            if (--proc->out_count == 0)                fdevent_del( proc->fde, FDE_WRITE );        }    }}intcreate_jdwp_connection_fd(int  pid){    JdwpProcess*  proc = _jdwp_list.next;    D("looking for pid %d in JDWP process list\n", pid);    for ( ; proc != &_jdwp_list; proc = proc->next ) {        if (proc->pid == pid) {            goto FoundIt;        }    }    D("search failed !!\n");    return -1;FoundIt:    {        int  fds[2];        if (proc->out_count >= MAX_OUT_FDS) {            D("%s: too many pending JDWP connection for pid %d\n",              __FUNCTION__, pid);            return -1;        }        if (adb_socketpair(fds) < 0) {            D("%s: socket pair creation failed: %s\n",              __FUNCTION__, strerror(errno));            return -1;        }        proc->out_fds[ proc->out_count ] = fds[1];        if (++proc->out_count == 1)            fdevent_add( proc->fde, FDE_WRITE );        return fds[0];    }}/**  VM DEBUG CONTROL SOCKET ** **  we do implement a custom asocket to receive the data **//* name of the debug control Unix socket */#define  JDWP_CONTROL_NAME      "\0jdwp-control"#define  JDWP_CONTROL_NAME_LEN  (sizeof(JDWP_CONTROL_NAME)-1)typedef struct {    int       listen_socket;    fdevent*  fde;} JdwpControl;static voidjdwp_control_event(int  s, unsigned events, void*  user);static intjdwp_control_init( JdwpControl*  control,                   const char*   sockname,                   int           socknamelen ){    struct sockaddr_un   addr;    socklen_t            addrlen;    int                  s;    int                  maxpath = sizeof(addr.sun_path);    int                  pathlen = socknamelen;    if (pathlen >= maxpath) {        D( "vm debug control socket name too long (%d extra chars)\n",           pathlen+1-maxpath );        return -1;    }    memset(&addr, 0, sizeof(addr));    addr.sun_family = AF_UNIX;    memcpy(addr.sun_path, sockname, socknamelen);    s = socket( AF_UNIX, SOCK_STREAM, 0 );    if (s < 0) {        D( "could not create vm debug control socket. %d: %s\n",           errno, strerror(errno));        return -1;    }    addrlen = (pathlen + sizeof(addr.sun_family));    if (bind(s, (struct sockaddr*)&addr, addrlen) < 0) {        D( "could not bind vm debug control socket: %d: %s\n",           errno, strerror(errno) );        adb_close(s);        return -1;    }    if ( listen(s, 4) < 0 ) {        D("listen failed in jdwp control socket: %d: %s\n",          errno, strerror(errno));        adb_close(s);        return -1;    }    control->listen_socket = s;    control->fde = fdevent_create(s, jdwp_control_event, control);    if (control->fde == NULL) {        D( "could not create fdevent for jdwp control socket\n" );        adb_close(s);        return -1;    }    /* only wait for incoming connections */    fdevent_add(control->fde, FDE_READ);    D("jdwp control socket started (%d)\n", control->listen_socket);    return 0;}static voidjdwp_control_event( int  s, unsigned  events, void*  _control ){    JdwpControl*  control = (JdwpControl*) _control;    if (events & FDE_READ) {        struct sockaddr   addr;        socklen_t         addrlen = sizeof(addr);        int               s = -1;        JdwpProcess*      proc;        do {            s = adb_socket_accept( control->listen_socket, &addr, &addrlen );            if (s < 0) {                if (errno == EINTR)                    continue;                if (errno == ECONNABORTED) {                    /* oops, the JDWP process died really quick */                    D("oops, the JDWP process died really quick\n");                    return;                }                /* the socket is probably closed ? */                D( "weird accept() failed on jdwp control socket: %s\n",                   strerror(errno) );                return;            }        }        while (s < 0);        proc = jdwp_process_alloc( s );        if (proc == NULL)            return;    }}static JdwpControl   _jdwp_control;/** "jdwp" local service implementation ** this simply returns the list of known JDWP process pids **/typedef struct {    asocket  socket;    int      pass;} JdwpSocket;static voidjdwp_socket_close( asocket*  s ){    asocket*  peer = s->peer;    remove_socket(s);    if (peer) {        peer->peer = NULL;        peer->close(peer);    }    free(s);}static intjdwp_socket_enqueue( asocket*  s, apacket*  p ){    /* you can't write to this asocket */    put_apacket(p);    s->peer->close(s->peer);    return -1;}static voidjdwp_socket_ready( asocket*  s ){    JdwpSocket*  jdwp = (JdwpSocket*)s;    asocket*     peer = jdwp->socket.peer;   /* on the first call, send the list of pids,    * on the second one, close the connection    */    if (jdwp->pass == 0) {        apacket*  p = get_apacket();        p->len = jdwp_process_list((char*)p->data, MAX_PAYLOAD);        peer->enqueue(peer, p);        jdwp->pass = 1;    }    else {        peer->close(peer);    }}asocket*create_jdwp_service_socket( void ){    JdwpSocket*  s = calloc(sizeof(*s),1);    if (s == NULL)        return NULL;    install_local_socket(&s->socket);    s->socket.ready   = jdwp_socket_ready;    s->socket.enqueue = jdwp_socket_enqueue;    s->socket.close   = jdwp_socket_close;    s->pass           = 0;    return &s->socket;}/** "track-jdwp" local service implementation ** this periodically sends the list of known JDWP process pids ** to the client... **/typedef struct JdwpTracker  JdwpTracker;struct JdwpTracker {    asocket       socket;    JdwpTracker*  next;    JdwpTracker*  prev;    int           need_update;};static JdwpTracker   _jdwp_trackers_list;static voidjdwp_process_list_updated(void){    char             buffer[1024];    int              len;    JdwpTracker*  t = _jdwp_trackers_list.next;    len = jdwp_process_list_msg(buffer, sizeof(buffer));    for ( ; t != &_jdwp_trackers_list; t = t->next ) {        apacket*  p    = get_apacket();        asocket*  peer = t->socket.peer;        memcpy(p->data, buffer, len);        p->len = len;        peer->enqueue( peer, p );    }}static voidjdwp_tracker_close( asocket*  s ){    JdwpTracker*  tracker = (JdwpTracker*) s;    asocket*      peer    = s->peer;    if (peer) {        peer->peer = NULL;        peer->close(peer);    }    remove_socket(s);    tracker->prev->next = tracker->next;    tracker->next->prev = tracker->prev;    free(s);}static voidjdwp_tracker_ready( asocket*  s ){    JdwpTracker*  t = (JdwpTracker*) s;    if (t->need_update) {        apacket*  p = get_apacket();        t->need_update = 0;        p->len = jdwp_process_list_msg((char*)p->data, sizeof(p->data));        s->peer->enqueue(s->peer, p);    }}static intjdwp_tracker_enqueue( asocket*  s, apacket*  p ){    /* you can't write to this socket */    put_apacket(p);    s->peer->close(s->peer);    return -1;}asocket*create_jdwp_tracker_service_socket( void ){    JdwpTracker*  t = calloc(sizeof(*t),1);    if (t == NULL)        return NULL;    t->next = &_jdwp_trackers_list;    t->prev = t->next->prev;    t->next->prev = t;    t->prev->next = t;    install_local_socket(&t->socket);    t->socket.ready   = jdwp_tracker_ready;    t->socket.enqueue = jdwp_tracker_enqueue;    t->socket.close   = jdwp_tracker_close;    t->need_update    = 1;    return &t->socket;}intinit_jdwp(void){    _jdwp_list.next = &_jdwp_list;    _jdwp_list.prev = &_jdwp_list;    _jdwp_trackers_list.next = &_jdwp_trackers_list;    _jdwp_trackers_list.prev = &_jdwp_trackers_list;    return jdwp_control_init( &_jdwp_control,                              JDWP_CONTROL_NAME,                              JDWP_CONTROL_NAME_LEN );}#endif /* !ADB_HOST */

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?