18ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis/* implement the "debug-ports" and "track-debug-ports" device services */
28ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis#include "sysdeps.h"
38ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis#define  TRACE_TAG   TRACE_JDWP
48ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis#include "adb.h"
58ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis#include <errno.h>
68ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis#include <stdio.h>
78ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis#include <string.h>
88ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis#include <unistd.h>
98ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis
108ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis/* here's how these things work.
118ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis
128ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis   when adbd starts, it creates a unix server socket
138ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis   named @vm-debug-control (@ is a shortcut for "first byte is zero"
148ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis   to use the private namespace instead of the file system)
158ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis
168ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis   when a new JDWP daemon thread starts in a new VM process, it creates
178ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis   a connection to @vm-debug-control to announce its availability.
188ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis
198ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis
208ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis     JDWP thread                             @vm-debug-control
218ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis         |                                         |
228ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis         |------------------------------->         |
238ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis         | hello I'm in process <pid>              |
248ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis         |                                         |
258ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis         |                                         |
268ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis
278ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis    the connection is kept alive. it will be closed automatically if
282adaf04fab35cf47c824d74d901b54094e01ccd3Andy McFadden    the JDWP process terminates (this allows adbd to detect dead
298ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis    processes).
308ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis
318ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis    adbd thus maintains a list of "active" JDWP processes. it can send
328ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis    its content to clients through the "device:debug-ports" service,
338ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis    or even updates through the "device:track-debug-ports" service.
348ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis
358ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis    when a debugger wants to connect, it simply runs the command
368ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis    equivalent to  "adb forward tcp:<hostport> jdwp:<pid>"
378ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis
388ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis    "jdwp:<pid>" is a new forward destination format used to target
39eafabcdc1639fb96062d9e3c39b0ae27b0238ae1Mathias Agopian    a given JDWP process on the device. when sutch a request arrives,
408072711307aa98ee5ee6f7369860ae38c3e19656Mathias Agopian    adbd does the following:
41fe0a87b54654a1392650e7f1862df473287d8332Jamie Gennis
42fe0a87b54654a1392650e7f1862df473287d8332Jamie Gennis      - first, it calls socketpair() to create a pair of equivalent
438ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis        sockets.
448ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis
458ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis      - it attaches the first socket in the pair to a local socket
462adaf04fab35cf47c824d74d901b54094e01ccd3Andy McFadden        which is itself attached to the transport's remote socket:
478ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis
488ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis
492adaf04fab35cf47c824d74d901b54094e01ccd3Andy McFadden      - it sends the file descriptor of the second socket directly
502adaf04fab35cf47c824d74d901b54094e01ccd3Andy McFadden        to the JDWP process with the help of sendmsg()
518ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis
528ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis
538ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis     JDWP thread                             @vm-debug-control
547b305fffc39d0fe0926e7fd2d7f6a524fbce62b7Jamie Gennis         |                                         |
558ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis         |                  <----------------------|
562adaf04fab35cf47c824d74d901b54094e01ccd3Andy McFadden         |           OK, try this file descriptor  |
578ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis         |                                         |
588a29ff2a356816694c695db70460f93c7fb4ae6fJamie Gennis         |                                         |
598a29ff2a356816694c695db70460f93c7fb4ae6fJamie Gennis
608a29ff2a356816694c695db70460f93c7fb4ae6fJamie Gennis   then, the JDWP thread uses this new socket descriptor as its
618a29ff2a356816694c695db70460f93c7fb4ae6fJamie Gennis   pass-through connection to the debugger (and receives the
628ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis   JDWP-Handshake message, answers to it, etc...)
638ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis
647b305fffc39d0fe0926e7fd2d7f6a524fbce62b7Jamie Gennis   this gives the following graphics:
657b305fffc39d0fe0926e7fd2d7f6a524fbce62b7Jamie Gennis                    ____________________________________
668ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis                   |                                    |
678a29ff2a356816694c695db70460f93c7fb4ae6fJamie Gennis                   |          ADB Server (host)         |
687b305fffc39d0fe0926e7fd2d7f6a524fbce62b7Jamie Gennis                   |                                    |
698ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis        Debugger <---> LocalSocket <----> RemoteSocket  |
708ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis                   |                           ^^       |
718ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis                   |___________________________||_______|
728ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis                                               ||
738ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis                                     Transport ||
742adaf04fab35cf47c824d74d901b54094e01ccd3Andy McFadden           (TCP for emulator - USB for device) ||
758ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis                                               ||
768a29ff2a356816694c695db70460f93c7fb4ae6fJamie Gennis                    ___________________________||_______
778a29ff2a356816694c695db70460f93c7fb4ae6fJamie Gennis                   |                           ||       |
788a29ff2a356816694c695db70460f93c7fb4ae6fJamie Gennis                   |          ADBD  (device)   ||       |
798a29ff2a356816694c695db70460f93c7fb4ae6fJamie Gennis                   |                           VV       |
808a29ff2a356816694c695db70460f93c7fb4ae6fJamie Gennis         JDWP <======> LocalSocket <----> RemoteSocket  |
818a29ff2a356816694c695db70460f93c7fb4ae6fJamie Gennis                   |                                    |
828ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis                   |____________________________________|
838ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis
844c00cc11141da7d159eb2323b186ed344115c0f1Jesse Hall    due to the way adb works, this doesn't need a special socket
85f78575400977f644cf0b12beb2fa5fc278b6ed4cJesse Hall    type or fancy handling of socket termination if either the debugger
868ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis    or the JDWP process closes the connection.
872adaf04fab35cf47c824d74d901b54094e01ccd3Andy McFadden
88c04f153353cdb0d291297d10452239f791d3fd2bMathias Agopian    THIS IS THE SIMPLEST IMPLEMENTATION I COULD FIND, IF YOU HAPPEN
89c04f153353cdb0d291297d10452239f791d3fd2bMathias Agopian    TO HAVE A BETTER IDEA, LET ME KNOW - Digit
90c04f153353cdb0d291297d10452239f791d3fd2bMathias Agopian
91c04f153353cdb0d291297d10452239f791d3fd2bMathias Agopian**********************************************************************/
928a29ff2a356816694c695db70460f93c7fb4ae6fJamie Gennis
938a29ff2a356816694c695db70460f93c7fb4ae6fJamie Gennis/** JDWP PID List Support Code
948a29ff2a356816694c695db70460f93c7fb4ae6fJamie Gennis ** for each JDWP process, we record its pid and its connected socket
958a29ff2a356816694c695db70460f93c7fb4ae6fJamie Gennis **/
968ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis
971df8c345854155cbbcb9f80de9d12d66ea70ac08Jamie Gennis#define  MAX_OUT_FDS   4
981df8c345854155cbbcb9f80de9d12d66ea70ac08Jamie Gennis
991df8c345854155cbbcb9f80de9d12d66ea70ac08Jamie Gennis#if !ADB_HOST
1001df8c345854155cbbcb9f80de9d12d66ea70ac08Jamie Gennis
1011df8c345854155cbbcb9f80de9d12d66ea70ac08Jamie Gennis#include <sys/socket.h>
1024c00cc11141da7d159eb2323b186ed344115c0f1Jesse Hall#include <sys/un.h>
1034c00cc11141da7d159eb2323b186ed344115c0f1Jesse Hall
104f78575400977f644cf0b12beb2fa5fc278b6ed4cJesse Halltypedef struct JdwpProcess  JdwpProcess;
1058a29ff2a356816694c695db70460f93c7fb4ae6fJamie Gennisstruct JdwpProcess {
1068ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis    JdwpProcess*  next;
1078ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis    JdwpProcess*  prev;
1088ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis    int           pid;
109f0bc2f1d8d37977bd3aef3d3326a70e9e69d4246Mathias Agopian    int           socket;
110f0bc2f1d8d37977bd3aef3d3326a70e9e69d4246Mathias Agopian    fdevent*      fde;
1118ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis
1122adaf04fab35cf47c824d74d901b54094e01ccd3Andy McFadden    char          in_buff[4];  /* input character to read PID */
1138ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis    int           in_len;      /* number from JDWP process    */
114c777b0b3b9b0ea5d8e378fccde6935765e28e329Jesse Hall
1158a29ff2a356816694c695db70460f93c7fb4ae6fJamie Gennis    int           out_fds[MAX_OUT_FDS]; /* output array of file descriptors */
1168a29ff2a356816694c695db70460f93c7fb4ae6fJamie Gennis    int           out_count;            /* to send to the JDWP process      */
1178a29ff2a356816694c695db70460f93c7fb4ae6fJamie Gennis};
1188a29ff2a356816694c695db70460f93c7fb4ae6fJamie Gennis
119f0bc2f1d8d37977bd3aef3d3326a70e9e69d4246Mathias Agopianstatic JdwpProcess  _jdwp_list;
1208a29ff2a356816694c695db70460f93c7fb4ae6fJamie Gennis
1218ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennisstatic int
1228ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennisjdwp_process_list( char*  buffer, int  bufferlen )
1238ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis{
1244c00cc11141da7d159eb2323b186ed344115c0f1Jesse Hall    char*         end  = buffer + bufferlen;
1258ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis    char*         p    = buffer;
1262adaf04fab35cf47c824d74d901b54094e01ccd3Andy McFadden    JdwpProcess*  proc = _jdwp_list.next;
1278ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis
1281df8c345854155cbbcb9f80de9d12d66ea70ac08Jamie Gennis    for ( ; proc != &_jdwp_list; proc = proc->next ) {
1298ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis        int  len;
1308ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis
1318ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis        /* skip transient connections */
132eafabcdc1639fb96062d9e3c39b0ae27b0238ae1Mathias Agopian        if (proc->pid < 0)
133eafabcdc1639fb96062d9e3c39b0ae27b0238ae1Mathias Agopian            continue;
1342adaf04fab35cf47c824d74d901b54094e01ccd3Andy McFadden
135eafabcdc1639fb96062d9e3c39b0ae27b0238ae1Mathias Agopian        len = snprintf(p, end-p, "%d\n", proc->pid);
1368a29ff2a356816694c695db70460f93c7fb4ae6fJamie Gennis        if (p + len >= end)
1378a29ff2a356816694c695db70460f93c7fb4ae6fJamie Gennis            break;
1388a29ff2a356816694c695db70460f93c7fb4ae6fJamie Gennis        p += len;
1398a29ff2a356816694c695db70460f93c7fb4ae6fJamie Gennis    }
140eafabcdc1639fb96062d9e3c39b0ae27b0238ae1Mathias Agopian    p[0] = 0;
1418a29ff2a356816694c695db70460f93c7fb4ae6fJamie Gennis    return (p - buffer);
142eafabcdc1639fb96062d9e3c39b0ae27b0238ae1Mathias Agopian}
143eafabcdc1639fb96062d9e3c39b0ae27b0238ae1Mathias Agopian
144eafabcdc1639fb96062d9e3c39b0ae27b0238ae1Mathias Agopian
1458072711307aa98ee5ee6f7369860ae38c3e19656Mathias Agopianstatic int
1468072711307aa98ee5ee6f7369860ae38c3e19656Mathias Agopianjdwp_process_list_msg( char*  buffer, int  bufferlen )
1472adaf04fab35cf47c824d74d901b54094e01ccd3Andy McFadden{
1488072711307aa98ee5ee6f7369860ae38c3e19656Mathias Agopian    char  head[5];
1498a29ff2a356816694c695db70460f93c7fb4ae6fJamie Gennis    int   len = jdwp_process_list( buffer+4, bufferlen-4 );
1508a29ff2a356816694c695db70460f93c7fb4ae6fJamie Gennis    snprintf(head, sizeof head, "%04x", len);
1518a29ff2a356816694c695db70460f93c7fb4ae6fJamie Gennis    memcpy(buffer, head, 4);
1528a29ff2a356816694c695db70460f93c7fb4ae6fJamie Gennis    return len + 4;
1538a29ff2a356816694c695db70460f93c7fb4ae6fJamie Gennis}
1548072711307aa98ee5ee6f7369860ae38c3e19656Mathias Agopian
1558072711307aa98ee5ee6f7369860ae38c3e19656Mathias Agopian
1568072711307aa98ee5ee6f7369860ae38c3e19656Mathias Agopianstatic void  jdwp_process_list_updated(void);
15724202f5676c32edeef6544cf36e06b9fc970dbdeMathias Agopian
158fe0a87b54654a1392650e7f1862df473287d8332Jamie Gennisstatic void
1592adaf04fab35cf47c824d74d901b54094e01ccd3Andy McFaddenjdwp_process_free( JdwpProcess*  proc )
160fe0a87b54654a1392650e7f1862df473287d8332Jamie Gennis{
1618a29ff2a356816694c695db70460f93c7fb4ae6fJamie Gennis    if (proc) {
1628a29ff2a356816694c695db70460f93c7fb4ae6fJamie Gennis        int  n;
1638a29ff2a356816694c695db70460f93c7fb4ae6fJamie Gennis
1648a29ff2a356816694c695db70460f93c7fb4ae6fJamie Gennis        proc->prev->next = proc->next;
16524202f5676c32edeef6544cf36e06b9fc970dbdeMathias Agopian        proc->next->prev = proc->prev;
1668a29ff2a356816694c695db70460f93c7fb4ae6fJamie Gennis
167fe0a87b54654a1392650e7f1862df473287d8332Jamie Gennis        if (proc->socket >= 0) {
168fe0a87b54654a1392650e7f1862df473287d8332Jamie Gennis            adb_shutdown(proc->socket);
1698072711307aa98ee5ee6f7369860ae38c3e19656Mathias Agopian            adb_close(proc->socket);
170fe0a87b54654a1392650e7f1862df473287d8332Jamie Gennis            proc->socket = -1;
171fe0a87b54654a1392650e7f1862df473287d8332Jamie Gennis        }
1722adaf04fab35cf47c824d74d901b54094e01ccd3Andy McFadden
173fe0a87b54654a1392650e7f1862df473287d8332Jamie Gennis        if (proc->fde != NULL) {
1748a29ff2a356816694c695db70460f93c7fb4ae6fJamie Gennis            fdevent_destroy(proc->fde);
1758a29ff2a356816694c695db70460f93c7fb4ae6fJamie Gennis            proc->fde = NULL;
1768a29ff2a356816694c695db70460f93c7fb4ae6fJamie Gennis        }
1778a29ff2a356816694c695db70460f93c7fb4ae6fJamie Gennis        proc->pid = -1;
1788a29ff2a356816694c695db70460f93c7fb4ae6fJamie Gennis
179fe0a87b54654a1392650e7f1862df473287d8332Jamie Gennis        for (n = 0; n < proc->out_count; n++) {
180fe0a87b54654a1392650e7f1862df473287d8332Jamie Gennis            adb_close(proc->out_fds[n]);
1818ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis        }
1828ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis        proc->out_count = 0;
183466a192d2088f9238d34597d1aa28da41367c1caAndy McFadden
1848ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis        free(proc);
1858ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis
1868ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis        jdwp_process_list_updated();
1872adaf04fab35cf47c824d74d901b54094e01ccd3Andy McFadden    }
1888ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis}
1898ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis
1908ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis
1918ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennisstatic void  jdwp_process_event(int, unsigned, void*);  /* forward */
1922adaf04fab35cf47c824d74d901b54094e01ccd3Andy McFadden
1938ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis
1947b305fffc39d0fe0926e7fd2d7f6a524fbce62b7Jamie Gennisstatic JdwpProcess*
1957b305fffc39d0fe0926e7fd2d7f6a524fbce62b7Jamie Gennisjdwp_process_alloc( int  socket )
1968ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis{
1978ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis    JdwpProcess*  proc = calloc(1,sizeof(*proc));
1988ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis
1998ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis    if (proc == NULL) {
2007b305fffc39d0fe0926e7fd2d7f6a524fbce62b7Jamie Gennis        D("not enough memory to create new JDWP process\n");
2018ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis        return NULL;
2028ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis    }
2038ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis
2042adaf04fab35cf47c824d74d901b54094e01ccd3Andy McFadden    proc->socket = socket;
2058ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis    proc->pid    = -1;
2068ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis    proc->next   = proc;
2078ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis    proc->prev   = proc;
2088ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis
2098ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis    proc->fde = fdevent_create( socket, jdwp_process_event, proc );
2108ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis    if (proc->fde == NULL) {
2112adaf04fab35cf47c824d74d901b54094e01ccd3Andy McFadden        D("could not create fdevent for new JDWP process\n" );
212c04f153353cdb0d291297d10452239f791d3fd2bMathias Agopian        free(proc);
213c04f153353cdb0d291297d10452239f791d3fd2bMathias Agopian        return NULL;
214c04f153353cdb0d291297d10452239f791d3fd2bMathias Agopian    }
215c04f153353cdb0d291297d10452239f791d3fd2bMathias Agopian
2168ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis    proc->fde->state |= FDE_DONT_CLOSE;
217f78575400977f644cf0b12beb2fa5fc278b6ed4cJesse Hall    proc->in_len      = 0;
2184c00cc11141da7d159eb2323b186ed344115c0f1Jesse Hall    proc->out_count   = 0;
2198ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis
2201df8c345854155cbbcb9f80de9d12d66ea70ac08Jamie Gennis    /* append to list */
2211df8c345854155cbbcb9f80de9d12d66ea70ac08Jamie Gennis    proc->next = &_jdwp_list;
222f78575400977f644cf0b12beb2fa5fc278b6ed4cJesse Hall    proc->prev = proc->next->prev;
223f78575400977f644cf0b12beb2fa5fc278b6ed4cJesse Hall
2248ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis    proc->prev->next = proc;
2258ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis    proc->next->prev = proc;
2268ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis
2278ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis    /* start by waiting for the PID */
2282adaf04fab35cf47c824d74d901b54094e01ccd3Andy McFadden    fdevent_add(proc->fde, FDE_READ);
2298ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis
230c777b0b3b9b0ea5d8e378fccde6935765e28e329Jesse Hall    return proc;
231f0bc2f1d8d37977bd3aef3d3326a70e9e69d4246Mathias Agopian}
232f0bc2f1d8d37977bd3aef3d3326a70e9e69d4246Mathias Agopian
233f0bc2f1d8d37977bd3aef3d3326a70e9e69d4246Mathias Agopian
234c777b0b3b9b0ea5d8e378fccde6935765e28e329Jesse Hallstatic void
2358ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennisjdwp_process_event( int  socket, unsigned  events, void*  _proc )
2368ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis{
2378ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis    JdwpProcess*  proc = _proc;
2388ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis
2392adaf04fab35cf47c824d74d901b54094e01ccd3Andy McFadden    if (events & FDE_READ) {
2408ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis        if (proc->pid < 0) {
2411df8c345854155cbbcb9f80de9d12d66ea70ac08Jamie Gennis            /* read the PID as a 4-hexchar string */
2421df8c345854155cbbcb9f80de9d12d66ea70ac08Jamie Gennis            char*  p    = proc->in_buff + proc->in_len;
243c777b0b3b9b0ea5d8e378fccde6935765e28e329Jesse Hall            int    size = 4 - proc->in_len;
2448ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis            char   temp[5];
2458ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis            while (size > 0) {
246eafabcdc1639fb96062d9e3c39b0ae27b0238ae1Mathias Agopian                int  len = recv( socket, p, size, 0 );
2472adaf04fab35cf47c824d74d901b54094e01ccd3Andy McFadden                if (len < 0) {
248eafabcdc1639fb96062d9e3c39b0ae27b0238ae1Mathias Agopian                    if (errno == EINTR)
249eafabcdc1639fb96062d9e3c39b0ae27b0238ae1Mathias Agopian                        continue;
250eafabcdc1639fb96062d9e3c39b0ae27b0238ae1Mathias Agopian                    if (errno == EAGAIN)
251eafabcdc1639fb96062d9e3c39b0ae27b0238ae1Mathias Agopian                        return;
252eafabcdc1639fb96062d9e3c39b0ae27b0238ae1Mathias Agopian                    /* this can fail here if the JDWP process crashes very fast */
253eafabcdc1639fb96062d9e3c39b0ae27b0238ae1Mathias Agopian                    D("weird unknown JDWP process failure: %s\n",
254eafabcdc1639fb96062d9e3c39b0ae27b0238ae1Mathias Agopian                      strerror(errno));
2558072711307aa98ee5ee6f7369860ae38c3e19656Mathias Agopian
2562adaf04fab35cf47c824d74d901b54094e01ccd3Andy McFadden                    goto CloseProcess;
2578072711307aa98ee5ee6f7369860ae38c3e19656Mathias Agopian                }
2588072711307aa98ee5ee6f7369860ae38c3e19656Mathias Agopian                if (len == 0) {  /* end of stream ? */
2598072711307aa98ee5ee6f7369860ae38c3e19656Mathias Agopian                    D("weird end-of-stream from unknown JDWP process\n");
2608072711307aa98ee5ee6f7369860ae38c3e19656Mathias Agopian                    goto CloseProcess;
2618072711307aa98ee5ee6f7369860ae38c3e19656Mathias Agopian                }
262fe0a87b54654a1392650e7f1862df473287d8332Jamie Gennis                p            += len;
2632adaf04fab35cf47c824d74d901b54094e01ccd3Andy McFadden                proc->in_len += len;
264fe0a87b54654a1392650e7f1862df473287d8332Jamie Gennis                size         -= len;
26524202f5676c32edeef6544cf36e06b9fc970dbdeMathias Agopian            }
26624202f5676c32edeef6544cf36e06b9fc970dbdeMathias Agopian            /* we have read 4 characters, now decode the pid */
26724202f5676c32edeef6544cf36e06b9fc970dbdeMathias Agopian            memcpy(temp, proc->in_buff, 4);
26824202f5676c32edeef6544cf36e06b9fc970dbdeMathias Agopian            temp[4] = 0;
269fe0a87b54654a1392650e7f1862df473287d8332Jamie Gennis
270fe0a87b54654a1392650e7f1862df473287d8332Jamie Gennis            if (sscanf( temp, "%04x", &proc->pid ) != 1) {
271fe0a87b54654a1392650e7f1862df473287d8332Jamie Gennis                D("could not decode JDWP %p PID number: '%s'\n", proc, temp);
272fe0a87b54654a1392650e7f1862df473287d8332Jamie Gennis                goto CloseProcess;
2732adaf04fab35cf47c824d74d901b54094e01ccd3Andy McFadden            }
274fe0a87b54654a1392650e7f1862df473287d8332Jamie Gennis
2752773004a83624ed41cf3f94f2b11878cd8521812Mathias Agopian            /* all is well, keep reading to detect connection closure */
276fe0a87b54654a1392650e7f1862df473287d8332Jamie Gennis            D("Adding pid %d to jdwp process list\n", proc->pid);
277fe0a87b54654a1392650e7f1862df473287d8332Jamie Gennis            jdwp_process_list_updated();
278fe0a87b54654a1392650e7f1862df473287d8332Jamie Gennis        }
2798ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis        else
2808ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis        {
2818ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis            /* the pid was read, if we get there it's probably because the connection
2828ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis             * was closed (e.g. the JDWP process exited or crashed) */
2838ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis            char  buf[32];
2848ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis
2852adaf04fab35cf47c824d74d901b54094e01ccd3Andy McFadden            for (;;) {
286c777b0b3b9b0ea5d8e378fccde6935765e28e329Jesse Hall                int  len = recv(socket, buf, sizeof(buf), 0);
287c777b0b3b9b0ea5d8e378fccde6935765e28e329Jesse Hall
288c777b0b3b9b0ea5d8e378fccde6935765e28e329Jesse Hall                if (len <= 0) {
2892adaf04fab35cf47c824d74d901b54094e01ccd3Andy McFadden                    if (len < 0 && errno == EINTR)
290c777b0b3b9b0ea5d8e378fccde6935765e28e329Jesse Hall                        continue;
291c777b0b3b9b0ea5d8e378fccde6935765e28e329Jesse Hall                    if (len < 0 && errno == EAGAIN)
292c777b0b3b9b0ea5d8e378fccde6935765e28e329Jesse Hall                        return;
293c777b0b3b9b0ea5d8e378fccde6935765e28e329Jesse Hall                    else {
294c777b0b3b9b0ea5d8e378fccde6935765e28e329Jesse Hall                        D("terminating JDWP %d connection: %s\n", proc->pid,
2951df8c345854155cbbcb9f80de9d12d66ea70ac08Jamie Gennis                          strerror(errno));
296c777b0b3b9b0ea5d8e378fccde6935765e28e329Jesse Hall                        break;
297c777b0b3b9b0ea5d8e378fccde6935765e28e329Jesse Hall                    }
2982adaf04fab35cf47c824d74d901b54094e01ccd3Andy McFadden                }
299c777b0b3b9b0ea5d8e378fccde6935765e28e329Jesse Hall                else {
3001df8c345854155cbbcb9f80de9d12d66ea70ac08Jamie Gennis                    D( "ignoring unexpected JDWP %d control socket activity (%d bytes)\n",
301c777b0b3b9b0ea5d8e378fccde6935765e28e329Jesse Hall                       proc->pid, len );
302c777b0b3b9b0ea5d8e378fccde6935765e28e329Jesse Hall                }
3032adaf04fab35cf47c824d74d901b54094e01ccd3Andy McFadden            }
304c777b0b3b9b0ea5d8e378fccde6935765e28e329Jesse Hall
305c777b0b3b9b0ea5d8e378fccde6935765e28e329Jesse Hall        CloseProcess:
306c777b0b3b9b0ea5d8e378fccde6935765e28e329Jesse Hall            if (proc->pid >= 0)
307c777b0b3b9b0ea5d8e378fccde6935765e28e329Jesse Hall                D( "remove pid %d to jdwp process list\n", proc->pid );
308c777b0b3b9b0ea5d8e378fccde6935765e28e329Jesse Hall            jdwp_process_free(proc);
309c777b0b3b9b0ea5d8e378fccde6935765e28e329Jesse Hall            return;
310c777b0b3b9b0ea5d8e378fccde6935765e28e329Jesse Hall        }
311c777b0b3b9b0ea5d8e378fccde6935765e28e329Jesse Hall    }
3121df8c345854155cbbcb9f80de9d12d66ea70ac08Jamie Gennis
313c777b0b3b9b0ea5d8e378fccde6935765e28e329Jesse Hall    if (events & FDE_WRITE) {
314c777b0b3b9b0ea5d8e378fccde6935765e28e329Jesse Hall        D("trying to write to JDWP pid controli (count=%d first=%d) %d\n",
315c777b0b3b9b0ea5d8e378fccde6935765e28e329Jesse Hall          proc->pid, proc->out_count, proc->out_fds[0]);
3162adaf04fab35cf47c824d74d901b54094e01ccd3Andy McFadden        if (proc->out_count > 0) {
317c777b0b3b9b0ea5d8e378fccde6935765e28e329Jesse Hall            int  fd = proc->out_fds[0];
318c777b0b3b9b0ea5d8e378fccde6935765e28e329Jesse Hall            int  n, ret;
319c777b0b3b9b0ea5d8e378fccde6935765e28e329Jesse Hall            struct cmsghdr*  cmsg;
320c777b0b3b9b0ea5d8e378fccde6935765e28e329Jesse Hall            struct msghdr    msg;
321c777b0b3b9b0ea5d8e378fccde6935765e28e329Jesse Hall            struct iovec     iov;
322c777b0b3b9b0ea5d8e378fccde6935765e28e329Jesse Hall            char             dummy = '!';
323c777b0b3b9b0ea5d8e378fccde6935765e28e329Jesse Hall            char             buffer[sizeof(struct cmsghdr) + sizeof(int)];
324c777b0b3b9b0ea5d8e378fccde6935765e28e329Jesse Hall            int flags;
3251df8c345854155cbbcb9f80de9d12d66ea70ac08Jamie Gennis
3261df8c345854155cbbcb9f80de9d12d66ea70ac08Jamie Gennis            iov.iov_base       = &dummy;
327c777b0b3b9b0ea5d8e378fccde6935765e28e329Jesse Hall            iov.iov_len        = 1;
328c777b0b3b9b0ea5d8e378fccde6935765e28e329Jesse Hall            msg.msg_name       = NULL;
329c777b0b3b9b0ea5d8e378fccde6935765e28e329Jesse Hall            msg.msg_namelen    = 0;
3308ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis            msg.msg_iov        = &iov;
331            msg.msg_iovlen     = 1;
332            msg.msg_flags      = 0;
333            msg.msg_control    = buffer;
334            msg.msg_controllen = sizeof(buffer);
335
336            cmsg = CMSG_FIRSTHDR(&msg);
337            cmsg->cmsg_len   = msg.msg_controllen;
338            cmsg->cmsg_level = SOL_SOCKET;
339            cmsg->cmsg_type  = SCM_RIGHTS;
340            ((int*)CMSG_DATA(cmsg))[0] = fd;
341
342            flags = fcntl(proc->socket,F_GETFL,0);
343
344            if (flags == -1) {
345                D("failed to get cntl flags for socket %d: %s\n",
346                  proc->pid, strerror(errno));
347                goto CloseProcess;
348
349            }
350
351            if (fcntl(proc->socket, F_SETFL, flags & ~O_NONBLOCK) == -1) {
352                D("failed to remove O_NONBLOCK flag for socket %d: %s\n",
353                  proc->pid, strerror(errno));
354                goto CloseProcess;
355            }
356
357            for (;;) {
358                ret = sendmsg(proc->socket, &msg, 0);
359                if (ret >= 0) {
360                    adb_close(fd);
361                    break;
362                }
363                if (errno == EINTR)
364                    continue;
365                D("sending new file descriptor to JDWP %d failed: %s\n",
366                  proc->pid, strerror(errno));
367                goto CloseProcess;
368            }
369
370            D("sent file descriptor %d to JDWP process %d\n",
371              fd, proc->pid);
372
373            for (n = 1; n < proc->out_count; n++)
374                proc->out_fds[n-1] = proc->out_fds[n];
375
376            if (fcntl(proc->socket, F_SETFL, flags) == -1) {
377                D("failed to set O_NONBLOCK flag for socket %d: %s\n",
378                  proc->pid, strerror(errno));
379                goto CloseProcess;
380            }
381
382            if (--proc->out_count == 0)
383                fdevent_del( proc->fde, FDE_WRITE );
384        }
385    }
386}
387
388
389int
390create_jdwp_connection_fd(int  pid)
391{
392    JdwpProcess*  proc = _jdwp_list.next;
393
394    D("looking for pid %d in JDWP process list\n", pid);
395    for ( ; proc != &_jdwp_list; proc = proc->next ) {
396        if (proc->pid == pid) {
397            goto FoundIt;
398        }
399    }
400    D("search failed !!\n");
401    return -1;
402
403FoundIt:
404    {
405        int  fds[2];
406
407        if (proc->out_count >= MAX_OUT_FDS) {
408            D("%s: too many pending JDWP connection for pid %d\n",
409              __FUNCTION__, pid);
410            return -1;
411        }
412
413        if (adb_socketpair(fds) < 0) {
414            D("%s: socket pair creation failed: %s\n",
415              __FUNCTION__, strerror(errno));
416            return -1;
417        }
418
419        proc->out_fds[ proc->out_count ] = fds[1];
420        if (++proc->out_count == 1)
421            fdevent_add( proc->fde, FDE_WRITE );
422
423        return fds[0];
424    }
425}
426
427/**  VM DEBUG CONTROL SOCKET
428 **
429 **  we do implement a custom asocket to receive the data
430 **/
431
432/* name of the debug control Unix socket */
433#define  JDWP_CONTROL_NAME      "\0jdwp-control"
434#define  JDWP_CONTROL_NAME_LEN  (sizeof(JDWP_CONTROL_NAME)-1)
435
436typedef struct {
437    int       listen_socket;
438    fdevent*  fde;
439
440} JdwpControl;
441
442
443static void
444jdwp_control_event(int  s, unsigned events, void*  user);
445
446
447static int
448jdwp_control_init( JdwpControl*  control,
449                   const char*   sockname,
450                   int           socknamelen )
451{
452    struct sockaddr_un   addr;
453    socklen_t            addrlen;
454    int                  s;
455    int                  maxpath = sizeof(addr.sun_path);
456    int                  pathlen = socknamelen;
457
458    if (pathlen >= maxpath) {
459        D( "vm debug control socket name too long (%d extra chars)\n",
460           pathlen+1-maxpath );
461        return -1;
462    }
463
464    memset(&addr, 0, sizeof(addr));
465    addr.sun_family = AF_UNIX;
466    memcpy(addr.sun_path, sockname, socknamelen);
467
468    s = socket( AF_UNIX, SOCK_STREAM, 0 );
469    if (s < 0) {
470        D( "could not create vm debug control socket. %d: %s\n",
471           errno, strerror(errno));
472        return -1;
473    }
474
475    addrlen = (pathlen + sizeof(addr.sun_family));
476
477    if (bind(s, (struct sockaddr*)&addr, addrlen) < 0) {
478        D( "could not bind vm debug control socket: %d: %s\n",
479           errno, strerror(errno) );
480        adb_close(s);
481        return -1;
482    }
483
484    if ( listen(s, 4) < 0 ) {
485        D("listen failed in jdwp control socket: %d: %s\n",
486          errno, strerror(errno));
487        adb_close(s);
488        return -1;
489    }
490
491    control->listen_socket = s;
492
493    control->fde = fdevent_create(s, jdwp_control_event, control);
494    if (control->fde == NULL) {
495        D( "could not create fdevent for jdwp control socket\n" );
496        adb_close(s);
497        return -1;
498    }
499
500    /* only wait for incoming connections */
501    fdevent_add(control->fde, FDE_READ);
502    close_on_exec(s);
503
504    D("jdwp control socket started (%d)\n", control->listen_socket);
505    return 0;
506}
507
508
509static void
510jdwp_control_event( int  s, unsigned  events, void*  _control )
511{
512    JdwpControl*  control = (JdwpControl*) _control;
513
514    if (events & FDE_READ) {
515        struct sockaddr   addr;
516        socklen_t         addrlen = sizeof(addr);
517        int               s = -1;
518        JdwpProcess*      proc;
519
520        do {
521            s = adb_socket_accept( control->listen_socket, &addr, &addrlen );
522            if (s < 0) {
523                if (errno == EINTR)
524                    continue;
525                if (errno == ECONNABORTED) {
526                    /* oops, the JDWP process died really quick */
527                    D("oops, the JDWP process died really quick\n");
528                    return;
529                }
530                /* the socket is probably closed ? */
531                D( "weird accept() failed on jdwp control socket: %s\n",
532                   strerror(errno) );
533                return;
534            }
535        }
536        while (s < 0);
537
538        proc = jdwp_process_alloc( s );
539        if (proc == NULL)
540            return;
541    }
542}
543
544
545static JdwpControl   _jdwp_control;
546
547/** "jdwp" local service implementation
548 ** this simply returns the list of known JDWP process pids
549 **/
550
551typedef struct {
552    asocket  socket;
553    int      pass;
554} JdwpSocket;
555
556static void
557jdwp_socket_close( asocket*  s )
558{
559    asocket*  peer = s->peer;
560
561    remove_socket(s);
562
563    if (peer) {
564        peer->peer = NULL;
565        peer->close(peer);
566    }
567    free(s);
568}
569
570static int
571jdwp_socket_enqueue( asocket*  s, apacket*  p )
572{
573    /* you can't write to this asocket */
574    put_apacket(p);
575    s->peer->close(s->peer);
576    return -1;
577}
578
579
580static void
581jdwp_socket_ready( asocket*  s )
582{
583    JdwpSocket*  jdwp = (JdwpSocket*)s;
584    asocket*     peer = jdwp->socket.peer;
585
586   /* on the first call, send the list of pids,
587    * on the second one, close the connection
588    */
589    if (jdwp->pass == 0) {
590        apacket*  p = get_apacket();
591        p->len = jdwp_process_list((char*)p->data, MAX_PAYLOAD);
592        peer->enqueue(peer, p);
593        jdwp->pass = 1;
594    }
595    else {
596        peer->close(peer);
597    }
598}
599
600asocket*
601create_jdwp_service_socket( void )
602{
603    JdwpSocket*  s = calloc(sizeof(*s),1);
604
605    if (s == NULL)
606        return NULL;
607
608    install_local_socket(&s->socket);
609
610    s->socket.ready   = jdwp_socket_ready;
611    s->socket.enqueue = jdwp_socket_enqueue;
612    s->socket.close   = jdwp_socket_close;
613    s->pass           = 0;
614
615    return &s->socket;
616}
617
618/** "track-jdwp" local service implementation
619 ** this periodically sends the list of known JDWP process pids
620 ** to the client...
621 **/
622
623typedef struct JdwpTracker  JdwpTracker;
624
625struct JdwpTracker {
626    asocket       socket;
627    JdwpTracker*  next;
628    JdwpTracker*  prev;
629    int           need_update;
630};
631
632static JdwpTracker   _jdwp_trackers_list;
633
634
635static void
636jdwp_process_list_updated(void)
637{
638    char             buffer[1024];
639    int              len;
640    JdwpTracker*  t = _jdwp_trackers_list.next;
641
642    len = jdwp_process_list_msg(buffer, sizeof(buffer));
643
644    for ( ; t != &_jdwp_trackers_list; t = t->next ) {
645        apacket*  p    = get_apacket();
646        asocket*  peer = t->socket.peer;
647        memcpy(p->data, buffer, len);
648        p->len = len;
649        peer->enqueue( peer, p );
650    }
651}
652
653static void
654jdwp_tracker_close( asocket*  s )
655{
656    JdwpTracker*  tracker = (JdwpTracker*) s;
657    asocket*      peer    = s->peer;
658
659    if (peer) {
660        peer->peer = NULL;
661        peer->close(peer);
662    }
663
664    remove_socket(s);
665
666    tracker->prev->next = tracker->next;
667    tracker->next->prev = tracker->prev;
668
669    free(s);
670}
671
672static void
673jdwp_tracker_ready( asocket*  s )
674{
675    JdwpTracker*  t = (JdwpTracker*) s;
676
677    if (t->need_update) {
678        apacket*  p = get_apacket();
679        t->need_update = 0;
680        p->len = jdwp_process_list_msg((char*)p->data, sizeof(p->data));
681        s->peer->enqueue(s->peer, p);
682    }
683}
684
685static int
686jdwp_tracker_enqueue( asocket*  s, apacket*  p )
687{
688    /* you can't write to this socket */
689    put_apacket(p);
690    s->peer->close(s->peer);
691    return -1;
692}
693
694
695asocket*
696create_jdwp_tracker_service_socket( void )
697{
698    JdwpTracker*  t = calloc(sizeof(*t),1);
699
700    if (t == NULL)
701        return NULL;
702
703    t->next = &_jdwp_trackers_list;
704    t->prev = t->next->prev;
705
706    t->next->prev = t;
707    t->prev->next = t;
708
709    install_local_socket(&t->socket);
710
711    t->socket.ready   = jdwp_tracker_ready;
712    t->socket.enqueue = jdwp_tracker_enqueue;
713    t->socket.close   = jdwp_tracker_close;
714    t->need_update    = 1;
715
716    return &t->socket;
717}
718
719
720int
721init_jdwp(void)
722{
723    _jdwp_list.next = &_jdwp_list;
724    _jdwp_list.prev = &_jdwp_list;
725
726    _jdwp_trackers_list.next = &_jdwp_trackers_list;
727    _jdwp_trackers_list.prev = &_jdwp_trackers_list;
728
729    return jdwp_control_init( &_jdwp_control,
730                              JDWP_CONTROL_NAME,
731                              JDWP_CONTROL_NAME_LEN );
732}
733
734#endif /* !ADB_HOST */
735
736