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