blob: 7a4480168ac34877617c644c0033ef3be5744103 [file] [log] [blame]
Dan Albert33134262015-03-19 15:21:08 -07001/*
2 * Copyright (C) 2015 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
Josh Gao52338a32016-05-13 15:28:34 -070017#if !ADB_HOST
Dan Albert33134262015-03-19 15:21:08 -070018
Yabin Cuiaed3c612015-09-22 15:52:57 -070019#define TRACE_TAG JDWP
Dan Albert33134262015-03-19 15:21:08 -070020
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080021#include "sysdeps.h"
Dan Albert33134262015-03-19 15:21:08 -070022
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080023#include <errno.h>
24#include <stdio.h>
Elliott Hughes381cfa92015-07-23 17:12:58 -070025#include <stdlib.h>
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080026#include <string.h>
Josh Gao52338a32016-05-13 15:28:34 -070027#include <sys/socket.h>
28#include <sys/un.h>
Teddie Stenvi8f5daad2010-02-15 12:20:44 +010029#include <unistd.h>
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080030
Josh Gao52338a32016-05-13 15:28:34 -070031#include <list>
32#include <memory>
33#include <vector>
34
Dan Albert33134262015-03-19 15:21:08 -070035#include "adb.h"
Josh Gao52338a32016-05-13 15:28:34 -070036#include "adb_io.h"
Yabin Cui6dfef252015-10-06 15:10:05 -070037#include "adb_utils.h"
Dan Albert33134262015-03-19 15:21:08 -070038
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080039/* here's how these things work.
40
41 when adbd starts, it creates a unix server socket
Josh Gao52338a32016-05-13 15:28:34 -070042 named @jdwp-control (@ is a shortcut for "first byte is zero"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080043 to use the private namespace instead of the file system)
44
45 when a new JDWP daemon thread starts in a new VM process, it creates
Josh Gao52338a32016-05-13 15:28:34 -070046 a connection to @jdwp-control to announce its availability.
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080047
48
Josh Gao52338a32016-05-13 15:28:34 -070049 JDWP thread @jdwp-control
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080050 | |
51 |-------------------------------> |
52 | hello I'm in process <pid> |
53 | |
54 | |
55
56 the connection is kept alive. it will be closed automatically if
57 the JDWP process terminates (this allows adbd to detect dead
58 processes).
59
60 adbd thus maintains a list of "active" JDWP processes. it can send
61 its content to clients through the "device:debug-ports" service,
62 or even updates through the "device:track-debug-ports" service.
63
64 when a debugger wants to connect, it simply runs the command
65 equivalent to "adb forward tcp:<hostport> jdwp:<pid>"
66
67 "jdwp:<pid>" is a new forward destination format used to target
68 a given JDWP process on the device. when sutch a request arrives,
69 adbd does the following:
70
71 - first, it calls socketpair() to create a pair of equivalent
72 sockets.
73
74 - it attaches the first socket in the pair to a local socket
75 which is itself attached to the transport's remote socket:
76
77
78 - it sends the file descriptor of the second socket directly
79 to the JDWP process with the help of sendmsg()
80
81
Josh Gao52338a32016-05-13 15:28:34 -070082 JDWP thread @jdwp-control
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080083 | |
84 | <----------------------|
85 | OK, try this file descriptor |
86 | |
87 | |
88
89 then, the JDWP thread uses this new socket descriptor as its
90 pass-through connection to the debugger (and receives the
91 JDWP-Handshake message, answers to it, etc...)
92
93 this gives the following graphics:
94 ____________________________________
95 | |
96 | ADB Server (host) |
97 | |
98 Debugger <---> LocalSocket <----> RemoteSocket |
99 | ^^ |
100 |___________________________||_______|
101 ||
102 Transport ||
103 (TCP for emulator - USB for device) ||
104 ||
105 ___________________________||_______
106 | || |
107 | ADBD (device) || |
108 | VV |
109 JDWP <======> LocalSocket <----> RemoteSocket |
110 | |
111 |____________________________________|
112
113 due to the way adb works, this doesn't need a special socket
114 type or fancy handling of socket termination if either the debugger
115 or the JDWP process closes the connection.
116
117 THIS IS THE SIMPLEST IMPLEMENTATION I COULD FIND, IF YOU HAPPEN
118 TO HAVE A BETTER IDEA, LET ME KNOW - Digit
119
120**********************************************************************/
121
122/** JDWP PID List Support Code
123 ** for each JDWP process, we record its pid and its connected socket
124 **/
125
Josh Gao52338a32016-05-13 15:28:34 -0700126// PIDs are transmitted as 4 hex digits in ascii.
127static constexpr size_t PID_LEN = 4;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800128
Josh Gao52338a32016-05-13 15:28:34 -0700129static void jdwp_process_event(int socket, unsigned events, void* _proc);
130static void jdwp_process_list_updated(void);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800131
Josh Gao52338a32016-05-13 15:28:34 -0700132struct JdwpProcess;
133static std::list<std::unique_ptr<JdwpProcess>> _jdwp_list;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800134
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800135struct JdwpProcess {
Josh Gao52338a32016-05-13 15:28:34 -0700136 explicit JdwpProcess(int socket) {
137 this->socket = socket;
138 this->fde = fdevent_create(socket, jdwp_process_event, this);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800139
Josh Gao52338a32016-05-13 15:28:34 -0700140 if (!this->fde) {
141 fatal("could not create fdevent for new JDWP process");
142 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800143
Josh Gao52338a32016-05-13 15:28:34 -0700144 this->fde->state |= FDE_DONT_CLOSE;
145
146 /* start by waiting for the PID */
147 fdevent_add(this->fde, FDE_READ);
148 }
149
150 ~JdwpProcess() {
151 if (this->socket >= 0) {
152 adb_shutdown(this->socket);
153 adb_close(this->socket);
154 this->socket = -1;
155 }
156
157 if (this->fde) {
158 fdevent_destroy(this->fde);
159 this->fde = nullptr;
160 }
161
162 out_fds.clear();
163 }
164
165 void RemoveFromList() {
166 if (this->pid >= 0) {
167 D("removing pid %d from jdwp process list", this->pid);
168 } else {
169 D("removing transient JdwpProcess from list");
170 }
171
172 auto pred = [this](const auto& proc) { return proc.get() == this; };
173 _jdwp_list.remove_if(pred);
174 }
175
176 int pid = -1;
177 int socket = -1;
178 fdevent* fde = nullptr;
179
180 std::vector<unique_fd> out_fds;
181 char in_buf[PID_LEN + 1];
182 ssize_t in_len = 0;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800183};
184
Josh Gao52338a32016-05-13 15:28:34 -0700185static size_t jdwp_process_list(char* buffer, size_t bufferlen) {
186 std::string temp;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800187
Josh Gao52338a32016-05-13 15:28:34 -0700188 for (auto& proc : _jdwp_list) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800189 /* skip transient connections */
Josh Gao52338a32016-05-13 15:28:34 -0700190 if (proc->pid < 0) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800191 continue;
Josh Gao52338a32016-05-13 15:28:34 -0700192 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800193
Josh Gao52338a32016-05-13 15:28:34 -0700194 std::string next = std::to_string(proc->pid) + "\n";
195 if (temp.length() + next.length() > bufferlen) {
196 D("truncating JDWP process list (max len = %zu)", bufferlen);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800197 break;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800198 }
Josh Gao52338a32016-05-13 15:28:34 -0700199 temp.append(next);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800200 }
Josh Gao52338a32016-05-13 15:28:34 -0700201
202 memcpy(buffer, temp.data(), temp.length());
203 return temp.length();
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800204}
205
Josh Gao52338a32016-05-13 15:28:34 -0700206static size_t jdwp_process_list_msg(char* buffer, size_t bufferlen) {
207 // Message is length-prefixed with 4 hex digits in ASCII.
208 static constexpr size_t header_len = 4;
209 if (bufferlen < header_len) {
210 fatal("invalid JDWP process list buffer size: %zu", bufferlen);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800211 }
212
Josh Gao52338a32016-05-13 15:28:34 -0700213 char head[header_len + 1];
214 size_t len = jdwp_process_list(buffer + header_len, bufferlen - header_len);
215 snprintf(head, sizeof head, "%04zx", len);
216 memcpy(buffer, head, header_len);
217 return len + header_len;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800218}
219
Josh Gao52338a32016-05-13 15:28:34 -0700220static void jdwp_process_event(int socket, unsigned events, void* _proc) {
221 JdwpProcess* proc = reinterpret_cast<JdwpProcess*>(_proc);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800222
223 if (events & FDE_READ) {
224 if (proc->pid < 0) {
225 /* read the PID as a 4-hexchar string */
Josh Gao52338a32016-05-13 15:28:34 -0700226 if (proc->in_len < 0) {
227 fatal("attempting to read JDWP pid again?");
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800228 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800229
Josh Gao52338a32016-05-13 15:28:34 -0700230 char* p = proc->in_buf + proc->in_len;
231 size_t size = PID_LEN - proc->in_len;
232
233 ssize_t rc = TEMP_FAILURE_RETRY(recv(socket, p, size, 0));
234 if (rc < 0) {
235 if (errno == EAGAIN) {
236 return;
237 }
238
239 D("failed to read jdwp pid: %s", strerror(errno));
240 goto CloseProcess;
241 }
242
243 proc->in_len += rc;
244 if (proc->in_len != PID_LEN) {
245 return;
246 }
247
248 proc->in_buf[PID_LEN] = '\0';
249 proc->in_len = -1;
250
251 if (sscanf(proc->in_buf, "%04x", &proc->pid) != 1) {
252 D("could not decode JDWP %p PID number: '%s'", proc, p);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800253 goto CloseProcess;
254 }
255
256 /* all is well, keep reading to detect connection closure */
Yabin Cui7a3f8d62015-09-02 17:44:28 -0700257 D("Adding pid %d to jdwp process list", proc->pid);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800258 jdwp_process_list_updated();
Josh Gao52338a32016-05-13 15:28:34 -0700259 } else {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800260 /* the pid was read, if we get there it's probably because the connection
261 * was closed (e.g. the JDWP process exited or crashed) */
Josh Gao52338a32016-05-13 15:28:34 -0700262 char buf[32];
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800263
Josh Gao52338a32016-05-13 15:28:34 -0700264 while (true) {
265 int len = TEMP_FAILURE_RETRY(recv(socket, buf, sizeof(buf), 0));
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800266
Josh Gao52338a32016-05-13 15:28:34 -0700267 if (len == 0) {
268 D("terminating JDWP %d connection: EOF", proc->pid);
269 break;
270 } else if (len < 0) {
271 if (len < 0 && errno == EAGAIN) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800272 return;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800273 }
Josh Gao52338a32016-05-13 15:28:34 -0700274
275 D("terminating JDWP %d connection: EOF", proc->pid);
276 break;
277 } else {
278 D("ignoring unexpected JDWP %d control socket activity (%d bytes)", proc->pid,
279 len);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800280 }
281 }
282
Josh Gao52338a32016-05-13 15:28:34 -0700283 goto CloseProcess;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800284 }
285 }
286
287 if (events & FDE_WRITE) {
Josh Gao52338a32016-05-13 15:28:34 -0700288 D("trying to send fd to JDWP process (count = %zu)", proc->out_fds.size());
289 if (!proc->out_fds.empty()) {
290 int fd = proc->out_fds.back().get();
291 struct cmsghdr* cmsg;
292 struct msghdr msg;
293 struct iovec iov;
294 char dummy = '!';
295 char buffer[sizeof(struct cmsghdr) + sizeof(int)];
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800296
Josh Gao52338a32016-05-13 15:28:34 -0700297 iov.iov_base = &dummy;
298 iov.iov_len = 1;
299 msg.msg_name = NULL;
300 msg.msg_namelen = 0;
301 msg.msg_iov = &iov;
302 msg.msg_iovlen = 1;
303 msg.msg_flags = 0;
304 msg.msg_control = buffer;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800305 msg.msg_controllen = sizeof(buffer);
306
307 cmsg = CMSG_FIRSTHDR(&msg);
Josh Gao52338a32016-05-13 15:28:34 -0700308 cmsg->cmsg_len = msg.msg_controllen;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800309 cmsg->cmsg_level = SOL_SOCKET;
Josh Gao52338a32016-05-13 15:28:34 -0700310 cmsg->cmsg_type = SCM_RIGHTS;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800311 ((int*)CMSG_DATA(cmsg))[0] = fd;
312
Yabin Cui6dfef252015-10-06 15:10:05 -0700313 if (!set_file_block_mode(proc->socket, true)) {
314 VLOG(JDWP) << "failed to set blocking mode for fd " << proc->socket;
Teddie Stenvi8f5daad2010-02-15 12:20:44 +0100315 goto CloseProcess;
316 }
317
Josh Gao52338a32016-05-13 15:28:34 -0700318 int ret = TEMP_FAILURE_RETRY(sendmsg(proc->socket, &msg, 0));
319 if (ret < 0) {
320 D("sending new file descriptor to JDWP %d failed: %s", proc->pid, strerror(errno));
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800321 goto CloseProcess;
322 }
323
Josh Gao52338a32016-05-13 15:28:34 -0700324 adb_close(fd);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800325
Josh Gao52338a32016-05-13 15:28:34 -0700326 D("sent file descriptor %d to JDWP process %d", fd, proc->pid);
327
328 proc->out_fds.pop_back();
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800329
Yabin Cui6dfef252015-10-06 15:10:05 -0700330 if (!set_file_block_mode(proc->socket, false)) {
331 VLOG(JDWP) << "failed to set non-blocking mode for fd " << proc->socket;
Teddie Stenvi8f5daad2010-02-15 12:20:44 +0100332 goto CloseProcess;
333 }
334
Josh Gao52338a32016-05-13 15:28:34 -0700335 if (proc->out_fds.empty()) {
336 fdevent_del(proc->fde, FDE_WRITE);
337 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800338 }
339 }
Josh Gao52338a32016-05-13 15:28:34 -0700340
341 return;
342
343CloseProcess:
344 proc->RemoveFromList();
345 jdwp_process_list_updated();
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800346}
347
Josh Gao52338a32016-05-13 15:28:34 -0700348int create_jdwp_connection_fd(int pid) {
Yabin Cui7a3f8d62015-09-02 17:44:28 -0700349 D("looking for pid %d in JDWP process list", pid);
Josh Gao52338a32016-05-13 15:28:34 -0700350
351 for (auto& proc : _jdwp_list) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800352 if (proc->pid == pid) {
Josh Gao52338a32016-05-13 15:28:34 -0700353 int fds[2];
354
355 if (adb_socketpair(fds) < 0) {
356 D("%s: socket pair creation failed: %s", __FUNCTION__, strerror(errno));
357 return -1;
358 }
359 D("socketpair: (%d,%d)", fds[0], fds[1]);
360
361 proc->out_fds.emplace_back(fds[1]);
362 if (proc->out_fds.size() == 1) {
363 fdevent_add(proc->fde, FDE_WRITE);
364 }
365
366 return fds[0];
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800367 }
368 }
Yabin Cui7a3f8d62015-09-02 17:44:28 -0700369 D("search failed !!");
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800370 return -1;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800371}
372
373/** VM DEBUG CONTROL SOCKET
374 **
375 ** we do implement a custom asocket to receive the data
376 **/
377
378/* name of the debug control Unix socket */
Josh Gao52338a32016-05-13 15:28:34 -0700379#define JDWP_CONTROL_NAME "\0jdwp-control"
380#define JDWP_CONTROL_NAME_LEN (sizeof(JDWP_CONTROL_NAME) - 1)
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800381
Elliott Hughes2d4121c2015-04-17 09:47:42 -0700382struct JdwpControl {
Josh Gao52338a32016-05-13 15:28:34 -0700383 int listen_socket;
384 fdevent* fde;
Elliott Hughes2d4121c2015-04-17 09:47:42 -0700385};
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800386
Josh Gao52338a32016-05-13 15:28:34 -0700387static JdwpControl _jdwp_control;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800388
Josh Gao52338a32016-05-13 15:28:34 -0700389static void jdwp_control_event(int s, unsigned events, void* user);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800390
Josh Gao52338a32016-05-13 15:28:34 -0700391static int jdwp_control_init(JdwpControl* control, const char* sockname, int socknamelen) {
392 sockaddr_un addr;
393 socklen_t addrlen;
394 int s;
395 int maxpath = sizeof(addr.sun_path);
396 int pathlen = socknamelen;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800397
398 if (pathlen >= maxpath) {
Josh Gao52338a32016-05-13 15:28:34 -0700399 D("vm debug control socket name too long (%d extra chars)", pathlen + 1 - maxpath);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800400 return -1;
401 }
402
403 memset(&addr, 0, sizeof(addr));
404 addr.sun_family = AF_UNIX;
405 memcpy(addr.sun_path, sockname, socknamelen);
406
Josh Gao52338a32016-05-13 15:28:34 -0700407 s = socket(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800408 if (s < 0) {
Josh Gao52338a32016-05-13 15:28:34 -0700409 D("could not create vm debug control socket. %d: %s", errno, strerror(errno));
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800410 return -1;
411 }
412
Josh Gao52338a32016-05-13 15:28:34 -0700413 addrlen = pathlen + sizeof(addr.sun_family);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800414
Erik Kline7e16cc12015-12-01 17:27:59 +0900415 if (bind(s, reinterpret_cast<sockaddr*>(&addr), addrlen) < 0) {
Josh Gao52338a32016-05-13 15:28:34 -0700416 D("could not bind vm debug control socket: %d: %s", errno, strerror(errno));
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800417 adb_close(s);
418 return -1;
419 }
420
Josh Gao52338a32016-05-13 15:28:34 -0700421 if (listen(s, 4) < 0) {
422 D("listen failed in jdwp control socket: %d: %s", errno, strerror(errno));
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800423 adb_close(s);
424 return -1;
425 }
426
427 control->listen_socket = s;
428
429 control->fde = fdevent_create(s, jdwp_control_event, control);
430 if (control->fde == NULL) {
Josh Gao52338a32016-05-13 15:28:34 -0700431 D("could not create fdevent for jdwp control socket");
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800432 adb_close(s);
433 return -1;
434 }
435
436 /* only wait for incoming connections */
437 fdevent_add(control->fde, FDE_READ);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800438
Yabin Cui7a3f8d62015-09-02 17:44:28 -0700439 D("jdwp control socket started (%d)", control->listen_socket);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800440 return 0;
441}
442
Josh Gao52338a32016-05-13 15:28:34 -0700443static void jdwp_control_event(int s, unsigned events, void* _control) {
444 JdwpControl* control = (JdwpControl*)_control;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800445
446 if (events & FDE_READ) {
Josh Gao52338a32016-05-13 15:28:34 -0700447 sockaddr_storage ss;
448 sockaddr* addrp = reinterpret_cast<sockaddr*>(&ss);
449 socklen_t addrlen = sizeof(ss);
450 int s = adb_socket_accept(control->listen_socket, addrp, &addrlen);
451 if (s < 0) {
452 if (errno == ECONNABORTED) {
453 /* oops, the JDWP process died really quick */
454 D("oops, the JDWP process died really quick");
455 return;
456 } else {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800457 /* the socket is probably closed ? */
Josh Gao52338a32016-05-13 15:28:34 -0700458 D("weird accept() failed on jdwp control socket: %s", strerror(errno));
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800459 return;
460 }
461 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800462
Josh Gao52338a32016-05-13 15:28:34 -0700463 auto proc = std::make_unique<JdwpProcess>(s);
464 if (!proc) {
465 fatal("failed to allocate JdwpProcess");
466 }
467
468 _jdwp_list.emplace_back(std::move(proc));
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800469 }
470}
471
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800472/** "jdwp" local service implementation
473 ** this simply returns the list of known JDWP process pids
474 **/
475
Josh Gao52338a32016-05-13 15:28:34 -0700476struct JdwpSocket : public asocket {
477 bool pass;
Elliott Hughes2d4121c2015-04-17 09:47:42 -0700478};
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800479
Josh Gao52338a32016-05-13 15:28:34 -0700480static void jdwp_socket_close(asocket* s) {
481 D("LS(%d): closing jdwp socket", s->id);
482
483 if (s->peer) {
484 D("LS(%d) peer->close()ing peer->id=%d peer->fd=%d", s->id, s->peer->id, s->peer->fd);
485 s->peer->peer = nullptr;
486 s->peer->close(s->peer);
487 s->peer = nullptr;
488 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800489
490 remove_socket(s);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800491 free(s);
492}
493
Josh Gao52338a32016-05-13 15:28:34 -0700494static int jdwp_socket_enqueue(asocket* s, apacket* p) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800495 /* you can't write to this asocket */
Josh Gao52338a32016-05-13 15:28:34 -0700496 D("LS(%d): JDWP socket received data?", s->id);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800497 put_apacket(p);
498 s->peer->close(s->peer);
499 return -1;
500}
501
Josh Gao52338a32016-05-13 15:28:34 -0700502static void jdwp_socket_ready(asocket* s) {
503 JdwpSocket* jdwp = (JdwpSocket*)s;
504 asocket* peer = jdwp->peer;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800505
Josh Gao52338a32016-05-13 15:28:34 -0700506 /* on the first call, send the list of pids,
507 * on the second one, close the connection
508 */
509 if (!jdwp->pass) {
510 apacket* p = get_apacket();
Tamas Berghammer3d2904c2015-07-13 19:12:28 +0100511 p->len = jdwp_process_list((char*)p->data, s->get_max_payload());
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800512 peer->enqueue(peer, p);
Josh Gao52338a32016-05-13 15:28:34 -0700513 jdwp->pass = true;
514 } else {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800515 peer->close(peer);
516 }
517}
518
Josh Gao52338a32016-05-13 15:28:34 -0700519asocket* create_jdwp_service_socket(void) {
Dan Albertbac34742015-02-25 17:51:28 -0800520 JdwpSocket* s = reinterpret_cast<JdwpSocket*>(calloc(sizeof(*s), 1));
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800521
Josh Gao52338a32016-05-13 15:28:34 -0700522 if (!s) {
523 fatal("failed to allocate JdwpSocket");
524 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800525
Josh Gao52338a32016-05-13 15:28:34 -0700526 install_local_socket(s);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800527
Josh Gao52338a32016-05-13 15:28:34 -0700528 s->ready = jdwp_socket_ready;
529 s->enqueue = jdwp_socket_enqueue;
530 s->close = jdwp_socket_close;
531 s->pass = false;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800532
Josh Gao52338a32016-05-13 15:28:34 -0700533 return s;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800534}
535
536/** "track-jdwp" local service implementation
537 ** this periodically sends the list of known JDWP process pids
538 ** to the client...
539 **/
540
Josh Gao52338a32016-05-13 15:28:34 -0700541struct JdwpTracker : public asocket {
542 bool need_initial;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800543};
544
Josh Gao52338a32016-05-13 15:28:34 -0700545static std::vector<std::unique_ptr<JdwpTracker>> _jdwp_trackers;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800546
Josh Gao52338a32016-05-13 15:28:34 -0700547static void jdwp_process_list_updated(void) {
548 char buffer[1024];
549 int len = jdwp_process_list_msg(buffer, sizeof(buffer));
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800550
Josh Gao52338a32016-05-13 15:28:34 -0700551 for (auto& t : _jdwp_trackers) {
552 apacket* p = get_apacket();
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800553 memcpy(p->data, buffer, len);
554 p->len = len;
Josh Gao52338a32016-05-13 15:28:34 -0700555
556 if (t->peer) {
557 // The tracker might not have been connected yet.
558 t->peer->enqueue(t->peer, p);
559 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800560 }
561}
562
Josh Gao52338a32016-05-13 15:28:34 -0700563static void jdwp_tracker_close(asocket* s) {
564 D("LS(%d): destroying jdwp tracker service", s->id);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800565
Josh Gao52338a32016-05-13 15:28:34 -0700566 if (s->peer) {
567 D("LS(%d) peer->close()ing peer->id=%d peer->fd=%d", s->id, s->peer->id, s->peer->fd);
568 s->peer->peer = nullptr;
569 s->peer->close(s->peer);
570 s->peer = nullptr;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800571 }
572
573 remove_socket(s);
574
Josh Gao52338a32016-05-13 15:28:34 -0700575 auto pred = [s](const auto& tracker) { return tracker.get() == s; };
576 std::remove_if(_jdwp_trackers.begin(), _jdwp_trackers.end(), pred);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800577}
578
Josh Gao52338a32016-05-13 15:28:34 -0700579static void jdwp_tracker_ready(asocket* s) {
580 JdwpTracker* t = (JdwpTracker*)s;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800581
Josh Gao52338a32016-05-13 15:28:34 -0700582 if (t->need_initial) {
583 apacket* p = get_apacket();
584 t->need_initial = false;
Tamas Berghammer3d2904c2015-07-13 19:12:28 +0100585 p->len = jdwp_process_list_msg((char*)p->data, s->get_max_payload());
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800586 s->peer->enqueue(s->peer, p);
587 }
588}
589
Josh Gao52338a32016-05-13 15:28:34 -0700590static int jdwp_tracker_enqueue(asocket* s, apacket* p) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800591 /* you can't write to this socket */
Josh Gao52338a32016-05-13 15:28:34 -0700592 D("LS(%d): JDWP tracker received data?", s->id);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800593 put_apacket(p);
594 s->peer->close(s->peer);
595 return -1;
596}
597
Josh Gao52338a32016-05-13 15:28:34 -0700598asocket* create_jdwp_tracker_service_socket(void) {
599 auto t = std::make_unique<JdwpTracker>();
600 if (!t) {
601 fatal("failed to allocate JdwpTracker");
602 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800603
Josh Gao52338a32016-05-13 15:28:34 -0700604 memset(t.get(), 0, sizeof(asocket));
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800605
Josh Gao52338a32016-05-13 15:28:34 -0700606 install_local_socket(t.get());
607 D("LS(%d): created new jdwp tracker service", t->id);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800608
Josh Gao52338a32016-05-13 15:28:34 -0700609 t->ready = jdwp_tracker_ready;
610 t->enqueue = jdwp_tracker_enqueue;
611 t->close = jdwp_tracker_close;
612 t->need_initial = true;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800613
Josh Gao52338a32016-05-13 15:28:34 -0700614 asocket* result = t.get();
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800615
Josh Gao52338a32016-05-13 15:28:34 -0700616 _jdwp_trackers.emplace_back(std::move(t));
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800617
Josh Gao52338a32016-05-13 15:28:34 -0700618 return result;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800619}
620
Josh Gao52338a32016-05-13 15:28:34 -0700621int init_jdwp(void) {
622 return jdwp_control_init(&_jdwp_control, JDWP_CONTROL_NAME, JDWP_CONTROL_NAME_LEN);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800623}
624
625#endif /* !ADB_HOST */