blob: af911bf9008350ab3b4eb29672d8d2d03a6475e2 [file] [log] [blame]
Dan Albertdb6fe642015-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 Gao9eaf33c2016-05-13 15:28:34 -070017#if !ADB_HOST
Dan Albertdb6fe642015-03-19 15:21:08 -070018
Yabin Cui19bec5b2015-09-22 15:52:57 -070019#define TRACE_TAG JDWP
Dan Albertdb6fe642015-03-19 15:21:08 -070020
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -080021#include "sysdeps.h"
Dan Albertdb6fe642015-03-19 15:21:08 -070022
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -080023#include <errno.h>
24#include <stdio.h>
Elliott Hughes43df1092015-07-23 17:12:58 -070025#include <stdlib.h>
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -080026#include <string.h>
Josh Gao9eaf33c2016-05-13 15:28:34 -070027#include <sys/socket.h>
28#include <sys/un.h>
Teddie Stenvif56e7f52010-02-15 12:20:44 +010029#include <unistd.h>
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -080030
Josh Gao9eaf33c2016-05-13 15:28:34 -070031#include <list>
32#include <memory>
33#include <vector>
34
Dan Albertdb6fe642015-03-19 15:21:08 -070035#include "adb.h"
Josh Gao9eaf33c2016-05-13 15:28:34 -070036#include "adb_io.h"
Josh Gaoea7457b2016-08-30 15:39:25 -070037#include "adb_unique_fd.h"
Yabin Cui5fc22312015-10-06 15:10:05 -070038#include "adb_utils.h"
Dan Albertdb6fe642015-03-19 15:21:08 -070039
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -080040/* here's how these things work.
41
42 when adbd starts, it creates a unix server socket
Josh Gao9eaf33c2016-05-13 15:28:34 -070043 named @jdwp-control (@ is a shortcut for "first byte is zero"
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -080044 to use the private namespace instead of the file system)
45
46 when a new JDWP daemon thread starts in a new VM process, it creates
Josh Gao9eaf33c2016-05-13 15:28:34 -070047 a connection to @jdwp-control to announce its availability.
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -080048
49
Josh Gao9eaf33c2016-05-13 15:28:34 -070050 JDWP thread @jdwp-control
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -080051 | |
52 |-------------------------------> |
53 | hello I'm in process <pid> |
54 | |
55 | |
56
57 the connection is kept alive. it will be closed automatically if
58 the JDWP process terminates (this allows adbd to detect dead
59 processes).
60
61 adbd thus maintains a list of "active" JDWP processes. it can send
62 its content to clients through the "device:debug-ports" service,
63 or even updates through the "device:track-debug-ports" service.
64
65 when a debugger wants to connect, it simply runs the command
66 equivalent to "adb forward tcp:<hostport> jdwp:<pid>"
67
68 "jdwp:<pid>" is a new forward destination format used to target
69 a given JDWP process on the device. when sutch a request arrives,
70 adbd does the following:
71
72 - first, it calls socketpair() to create a pair of equivalent
73 sockets.
74
75 - it attaches the first socket in the pair to a local socket
76 which is itself attached to the transport's remote socket:
77
78
79 - it sends the file descriptor of the second socket directly
80 to the JDWP process with the help of sendmsg()
81
82
Josh Gao9eaf33c2016-05-13 15:28:34 -070083 JDWP thread @jdwp-control
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -080084 | |
85 | <----------------------|
86 | OK, try this file descriptor |
87 | |
88 | |
89
90 then, the JDWP thread uses this new socket descriptor as its
91 pass-through connection to the debugger (and receives the
92 JDWP-Handshake message, answers to it, etc...)
93
94 this gives the following graphics:
95 ____________________________________
96 | |
97 | ADB Server (host) |
98 | |
99 Debugger <---> LocalSocket <----> RemoteSocket |
100 | ^^ |
101 |___________________________||_______|
102 ||
103 Transport ||
104 (TCP for emulator - USB for device) ||
105 ||
106 ___________________________||_______
107 | || |
108 | ADBD (device) || |
109 | VV |
110 JDWP <======> LocalSocket <----> RemoteSocket |
111 | |
112 |____________________________________|
113
114 due to the way adb works, this doesn't need a special socket
115 type or fancy handling of socket termination if either the debugger
116 or the JDWP process closes the connection.
117
118 THIS IS THE SIMPLEST IMPLEMENTATION I COULD FIND, IF YOU HAPPEN
119 TO HAVE A BETTER IDEA, LET ME KNOW - Digit
120
121**********************************************************************/
122
123/** JDWP PID List Support Code
124 ** for each JDWP process, we record its pid and its connected socket
125 **/
126
Josh Gao9eaf33c2016-05-13 15:28:34 -0700127// PIDs are transmitted as 4 hex digits in ascii.
128static constexpr size_t PID_LEN = 4;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800129
Josh Gao9eaf33c2016-05-13 15:28:34 -0700130static void jdwp_process_event(int socket, unsigned events, void* _proc);
131static void jdwp_process_list_updated(void);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800132
Josh Gao9eaf33c2016-05-13 15:28:34 -0700133struct JdwpProcess;
134static std::list<std::unique_ptr<JdwpProcess>> _jdwp_list;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800135
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800136struct JdwpProcess {
Josh Gao9eaf33c2016-05-13 15:28:34 -0700137 explicit JdwpProcess(int socket) {
138 this->socket = socket;
139 this->fde = fdevent_create(socket, jdwp_process_event, this);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800140
Josh Gao9eaf33c2016-05-13 15:28:34 -0700141 if (!this->fde) {
142 fatal("could not create fdevent for new JDWP process");
143 }
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800144
Josh Gao9eaf33c2016-05-13 15:28:34 -0700145 this->fde->state |= FDE_DONT_CLOSE;
146
147 /* start by waiting for the PID */
148 fdevent_add(this->fde, FDE_READ);
149 }
150
151 ~JdwpProcess() {
152 if (this->socket >= 0) {
153 adb_shutdown(this->socket);
154 adb_close(this->socket);
155 this->socket = -1;
156 }
157
158 if (this->fde) {
159 fdevent_destroy(this->fde);
160 this->fde = nullptr;
161 }
162
163 out_fds.clear();
164 }
165
166 void RemoveFromList() {
167 if (this->pid >= 0) {
168 D("removing pid %d from jdwp process list", this->pid);
169 } else {
170 D("removing transient JdwpProcess from list");
171 }
172
173 auto pred = [this](const auto& proc) { return proc.get() == this; };
174 _jdwp_list.remove_if(pred);
175 }
176
177 int pid = -1;
178 int socket = -1;
179 fdevent* fde = nullptr;
180
181 std::vector<unique_fd> out_fds;
182 char in_buf[PID_LEN + 1];
183 ssize_t in_len = 0;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800184};
185
Josh Gao9eaf33c2016-05-13 15:28:34 -0700186static size_t jdwp_process_list(char* buffer, size_t bufferlen) {
187 std::string temp;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800188
Josh Gao9eaf33c2016-05-13 15:28:34 -0700189 for (auto& proc : _jdwp_list) {
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800190 /* skip transient connections */
Josh Gao9eaf33c2016-05-13 15:28:34 -0700191 if (proc->pid < 0) {
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800192 continue;
Josh Gao9eaf33c2016-05-13 15:28:34 -0700193 }
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800194
Josh Gao9eaf33c2016-05-13 15:28:34 -0700195 std::string next = std::to_string(proc->pid) + "\n";
196 if (temp.length() + next.length() > bufferlen) {
197 D("truncating JDWP process list (max len = %zu)", bufferlen);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800198 break;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800199 }
Josh Gao9eaf33c2016-05-13 15:28:34 -0700200 temp.append(next);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800201 }
Josh Gao9eaf33c2016-05-13 15:28:34 -0700202
203 memcpy(buffer, temp.data(), temp.length());
204 return temp.length();
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800205}
206
Josh Gao9eaf33c2016-05-13 15:28:34 -0700207static size_t jdwp_process_list_msg(char* buffer, size_t bufferlen) {
208 // Message is length-prefixed with 4 hex digits in ASCII.
209 static constexpr size_t header_len = 4;
210 if (bufferlen < header_len) {
211 fatal("invalid JDWP process list buffer size: %zu", bufferlen);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800212 }
213
Josh Gao9eaf33c2016-05-13 15:28:34 -0700214 char head[header_len + 1];
215 size_t len = jdwp_process_list(buffer + header_len, bufferlen - header_len);
216 snprintf(head, sizeof head, "%04zx", len);
217 memcpy(buffer, head, header_len);
218 return len + header_len;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800219}
220
Josh Gao9eaf33c2016-05-13 15:28:34 -0700221static void jdwp_process_event(int socket, unsigned events, void* _proc) {
222 JdwpProcess* proc = reinterpret_cast<JdwpProcess*>(_proc);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800223
224 if (events & FDE_READ) {
225 if (proc->pid < 0) {
226 /* read the PID as a 4-hexchar string */
Josh Gao9eaf33c2016-05-13 15:28:34 -0700227 if (proc->in_len < 0) {
228 fatal("attempting to read JDWP pid again?");
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800229 }
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800230
Josh Gao9eaf33c2016-05-13 15:28:34 -0700231 char* p = proc->in_buf + proc->in_len;
232 size_t size = PID_LEN - proc->in_len;
233
234 ssize_t rc = TEMP_FAILURE_RETRY(recv(socket, p, size, 0));
Josh Gaobc46f6b2017-03-20 11:11:19 -0700235 if (rc <= 0) {
Josh Gao9eaf33c2016-05-13 15:28:34 -0700236 D("failed to read jdwp pid: %s", strerror(errno));
237 goto CloseProcess;
238 }
239
240 proc->in_len += rc;
241 if (proc->in_len != PID_LEN) {
242 return;
243 }
244
245 proc->in_buf[PID_LEN] = '\0';
246 proc->in_len = -1;
247
248 if (sscanf(proc->in_buf, "%04x", &proc->pid) != 1) {
249 D("could not decode JDWP %p PID number: '%s'", proc, p);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800250 goto CloseProcess;
251 }
252
253 /* all is well, keep reading to detect connection closure */
Yabin Cui815ad882015-09-02 17:44:28 -0700254 D("Adding pid %d to jdwp process list", proc->pid);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800255 jdwp_process_list_updated();
Josh Gao9eaf33c2016-05-13 15:28:34 -0700256 } else {
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800257 /* the pid was read, if we get there it's probably because the connection
258 * was closed (e.g. the JDWP process exited or crashed) */
Josh Gao9eaf33c2016-05-13 15:28:34 -0700259 char buf[32];
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800260
Josh Gao9eaf33c2016-05-13 15:28:34 -0700261 while (true) {
262 int len = TEMP_FAILURE_RETRY(recv(socket, buf, sizeof(buf), 0));
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800263
Josh Gao9eaf33c2016-05-13 15:28:34 -0700264 if (len == 0) {
265 D("terminating JDWP %d connection: EOF", proc->pid);
266 break;
267 } else if (len < 0) {
268 if (len < 0 && errno == EAGAIN) {
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800269 return;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800270 }
Josh Gao9eaf33c2016-05-13 15:28:34 -0700271
272 D("terminating JDWP %d connection: EOF", proc->pid);
273 break;
274 } else {
275 D("ignoring unexpected JDWP %d control socket activity (%d bytes)", proc->pid,
276 len);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800277 }
278 }
279
Josh Gao9eaf33c2016-05-13 15:28:34 -0700280 goto CloseProcess;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800281 }
282 }
283
284 if (events & FDE_WRITE) {
Josh Gao9eaf33c2016-05-13 15:28:34 -0700285 D("trying to send fd to JDWP process (count = %zu)", proc->out_fds.size());
286 if (!proc->out_fds.empty()) {
287 int fd = proc->out_fds.back().get();
288 struct cmsghdr* cmsg;
289 struct msghdr msg;
290 struct iovec iov;
291 char dummy = '!';
292 char buffer[sizeof(struct cmsghdr) + sizeof(int)];
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800293
Josh Gao9eaf33c2016-05-13 15:28:34 -0700294 iov.iov_base = &dummy;
295 iov.iov_len = 1;
296 msg.msg_name = NULL;
297 msg.msg_namelen = 0;
298 msg.msg_iov = &iov;
299 msg.msg_iovlen = 1;
300 msg.msg_flags = 0;
301 msg.msg_control = buffer;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800302 msg.msg_controllen = sizeof(buffer);
303
304 cmsg = CMSG_FIRSTHDR(&msg);
Josh Gao9eaf33c2016-05-13 15:28:34 -0700305 cmsg->cmsg_len = msg.msg_controllen;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800306 cmsg->cmsg_level = SOL_SOCKET;
Josh Gao9eaf33c2016-05-13 15:28:34 -0700307 cmsg->cmsg_type = SCM_RIGHTS;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800308 ((int*)CMSG_DATA(cmsg))[0] = fd;
309
Yabin Cui5fc22312015-10-06 15:10:05 -0700310 if (!set_file_block_mode(proc->socket, true)) {
311 VLOG(JDWP) << "failed to set blocking mode for fd " << proc->socket;
Teddie Stenvif56e7f52010-02-15 12:20:44 +0100312 goto CloseProcess;
313 }
314
Josh Gao9eaf33c2016-05-13 15:28:34 -0700315 int ret = TEMP_FAILURE_RETRY(sendmsg(proc->socket, &msg, 0));
316 if (ret < 0) {
317 D("sending new file descriptor to JDWP %d failed: %s", proc->pid, strerror(errno));
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800318 goto CloseProcess;
319 }
320
Josh Gao9eaf33c2016-05-13 15:28:34 -0700321 adb_close(fd);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800322
Josh Gao9eaf33c2016-05-13 15:28:34 -0700323 D("sent file descriptor %d to JDWP process %d", fd, proc->pid);
324
325 proc->out_fds.pop_back();
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800326
Yabin Cui5fc22312015-10-06 15:10:05 -0700327 if (!set_file_block_mode(proc->socket, false)) {
328 VLOG(JDWP) << "failed to set non-blocking mode for fd " << proc->socket;
Teddie Stenvif56e7f52010-02-15 12:20:44 +0100329 goto CloseProcess;
330 }
331
Josh Gao9eaf33c2016-05-13 15:28:34 -0700332 if (proc->out_fds.empty()) {
333 fdevent_del(proc->fde, FDE_WRITE);
334 }
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800335 }
336 }
Josh Gao9eaf33c2016-05-13 15:28:34 -0700337
338 return;
339
340CloseProcess:
341 proc->RemoveFromList();
342 jdwp_process_list_updated();
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800343}
344
Josh Gao9eaf33c2016-05-13 15:28:34 -0700345int create_jdwp_connection_fd(int pid) {
Yabin Cui815ad882015-09-02 17:44:28 -0700346 D("looking for pid %d in JDWP process list", pid);
Josh Gao9eaf33c2016-05-13 15:28:34 -0700347
348 for (auto& proc : _jdwp_list) {
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800349 if (proc->pid == pid) {
Josh Gao9eaf33c2016-05-13 15:28:34 -0700350 int fds[2];
351
352 if (adb_socketpair(fds) < 0) {
353 D("%s: socket pair creation failed: %s", __FUNCTION__, strerror(errno));
354 return -1;
355 }
356 D("socketpair: (%d,%d)", fds[0], fds[1]);
357
358 proc->out_fds.emplace_back(fds[1]);
359 if (proc->out_fds.size() == 1) {
360 fdevent_add(proc->fde, FDE_WRITE);
361 }
362
363 return fds[0];
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800364 }
365 }
Yabin Cui815ad882015-09-02 17:44:28 -0700366 D("search failed !!");
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800367 return -1;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800368}
369
370/** VM DEBUG CONTROL SOCKET
371 **
372 ** we do implement a custom asocket to receive the data
373 **/
374
375/* name of the debug control Unix socket */
Josh Gao9eaf33c2016-05-13 15:28:34 -0700376#define JDWP_CONTROL_NAME "\0jdwp-control"
377#define JDWP_CONTROL_NAME_LEN (sizeof(JDWP_CONTROL_NAME) - 1)
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800378
Elliott Hughesfe7ff812015-04-17 09:47:42 -0700379struct JdwpControl {
Josh Gao9eaf33c2016-05-13 15:28:34 -0700380 int listen_socket;
381 fdevent* fde;
Elliott Hughesfe7ff812015-04-17 09:47:42 -0700382};
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800383
Josh Gao9eaf33c2016-05-13 15:28:34 -0700384static JdwpControl _jdwp_control;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800385
Josh Gao9eaf33c2016-05-13 15:28:34 -0700386static void jdwp_control_event(int s, unsigned events, void* user);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800387
Josh Gao9eaf33c2016-05-13 15:28:34 -0700388static int jdwp_control_init(JdwpControl* control, const char* sockname, int socknamelen) {
389 sockaddr_un addr;
390 socklen_t addrlen;
391 int s;
392 int maxpath = sizeof(addr.sun_path);
393 int pathlen = socknamelen;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800394
395 if (pathlen >= maxpath) {
Josh Gao9eaf33c2016-05-13 15:28:34 -0700396 D("vm debug control socket name too long (%d extra chars)", pathlen + 1 - maxpath);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800397 return -1;
398 }
399
400 memset(&addr, 0, sizeof(addr));
401 addr.sun_family = AF_UNIX;
402 memcpy(addr.sun_path, sockname, socknamelen);
403
Josh Gao9eaf33c2016-05-13 15:28:34 -0700404 s = socket(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800405 if (s < 0) {
Josh Gao9eaf33c2016-05-13 15:28:34 -0700406 D("could not create vm debug control socket. %d: %s", errno, strerror(errno));
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800407 return -1;
408 }
409
Josh Gao9eaf33c2016-05-13 15:28:34 -0700410 addrlen = pathlen + sizeof(addr.sun_family);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800411
Erik Kline3c8d44d2015-12-01 17:27:59 +0900412 if (bind(s, reinterpret_cast<sockaddr*>(&addr), addrlen) < 0) {
Josh Gao9eaf33c2016-05-13 15:28:34 -0700413 D("could not bind vm debug control socket: %d: %s", errno, strerror(errno));
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800414 adb_close(s);
415 return -1;
416 }
417
Josh Gao9eaf33c2016-05-13 15:28:34 -0700418 if (listen(s, 4) < 0) {
419 D("listen failed in jdwp control socket: %d: %s", errno, strerror(errno));
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800420 adb_close(s);
421 return -1;
422 }
423
424 control->listen_socket = s;
425
426 control->fde = fdevent_create(s, jdwp_control_event, control);
427 if (control->fde == NULL) {
Josh Gao9eaf33c2016-05-13 15:28:34 -0700428 D("could not create fdevent for jdwp control socket");
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800429 adb_close(s);
430 return -1;
431 }
432
433 /* only wait for incoming connections */
434 fdevent_add(control->fde, FDE_READ);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800435
Yabin Cui815ad882015-09-02 17:44:28 -0700436 D("jdwp control socket started (%d)", control->listen_socket);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800437 return 0;
438}
439
Josh Gao9eaf33c2016-05-13 15:28:34 -0700440static void jdwp_control_event(int s, unsigned events, void* _control) {
441 JdwpControl* control = (JdwpControl*)_control;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800442
443 if (events & FDE_READ) {
Josh Gao782d8d42016-08-23 15:41:56 -0700444 int s = adb_socket_accept(control->listen_socket, nullptr, nullptr);
Josh Gao9eaf33c2016-05-13 15:28:34 -0700445 if (s < 0) {
446 if (errno == ECONNABORTED) {
447 /* oops, the JDWP process died really quick */
448 D("oops, the JDWP process died really quick");
449 return;
450 } else {
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800451 /* the socket is probably closed ? */
Josh Gao9eaf33c2016-05-13 15:28:34 -0700452 D("weird accept() failed on jdwp control socket: %s", strerror(errno));
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800453 return;
454 }
455 }
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800456
Josh Gao9eaf33c2016-05-13 15:28:34 -0700457 auto proc = std::make_unique<JdwpProcess>(s);
458 if (!proc) {
459 fatal("failed to allocate JdwpProcess");
460 }
461
462 _jdwp_list.emplace_back(std::move(proc));
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800463 }
464}
465
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800466/** "jdwp" local service implementation
467 ** this simply returns the list of known JDWP process pids
468 **/
469
Josh Gao9eaf33c2016-05-13 15:28:34 -0700470struct JdwpSocket : public asocket {
471 bool pass;
Elliott Hughesfe7ff812015-04-17 09:47:42 -0700472};
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800473
Josh Gao9eaf33c2016-05-13 15:28:34 -0700474static void jdwp_socket_close(asocket* s) {
475 D("LS(%d): closing jdwp socket", s->id);
476
477 if (s->peer) {
478 D("LS(%d) peer->close()ing peer->id=%d peer->fd=%d", s->id, s->peer->id, s->peer->fd);
479 s->peer->peer = nullptr;
480 s->peer->close(s->peer);
481 s->peer = nullptr;
482 }
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800483
484 remove_socket(s);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800485 free(s);
486}
487
Josh Gao9eaf33c2016-05-13 15:28:34 -0700488static int jdwp_socket_enqueue(asocket* s, apacket* p) {
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800489 /* you can't write to this asocket */
Josh Gao9eaf33c2016-05-13 15:28:34 -0700490 D("LS(%d): JDWP socket received data?", s->id);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800491 put_apacket(p);
492 s->peer->close(s->peer);
493 return -1;
494}
495
Josh Gao9eaf33c2016-05-13 15:28:34 -0700496static void jdwp_socket_ready(asocket* s) {
497 JdwpSocket* jdwp = (JdwpSocket*)s;
498 asocket* peer = jdwp->peer;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800499
Josh Gao9eaf33c2016-05-13 15:28:34 -0700500 /* on the first call, send the list of pids,
501 * on the second one, close the connection
502 */
503 if (!jdwp->pass) {
504 apacket* p = get_apacket();
Tamas Berghammera1c60c02015-07-13 19:12:28 +0100505 p->len = jdwp_process_list((char*)p->data, s->get_max_payload());
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800506 peer->enqueue(peer, p);
Josh Gao9eaf33c2016-05-13 15:28:34 -0700507 jdwp->pass = true;
508 } else {
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800509 peer->close(peer);
510 }
511}
512
Josh Gao9eaf33c2016-05-13 15:28:34 -0700513asocket* create_jdwp_service_socket(void) {
Dan Albertf30d73c2015-02-25 17:51:28 -0800514 JdwpSocket* s = reinterpret_cast<JdwpSocket*>(calloc(sizeof(*s), 1));
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800515
Josh Gao9eaf33c2016-05-13 15:28:34 -0700516 if (!s) {
517 fatal("failed to allocate JdwpSocket");
518 }
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800519
Josh Gao9eaf33c2016-05-13 15:28:34 -0700520 install_local_socket(s);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800521
Josh Gao9eaf33c2016-05-13 15:28:34 -0700522 s->ready = jdwp_socket_ready;
523 s->enqueue = jdwp_socket_enqueue;
524 s->close = jdwp_socket_close;
525 s->pass = false;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800526
Josh Gao9eaf33c2016-05-13 15:28:34 -0700527 return s;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800528}
529
530/** "track-jdwp" local service implementation
531 ** this periodically sends the list of known JDWP process pids
532 ** to the client...
533 **/
534
Josh Gao9eaf33c2016-05-13 15:28:34 -0700535struct JdwpTracker : public asocket {
536 bool need_initial;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800537};
538
Josh Gao9eaf33c2016-05-13 15:28:34 -0700539static std::vector<std::unique_ptr<JdwpTracker>> _jdwp_trackers;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800540
Josh Gao9eaf33c2016-05-13 15:28:34 -0700541static void jdwp_process_list_updated(void) {
542 char buffer[1024];
543 int len = jdwp_process_list_msg(buffer, sizeof(buffer));
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800544
Josh Gao9eaf33c2016-05-13 15:28:34 -0700545 for (auto& t : _jdwp_trackers) {
546 apacket* p = get_apacket();
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800547 memcpy(p->data, buffer, len);
548 p->len = len;
Josh Gao9eaf33c2016-05-13 15:28:34 -0700549
550 if (t->peer) {
551 // The tracker might not have been connected yet.
552 t->peer->enqueue(t->peer, p);
553 }
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800554 }
555}
556
Josh Gao9eaf33c2016-05-13 15:28:34 -0700557static void jdwp_tracker_close(asocket* s) {
558 D("LS(%d): destroying jdwp tracker service", s->id);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800559
Josh Gao9eaf33c2016-05-13 15:28:34 -0700560 if (s->peer) {
561 D("LS(%d) peer->close()ing peer->id=%d peer->fd=%d", s->id, s->peer->id, s->peer->fd);
562 s->peer->peer = nullptr;
563 s->peer->close(s->peer);
564 s->peer = nullptr;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800565 }
566
567 remove_socket(s);
568
Josh Gao9eaf33c2016-05-13 15:28:34 -0700569 auto pred = [s](const auto& tracker) { return tracker.get() == s; };
Josh Gaoeea5fea2017-03-10 11:19:48 -0800570 _jdwp_trackers.erase(std::remove_if(_jdwp_trackers.begin(), _jdwp_trackers.end(), pred),
571 _jdwp_trackers.end());
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800572}
573
Josh Gao9eaf33c2016-05-13 15:28:34 -0700574static void jdwp_tracker_ready(asocket* s) {
575 JdwpTracker* t = (JdwpTracker*)s;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800576
Josh Gao9eaf33c2016-05-13 15:28:34 -0700577 if (t->need_initial) {
578 apacket* p = get_apacket();
579 t->need_initial = false;
Tamas Berghammera1c60c02015-07-13 19:12:28 +0100580 p->len = jdwp_process_list_msg((char*)p->data, s->get_max_payload());
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800581 s->peer->enqueue(s->peer, p);
582 }
583}
584
Josh Gao9eaf33c2016-05-13 15:28:34 -0700585static int jdwp_tracker_enqueue(asocket* s, apacket* p) {
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800586 /* you can't write to this socket */
Josh Gao9eaf33c2016-05-13 15:28:34 -0700587 D("LS(%d): JDWP tracker received data?", s->id);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800588 put_apacket(p);
589 s->peer->close(s->peer);
590 return -1;
591}
592
Josh Gao9eaf33c2016-05-13 15:28:34 -0700593asocket* create_jdwp_tracker_service_socket(void) {
594 auto t = std::make_unique<JdwpTracker>();
595 if (!t) {
596 fatal("failed to allocate JdwpTracker");
597 }
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800598
Josh Gao9eaf33c2016-05-13 15:28:34 -0700599 memset(t.get(), 0, sizeof(asocket));
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800600
Josh Gao9eaf33c2016-05-13 15:28:34 -0700601 install_local_socket(t.get());
602 D("LS(%d): created new jdwp tracker service", t->id);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800603
Josh Gao9eaf33c2016-05-13 15:28:34 -0700604 t->ready = jdwp_tracker_ready;
605 t->enqueue = jdwp_tracker_enqueue;
606 t->close = jdwp_tracker_close;
607 t->need_initial = true;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800608
Josh Gao9eaf33c2016-05-13 15:28:34 -0700609 asocket* result = t.get();
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800610
Josh Gao9eaf33c2016-05-13 15:28:34 -0700611 _jdwp_trackers.emplace_back(std::move(t));
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800612
Josh Gao9eaf33c2016-05-13 15:28:34 -0700613 return result;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800614}
615
Josh Gao9eaf33c2016-05-13 15:28:34 -0700616int init_jdwp(void) {
617 return jdwp_control_init(&_jdwp_control, JDWP_CONTROL_NAME, JDWP_CONTROL_NAME_LEN);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800618}
619
620#endif /* !ADB_HOST */