jdwp_service.c revision 8cf0d59f61ae0b8554ecf3fe051850508b761b79
1dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project/* implement the "debug-ports" and "track-debug-ports" device services */
2dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include "sysdeps.h"
3dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#define  TRACE_TAG   TRACE_JDWP
4dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include "adb.h"
5dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <errno.h>
6dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <stdio.h>
7dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <string.h>
8dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
9dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project/* here's how these things work.
10dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
11dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project   when adbd starts, it creates a unix server socket
12dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project   named @vm-debug-control (@ is a shortcut for "first byte is zero"
13dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project   to use the private namespace instead of the file system)
14dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
15dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project   when a new JDWP daemon thread starts in a new VM process, it creates
16dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project   a connection to @vm-debug-control to announce its availability.
17dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
18dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
19dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project     JDWP thread                             @vm-debug-control
20dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project         |                                         |
21dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project         |------------------------------->         |
22dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project         | hello I'm in process <pid>              |
23dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project         |                                         |
24dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project         |                                         |
25dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
26dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    the connection is kept alive. it will be closed automatically if
27dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    the JDWP process terminates (this allows adbd to detect dead
28dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    processes).
29dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
30dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    adbd thus maintains a list of "active" JDWP processes. it can send
31dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    its content to clients through the "device:debug-ports" service,
32dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    or even updates through the "device:track-debug-ports" service.
33dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
34dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    when a debugger wants to connect, it simply runs the command
35dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    equivalent to  "adb forward tcp:<hostport> jdwp:<pid>"
36dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
37dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    "jdwp:<pid>" is a new forward destination format used to target
38dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    a given JDWP process on the device. when sutch a request arrives,
39dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    adbd does the following:
40dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
41dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project      - first, it calls socketpair() to create a pair of equivalent
42dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        sockets.
43dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
44dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project      - it attaches the first socket in the pair to a local socket
45dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        which is itself attached to the transport's remote socket:
46dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
47dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
48dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project      - it sends the file descriptor of the second socket directly
49dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        to the JDWP process with the help of sendmsg()
50dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
51dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
52dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project     JDWP thread                             @vm-debug-control
53dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project         |                                         |
54dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project         |                  <----------------------|
55dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project         |           OK, try this file descriptor  |
56dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project         |                                         |
57dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project         |                                         |
58dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
59dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project   then, the JDWP thread uses this new socket descriptor as its
60dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project   pass-through connection to the debugger (and receives the
61dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project   JDWP-Handshake message, answers to it, etc...)
62dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
63dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project   this gives the following graphics:
64dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                    ____________________________________
65dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                   |                                    |
66dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                   |          ADB Server (host)         |
67dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                   |                                    |
68dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        Debugger <---> LocalSocket <----> RemoteSocket  |
69dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                   |                           ^^       |
70dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                   |___________________________||_______|
71dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                                               ||
72dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                                     Transport ||
73dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project           (TCP for emulator - USB for device) ||
74dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                                               ||
75dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                    ___________________________||_______
76dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                   |                           ||       |
77dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                   |          ADBD  (device)   ||       |
78dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                   |                           VV       |
79dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project         JDWP <======> LocalSocket <----> RemoteSocket  |
80dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                   |                                    |
81dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                   |____________________________________|
82dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
83dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    due to the way adb works, this doesn't need a special socket
84dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    type or fancy handling of socket termination if either the debugger
85dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    or the JDWP process closes the connection.
86dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
87dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    THIS IS THE SIMPLEST IMPLEMENTATION I COULD FIND, IF YOU HAPPEN
88dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    TO HAVE A BETTER IDEA, LET ME KNOW - Digit
89dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
90dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project**********************************************************************/
91dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
92dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project/** JDWP PID List Support Code
93dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project ** for each JDWP process, we record its pid and its connected socket
94dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project **/
95dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
96dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#define  MAX_OUT_FDS   4
97dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
98dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#if !ADB_HOST
99dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
100dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <sys/socket.h>
101dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <sys/un.h>
102dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
103dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projecttypedef struct JdwpProcess  JdwpProcess;
104dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstruct JdwpProcess {
105dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    JdwpProcess*  next;
106dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    JdwpProcess*  prev;
107dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    int           pid;
108dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    int           socket;
109dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    fdevent*      fde;
110dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
111dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    char          in_buff[4];  /* input character to read PID */
112dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    int           in_len;      /* number from JDWP process    */
113dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
114dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    int           out_fds[MAX_OUT_FDS]; /* output array of file descriptors */
115dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    int           out_count;            /* to send to the JDWP process      */
116dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project};
117dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
118dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic JdwpProcess  _jdwp_list;
119dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
120dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic int
121dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectjdwp_process_list( char*  buffer, int  bufferlen )
122dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
123dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    char*         end  = buffer + bufferlen;
124dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    char*         p    = buffer;
125dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    JdwpProcess*  proc = _jdwp_list.next;
126dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
127dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    for ( ; proc != &_jdwp_list; proc = proc->next ) {
128dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        int  len;
129dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
130dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        /* skip transient connections */
131dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if (proc->pid < 0)
132dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            continue;
133dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
134dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        len = snprintf(p, end-p, "%d\n", proc->pid);
135dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if (p + len >= end)
136dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            break;
137dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        p += len;
138dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
139dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    p[0] = 0;
140dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    return (p - buffer);
141dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
142dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
143dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
144dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic int
145dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectjdwp_process_list_msg( char*  buffer, int  bufferlen )
146dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
147dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    char  head[5];
148dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    int   len = jdwp_process_list( buffer+4, bufferlen-4 );
149dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    snprintf(head, sizeof head, "%04x", len);
150dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    memcpy(buffer, head, 4);
151dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    return len + 4;
152dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
153dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
154dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
155dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic void  jdwp_process_list_updated(void);
156dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
157dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic void
158dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectjdwp_process_free( JdwpProcess*  proc )
159dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
160dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (proc) {
161dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        int  n;
162dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
163dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        proc->prev->next = proc->next;
164dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        proc->next->prev = proc->prev;
165dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
166dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if (proc->socket >= 0) {
1678cf0d59f61ae0b8554ecf3fe051850508b761b79Mike Lockwood            adb_shutdown(proc->socket);
168dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            adb_close(proc->socket);
169dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            proc->socket = -1;
170dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
171dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
172dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if (proc->fde != NULL) {
173dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            fdevent_destroy(proc->fde);
174dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            proc->fde = NULL;
175dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
176dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        proc->pid = -1;
177dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
178dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        for (n = 0; n < proc->out_count; n++) {
179dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            adb_close(proc->out_fds[n]);
180dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
181dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        proc->out_count = 0;
182dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
183dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        free(proc);
184dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
185dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        jdwp_process_list_updated();
186dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
187dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
188dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
189dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
190dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic void  jdwp_process_event(int, unsigned, void*);  /* forward */
191dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
192dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
193dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic JdwpProcess*
194dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectjdwp_process_alloc( int  socket )
195dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
196dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    JdwpProcess*  proc = calloc(1,sizeof(*proc));
197dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
198dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (proc == NULL) {
199dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        D("not enough memory to create new JDWP process\n");
200dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        return NULL;
201dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
202dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
203dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    proc->socket = socket;
204dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    proc->pid    = -1;
205dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    proc->next   = proc;
206dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    proc->prev   = proc;
207dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
208dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    proc->fde = fdevent_create( socket, jdwp_process_event, proc );
209dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (proc->fde == NULL) {
210dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        D("could not create fdevent for new JDWP process\n" );
211dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        free(proc);
212dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        return NULL;
213dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
214dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
215dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    proc->fde->state |= FDE_DONT_CLOSE;
216dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    proc->in_len      = 0;
217dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    proc->out_count   = 0;
218dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
219dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    /* append to list */
220dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    proc->next = &_jdwp_list;
221dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    proc->prev = proc->next->prev;
222dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
223dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    proc->prev->next = proc;
224dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    proc->next->prev = proc;
225dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
226dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    /* start by waiting for the PID */
227dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    fdevent_add(proc->fde, FDE_READ);
228dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
229dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    return proc;
230dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
231dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
232dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
233dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic void
234dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectjdwp_process_event( int  socket, unsigned  events, void*  _proc )
235dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
236dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    JdwpProcess*  proc = _proc;
237dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
238dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (events & FDE_READ) {
239dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if (proc->pid < 0) {
240dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            /* read the PID as a 4-hexchar string */
241dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            char*  p    = proc->in_buff + proc->in_len;
242dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            int    size = 4 - proc->in_len;
243dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            char   temp[5];
244dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            while (size > 0) {
245dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                int  len = recv( socket, p, size, 0 );
246dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                if (len < 0) {
247dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                    if (errno == EINTR)
248dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                        continue;
249dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                    if (errno == EAGAIN)
250dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                        return;
251dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                    /* this can fail here if the JDWP process crashes very fast */
252dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                    D("weird unknown JDWP process failure: %s\n",
253dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                      strerror(errno));
254dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
255dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                    goto CloseProcess;
256dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                }
257dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                if (len == 0) {  /* end of stream ? */
258dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                    D("weird end-of-stream from unknown JDWP process\n");
259dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                    goto CloseProcess;
260dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                }
261dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                p            += len;
262dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                proc->in_len += len;
263dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                size         -= len;
264dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            }
265dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            /* we have read 4 characters, now decode the pid */
266dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            memcpy(temp, proc->in_buff, 4);
267dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            temp[4] = 0;
268dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
269dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            if (sscanf( temp, "%04x", &proc->pid ) != 1) {
270dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                D("could not decode JDWP %p PID number: '%s'\n", proc, temp);
271dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                goto CloseProcess;
272dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            }
273dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
274dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            /* all is well, keep reading to detect connection closure */
275dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            D("Adding pid %d to jdwp process list\n", proc->pid);
276dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            jdwp_process_list_updated();
277dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
278dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        else
279dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        {
280dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            /* the pid was read, if we get there it's probably because the connection
281dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project             * was closed (e.g. the JDWP process exited or crashed) */
282dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            char  buf[32];
283dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
284dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            for (;;) {
285dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                int  len = recv(socket, buf, sizeof(buf), 0);
286dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
287dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                if (len <= 0) {
288dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                    if (len < 0 && errno == EINTR)
289dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                        continue;
290dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                    if (len < 0 && errno == EAGAIN)
291dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                        return;
292dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                    else {
293dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                        D("terminating JDWP %d connection: %s\n", proc->pid,
294dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                          strerror(errno));
295dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                        break;
296dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                    }
297dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                }
298dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                else {
299dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                    D( "ignoring unexpected JDWP %d control socket activity (%d bytes)\n",
300dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                       proc->pid, len );
301dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                }
302dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            }
303dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
304dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        CloseProcess:
305dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            if (proc->pid >= 0)
306dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                D( "remove pid %d to jdwp process list\n", proc->pid );
307dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            jdwp_process_free(proc);
308dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            return;
309dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
310dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
311dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
312dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (events & FDE_WRITE) {
313dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        D("trying to write to JDWP pid controli (count=%d first=%d) %d\n",
314dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project          proc->pid, proc->out_count, proc->out_fds[0]);
315dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if (proc->out_count > 0) {
316dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            int  fd = proc->out_fds[0];
317dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            int  n, ret;
318dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            struct cmsghdr*  cmsg;
319dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            struct msghdr    msg;
320dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            struct iovec     iov;
321dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            char             dummy = '!';
322dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            char             buffer[sizeof(struct cmsghdr) + sizeof(int)];
323dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
324dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            iov.iov_base       = &dummy;
325dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            iov.iov_len        = 1;
326dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            msg.msg_name       = NULL;
327dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            msg.msg_namelen    = 0;
328dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            msg.msg_iov        = &iov;
329dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            msg.msg_iovlen     = 1;
330dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            msg.msg_flags      = 0;
331dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            msg.msg_control    = buffer;
332dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            msg.msg_controllen = sizeof(buffer);
333dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
334dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            cmsg = CMSG_FIRSTHDR(&msg);
335dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            cmsg->cmsg_len   = msg.msg_controllen;
336dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            cmsg->cmsg_level = SOL_SOCKET;
337dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            cmsg->cmsg_type  = SCM_RIGHTS;
338dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            ((int*)CMSG_DATA(cmsg))[0] = fd;
339dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
340dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            for (;;) {
341dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                ret = sendmsg(proc->socket, &msg, 0);
342dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                if (ret >= 0)
343dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                    break;
344dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                if (errno == EINTR)
345dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                    continue;
346dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                D("sending new file descriptor to JDWP %d failed: %s\n",
347dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                  proc->pid, strerror(errno));
348dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                goto CloseProcess;
349dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            }
350dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
351dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            D("sent file descriptor %d to JDWP process %d\n",
352dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project              fd, proc->pid);
353dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
354dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            for (n = 1; n < proc->out_count; n++)
355dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                proc->out_fds[n-1] = proc->out_fds[n];
356dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
357dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            if (--proc->out_count == 0)
358dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                fdevent_del( proc->fde, FDE_WRITE );
359dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
360dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
361dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
362dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
363dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
364dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectint
365dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectcreate_jdwp_connection_fd(int  pid)
366dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
367dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    JdwpProcess*  proc = _jdwp_list.next;
368dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
369dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    D("looking for pid %d in JDWP process list\n", pid);
370dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    for ( ; proc != &_jdwp_list; proc = proc->next ) {
371dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if (proc->pid == pid) {
372dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            goto FoundIt;
373dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
374dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
375dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    D("search failed !!\n");
376dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    return -1;
377dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
378dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source ProjectFoundIt:
379dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    {
380dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        int  fds[2];
381dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
382dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if (proc->out_count >= MAX_OUT_FDS) {
383dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            D("%s: too many pending JDWP connection for pid %d\n",
384dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project              __FUNCTION__, pid);
385dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            return -1;
386dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
387dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
388dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if (adb_socketpair(fds) < 0) {
389dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            D("%s: socket pair creation failed: %s\n",
390dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project              __FUNCTION__, strerror(errno));
391dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            return -1;
392dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
393dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
394dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        proc->out_fds[ proc->out_count ] = fds[1];
395dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if (++proc->out_count == 1)
396dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            fdevent_add( proc->fde, FDE_WRITE );
397dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
398dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        return fds[0];
399dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
400dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
401dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
402dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project/**  VM DEBUG CONTROL SOCKET
403dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project **
404dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project **  we do implement a custom asocket to receive the data
405dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project **/
406dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
407dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project/* name of the debug control Unix socket */
408dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#define  JDWP_CONTROL_NAME      "\0jdwp-control"
409dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#define  JDWP_CONTROL_NAME_LEN  (sizeof(JDWP_CONTROL_NAME)-1)
410dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
411dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projecttypedef struct {
412dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    int       listen_socket;
413dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    fdevent*  fde;
414dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
415dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} JdwpControl;
416dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
417dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
418dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic void
419dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectjdwp_control_event(int  s, unsigned events, void*  user);
420dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
421dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
422dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic int
423dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectjdwp_control_init( JdwpControl*  control,
424dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                   const char*   sockname,
425dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                   int           socknamelen )
426dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
427dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    struct sockaddr_un   addr;
428dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    socklen_t            addrlen;
429dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    int                  s;
430dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    int                  maxpath = sizeof(addr.sun_path);
431dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    int                  pathlen = socknamelen;
432dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
433dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (pathlen >= maxpath) {
434dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        D( "vm debug control socket name too long (%d extra chars)\n",
435dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project           pathlen+1-maxpath );
436dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        return -1;
437dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
438dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
439dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    memset(&addr, 0, sizeof(addr));
440dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    addr.sun_family = AF_UNIX;
441dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    memcpy(addr.sun_path, sockname, socknamelen);
442dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
443dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    s = socket( AF_UNIX, SOCK_STREAM, 0 );
444dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (s < 0) {
445dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        D( "could not create vm debug control socket. %d: %s\n",
446dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project           errno, strerror(errno));
447dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        return -1;
448dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
449dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
450dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    addrlen = (pathlen + sizeof(addr.sun_family));
451dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
452dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (bind(s, (struct sockaddr*)&addr, addrlen) < 0) {
453dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        D( "could not bind vm debug control socket: %d: %s\n",
454dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project           errno, strerror(errno) );
455dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        adb_close(s);
456dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        return -1;
457dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
458dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
459dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if ( listen(s, 4) < 0 ) {
460dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        D("listen failed in jdwp control socket: %d: %s\n",
461dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project          errno, strerror(errno));
462dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        adb_close(s);
463dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        return -1;
464dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
465dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
466dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    control->listen_socket = s;
467dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
468dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    control->fde = fdevent_create(s, jdwp_control_event, control);
469dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (control->fde == NULL) {
470dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        D( "could not create fdevent for jdwp control socket\n" );
471dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        adb_close(s);
472dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        return -1;
473dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
474dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
475dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    /* only wait for incoming connections */
476dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    fdevent_add(control->fde, FDE_READ);
477dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
478dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    D("jdwp control socket started (%d)\n", control->listen_socket);
479dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    return 0;
480dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
481dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
482dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
483dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic void
484dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectjdwp_control_event( int  s, unsigned  events, void*  _control )
485dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
486dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    JdwpControl*  control = (JdwpControl*) _control;
487dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
488dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (events & FDE_READ) {
489dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        struct sockaddr   addr;
490dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        socklen_t         addrlen = sizeof(addr);
491dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        int               s = -1;
492dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        JdwpProcess*      proc;
493dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
494dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        do {
495dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            s = adb_socket_accept( control->listen_socket, &addr, &addrlen );
496dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            if (s < 0) {
497dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                if (errno == EINTR)
498dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                    continue;
499dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                if (errno == ECONNABORTED) {
500dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                    /* oops, the JDWP process died really quick */
501dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                    D("oops, the JDWP process died really quick\n");
502dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                    return;
503dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                }
504dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                /* the socket is probably closed ? */
505dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                D( "weird accept() failed on jdwp control socket: %s\n",
506dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                   strerror(errno) );
507dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                return;
508dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            }
509dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
510dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        while (s < 0);
511dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
512dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        proc = jdwp_process_alloc( s );
513dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if (proc == NULL)
514dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            return;
515dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
516dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
517dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
518dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
519dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic JdwpControl   _jdwp_control;
520dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
521dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project/** "jdwp" local service implementation
522dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project ** this simply returns the list of known JDWP process pids
523dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project **/
524dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
525dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projecttypedef struct {
526dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    asocket  socket;
527dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    int      pass;
528dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} JdwpSocket;
529dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
530dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic void
531dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectjdwp_socket_close( asocket*  s )
532dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
533dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    asocket*  peer = s->peer;
534dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
535dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    remove_socket(s);
536dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
537dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (peer) {
538dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        peer->peer = NULL;
539dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        peer->close(peer);
540dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
541dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    free(s);
542dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
543dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
544dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic int
545dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectjdwp_socket_enqueue( asocket*  s, apacket*  p )
546dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
547dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    /* you can't write to this asocket */
548dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    put_apacket(p);
549dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    s->peer->close(s->peer);
550dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    return -1;
551dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
552dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
553dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
554dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic void
555dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectjdwp_socket_ready( asocket*  s )
556dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
557dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    JdwpSocket*  jdwp = (JdwpSocket*)s;
558dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    asocket*     peer = jdwp->socket.peer;
559dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
560dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project   /* on the first call, send the list of pids,
561dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    * on the second one, close the connection
562dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    */
563dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (jdwp->pass == 0) {
564dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        apacket*  p = get_apacket();
565dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        p->len = jdwp_process_list((char*)p->data, MAX_PAYLOAD);
566dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        peer->enqueue(peer, p);
567dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        jdwp->pass = 1;
568dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
569dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    else {
570dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        peer->close(peer);
571dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
572dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
573dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
574dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectasocket*
575dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectcreate_jdwp_service_socket( void )
576dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
577dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    JdwpSocket*  s = calloc(sizeof(*s),1);
578dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
579dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (s == NULL)
580dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        return NULL;
581dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
582dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    install_local_socket(&s->socket);
583dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
584dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    s->socket.ready   = jdwp_socket_ready;
585dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    s->socket.enqueue = jdwp_socket_enqueue;
586dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    s->socket.close   = jdwp_socket_close;
587dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    s->pass           = 0;
588dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
589dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    return &s->socket;
590dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
591dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
592dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project/** "track-jdwp" local service implementation
593dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project ** this periodically sends the list of known JDWP process pids
594dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project ** to the client...
595dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project **/
596dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
597dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projecttypedef struct JdwpTracker  JdwpTracker;
598dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
599dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstruct JdwpTracker {
600dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    asocket       socket;
601dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    JdwpTracker*  next;
602dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    JdwpTracker*  prev;
603dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    int           need_update;
604dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project};
605dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
606dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic JdwpTracker   _jdwp_trackers_list;
607dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
608dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
609dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic void
610dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectjdwp_process_list_updated(void)
611dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
612dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    char             buffer[1024];
613dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    int              len;
614dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    JdwpTracker*  t = _jdwp_trackers_list.next;
615dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
616dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    len = jdwp_process_list_msg(buffer, sizeof(buffer));
617dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
618dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    for ( ; t != &_jdwp_trackers_list; t = t->next ) {
619dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        apacket*  p    = get_apacket();
620dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        asocket*  peer = t->socket.peer;
621dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        memcpy(p->data, buffer, len);
622dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        p->len = len;
623dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        peer->enqueue( peer, p );
624dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
625dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
626dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
627dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic void
628dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectjdwp_tracker_close( asocket*  s )
629dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
630dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    JdwpTracker*  tracker = (JdwpTracker*) s;
631dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    asocket*      peer    = s->peer;
632dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
633dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (peer) {
634dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        peer->peer = NULL;
635dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        peer->close(peer);
636dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
637dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
638dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    remove_socket(s);
639dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
640dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    tracker->prev->next = tracker->next;
641dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    tracker->next->prev = tracker->prev;
642dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
643dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    free(s);
644dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
645dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
646dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic void
647dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectjdwp_tracker_ready( asocket*  s )
648dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
649dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    JdwpTracker*  t = (JdwpTracker*) s;
650dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
651dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (t->need_update) {
652dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        apacket*  p = get_apacket();
653dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        t->need_update = 0;
654dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        p->len = jdwp_process_list_msg((char*)p->data, sizeof(p->data));
655dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        s->peer->enqueue(s->peer, p);
656dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
657dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
658dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
659dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic int
660dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectjdwp_tracker_enqueue( asocket*  s, apacket*  p )
661dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
662dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    /* you can't write to this socket */
663dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    put_apacket(p);
664dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    s->peer->close(s->peer);
665dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    return -1;
666dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
667dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
668dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
669dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectasocket*
670dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectcreate_jdwp_tracker_service_socket( void )
671dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
672dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    JdwpTracker*  t = calloc(sizeof(*t),1);
673dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
674dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (t == NULL)
675dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        return NULL;
676dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
677dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    t->next = &_jdwp_trackers_list;
678dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    t->prev = t->next->prev;
679dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
680dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    t->next->prev = t;
681dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    t->prev->next = t;
682dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
683dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    install_local_socket(&t->socket);
684dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
685dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    t->socket.ready   = jdwp_tracker_ready;
686dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    t->socket.enqueue = jdwp_tracker_enqueue;
687dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    t->socket.close   = jdwp_tracker_close;
688dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    t->need_update    = 1;
689dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
690dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    return &t->socket;
691dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
692dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
693dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
694dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectint
695dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectinit_jdwp(void)
696dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
697dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    _jdwp_list.next = &_jdwp_list;
698dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    _jdwp_list.prev = &_jdwp_list;
699dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
700dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    _jdwp_trackers_list.next = &_jdwp_trackers_list;
701dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    _jdwp_trackers_list.prev = &_jdwp_trackers_list;
702dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
703dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    return jdwp_control_init( &_jdwp_control,
704dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                              JDWP_CONTROL_NAME,
705dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                              JDWP_CONTROL_NAME_LEN );
706dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
707dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
708dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#endif /* !ADB_HOST */
709dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
710