blob: 5f070d9174f55f15f06dac22d2b071e1dd0e66b2 [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"
Josh Gao924d35a2016-08-30 15:39:25 -070037#include "adb_unique_fd.h"
Yabin Cui6dfef252015-10-06 15:10:05 -070038#include "adb_utils.h"
Dan Albert33134262015-03-19 15:21:08 -070039
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080040/* here's how these things work.
41
42 when adbd starts, it creates a unix server socket
Josh Gao52338a32016-05-13 15:28:34 -070043 named @jdwp-control (@ is a shortcut for "first byte is zero"
The Android Open Source Projectdd7bc332009-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 Gao52338a32016-05-13 15:28:34 -070047 a connection to @jdwp-control to announce its availability.
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080048
49
Josh Gao52338a32016-05-13 15:28:34 -070050 JDWP thread @jdwp-control
The Android Open Source Projectdd7bc332009-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 Gao52338a32016-05-13 15:28:34 -070083 JDWP thread @jdwp-control
The Android Open Source Projectdd7bc332009-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 Gao52338a32016-05-13 15:28:34 -0700127static void jdwp_process_event(int socket, unsigned events, void* _proc);
128static void jdwp_process_list_updated(void);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800129
Josh Gao52338a32016-05-13 15:28:34 -0700130struct JdwpProcess;
131static std::list<std::unique_ptr<JdwpProcess>> _jdwp_list;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800132
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800133struct JdwpProcess {
Josh Gao52338a32016-05-13 15:28:34 -0700134 explicit JdwpProcess(int socket) {
135 this->socket = socket;
136 this->fde = fdevent_create(socket, jdwp_process_event, this);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800137
Josh Gao52338a32016-05-13 15:28:34 -0700138 if (!this->fde) {
139 fatal("could not create fdevent for new JDWP process");
140 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800141
Josh Gao52338a32016-05-13 15:28:34 -0700142 this->fde->state |= FDE_DONT_CLOSE;
143
144 /* start by waiting for the PID */
145 fdevent_add(this->fde, FDE_READ);
146 }
147
148 ~JdwpProcess() {
149 if (this->socket >= 0) {
150 adb_shutdown(this->socket);
151 adb_close(this->socket);
152 this->socket = -1;
153 }
154
155 if (this->fde) {
156 fdevent_destroy(this->fde);
157 this->fde = nullptr;
158 }
159
160 out_fds.clear();
161 }
162
163 void RemoveFromList() {
164 if (this->pid >= 0) {
165 D("removing pid %d from jdwp process list", this->pid);
166 } else {
167 D("removing transient JdwpProcess from list");
168 }
169
170 auto pred = [this](const auto& proc) { return proc.get() == this; };
171 _jdwp_list.remove_if(pred);
172 }
173
Josh Gao86f39b42018-02-12 15:05:05 -0800174 int32_t pid = -1;
Josh Gao52338a32016-05-13 15:28:34 -0700175 int socket = -1;
176 fdevent* fde = nullptr;
177
178 std::vector<unique_fd> out_fds;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800179};
180
Josh Gao52338a32016-05-13 15:28:34 -0700181static size_t jdwp_process_list(char* buffer, size_t bufferlen) {
182 std::string temp;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800183
Josh Gao52338a32016-05-13 15:28:34 -0700184 for (auto& proc : _jdwp_list) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800185 /* skip transient connections */
Josh Gao52338a32016-05-13 15:28:34 -0700186 if (proc->pid < 0) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800187 continue;
Josh Gao52338a32016-05-13 15:28:34 -0700188 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800189
Josh Gao52338a32016-05-13 15:28:34 -0700190 std::string next = std::to_string(proc->pid) + "\n";
191 if (temp.length() + next.length() > bufferlen) {
192 D("truncating JDWP process list (max len = %zu)", bufferlen);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800193 break;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800194 }
Josh Gao52338a32016-05-13 15:28:34 -0700195 temp.append(next);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800196 }
Josh Gao52338a32016-05-13 15:28:34 -0700197
198 memcpy(buffer, temp.data(), temp.length());
199 return temp.length();
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800200}
201
Josh Gao52338a32016-05-13 15:28:34 -0700202static size_t jdwp_process_list_msg(char* buffer, size_t bufferlen) {
203 // Message is length-prefixed with 4 hex digits in ASCII.
204 static constexpr size_t header_len = 4;
205 if (bufferlen < header_len) {
206 fatal("invalid JDWP process list buffer size: %zu", bufferlen);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800207 }
208
Josh Gao52338a32016-05-13 15:28:34 -0700209 char head[header_len + 1];
210 size_t len = jdwp_process_list(buffer + header_len, bufferlen - header_len);
211 snprintf(head, sizeof head, "%04zx", len);
212 memcpy(buffer, head, header_len);
213 return len + header_len;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800214}
215
Josh Gao52338a32016-05-13 15:28:34 -0700216static void jdwp_process_event(int socket, unsigned events, void* _proc) {
217 JdwpProcess* proc = reinterpret_cast<JdwpProcess*>(_proc);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800218
219 if (events & FDE_READ) {
220 if (proc->pid < 0) {
Josh Gao86f39b42018-02-12 15:05:05 -0800221 ssize_t rc = TEMP_FAILURE_RETRY(recv(socket, &proc->pid, sizeof(proc->pid), 0));
222 if (rc != sizeof(proc->pid)) {
223 D("failed to read jdwp pid: rc = %zd, errno = %s", rc, strerror(errno));
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800224 goto CloseProcess;
225 }
226
227 /* all is well, keep reading to detect connection closure */
Yabin Cui7a3f8d62015-09-02 17:44:28 -0700228 D("Adding pid %d to jdwp process list", proc->pid);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800229 jdwp_process_list_updated();
Josh Gao52338a32016-05-13 15:28:34 -0700230 } else {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800231 /* the pid was read, if we get there it's probably because the connection
232 * was closed (e.g. the JDWP process exited or crashed) */
Josh Gao52338a32016-05-13 15:28:34 -0700233 char buf[32];
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800234
Josh Gao52338a32016-05-13 15:28:34 -0700235 while (true) {
236 int len = TEMP_FAILURE_RETRY(recv(socket, buf, sizeof(buf), 0));
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800237
Josh Gao52338a32016-05-13 15:28:34 -0700238 if (len == 0) {
239 D("terminating JDWP %d connection: EOF", proc->pid);
240 break;
241 } else if (len < 0) {
242 if (len < 0 && errno == EAGAIN) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800243 return;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800244 }
Josh Gao52338a32016-05-13 15:28:34 -0700245
246 D("terminating JDWP %d connection: EOF", proc->pid);
247 break;
248 } else {
249 D("ignoring unexpected JDWP %d control socket activity (%d bytes)", proc->pid,
250 len);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800251 }
252 }
253
Josh Gao52338a32016-05-13 15:28:34 -0700254 goto CloseProcess;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800255 }
256 }
257
258 if (events & FDE_WRITE) {
Josh Gao52338a32016-05-13 15:28:34 -0700259 D("trying to send fd to JDWP process (count = %zu)", proc->out_fds.size());
260 if (!proc->out_fds.empty()) {
261 int fd = proc->out_fds.back().get();
262 struct cmsghdr* cmsg;
263 struct msghdr msg;
264 struct iovec iov;
265 char dummy = '!';
266 char buffer[sizeof(struct cmsghdr) + sizeof(int)];
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800267
Josh Gao52338a32016-05-13 15:28:34 -0700268 iov.iov_base = &dummy;
269 iov.iov_len = 1;
270 msg.msg_name = NULL;
271 msg.msg_namelen = 0;
272 msg.msg_iov = &iov;
273 msg.msg_iovlen = 1;
274 msg.msg_flags = 0;
275 msg.msg_control = buffer;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800276 msg.msg_controllen = sizeof(buffer);
277
278 cmsg = CMSG_FIRSTHDR(&msg);
Josh Gao52338a32016-05-13 15:28:34 -0700279 cmsg->cmsg_len = msg.msg_controllen;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800280 cmsg->cmsg_level = SOL_SOCKET;
Josh Gao52338a32016-05-13 15:28:34 -0700281 cmsg->cmsg_type = SCM_RIGHTS;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800282 ((int*)CMSG_DATA(cmsg))[0] = fd;
283
Yabin Cui6dfef252015-10-06 15:10:05 -0700284 if (!set_file_block_mode(proc->socket, true)) {
285 VLOG(JDWP) << "failed to set blocking mode for fd " << proc->socket;
Teddie Stenvi8f5daad2010-02-15 12:20:44 +0100286 goto CloseProcess;
287 }
288
Josh Gao52338a32016-05-13 15:28:34 -0700289 int ret = TEMP_FAILURE_RETRY(sendmsg(proc->socket, &msg, 0));
290 if (ret < 0) {
291 D("sending new file descriptor to JDWP %d failed: %s", proc->pid, strerror(errno));
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800292 goto CloseProcess;
293 }
294
Josh Gao52338a32016-05-13 15:28:34 -0700295 D("sent file descriptor %d to JDWP process %d", fd, proc->pid);
296
297 proc->out_fds.pop_back();
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800298
Yabin Cui6dfef252015-10-06 15:10:05 -0700299 if (!set_file_block_mode(proc->socket, false)) {
300 VLOG(JDWP) << "failed to set non-blocking mode for fd " << proc->socket;
Teddie Stenvi8f5daad2010-02-15 12:20:44 +0100301 goto CloseProcess;
302 }
303
Josh Gao52338a32016-05-13 15:28:34 -0700304 if (proc->out_fds.empty()) {
305 fdevent_del(proc->fde, FDE_WRITE);
306 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800307 }
308 }
Josh Gao52338a32016-05-13 15:28:34 -0700309
310 return;
311
312CloseProcess:
313 proc->RemoveFromList();
314 jdwp_process_list_updated();
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800315}
316
Josh Gao52338a32016-05-13 15:28:34 -0700317int create_jdwp_connection_fd(int pid) {
Yabin Cui7a3f8d62015-09-02 17:44:28 -0700318 D("looking for pid %d in JDWP process list", pid);
Josh Gao52338a32016-05-13 15:28:34 -0700319
320 for (auto& proc : _jdwp_list) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800321 if (proc->pid == pid) {
Josh Gao52338a32016-05-13 15:28:34 -0700322 int fds[2];
323
324 if (adb_socketpair(fds) < 0) {
325 D("%s: socket pair creation failed: %s", __FUNCTION__, strerror(errno));
326 return -1;
327 }
328 D("socketpair: (%d,%d)", fds[0], fds[1]);
329
330 proc->out_fds.emplace_back(fds[1]);
331 if (proc->out_fds.size() == 1) {
332 fdevent_add(proc->fde, FDE_WRITE);
333 }
334
335 return fds[0];
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800336 }
337 }
Yabin Cui7a3f8d62015-09-02 17:44:28 -0700338 D("search failed !!");
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800339 return -1;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800340}
341
342/** VM DEBUG CONTROL SOCKET
343 **
344 ** we do implement a custom asocket to receive the data
345 **/
346
347/* name of the debug control Unix socket */
Josh Gao52338a32016-05-13 15:28:34 -0700348#define JDWP_CONTROL_NAME "\0jdwp-control"
349#define JDWP_CONTROL_NAME_LEN (sizeof(JDWP_CONTROL_NAME) - 1)
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800350
Elliott Hughes2d4121c2015-04-17 09:47:42 -0700351struct JdwpControl {
Josh Gao52338a32016-05-13 15:28:34 -0700352 int listen_socket;
353 fdevent* fde;
Elliott Hughes2d4121c2015-04-17 09:47:42 -0700354};
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800355
Josh Gao52338a32016-05-13 15:28:34 -0700356static JdwpControl _jdwp_control;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800357
Josh Gao52338a32016-05-13 15:28:34 -0700358static void jdwp_control_event(int s, unsigned events, void* user);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800359
Josh Gao52338a32016-05-13 15:28:34 -0700360static int jdwp_control_init(JdwpControl* control, const char* sockname, int socknamelen) {
361 sockaddr_un addr;
362 socklen_t addrlen;
363 int s;
364 int maxpath = sizeof(addr.sun_path);
365 int pathlen = socknamelen;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800366
367 if (pathlen >= maxpath) {
Josh Gao52338a32016-05-13 15:28:34 -0700368 D("vm debug control socket name too long (%d extra chars)", pathlen + 1 - maxpath);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800369 return -1;
370 }
371
372 memset(&addr, 0, sizeof(addr));
373 addr.sun_family = AF_UNIX;
374 memcpy(addr.sun_path, sockname, socknamelen);
375
Josh Gaob2a72512017-03-20 13:37:13 -0700376 s = socket(AF_UNIX, SOCK_SEQPACKET | SOCK_CLOEXEC, 0);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800377 if (s < 0) {
Josh Gao52338a32016-05-13 15:28:34 -0700378 D("could not create vm debug control socket. %d: %s", errno, strerror(errno));
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800379 return -1;
380 }
381
Josh Gao52338a32016-05-13 15:28:34 -0700382 addrlen = pathlen + sizeof(addr.sun_family);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800383
Erik Kline7e16cc12015-12-01 17:27:59 +0900384 if (bind(s, reinterpret_cast<sockaddr*>(&addr), addrlen) < 0) {
Josh Gao52338a32016-05-13 15:28:34 -0700385 D("could not bind vm debug control socket: %d: %s", errno, strerror(errno));
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800386 adb_close(s);
387 return -1;
388 }
389
Josh Gao52338a32016-05-13 15:28:34 -0700390 if (listen(s, 4) < 0) {
391 D("listen failed in jdwp control socket: %d: %s", errno, strerror(errno));
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800392 adb_close(s);
393 return -1;
394 }
395
396 control->listen_socket = s;
397
398 control->fde = fdevent_create(s, jdwp_control_event, control);
399 if (control->fde == NULL) {
Josh Gao52338a32016-05-13 15:28:34 -0700400 D("could not create fdevent for jdwp control socket");
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800401 adb_close(s);
402 return -1;
403 }
404
405 /* only wait for incoming connections */
406 fdevent_add(control->fde, FDE_READ);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800407
Yabin Cui7a3f8d62015-09-02 17:44:28 -0700408 D("jdwp control socket started (%d)", control->listen_socket);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800409 return 0;
410}
411
Josh Gao52338a32016-05-13 15:28:34 -0700412static void jdwp_control_event(int s, unsigned events, void* _control) {
413 JdwpControl* control = (JdwpControl*)_control;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800414
415 if (events & FDE_READ) {
Josh Gao78e1eb12016-08-23 15:41:56 -0700416 int s = adb_socket_accept(control->listen_socket, nullptr, nullptr);
Josh Gao52338a32016-05-13 15:28:34 -0700417 if (s < 0) {
418 if (errno == ECONNABORTED) {
419 /* oops, the JDWP process died really quick */
420 D("oops, the JDWP process died really quick");
421 return;
422 } else {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800423 /* the socket is probably closed ? */
Josh Gao52338a32016-05-13 15:28:34 -0700424 D("weird accept() failed on jdwp control socket: %s", strerror(errno));
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800425 return;
426 }
427 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800428
Josh Gao52338a32016-05-13 15:28:34 -0700429 auto proc = std::make_unique<JdwpProcess>(s);
430 if (!proc) {
431 fatal("failed to allocate JdwpProcess");
432 }
433
434 _jdwp_list.emplace_back(std::move(proc));
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800435 }
436}
437
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800438/** "jdwp" local service implementation
439 ** this simply returns the list of known JDWP process pids
440 **/
441
Josh Gao52338a32016-05-13 15:28:34 -0700442struct JdwpSocket : public asocket {
Josh Gaoe0361d12018-02-12 17:24:00 -0800443 bool pass = false;
Elliott Hughes2d4121c2015-04-17 09:47:42 -0700444};
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800445
Josh Gao52338a32016-05-13 15:28:34 -0700446static void jdwp_socket_close(asocket* s) {
447 D("LS(%d): closing jdwp socket", s->id);
448
449 if (s->peer) {
450 D("LS(%d) peer->close()ing peer->id=%d peer->fd=%d", s->id, s->peer->id, s->peer->fd);
451 s->peer->peer = nullptr;
452 s->peer->close(s->peer);
453 s->peer = nullptr;
454 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800455
456 remove_socket(s);
Josh Gaoe0361d12018-02-12 17:24:00 -0800457 delete s;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800458}
459
Josh Gao27cb7dc2018-02-01 13:17:50 -0800460static int jdwp_socket_enqueue(asocket* s, std::string) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800461 /* you can't write to this asocket */
Josh Gao52338a32016-05-13 15:28:34 -0700462 D("LS(%d): JDWP socket received data?", s->id);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800463 s->peer->close(s->peer);
464 return -1;
465}
466
Josh Gao52338a32016-05-13 15:28:34 -0700467static void jdwp_socket_ready(asocket* s) {
468 JdwpSocket* jdwp = (JdwpSocket*)s;
469 asocket* peer = jdwp->peer;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800470
Josh Gao52338a32016-05-13 15:28:34 -0700471 /* on the first call, send the list of pids,
472 * on the second one, close the connection
473 */
474 if (!jdwp->pass) {
Josh Gao27cb7dc2018-02-01 13:17:50 -0800475 std::string data;
476 data.resize(s->get_max_payload());
477 size_t len = jdwp_process_list(&data[0], data.size());
478 data.resize(len);
479 peer->enqueue(peer, std::move(data));
Josh Gao52338a32016-05-13 15:28:34 -0700480 jdwp->pass = true;
481 } else {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800482 peer->close(peer);
483 }
484}
485
Josh Gao52338a32016-05-13 15:28:34 -0700486asocket* create_jdwp_service_socket(void) {
Josh Gaoe0361d12018-02-12 17:24:00 -0800487 JdwpSocket* s = new JdwpSocket();
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800488
Josh Gao52338a32016-05-13 15:28:34 -0700489 if (!s) {
490 fatal("failed to allocate JdwpSocket");
491 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800492
Josh Gao52338a32016-05-13 15:28:34 -0700493 install_local_socket(s);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800494
Josh Gao52338a32016-05-13 15:28:34 -0700495 s->ready = jdwp_socket_ready;
496 s->enqueue = jdwp_socket_enqueue;
497 s->close = jdwp_socket_close;
498 s->pass = false;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800499
Josh Gao52338a32016-05-13 15:28:34 -0700500 return s;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800501}
502
503/** "track-jdwp" local service implementation
504 ** this periodically sends the list of known JDWP process pids
505 ** to the client...
506 **/
507
Josh Gao52338a32016-05-13 15:28:34 -0700508struct JdwpTracker : public asocket {
509 bool need_initial;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800510};
511
Josh Gao52338a32016-05-13 15:28:34 -0700512static std::vector<std::unique_ptr<JdwpTracker>> _jdwp_trackers;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800513
Josh Gao52338a32016-05-13 15:28:34 -0700514static void jdwp_process_list_updated(void) {
Josh Gao27cb7dc2018-02-01 13:17:50 -0800515 std::string data;
516 data.resize(1024);
517 data.resize(jdwp_process_list_msg(&data[0], data.size()));
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800518
Josh Gao52338a32016-05-13 15:28:34 -0700519 for (auto& t : _jdwp_trackers) {
Josh Gao52338a32016-05-13 15:28:34 -0700520 if (t->peer) {
521 // The tracker might not have been connected yet.
Josh Gao27cb7dc2018-02-01 13:17:50 -0800522 t->peer->enqueue(t->peer, data);
Josh Gao52338a32016-05-13 15:28:34 -0700523 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800524 }
525}
526
Josh Gao52338a32016-05-13 15:28:34 -0700527static void jdwp_tracker_close(asocket* s) {
528 D("LS(%d): destroying jdwp tracker service", s->id);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800529
Josh Gao52338a32016-05-13 15:28:34 -0700530 if (s->peer) {
531 D("LS(%d) peer->close()ing peer->id=%d peer->fd=%d", s->id, s->peer->id, s->peer->fd);
532 s->peer->peer = nullptr;
533 s->peer->close(s->peer);
534 s->peer = nullptr;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800535 }
536
537 remove_socket(s);
538
Josh Gao52338a32016-05-13 15:28:34 -0700539 auto pred = [s](const auto& tracker) { return tracker.get() == s; };
Josh Gao6def9bd2017-03-10 11:19:48 -0800540 _jdwp_trackers.erase(std::remove_if(_jdwp_trackers.begin(), _jdwp_trackers.end(), pred),
541 _jdwp_trackers.end());
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800542}
543
Josh Gao52338a32016-05-13 15:28:34 -0700544static void jdwp_tracker_ready(asocket* s) {
545 JdwpTracker* t = (JdwpTracker*)s;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800546
Josh Gao52338a32016-05-13 15:28:34 -0700547 if (t->need_initial) {
Josh Gao27cb7dc2018-02-01 13:17:50 -0800548 std::string data;
549 data.resize(s->get_max_payload());
550 data.resize(jdwp_process_list_msg(&data[0], data.size()));
Josh Gao52338a32016-05-13 15:28:34 -0700551 t->need_initial = false;
Josh Gao27cb7dc2018-02-01 13:17:50 -0800552 s->peer->enqueue(s->peer, std::move(data));
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800553 }
554}
555
Josh Gao27cb7dc2018-02-01 13:17:50 -0800556static int jdwp_tracker_enqueue(asocket* s, std::string) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800557 /* you can't write to this socket */
Josh Gao52338a32016-05-13 15:28:34 -0700558 D("LS(%d): JDWP tracker received data?", s->id);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800559 s->peer->close(s->peer);
560 return -1;
561}
562
Josh Gao52338a32016-05-13 15:28:34 -0700563asocket* create_jdwp_tracker_service_socket(void) {
564 auto t = std::make_unique<JdwpTracker>();
565 if (!t) {
566 fatal("failed to allocate JdwpTracker");
567 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800568
Josh Gao52338a32016-05-13 15:28:34 -0700569 memset(t.get(), 0, sizeof(asocket));
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800570
Josh Gao52338a32016-05-13 15:28:34 -0700571 install_local_socket(t.get());
572 D("LS(%d): created new jdwp tracker service", t->id);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800573
Josh Gao52338a32016-05-13 15:28:34 -0700574 t->ready = jdwp_tracker_ready;
575 t->enqueue = jdwp_tracker_enqueue;
576 t->close = jdwp_tracker_close;
577 t->need_initial = true;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800578
Josh Gao52338a32016-05-13 15:28:34 -0700579 asocket* result = t.get();
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800580
Josh Gao52338a32016-05-13 15:28:34 -0700581 _jdwp_trackers.emplace_back(std::move(t));
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800582
Josh Gao52338a32016-05-13 15:28:34 -0700583 return result;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800584}
585
Josh Gao52338a32016-05-13 15:28:34 -0700586int init_jdwp(void) {
587 return jdwp_control_init(&_jdwp_control, JDWP_CONTROL_NAME, JDWP_CONTROL_NAME_LEN);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800588}
589
590#endif /* !ADB_HOST */