blob: 9ff50f5b7e6cb02b5662ef47acd8cad8f7435ef4 [file] [log] [blame]
Elliott Hughes872d4ec2011-10-21 17:07:15 -07001/*
2 * Copyright (C) 2008 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/*
17 * JDWP TCP socket network code.
18 */
19#include "jdwp/jdwp_priv.h"
20#include "jdwp/jdwp_handler.h"
21#include "logging.h"
22#include "stringprintf.h"
23
24#include <stdlib.h>
25#include <unistd.h>
26#include <stdio.h>
27#include <string.h>
28#include <errno.h>
29#include <sys/types.h>
30#include <sys/socket.h>
31#include <netinet/in.h>
32#include <netinet/tcp.h>
33#include <arpa/inet.h>
34#include <netdb.h>
35
36#define kBasePort 8000
37#define kMaxPort 8040
38
39#define kInputBufferSize 8192
40
41#define kMagicHandshake "JDWP-Handshake"
42#define kMagicHandshakeLen (sizeof(kMagicHandshake)-1)
43
44namespace art {
45
46namespace JDWP {
47
48// fwd
49static void netShutdown(JdwpNetState* state);
50static void netFree(JdwpNetState* state);
51
52/*
53 * JDWP network state.
54 *
55 * We only talk to one debugger at a time.
56 */
57struct JdwpNetState : public JdwpNetStateBase {
Elliott Hughes6d8dd472012-01-17 18:27:41 -080058 uint16_t listenPort;
Elliott Hughes872d4ec2011-10-21 17:07:15 -070059 int listenSock; /* listen for connection from debugger */
60 int wakePipe[2]; /* break out of select */
61
Elliott Hughes7b9d9962012-04-20 18:48:18 -070062 in_addr remoteAddr;
Elliott Hughes6d8dd472012-01-17 18:27:41 -080063 uint16_t remotePort;
Elliott Hughes872d4ec2011-10-21 17:07:15 -070064
65 bool awaitingHandshake; /* waiting for "JDWP-Handshake" */
66
67 /* pending data from the network; would be more efficient as circular buf */
68 unsigned char inputBuffer[kInputBufferSize];
69 int inputCount;
70
Elliott Hughes376a7a02011-10-24 18:35:55 -070071 JdwpNetState() {
Elliott Hughes872d4ec2011-10-21 17:07:15 -070072 listenPort = 0;
73 listenSock = -1;
74 wakePipe[0] = -1;
75 wakePipe[1] = -1;
76
77 awaitingHandshake = false;
78
79 inputCount = 0;
80 }
81};
82
Elliott Hughes6d8dd472012-01-17 18:27:41 -080083static JdwpNetState* netStartup(uint16_t port, bool probe);
Elliott Hughes872d4ec2011-10-21 17:07:15 -070084
85/*
86 * Set up some stuff for transport=dt_socket.
87 */
Elliott Hughes376a7a02011-10-24 18:35:55 -070088static bool prepareSocket(JdwpState* state, const JdwpOptions* options) {
Elliott Hughes6d8dd472012-01-17 18:27:41 -080089 uint16_t port = options->port;
Elliott Hughes872d4ec2011-10-21 17:07:15 -070090
Elliott Hughes376a7a02011-10-24 18:35:55 -070091 if (options->server) {
92 if (options->port != 0) {
Elliott Hughes872d4ec2011-10-21 17:07:15 -070093 /* try only the specified port */
Elliott Hughes3d30d9b2011-12-07 17:35:48 -080094 state->netState = netStartup(port, false);
Elliott Hughes872d4ec2011-10-21 17:07:15 -070095 } else {
96 /* scan through a range of ports, binding to the first available */
97 for (port = kBasePort; port <= kMaxPort; port++) {
Elliott Hughes3d30d9b2011-12-07 17:35:48 -080098 state->netState = netStartup(port, true);
Elliott Hughes872d4ec2011-10-21 17:07:15 -070099 if (state->netState != NULL) {
100 break;
101 }
102 }
103 }
104 if (state->netState == NULL) {
Elliott Hughes376a7a02011-10-24 18:35:55 -0700105 LOG(ERROR) << "JDWP net startup failed (req port=" << options->port << ")";
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700106 return false;
107 }
108 } else {
Elliott Hughes6d8dd472012-01-17 18:27:41 -0800109 state->netState = netStartup(0, false);
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700110 }
111
Elliott Hughes376a7a02011-10-24 18:35:55 -0700112 if (options->suspend) {
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700113 LOG(INFO) << "JDWP will wait for debugger on port " << port;
114 } else {
Elliott Hughes376a7a02011-10-24 18:35:55 -0700115 LOG(INFO) << "JDWP will " << (options->server ? "listen" : "connect") << " on port " << port;
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700116 }
117
118 return true;
119}
120
121/*
122 * Are we still waiting for the handshake string?
123 */
124static bool awaitingHandshake(JdwpState* state) {
125 return state->netState->awaitingHandshake;
126}
127
128/*
129 * Initialize JDWP stuff.
130 *
Elliott Hughes6d8dd472012-01-17 18:27:41 -0800131 * Allocates a new state structure. If "port" is non-zero, this also
132 * tries to bind to a listen port. If "port" is zero, we assume
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700133 * we're preparing for an outbound connection, and return without binding
134 * to anything.
135 *
136 * This may be called several times if we're probing for a port.
137 *
138 * Returns 0 on success.
139 */
Elliott Hughes6d8dd472012-01-17 18:27:41 -0800140static JdwpNetState* netStartup(uint16_t port, bool probe) {
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700141 JdwpNetState* netState = new JdwpNetState;
Elliott Hughes6d8dd472012-01-17 18:27:41 -0800142 if (port == 0) {
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700143 return netState;
144 }
145
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700146 netState->listenSock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
147 if (netState->listenSock < 0) {
Elliott Hughes3d30d9b2011-12-07 17:35:48 -0800148 PLOG(probe ? ERROR : FATAL) << "Socket create failed";
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700149 goto fail;
150 }
151
152 /* allow immediate re-use */
Elliott Hughes6d8dd472012-01-17 18:27:41 -0800153 {
154 int one = 1;
155 if (setsockopt(netState->listenSock, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one)) < 0) {
156 PLOG(probe ? ERROR : FATAL) << "setsockopt(SO_REUSEADDR) failed";
157 goto fail;
158 }
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700159 }
160
161 union {
Elliott Hughes7b9d9962012-04-20 18:48:18 -0700162 sockaddr_in addrInet;
163 sockaddr addrPlain;
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700164 } addr;
165 addr.addrInet.sin_family = AF_INET;
166 addr.addrInet.sin_port = htons(port);
167 inet_aton("127.0.0.1", &addr.addrInet.sin_addr);
168
169 if (bind(netState->listenSock, &addr.addrPlain, sizeof(addr)) != 0) {
Elliott Hughes3d30d9b2011-12-07 17:35:48 -0800170 PLOG(probe ? ERROR : FATAL) << "Attempt to bind to port " << port << " failed";
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700171 goto fail;
172 }
173
174 netState->listenPort = port;
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700175
176 if (listen(netState->listenSock, 5) != 0) {
Elliott Hughes3d30d9b2011-12-07 17:35:48 -0800177 PLOG(probe ? ERROR : FATAL) << "Listen failed";
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700178 goto fail;
179 }
180
181 return netState;
182
183fail:
184 netShutdown(netState);
185 netFree(netState);
186 return NULL;
187}
188
189/*
190 * Shut down JDWP listener. Don't free state.
191 *
192 * Note that "netState" may be partially initialized if "startup" failed.
193 *
194 * This may be called from a non-JDWP thread as part of shutting the
195 * JDWP thread down.
196 *
197 * (This is currently called several times during startup as we probe
198 * for an open port.)
199 */
200static void netShutdown(JdwpNetState* netState) {
201 if (netState == NULL) {
202 return;
203 }
204
205 int listenSock = netState->listenSock;
206 int clientSock = netState->clientSock;
207
208 /* clear these out so it doesn't wake up and try to reuse them */
209 netState->listenSock = netState->clientSock = -1;
210
211 /* "shutdown" dislodges blocking read() and accept() calls */
212 if (listenSock >= 0) {
213 shutdown(listenSock, SHUT_RDWR);
214 close(listenSock);
215 }
216 if (clientSock >= 0) {
217 shutdown(clientSock, SHUT_RDWR);
218 close(clientSock);
219 }
220
221 /* if we might be sitting in select, kick us loose */
222 if (netState->wakePipe[1] >= 0) {
Elliott Hughes4dd9b4d2011-12-12 18:29:24 -0800223 VLOG(jdwp) << "+++ writing to wakePipe";
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700224 (void) write(netState->wakePipe[1], "", 1);
225 }
226}
227
228static void netShutdownExtern(JdwpState* state) {
229 netShutdown(state->netState);
230}
231
232/*
233 * Free JDWP state.
234 *
235 * Call this after shutting the network down with netShutdown().
236 */
237static void netFree(JdwpNetState* netState) {
238 if (netState == NULL) {
239 return;
240 }
241 CHECK_EQ(netState->listenSock, -1);
242 CHECK_EQ(netState->clientSock, -1);
243
244 if (netState->wakePipe[0] >= 0) {
245 close(netState->wakePipe[0]);
246 netState->wakePipe[0] = -1;
247 }
248 if (netState->wakePipe[1] >= 0) {
249 close(netState->wakePipe[1]);
250 netState->wakePipe[1] = -1;
251 }
252
253 delete netState;
254}
255
256static void netFreeExtern(JdwpState* state) {
257 netFree(state->netState);
258}
259
260/*
261 * Returns "true" if we're connected to a debugger.
262 */
263static bool isConnected(JdwpState* state) {
264 return (state->netState != NULL && state->netState->clientSock >= 0);
265}
266
267/*
268 * Returns "true" if the fd is ready, "false" if not.
269 */
270#if 0
271static bool isFdReadable(int sock)
272{
273 fd_set readfds;
Elliott Hughes7b9d9962012-04-20 18:48:18 -0700274 timeval tv;
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700275 int count;
276
277 FD_ZERO(&readfds);
278 FD_SET(sock, &readfds);
279
280 tv.tv_sec = 0;
281 tv.tv_usec = 0;
282 count = select(sock+1, &readfds, NULL, NULL, &tv);
283 if (count <= 0)
284 return false;
285
286 if (FD_ISSET(sock, &readfds)) /* make sure it's our fd */
287 return true;
288
289 LOG(ERROR) << "WEIRD: odd behavior in select (count=" << count << ")";
290 return false;
291}
292#endif
293
294#if 0
295/*
296 * Check to see if we have a pending connection from the debugger.
297 *
298 * Returns true on success (meaning a connection is available).
299 */
300static bool checkConnection(JdwpState* state) {
301 JdwpNetState* netState = state->netState;
302
303 CHECK_GE(netState->listenSock, 0);
304 /* not expecting to be called when debugger is actively connected */
305 CHECK_LT(netState->clientSock, 0);
306
307 if (!isFdReadable(netState->listenSock))
308 return false;
309 return true;
310}
311#endif
312
313/*
314 * Disable the TCP Nagle algorithm, which delays transmission of outbound
315 * packets until the previous transmissions have been acked. JDWP does a
316 * lot of back-and-forth with small packets, so this may help.
317 */
318static int setNoDelay(int fd)
319{
320 int on = 1;
321 int cc = setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &on, sizeof(on));
322 CHECK_EQ(cc, 0);
323 return cc;
324}
325
326/*
327 * Accept a connection. This will block waiting for somebody to show up.
328 * If that's not desirable, use checkConnection() to make sure something
329 * is pending.
330 */
331static bool acceptConnection(JdwpState* state)
332{
333 JdwpNetState* netState = state->netState;
334 union {
Elliott Hughes7b9d9962012-04-20 18:48:18 -0700335 sockaddr_in addrInet;
336 sockaddr addrPlain;
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700337 } addr;
338 socklen_t addrlen;
339 int sock;
340
341 if (netState->listenSock < 0) {
342 return false; /* you're not listening! */
343 }
344
345 CHECK_LT(netState->clientSock, 0); /* must not already be talking */
346
347 addrlen = sizeof(addr);
348 do {
349 sock = accept(netState->listenSock, &addr.addrPlain, &addrlen);
350 if (sock < 0 && errno != EINTR) {
351 // When we call shutdown() on the socket, accept() returns with
352 // EINVAL. Don't gripe about it.
353 if (errno == EINVAL) {
Elliott Hughes4dd9b4d2011-12-12 18:29:24 -0800354 if (VLOG_IS_ON(jdwp)) {
355 PLOG(ERROR) << "accept failed";
356 }
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700357 } else {
358 PLOG(ERROR) << "accept failed";
359 return false;
360 }
361 }
362 } while (sock < 0);
363
364 netState->remoteAddr = addr.addrInet.sin_addr;
365 netState->remotePort = ntohs(addr.addrInet.sin_port);
Elliott Hughes4dd9b4d2011-12-12 18:29:24 -0800366 VLOG(jdwp) << "+++ accepted connection from " << inet_ntoa(netState->remoteAddr) << ":" << netState->remotePort;
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700367
368 netState->clientSock = sock;
369 netState->awaitingHandshake = true;
370 netState->inputCount = 0;
371
Elliott Hughes4dd9b4d2011-12-12 18:29:24 -0800372 VLOG(jdwp) << "Setting TCP_NODELAY on accepted socket";
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700373 setNoDelay(netState->clientSock);
374
375 if (pipe(netState->wakePipe) < 0) {
376 PLOG(ERROR) << "pipe failed";
377 return false;
378 }
379
380 return true;
381}
382
383/*
384 * Create a connection to a waiting debugger.
385 */
386static bool establishConnection(JdwpState* state) {
387 union {
Elliott Hughes7b9d9962012-04-20 18:48:18 -0700388 sockaddr_in addrInet;
389 sockaddr addrPlain;
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700390 } addr;
Elliott Hughes7b9d9962012-04-20 18:48:18 -0700391 hostent* pEntry;
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700392
393 CHECK(state != NULL && state->netState != NULL);
Elliott Hughes376a7a02011-10-24 18:35:55 -0700394 CHECK(!state->options_->server);
395 CHECK(!state->options_->host.empty());
396 CHECK_NE(state->options_->port, 0);
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700397
398 /*
399 * Start by resolving the host name.
400 */
401//#undef HAVE_GETHOSTBYNAME_R
402//#warning "forcing non-R"
403#ifdef HAVE_GETHOSTBYNAME_R
Elliott Hughes7b9d9962012-04-20 18:48:18 -0700404 hostent he;
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700405 char auxBuf[128];
406 int error;
Elliott Hughes376a7a02011-10-24 18:35:55 -0700407 int cc = gethostbyname_r(state->options_->host.c_str(), &he, auxBuf, sizeof(auxBuf), &pEntry, &error);
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700408 if (cc != 0) {
Elliott Hughes376a7a02011-10-24 18:35:55 -0700409 LOG(WARNING) << "gethostbyname_r('" << state->options_->host << "') failed: " << hstrerror(error);
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700410 return false;
411 }
412#else
413 h_errno = 0;
Elliott Hughes376a7a02011-10-24 18:35:55 -0700414 pEntry = gethostbyname(state->options_->host.c_str());
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700415 if (pEntry == NULL) {
Elliott Hughes376a7a02011-10-24 18:35:55 -0700416 PLOG(WARNING) << "gethostbyname('" << state->options_->host << "') failed";
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700417 return false;
418 }
419#endif
420
421 /* copy it out ASAP to minimize risk of multithreaded annoyances */
422 memcpy(&addr.addrInet.sin_addr, pEntry->h_addr, pEntry->h_length);
423 addr.addrInet.sin_family = pEntry->h_addrtype;
424
Elliott Hughes376a7a02011-10-24 18:35:55 -0700425 addr.addrInet.sin_port = htons(state->options_->port);
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700426
427 LOG(INFO) << "Connecting out to " << inet_ntoa(addr.addrInet.sin_addr) << ":" << ntohs(addr.addrInet.sin_port);
428
429 /*
430 * Create a socket.
431 */
432 JdwpNetState* netState;
433 netState = state->netState;
434 netState->clientSock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
435 if (netState->clientSock < 0) {
436 PLOG(ERROR) << "Unable to create socket";
437 return false;
438 }
439
440 /*
441 * Try to connect.
442 */
443 if (connect(netState->clientSock, &addr.addrPlain, sizeof(addr)) != 0) {
444 PLOG(ERROR) << "Unable to connect to " << inet_ntoa(addr.addrInet.sin_addr) << ":" << ntohs(addr.addrInet.sin_port);
445 close(netState->clientSock);
446 netState->clientSock = -1;
447 return false;
448 }
449
Elliott Hughes376a7a02011-10-24 18:35:55 -0700450 LOG(INFO) << "Connection established to " << state->options_->host << " (" << inet_ntoa(addr.addrInet.sin_addr) << ":" << ntohs(addr.addrInet.sin_port) << ")";
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700451 netState->awaitingHandshake = true;
452 netState->inputCount = 0;
453
454 setNoDelay(netState->clientSock);
455
456 if (pipe(netState->wakePipe) < 0) {
457 PLOG(ERROR) << "pipe failed";
458 return false;
459 }
460
461 return true;
462}
463
464/*
465 * Close the connection to the debugger.
466 *
467 * Reset the state so we're ready to receive a new connection.
468 */
469static void closeConnection(JdwpState* state) {
470 JdwpNetState* netState;
471
472 CHECK(state != NULL && state->netState != NULL);
473
474 netState = state->netState;
475 if (netState->clientSock < 0) {
476 return;
477 }
478
Elliott Hughes4dd9b4d2011-12-12 18:29:24 -0800479 VLOG(jdwp) << "+++ closed connection to " << inet_ntoa(netState->remoteAddr) << ":" << netState->remotePort;
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700480
481 close(netState->clientSock);
482 netState->clientSock = -1;
483}
484
485/*
486 * Figure out if we have a full packet in the buffer.
487 */
488static bool haveFullPacket(JdwpNetState* netState) {
489 if (netState->awaitingHandshake) {
490 return (netState->inputCount >= (int) kMagicHandshakeLen);
491 }
492 if (netState->inputCount < 4) {
493 return false;
494 }
Elliott Hughesf7c3b662011-10-27 12:04:56 -0700495 long length = Get4BE(netState->inputBuffer);
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700496 return (netState->inputCount >= length);
497}
498
499/*
500 * Consume bytes from the buffer.
501 *
502 * This would be more efficient with a circular buffer. However, we're
503 * usually only going to find one packet, which is trivial to handle.
504 */
505static void consumeBytes(JdwpNetState* netState, int count) {
506 CHECK_GT(count, 0);
507 CHECK_LE(count, netState->inputCount);
508
509 if (count == netState->inputCount) {
510 netState->inputCount = 0;
511 return;
512 }
513
514 memmove(netState->inputBuffer, netState->inputBuffer + count, netState->inputCount - count);
515 netState->inputCount -= count;
516}
517
518/*
519 * Dump the contents of a packet to stdout.
520 */
521#if 0
Elliott Hughes376a7a02011-10-24 18:35:55 -0700522static void dumpPacket(const unsigned char* packetBuf) {
523 const unsigned char* buf = packetBuf;
524 uint32_t length, id;
525 uint8_t flags, cmdSet, cmd;
526 uint16_t error;
527 bool reply;
528 int dataLen;
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700529
Elliott Hughes376a7a02011-10-24 18:35:55 -0700530 cmd = cmdSet = 0xcc;
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700531
Elliott Hughesf7c3b662011-10-27 12:04:56 -0700532 length = Read4BE(&buf);
533 id = Read4BE(&buf);
534 flags = Read1(&buf);
Elliott Hughes376a7a02011-10-24 18:35:55 -0700535 if ((flags & kJDWPFlagReply) != 0) {
536 reply = true;
Elliott Hughesf7c3b662011-10-27 12:04:56 -0700537 error = Read2BE(&buf);
Elliott Hughes376a7a02011-10-24 18:35:55 -0700538 } else {
539 reply = false;
Elliott Hughesf7c3b662011-10-27 12:04:56 -0700540 cmdSet = Read1(&buf);
541 cmd = Read1(&buf);
Elliott Hughes376a7a02011-10-24 18:35:55 -0700542 }
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700543
Elliott Hughes376a7a02011-10-24 18:35:55 -0700544 dataLen = length - (buf - packetBuf);
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700545
Elliott Hughes4dd9b4d2011-12-12 18:29:24 -0800546 VLOG(jdwp) << StringPrintf("--- %s: dataLen=%u id=0x%08x flags=0x%02x cmd=%d/%d",
Elliott Hughesbfbf0e22012-03-29 18:09:19 -0700547 reply ? "reply" : "req", dataLen, id, flags, cmdSet, cmd);
548 VLOG(jdwp) << HexDump(buf, dataLen);
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700549}
550#endif
551
552/*
553 * Handle a packet. Returns "false" if we encounter a connection-fatal error.
554 */
Elliott Hughes376a7a02011-10-24 18:35:55 -0700555static bool handlePacket(JdwpState* state) {
556 JdwpNetState* netState = state->netState;
557 const unsigned char* buf = netState->inputBuffer;
558 JdwpReqHeader hdr;
559 uint32_t length, id;
560 uint8_t flags, cmdSet, cmd;
561 uint16_t error;
562 bool reply;
563 int dataLen;
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700564
Elliott Hughes376a7a02011-10-24 18:35:55 -0700565 cmd = cmdSet = 0; // shut up gcc
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700566
Elliott Hughes376a7a02011-10-24 18:35:55 -0700567 /*dumpPacket(netState->inputBuffer);*/
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700568
Elliott Hughesf7c3b662011-10-27 12:04:56 -0700569 length = Read4BE(&buf);
570 id = Read4BE(&buf);
571 flags = Read1(&buf);
Elliott Hughes376a7a02011-10-24 18:35:55 -0700572 if ((flags & kJDWPFlagReply) != 0) {
573 reply = true;
Elliott Hughesf7c3b662011-10-27 12:04:56 -0700574 error = Read2BE(&buf);
Elliott Hughes376a7a02011-10-24 18:35:55 -0700575 } else {
576 reply = false;
Elliott Hughesf7c3b662011-10-27 12:04:56 -0700577 cmdSet = Read1(&buf);
578 cmd = Read1(&buf);
Elliott Hughes376a7a02011-10-24 18:35:55 -0700579 }
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700580
Elliott Hughes376a7a02011-10-24 18:35:55 -0700581 CHECK_LE((int) length, netState->inputCount);
582 dataLen = length - (buf - netState->inputBuffer);
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700583
Elliott Hughes376a7a02011-10-24 18:35:55 -0700584 if (!reply) {
585 ExpandBuf* pReply = expandBufAlloc();
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700586
Elliott Hughes376a7a02011-10-24 18:35:55 -0700587 hdr.length = length;
588 hdr.id = id;
589 hdr.cmdSet = cmdSet;
590 hdr.cmd = cmd;
591 state->ProcessRequest(&hdr, buf, dataLen, pReply);
592 if (expandBufGetLength(pReply) > 0) {
593 ssize_t cc = netState->writePacket(pReply);
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700594
Elliott Hughes376a7a02011-10-24 18:35:55 -0700595 if (cc != (ssize_t) expandBufGetLength(pReply)) {
596 PLOG(ERROR) << "Failed sending reply to debugger";
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700597 expandBufFree(pReply);
Elliott Hughes376a7a02011-10-24 18:35:55 -0700598 return false;
599 }
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700600 } else {
Elliott Hughes376a7a02011-10-24 18:35:55 -0700601 LOG(WARNING) << "No reply created for set=" << cmdSet << " cmd=" << cmd;
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700602 }
Elliott Hughes376a7a02011-10-24 18:35:55 -0700603 expandBufFree(pReply);
604 } else {
605 LOG(ERROR) << "reply?!";
606 DCHECK(false);
607 }
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700608
Elliott Hughes4dd9b4d2011-12-12 18:29:24 -0800609 VLOG(jdwp) << "----------";
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700610
Elliott Hughes376a7a02011-10-24 18:35:55 -0700611 consumeBytes(netState, length);
612 return true;
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700613}
614
615/*
616 * Process incoming data. If no data is available, this will block until
617 * some arrives.
618 *
619 * If we get a full packet, handle it.
620 *
621 * To take some of the mystery out of life, we want to reject incoming
622 * connections if we already have a debugger attached. If we don't, the
623 * debugger will just mysteriously hang until it times out. We could just
624 * close the listen socket, but there's a good chance we won't be able to
625 * bind to the same port again, which would confuse utilities.
626 *
627 * Returns "false" on error (indicating that the connection has been severed),
628 * "true" if things are still okay.
629 */
630static bool processIncoming(JdwpState* state) {
631 JdwpNetState* netState = state->netState;
632 int readCount;
633
634 CHECK_GE(netState->clientSock, 0);
635
636 if (!haveFullPacket(netState)) {
637 /* read some more, looping until we have data */
638 errno = 0;
639 while (1) {
640 int selCount;
641 fd_set readfds;
642 int maxfd;
643 int fd;
644
645 maxfd = netState->listenSock;
646 if (netState->clientSock > maxfd) {
647 maxfd = netState->clientSock;
648 }
649 if (netState->wakePipe[0] > maxfd) {
650 maxfd = netState->wakePipe[0];
651 }
652
653 if (maxfd < 0) {
Elliott Hughes4dd9b4d2011-12-12 18:29:24 -0800654 VLOG(jdwp) << "+++ all fds are closed";
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700655 return false;
656 }
657
658 FD_ZERO(&readfds);
659
660 /* configure fds; note these may get zapped by another thread */
661 fd = netState->listenSock;
662 if (fd >= 0) {
663 FD_SET(fd, &readfds);
664 }
665 fd = netState->clientSock;
666 if (fd >= 0) {
667 FD_SET(fd, &readfds);
668 }
669 fd = netState->wakePipe[0];
670 if (fd >= 0) {
671 FD_SET(fd, &readfds);
672 } else {
673 LOG(INFO) << "NOTE: entering select w/o wakepipe";
674 }
675
676 /*
677 * Select blocks until it sees activity on the file descriptors.
678 * Closing the local file descriptor does not count as activity,
679 * so we can't rely on that to wake us up (it works for read()
680 * and accept(), but not select()).
681 *
682 * We can do one of three things: (1) send a signal and catch
683 * EINTR, (2) open an additional fd ("wakePipe") and write to
684 * it when it's time to exit, or (3) time out periodically and
685 * re-issue the select. We're currently using #2, as it's more
686 * reliable than #1 and generally better than #3. Wastes two fds.
687 */
688 selCount = select(maxfd+1, &readfds, NULL, NULL, NULL);
689 if (selCount < 0) {
690 if (errno == EINTR) {
691 continue;
692 }
693 PLOG(ERROR) << "select failed";
694 goto fail;
695 }
696
697 if (netState->wakePipe[0] >= 0 && FD_ISSET(netState->wakePipe[0], &readfds)) {
698 if (netState->listenSock >= 0) {
699 LOG(ERROR) << "Exit wake set, but not exiting?";
700 } else {
701 LOG(DEBUG) << "Got wake-up signal, bailing out of select";
702 }
703 goto fail;
704 }
705 if (netState->listenSock >= 0 && FD_ISSET(netState->listenSock, &readfds)) {
706 LOG(INFO) << "Ignoring second debugger -- accepting and dropping";
707 union {
Elliott Hughes7b9d9962012-04-20 18:48:18 -0700708 sockaddr_in addrInet;
709 sockaddr addrPlain;
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700710 } addr;
711 socklen_t addrlen;
712 int tmpSock;
713 tmpSock = accept(netState->listenSock, &addr.addrPlain, &addrlen);
714 if (tmpSock < 0) {
715 LOG(INFO) << "Weird -- accept failed";
716 } else {
717 close(tmpSock);
718 }
719 }
720 if (netState->clientSock >= 0 && FD_ISSET(netState->clientSock, &readfds)) {
721 readCount = read(netState->clientSock, netState->inputBuffer + netState->inputCount, sizeof(netState->inputBuffer) - netState->inputCount);
722 if (readCount < 0) {
723 /* read failed */
724 if (errno != EINTR) {
725 goto fail;
726 }
727 LOG(DEBUG) << "+++ EINTR hit";
728 return true;
729 } else if (readCount == 0) {
730 /* EOF hit -- far end went away */
731 LOG(DEBUG) << "+++ peer disconnected";
732 goto fail;
733 } else {
734 break;
735 }
736 }
737 }
738
739 netState->inputCount += readCount;
740 if (!haveFullPacket(netState)) {
741 return true; /* still not there yet */
742 }
743 }
744
745 /*
746 * Special-case the initial handshake. For some bizarre reason we're
747 * expected to emulate bad tty settings by echoing the request back
748 * exactly as it was sent. Note the handshake is always initiated by
749 * the debugger, no matter who connects to whom.
750 *
751 * Other than this one case, the protocol [claims to be] stateless.
752 */
753 if (netState->awaitingHandshake) {
754 int cc;
755
756 if (memcmp(netState->inputBuffer, kMagicHandshake, kMagicHandshakeLen) != 0) {
757 LOG(ERROR) << StringPrintf("ERROR: bad handshake '%.14s'", netState->inputBuffer);
758 goto fail;
759 }
760
761 errno = 0;
762 cc = write(netState->clientSock, netState->inputBuffer, kMagicHandshakeLen);
763 if (cc != kMagicHandshakeLen) {
764 PLOG(ERROR) << "Failed writing handshake bytes (" << cc << " of " << kMagicHandshakeLen << ")";
765 goto fail;
766 }
767
768 consumeBytes(netState, kMagicHandshakeLen);
769 netState->awaitingHandshake = false;
Elliott Hughes4dd9b4d2011-12-12 18:29:24 -0800770 VLOG(jdwp) << "+++ handshake complete";
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700771 return true;
772 }
773
774 /*
775 * Handle this packet.
776 */
777 return handlePacket(state);
778
779fail:
780 closeConnection(state);
781 return false;
782}
783
784/*
785 * Send a request.
786 *
787 * The entire packet must be sent with a single write() call to avoid
788 * threading issues.
789 *
790 * Returns "true" if it was sent successfully.
791 */
792static bool sendRequest(JdwpState* state, ExpandBuf* pReq) {
793 JdwpNetState* netState = state->netState;
794
795 /*dumpPacket(expandBufGetBuffer(pReq));*/
796 if (netState->clientSock < 0) {
797 /* can happen with some DDMS events */
Elliott Hughes4dd9b4d2011-12-12 18:29:24 -0800798 VLOG(jdwp) << "NOT sending request -- no debugger is attached";
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700799 return false;
800 }
801
802 errno = 0;
803 ssize_t cc = netState->writePacket(pReq);
804
805 if (cc != (ssize_t) expandBufGetLength(pReq)) {
806 PLOG(ERROR) << "Failed sending req to debugger (" << cc << " of " << expandBufGetLength(pReq) << ")";
807 return false;
808 }
809
810 return true;
811}
812
813/*
814 * Send a request that was split into multiple buffers.
815 *
816 * The entire packet must be sent with a single writev() call to avoid
817 * threading issues.
818 *
819 * Returns "true" if it was sent successfully.
820 */
Elliott Hughescccd84f2011-12-05 16:51:54 -0800821static bool sendBufferedRequest(JdwpState* state, const iovec* iov, int iov_count) {
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700822 JdwpNetState* netState = state->netState;
823
824 if (netState->clientSock < 0) {
825 /* can happen with some DDMS events */
Elliott Hughes4dd9b4d2011-12-12 18:29:24 -0800826 VLOG(jdwp) << "NOT sending request -- no debugger is attached";
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700827 return false;
828 }
829
830 size_t expected = 0;
Elliott Hughescccd84f2011-12-05 16:51:54 -0800831 for (int i = 0; i < iov_count; i++) {
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700832 expected += iov[i].iov_len;
833 }
834
Elliott Hughescccd84f2011-12-05 16:51:54 -0800835 ssize_t actual = netState->writeBufferedPacket(iov, iov_count);
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700836
837 if ((size_t)actual != expected) {
838 PLOG(ERROR) << "Failed sending b-req to debugger (" << actual << " of " << expected << ")";
839 return false;
840 }
841
842 return true;
843}
844
845/*
846 * Our functions.
847 *
848 * We can't generally share the implementations with other transports,
849 * even if they're also socket-based, because our JdwpNetState will be
850 * different from theirs.
851 */
852static const JdwpTransport socketTransport = {
853 prepareSocket,
854 acceptConnection,
855 establishConnection,
856 closeConnection,
857 netShutdownExtern,
858 netFreeExtern,
859 isConnected,
860 awaitingHandshake,
861 processIncoming,
862 sendRequest,
863 sendBufferedRequest,
864};
865
866/*
867 * Return our set.
868 */
869const JdwpTransport* SocketTransport() {
870 return &socketTransport;
871}
872
873} // namespace JDWP
874
875} // namespace art