13313426fad9eaaf53017cdbde889ebcec91358ecDan Albert/*
23313426fad9eaaf53017cdbde889ebcec91358ecDan Albert * Copyright (C) 2015 The Android Open Source Project
33313426fad9eaaf53017cdbde889ebcec91358ecDan Albert *
43313426fad9eaaf53017cdbde889ebcec91358ecDan Albert * Licensed under the Apache License, Version 2.0 (the "License");
53313426fad9eaaf53017cdbde889ebcec91358ecDan Albert * you may not use this file except in compliance with the License.
63313426fad9eaaf53017cdbde889ebcec91358ecDan Albert * You may obtain a copy of the License at
73313426fad9eaaf53017cdbde889ebcec91358ecDan Albert *
83313426fad9eaaf53017cdbde889ebcec91358ecDan Albert *      http://www.apache.org/licenses/LICENSE-2.0
93313426fad9eaaf53017cdbde889ebcec91358ecDan Albert *
103313426fad9eaaf53017cdbde889ebcec91358ecDan Albert * Unless required by applicable law or agreed to in writing, software
113313426fad9eaaf53017cdbde889ebcec91358ecDan Albert * distributed under the License is distributed on an "AS IS" BASIS,
123313426fad9eaaf53017cdbde889ebcec91358ecDan Albert * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
133313426fad9eaaf53017cdbde889ebcec91358ecDan Albert * See the License for the specific language governing permissions and
143313426fad9eaaf53017cdbde889ebcec91358ecDan Albert * limitations under the License.
153313426fad9eaaf53017cdbde889ebcec91358ecDan Albert */
163313426fad9eaaf53017cdbde889ebcec91358ecDan Albert
17dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project/* implement the "debug-ports" and "track-debug-ports" device services */
183313426fad9eaaf53017cdbde889ebcec91358ecDan Albert
19aed3c61c4437ebb05eadfb3bf85d6962c30b9935Yabin Cui#define TRACE_TAG JDWP
203313426fad9eaaf53017cdbde889ebcec91358ecDan Albert
21dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include "sysdeps.h"
223313426fad9eaaf53017cdbde889ebcec91358ecDan Albert
23dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <errno.h>
24dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <stdio.h>
25381cfa9a8bc262dcd823a8bb6adc189595a2fe7dElliott Hughes#include <stdlib.h>
26dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <string.h>
278f5daadcc13a238344f5121a38345a18abc5aa9aTeddie Stenvi#include <unistd.h>
28dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
293313426fad9eaaf53017cdbde889ebcec91358ecDan Albert#include "adb.h"
306dfef255b8fa77e3b5c0a69b7f276ea8e25e22cdYabin Cui#include "adb_utils.h"
313313426fad9eaaf53017cdbde889ebcec91358ecDan Albert
32dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project/* here's how these things work.
33dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
34dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project   when adbd starts, it creates a unix server socket
35dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project   named @vm-debug-control (@ is a shortcut for "first byte is zero"
36dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project   to use the private namespace instead of the file system)
37dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
38dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project   when a new JDWP daemon thread starts in a new VM process, it creates
39dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project   a connection to @vm-debug-control to announce its availability.
40dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
41dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
42dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project     JDWP thread                             @vm-debug-control
43dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project         |                                         |
44dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project         |------------------------------->         |
45dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project         | hello I'm in process <pid>              |
46dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project         |                                         |
47dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project         |                                         |
48dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
49dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    the connection is kept alive. it will be closed automatically if
50dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    the JDWP process terminates (this allows adbd to detect dead
51dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    processes).
52dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
53dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    adbd thus maintains a list of "active" JDWP processes. it can send
54dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    its content to clients through the "device:debug-ports" service,
55dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    or even updates through the "device:track-debug-ports" service.
56dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
57dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    when a debugger wants to connect, it simply runs the command
58dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    equivalent to  "adb forward tcp:<hostport> jdwp:<pid>"
59dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
60dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    "jdwp:<pid>" is a new forward destination format used to target
61dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    a given JDWP process on the device. when sutch a request arrives,
62dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    adbd does the following:
63dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
64dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project      - first, it calls socketpair() to create a pair of equivalent
65dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        sockets.
66dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
67dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project      - it attaches the first socket in the pair to a local socket
68dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        which is itself attached to the transport's remote socket:
69dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
70dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
71dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project      - it sends the file descriptor of the second socket directly
72dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        to the JDWP process with the help of sendmsg()
73dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
74dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
75dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project     JDWP thread                             @vm-debug-control
76dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project         |                                         |
77dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project         |                  <----------------------|
78dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project         |           OK, try this file descriptor  |
79dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project         |                                         |
80dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project         |                                         |
81dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
82dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project   then, the JDWP thread uses this new socket descriptor as its
83dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project   pass-through connection to the debugger (and receives the
84dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project   JDWP-Handshake message, answers to it, etc...)
85dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
86dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project   this gives the following graphics:
87dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                    ____________________________________
88dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                   |                                    |
89dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                   |          ADB Server (host)         |
90dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                   |                                    |
91dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        Debugger <---> LocalSocket <----> RemoteSocket  |
92dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                   |                           ^^       |
93dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                   |___________________________||_______|
94dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                                               ||
95dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                                     Transport ||
96dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project           (TCP for emulator - USB for device) ||
97dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                                               ||
98dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                    ___________________________||_______
99dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                   |                           ||       |
100dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                   |          ADBD  (device)   ||       |
101dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                   |                           VV       |
102dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project         JDWP <======> LocalSocket <----> RemoteSocket  |
103dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                   |                                    |
104dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                   |____________________________________|
105dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
106dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    due to the way adb works, this doesn't need a special socket
107dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    type or fancy handling of socket termination if either the debugger
108dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    or the JDWP process closes the connection.
109dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
110dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    THIS IS THE SIMPLEST IMPLEMENTATION I COULD FIND, IF YOU HAPPEN
111dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    TO HAVE A BETTER IDEA, LET ME KNOW - Digit
112dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
113dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project**********************************************************************/
114dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
115dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project/** JDWP PID List Support Code
116dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project ** for each JDWP process, we record its pid and its connected socket
117dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project **/
118dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
119dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#define  MAX_OUT_FDS   4
120dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
121dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#if !ADB_HOST
122dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
123dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <sys/socket.h>
124dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <sys/un.h>
125dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
126dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstruct JdwpProcess {
127dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    JdwpProcess*  next;
128dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    JdwpProcess*  prev;
129dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    int           pid;
130dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    int           socket;
131dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    fdevent*      fde;
132dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
133dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    char          in_buff[4];  /* input character to read PID */
134dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    int           in_len;      /* number from JDWP process    */
135dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
136dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    int           out_fds[MAX_OUT_FDS]; /* output array of file descriptors */
137dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    int           out_count;            /* to send to the JDWP process      */
138dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project};
139dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
140dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic JdwpProcess  _jdwp_list;
141dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
142dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic int
143dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectjdwp_process_list( char*  buffer, int  bufferlen )
144dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
145dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    char*         end  = buffer + bufferlen;
146dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    char*         p    = buffer;
147dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    JdwpProcess*  proc = _jdwp_list.next;
148dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
149dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    for ( ; proc != &_jdwp_list; proc = proc->next ) {
150dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        int  len;
151dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
152dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        /* skip transient connections */
153dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if (proc->pid < 0)
154dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            continue;
155dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
156dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        len = snprintf(p, end-p, "%d\n", proc->pid);
157dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if (p + len >= end)
158dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            break;
159dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        p += len;
160dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
161dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    p[0] = 0;
162dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    return (p - buffer);
163dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
164dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
165dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
166dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic int
167dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectjdwp_process_list_msg( char*  buffer, int  bufferlen )
168dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
169dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    char  head[5];
170dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    int   len = jdwp_process_list( buffer+4, bufferlen-4 );
171dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    snprintf(head, sizeof head, "%04x", len);
172dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    memcpy(buffer, head, 4);
173dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    return len + 4;
174dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
175dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
176dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
177dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic void  jdwp_process_list_updated(void);
178dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
179dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic void
180dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectjdwp_process_free( JdwpProcess*  proc )
181dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
182dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (proc) {
183dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        int  n;
184dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
185dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        proc->prev->next = proc->next;
186dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        proc->next->prev = proc->prev;
187dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
188dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if (proc->socket >= 0) {
1898cf0d59f61ae0b8554ecf3fe051850508b761b79Mike Lockwood            adb_shutdown(proc->socket);
190dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            adb_close(proc->socket);
191dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            proc->socket = -1;
192dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
193dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
194dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if (proc->fde != NULL) {
195dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            fdevent_destroy(proc->fde);
196dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            proc->fde = NULL;
197dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
198dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        proc->pid = -1;
199dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
200dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        for (n = 0; n < proc->out_count; n++) {
201dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            adb_close(proc->out_fds[n]);
202dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
203dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        proc->out_count = 0;
204dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
205dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        free(proc);
206dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
207dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        jdwp_process_list_updated();
208dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
209dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
210dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
211dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
212dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic void  jdwp_process_event(int, unsigned, void*);  /* forward */
213dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
214dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
215dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic JdwpProcess*
216dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectjdwp_process_alloc( int  socket )
217dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
218bac3474a8256cb32a29e8d46f78cad95a5502692Dan Albert    JdwpProcess* proc = reinterpret_cast<JdwpProcess*>(
219bac3474a8256cb32a29e8d46f78cad95a5502692Dan Albert        calloc(1, sizeof(*proc)));
220dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
221dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (proc == NULL) {
2227a3f8d6691b3fbd8014a98de8455dbcfcc9629e4Yabin Cui        D("not enough memory to create new JDWP process");
223dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        return NULL;
224dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
225dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
226dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    proc->socket = socket;
227dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    proc->pid    = -1;
228dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    proc->next   = proc;
229dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    proc->prev   = proc;
230dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
231dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    proc->fde = fdevent_create( socket, jdwp_process_event, proc );
232dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (proc->fde == NULL) {
2337a3f8d6691b3fbd8014a98de8455dbcfcc9629e4Yabin Cui        D("could not create fdevent for new JDWP process" );
234dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        free(proc);
235dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        return NULL;
236dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
237dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
238dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    proc->fde->state |= FDE_DONT_CLOSE;
239dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    proc->in_len      = 0;
240dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    proc->out_count   = 0;
241dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
242dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    /* append to list */
243dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    proc->next = &_jdwp_list;
244dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    proc->prev = proc->next->prev;
245dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
246dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    proc->prev->next = proc;
247dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    proc->next->prev = proc;
248dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
249dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    /* start by waiting for the PID */
250dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    fdevent_add(proc->fde, FDE_READ);
251dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
252dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    return proc;
253dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
254dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
255dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
256dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic void
257dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectjdwp_process_event( int  socket, unsigned  events, void*  _proc )
258dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
259bac3474a8256cb32a29e8d46f78cad95a5502692Dan Albert    JdwpProcess*  proc = reinterpret_cast<JdwpProcess*>(_proc);
260dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
261dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (events & FDE_READ) {
262dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if (proc->pid < 0) {
263dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            /* read the PID as a 4-hexchar string */
264dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            char*  p    = proc->in_buff + proc->in_len;
265dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            int    size = 4 - proc->in_len;
266dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            char   temp[5];
267dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            while (size > 0) {
268dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                int  len = recv( socket, p, size, 0 );
269dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                if (len < 0) {
270dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                    if (errno == EINTR)
271dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                        continue;
272dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                    if (errno == EAGAIN)
273dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                        return;
274dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                    /* this can fail here if the JDWP process crashes very fast */
2757a3f8d6691b3fbd8014a98de8455dbcfcc9629e4Yabin Cui                    D("weird unknown JDWP process failure: %s",
276dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                      strerror(errno));
277dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
278dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                    goto CloseProcess;
279dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                }
280dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                if (len == 0) {  /* end of stream ? */
2817a3f8d6691b3fbd8014a98de8455dbcfcc9629e4Yabin Cui                    D("weird end-of-stream from unknown JDWP process");
282dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                    goto CloseProcess;
283dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                }
284dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                p            += len;
285dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                proc->in_len += len;
286dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                size         -= len;
287dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            }
288dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            /* we have read 4 characters, now decode the pid */
289dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            memcpy(temp, proc->in_buff, 4);
290dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            temp[4] = 0;
291dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
292dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            if (sscanf( temp, "%04x", &proc->pid ) != 1) {
2937a3f8d6691b3fbd8014a98de8455dbcfcc9629e4Yabin Cui                D("could not decode JDWP %p PID number: '%s'", proc, temp);
294dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                goto CloseProcess;
295dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            }
296dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
297dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            /* all is well, keep reading to detect connection closure */
2987a3f8d6691b3fbd8014a98de8455dbcfcc9629e4Yabin Cui            D("Adding pid %d to jdwp process list", proc->pid);
299dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            jdwp_process_list_updated();
300dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
301dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        else
302dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        {
303dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            /* the pid was read, if we get there it's probably because the connection
304dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project             * was closed (e.g. the JDWP process exited or crashed) */
305dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            char  buf[32];
306dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
307dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            for (;;) {
308dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                int  len = recv(socket, buf, sizeof(buf), 0);
309dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
310dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                if (len <= 0) {
311dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                    if (len < 0 && errno == EINTR)
312dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                        continue;
313dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                    if (len < 0 && errno == EAGAIN)
314dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                        return;
315dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                    else {
3167a3f8d6691b3fbd8014a98de8455dbcfcc9629e4Yabin Cui                        D("terminating JDWP %d connection: %s", proc->pid,
317dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                          strerror(errno));
318dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                        break;
319dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                    }
320dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                }
321dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                else {
3227a3f8d6691b3fbd8014a98de8455dbcfcc9629e4Yabin Cui                    D( "ignoring unexpected JDWP %d control socket activity (%d bytes)",
323dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                       proc->pid, len );
324dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                }
325dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            }
326dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
327dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        CloseProcess:
328aed3c61c4437ebb05eadfb3bf85d6962c30b9935Yabin Cui            if (proc->pid >= 0) {
3297a3f8d6691b3fbd8014a98de8455dbcfcc9629e4Yabin Cui                D( "remove pid %d to jdwp process list", proc->pid );
330aed3c61c4437ebb05eadfb3bf85d6962c30b9935Yabin Cui            }
331dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            jdwp_process_free(proc);
332dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            return;
333dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
334dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
335dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
336dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (events & FDE_WRITE) {
3377a3f8d6691b3fbd8014a98de8455dbcfcc9629e4Yabin Cui        D("trying to write to JDWP pid controli (count=%d first=%d) %d",
338dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project          proc->pid, proc->out_count, proc->out_fds[0]);
339dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if (proc->out_count > 0) {
340dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            int  fd = proc->out_fds[0];
341dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            int  n, ret;
342dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            struct cmsghdr*  cmsg;
343dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            struct msghdr    msg;
344dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            struct iovec     iov;
345dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            char             dummy = '!';
346dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            char             buffer[sizeof(struct cmsghdr) + sizeof(int)];
347dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
348dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            iov.iov_base       = &dummy;
349dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            iov.iov_len        = 1;
350dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            msg.msg_name       = NULL;
351dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            msg.msg_namelen    = 0;
352dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            msg.msg_iov        = &iov;
353dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            msg.msg_iovlen     = 1;
354dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            msg.msg_flags      = 0;
355dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            msg.msg_control    = buffer;
356dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            msg.msg_controllen = sizeof(buffer);
357dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
358dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            cmsg = CMSG_FIRSTHDR(&msg);
359dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            cmsg->cmsg_len   = msg.msg_controllen;
360dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            cmsg->cmsg_level = SOL_SOCKET;
361dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            cmsg->cmsg_type  = SCM_RIGHTS;
362dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            ((int*)CMSG_DATA(cmsg))[0] = fd;
363dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
3646dfef255b8fa77e3b5c0a69b7f276ea8e25e22cdYabin Cui            if (!set_file_block_mode(proc->socket, true)) {
3656dfef255b8fa77e3b5c0a69b7f276ea8e25e22cdYabin Cui                VLOG(JDWP) << "failed to set blocking mode for fd " << proc->socket;
3668f5daadcc13a238344f5121a38345a18abc5aa9aTeddie Stenvi                goto CloseProcess;
3678f5daadcc13a238344f5121a38345a18abc5aa9aTeddie Stenvi            }
3688f5daadcc13a238344f5121a38345a18abc5aa9aTeddie Stenvi
369dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            for (;;) {
370dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                ret = sendmsg(proc->socket, &msg, 0);
3718f5daadcc13a238344f5121a38345a18abc5aa9aTeddie Stenvi                if (ret >= 0) {
3728f5daadcc13a238344f5121a38345a18abc5aa9aTeddie Stenvi                    adb_close(fd);
373dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                    break;
3748f5daadcc13a238344f5121a38345a18abc5aa9aTeddie Stenvi                }
375dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                if (errno == EINTR)
376dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                    continue;
3777a3f8d6691b3fbd8014a98de8455dbcfcc9629e4Yabin Cui                D("sending new file descriptor to JDWP %d failed: %s",
378dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                  proc->pid, strerror(errno));
379dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                goto CloseProcess;
380dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            }
381dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
3827a3f8d6691b3fbd8014a98de8455dbcfcc9629e4Yabin Cui            D("sent file descriptor %d to JDWP process %d",
383dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project              fd, proc->pid);
384dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
385dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            for (n = 1; n < proc->out_count; n++)
386dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                proc->out_fds[n-1] = proc->out_fds[n];
387dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
3886dfef255b8fa77e3b5c0a69b7f276ea8e25e22cdYabin Cui            if (!set_file_block_mode(proc->socket, false)) {
3896dfef255b8fa77e3b5c0a69b7f276ea8e25e22cdYabin Cui                VLOG(JDWP) << "failed to set non-blocking mode for fd " << proc->socket;
3908f5daadcc13a238344f5121a38345a18abc5aa9aTeddie Stenvi                goto CloseProcess;
3918f5daadcc13a238344f5121a38345a18abc5aa9aTeddie Stenvi            }
3928f5daadcc13a238344f5121a38345a18abc5aa9aTeddie Stenvi
393dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            if (--proc->out_count == 0)
394dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                fdevent_del( proc->fde, FDE_WRITE );
395dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
396dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
397dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
398dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
399dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
400dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectint
401dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectcreate_jdwp_connection_fd(int  pid)
402dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
403dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    JdwpProcess*  proc = _jdwp_list.next;
404dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
4057a3f8d6691b3fbd8014a98de8455dbcfcc9629e4Yabin Cui    D("looking for pid %d in JDWP process list", pid);
406dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    for ( ; proc != &_jdwp_list; proc = proc->next ) {
407dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if (proc->pid == pid) {
408dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            goto FoundIt;
409dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
410dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
4117a3f8d6691b3fbd8014a98de8455dbcfcc9629e4Yabin Cui    D("search failed !!");
412dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    return -1;
413dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
414dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source ProjectFoundIt:
415dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    {
416dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        int  fds[2];
417dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
418dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if (proc->out_count >= MAX_OUT_FDS) {
4197a3f8d6691b3fbd8014a98de8455dbcfcc9629e4Yabin Cui            D("%s: too many pending JDWP connection for pid %d",
420dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project              __FUNCTION__, pid);
421dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            return -1;
422dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
423dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
424dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if (adb_socketpair(fds) < 0) {
4257a3f8d6691b3fbd8014a98de8455dbcfcc9629e4Yabin Cui            D("%s: socket pair creation failed: %s",
426dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project              __FUNCTION__, strerror(errno));
427dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            return -1;
428dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
4297a3f8d6691b3fbd8014a98de8455dbcfcc9629e4Yabin Cui        D("socketpair: (%d,%d)", fds[0], fds[1]);
430dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
431dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        proc->out_fds[ proc->out_count ] = fds[1];
432dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if (++proc->out_count == 1)
433dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            fdevent_add( proc->fde, FDE_WRITE );
434dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
435dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        return fds[0];
436dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
437dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
438dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
439dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project/**  VM DEBUG CONTROL SOCKET
440dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project **
441dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project **  we do implement a custom asocket to receive the data
442dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project **/
443dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
444dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project/* name of the debug control Unix socket */
445dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#define  JDWP_CONTROL_NAME      "\0jdwp-control"
446dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#define  JDWP_CONTROL_NAME_LEN  (sizeof(JDWP_CONTROL_NAME)-1)
447dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
4482d4121c0dcc93382bcd7ea6476f433d8254919ddElliott Hughesstruct JdwpControl {
449dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    int       listen_socket;
450dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    fdevent*  fde;
4512d4121c0dcc93382bcd7ea6476f433d8254919ddElliott Hughes};
452dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
453dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
454dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic void
455dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectjdwp_control_event(int  s, unsigned events, void*  user);
456dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
457dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
458dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic int
459dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectjdwp_control_init( JdwpControl*  control,
460dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                   const char*   sockname,
461dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                   int           socknamelen )
462dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
4637e16cc15b5e16ec35f4c9f0516a6cacf90326856Erik Kline    sockaddr_un   addr;
4647e16cc15b5e16ec35f4c9f0516a6cacf90326856Erik Kline    socklen_t     addrlen;
4657e16cc15b5e16ec35f4c9f0516a6cacf90326856Erik Kline    int           s;
4667e16cc15b5e16ec35f4c9f0516a6cacf90326856Erik Kline    int           maxpath = sizeof(addr.sun_path);
4677e16cc15b5e16ec35f4c9f0516a6cacf90326856Erik Kline    int           pathlen = socknamelen;
468dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
469dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (pathlen >= maxpath) {
4707a3f8d6691b3fbd8014a98de8455dbcfcc9629e4Yabin Cui        D( "vm debug control socket name too long (%d extra chars)",
471dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project           pathlen+1-maxpath );
472dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        return -1;
473dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
474dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
475dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    memset(&addr, 0, sizeof(addr));
476dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    addr.sun_family = AF_UNIX;
477dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    memcpy(addr.sun_path, sockname, socknamelen);
478dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
479dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    s = socket( AF_UNIX, SOCK_STREAM, 0 );
480dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (s < 0) {
4817a3f8d6691b3fbd8014a98de8455dbcfcc9629e4Yabin Cui        D( "could not create vm debug control socket. %d: %s",
482dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project           errno, strerror(errno));
483dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        return -1;
484dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
485dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
486dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    addrlen = (pathlen + sizeof(addr.sun_family));
487dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
4887e16cc15b5e16ec35f4c9f0516a6cacf90326856Erik Kline    if (bind(s, reinterpret_cast<sockaddr*>(&addr), addrlen) < 0) {
4897a3f8d6691b3fbd8014a98de8455dbcfcc9629e4Yabin Cui        D( "could not bind vm debug control socket: %d: %s",
490dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project           errno, strerror(errno) );
491dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        adb_close(s);
492dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        return -1;
493dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
494dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
495dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if ( listen(s, 4) < 0 ) {
4967a3f8d6691b3fbd8014a98de8455dbcfcc9629e4Yabin Cui        D("listen failed in jdwp control socket: %d: %s",
497dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project          errno, strerror(errno));
498dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        adb_close(s);
499dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        return -1;
500dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
501dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
502dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    control->listen_socket = s;
503dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
504dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    control->fde = fdevent_create(s, jdwp_control_event, control);
505dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (control->fde == NULL) {
5067a3f8d6691b3fbd8014a98de8455dbcfcc9629e4Yabin Cui        D( "could not create fdevent for jdwp control socket" );
507dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        adb_close(s);
508dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        return -1;
509dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
510dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
511dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    /* only wait for incoming connections */
512dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    fdevent_add(control->fde, FDE_READ);
51395ef82866c7a922bf588027aa38c58a45eb84d9cBenoit Goby    close_on_exec(s);
514dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
5157a3f8d6691b3fbd8014a98de8455dbcfcc9629e4Yabin Cui    D("jdwp control socket started (%d)", control->listen_socket);
516dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    return 0;
517dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
518dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
519dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
520dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic void
521dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectjdwp_control_event( int  s, unsigned  events, void*  _control )
522dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
523dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    JdwpControl*  control = (JdwpControl*) _control;
524dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
525dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (events & FDE_READ) {
5267e16cc15b5e16ec35f4c9f0516a6cacf90326856Erik Kline        sockaddr_storage   ss;
5277e16cc15b5e16ec35f4c9f0516a6cacf90326856Erik Kline        sockaddr*          addrp = reinterpret_cast<sockaddr*>(&ss);
5287e16cc15b5e16ec35f4c9f0516a6cacf90326856Erik Kline        socklen_t          addrlen = sizeof(ss);
5297e16cc15b5e16ec35f4c9f0516a6cacf90326856Erik Kline        int                s = -1;
5307e16cc15b5e16ec35f4c9f0516a6cacf90326856Erik Kline        JdwpProcess*       proc;
531dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
532dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        do {
5337e16cc15b5e16ec35f4c9f0516a6cacf90326856Erik Kline            s = adb_socket_accept(control->listen_socket, addrp, &addrlen);
534dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            if (s < 0) {
535dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                if (errno == EINTR)
536dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                    continue;
537dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                if (errno == ECONNABORTED) {
538dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                    /* oops, the JDWP process died really quick */
5397a3f8d6691b3fbd8014a98de8455dbcfcc9629e4Yabin Cui                    D("oops, the JDWP process died really quick");
540dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                    return;
541dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                }
542dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                /* the socket is probably closed ? */
5437a3f8d6691b3fbd8014a98de8455dbcfcc9629e4Yabin Cui                D( "weird accept() failed on jdwp control socket: %s",
544dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                   strerror(errno) );
545dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                return;
546dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            }
547dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
548dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        while (s < 0);
549dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
550dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        proc = jdwp_process_alloc( s );
551dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if (proc == NULL)
552dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            return;
553dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
554dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
555dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
556dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
557dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic JdwpControl   _jdwp_control;
558dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
559dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project/** "jdwp" local service implementation
560dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project ** this simply returns the list of known JDWP process pids
561dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project **/
562dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
5632d4121c0dcc93382bcd7ea6476f433d8254919ddElliott Hughesstruct JdwpSocket {
564dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    asocket  socket;
565dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    int      pass;
5662d4121c0dcc93382bcd7ea6476f433d8254919ddElliott Hughes};
567dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
568dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic void
569dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectjdwp_socket_close( asocket*  s )
570dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
571dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    asocket*  peer = s->peer;
572dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
573dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    remove_socket(s);
574dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
575dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (peer) {
576dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        peer->peer = NULL;
577dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        peer->close(peer);
578dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
579dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    free(s);
580dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
581dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
582dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic int
583dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectjdwp_socket_enqueue( asocket*  s, apacket*  p )
584dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
585dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    /* you can't write to this asocket */
586dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    put_apacket(p);
587dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    s->peer->close(s->peer);
588dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    return -1;
589dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
590dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
591dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
592dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic void
593dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectjdwp_socket_ready( asocket*  s )
594dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
595dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    JdwpSocket*  jdwp = (JdwpSocket*)s;
596dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    asocket*     peer = jdwp->socket.peer;
597dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
598dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project   /* on the first call, send the list of pids,
599dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    * on the second one, close the connection
600dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    */
601dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (jdwp->pass == 0) {
602dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        apacket*  p = get_apacket();
6033d2904cdf2371e26c0465184436bd063979a5d97Tamas Berghammer        p->len = jdwp_process_list((char*)p->data, s->get_max_payload());
604dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        peer->enqueue(peer, p);
605dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        jdwp->pass = 1;
606dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
607dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    else {
608dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        peer->close(peer);
609dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
610dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
611dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
612dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectasocket*
613dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectcreate_jdwp_service_socket( void )
614dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
615bac3474a8256cb32a29e8d46f78cad95a5502692Dan Albert    JdwpSocket* s = reinterpret_cast<JdwpSocket*>(calloc(sizeof(*s), 1));
616dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
617dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (s == NULL)
618dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        return NULL;
619dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
620dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    install_local_socket(&s->socket);
621dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
622dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    s->socket.ready   = jdwp_socket_ready;
623dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    s->socket.enqueue = jdwp_socket_enqueue;
624dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    s->socket.close   = jdwp_socket_close;
625dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    s->pass           = 0;
626dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
627dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    return &s->socket;
628dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
629dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
630dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project/** "track-jdwp" local service implementation
631dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project ** this periodically sends the list of known JDWP process pids
632dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project ** to the client...
633dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project **/
634dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
635dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstruct JdwpTracker {
636dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    asocket       socket;
637dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    JdwpTracker*  next;
638dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    JdwpTracker*  prev;
639dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    int           need_update;
640dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project};
641dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
642dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic JdwpTracker   _jdwp_trackers_list;
643dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
644dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
645dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic void
646dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectjdwp_process_list_updated(void)
647dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
648dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    char             buffer[1024];
649dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    int              len;
650dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    JdwpTracker*  t = _jdwp_trackers_list.next;
651dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
652dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    len = jdwp_process_list_msg(buffer, sizeof(buffer));
653dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
654dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    for ( ; t != &_jdwp_trackers_list; t = t->next ) {
655dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        apacket*  p    = get_apacket();
656dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        asocket*  peer = t->socket.peer;
657dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        memcpy(p->data, buffer, len);
658dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        p->len = len;
659dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        peer->enqueue( peer, p );
660dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
661dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
662dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
663dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic void
664dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectjdwp_tracker_close( asocket*  s )
665dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
666dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    JdwpTracker*  tracker = (JdwpTracker*) s;
667dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    asocket*      peer    = s->peer;
668dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
669dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (peer) {
670dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        peer->peer = NULL;
671dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        peer->close(peer);
672dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
673dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
674dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    remove_socket(s);
675dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
676dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    tracker->prev->next = tracker->next;
677dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    tracker->next->prev = tracker->prev;
678dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
679dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    free(s);
680dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
681dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
682dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic void
683dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectjdwp_tracker_ready( asocket*  s )
684dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
685dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    JdwpTracker*  t = (JdwpTracker*) s;
686dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
687dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (t->need_update) {
688dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        apacket*  p = get_apacket();
689dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        t->need_update = 0;
6903d2904cdf2371e26c0465184436bd063979a5d97Tamas Berghammer        p->len = jdwp_process_list_msg((char*)p->data, s->get_max_payload());
691dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        s->peer->enqueue(s->peer, p);
692dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
693dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
694dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
695dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic int
696dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectjdwp_tracker_enqueue( asocket*  s, apacket*  p )
697dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
698dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    /* you can't write to this socket */
699dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    put_apacket(p);
700dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    s->peer->close(s->peer);
701dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    return -1;
702dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
703dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
704dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
705dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectasocket*
706dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectcreate_jdwp_tracker_service_socket( void )
707dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
708bac3474a8256cb32a29e8d46f78cad95a5502692Dan Albert    JdwpTracker* t = reinterpret_cast<JdwpTracker*>(calloc(sizeof(*t), 1));
709dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
710dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (t == NULL)
711dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        return NULL;
712dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
713dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    t->next = &_jdwp_trackers_list;
714dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    t->prev = t->next->prev;
715dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
716dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    t->next->prev = t;
717dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    t->prev->next = t;
718dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
719dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    install_local_socket(&t->socket);
720dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
721dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    t->socket.ready   = jdwp_tracker_ready;
722dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    t->socket.enqueue = jdwp_tracker_enqueue;
723dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    t->socket.close   = jdwp_tracker_close;
724dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    t->need_update    = 1;
725dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
726dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    return &t->socket;
727dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
728dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
729dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
730dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectint
731dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectinit_jdwp(void)
732dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
733dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    _jdwp_list.next = &_jdwp_list;
734dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    _jdwp_list.prev = &_jdwp_list;
735dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
736dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    _jdwp_trackers_list.next = &_jdwp_trackers_list;
737dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    _jdwp_trackers_list.prev = &_jdwp_trackers_list;
738dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
739dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    return jdwp_control_init( &_jdwp_control,
740dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                              JDWP_CONTROL_NAME,
741dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                              JDWP_CONTROL_NAME_LEN );
742dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
743dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
744dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#endif /* !ADB_HOST */
745