blob: aba893de9afe9ecc60f9d1ff184f5b9cd5dd12f3 [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 {
58 short listenPort;
59 int listenSock; /* listen for connection from debugger */
60 int wakePipe[2]; /* break out of select */
61
62 struct in_addr remoteAddr;
63 unsigned short remotePort;
64
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
83static JdwpNetState* netStartup(short port);
84
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 Hughes872d4ec2011-10-21 17:07:15 -070089 unsigned short port;
90
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 Hughes376a7a02011-10-24 18:35:55 -070094 port = options->port;
Elliott Hughes872d4ec2011-10-21 17:07:15 -070095 state->netState = netStartup(port);
96 } else {
97 /* scan through a range of ports, binding to the first available */
98 for (port = kBasePort; port <= kMaxPort; port++) {
99 state->netState = netStartup(port);
100 if (state->netState != NULL) {
101 break;
102 }
103 }
104 }
105 if (state->netState == NULL) {
Elliott Hughes376a7a02011-10-24 18:35:55 -0700106 LOG(ERROR) << "JDWP net startup failed (req port=" << options->port << ")";
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700107 return false;
108 }
109 } else {
Elliott Hughes376a7a02011-10-24 18:35:55 -0700110 port = options->port; // used in a debug msg later
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700111 state->netState = netStartup(-1);
112 }
113
Elliott Hughes376a7a02011-10-24 18:35:55 -0700114 if (options->suspend) {
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700115 LOG(INFO) << "JDWP will wait for debugger on port " << port;
116 } else {
Elliott Hughes376a7a02011-10-24 18:35:55 -0700117 LOG(INFO) << "JDWP will " << (options->server ? "listen" : "connect") << " on port " << port;
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700118 }
119
120 return true;
121}
122
123/*
124 * Are we still waiting for the handshake string?
125 */
126static bool awaitingHandshake(JdwpState* state) {
127 return state->netState->awaitingHandshake;
128}
129
130/*
131 * Initialize JDWP stuff.
132 *
133 * Allocates a new state structure. If "port" is non-negative, this also
134 * tries to bind to a listen port. If "port" is less than zero, we assume
135 * we're preparing for an outbound connection, and return without binding
136 * to anything.
137 *
138 * This may be called several times if we're probing for a port.
139 *
140 * Returns 0 on success.
141 */
142static JdwpNetState* netStartup(short port) {
143 int one = 1;
144 JdwpNetState* netState = new JdwpNetState;
145
146 if (port < 0) {
147 return netState;
148 }
149
150 CHECK_NE(port, 0);
151
152 netState->listenSock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
153 if (netState->listenSock < 0) {
154 PLOG(ERROR) << "Socket create failed";
155 goto fail;
156 }
157
158 /* allow immediate re-use */
159 if (setsockopt(netState->listenSock, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one)) < 0) {
160 PLOG(ERROR) << "setsockopt(SO_REUSEADDR) failed";
161 goto fail;
162 }
163
164 union {
165 struct sockaddr_in addrInet;
166 struct sockaddr addrPlain;
167 } addr;
168 addr.addrInet.sin_family = AF_INET;
169 addr.addrInet.sin_port = htons(port);
170 inet_aton("127.0.0.1", &addr.addrInet.sin_addr);
171
172 if (bind(netState->listenSock, &addr.addrPlain, sizeof(addr)) != 0) {
173 PLOG(VERBOSE) << "attempt to bind to port " << port << " failed";
174 goto fail;
175 }
176
177 netState->listenPort = port;
178 LOG(VERBOSE) << "+++ bound to port " << netState->listenPort;
179
180 if (listen(netState->listenSock, 5) != 0) {
181 PLOG(ERROR) << "Listen failed";
182 goto fail;
183 }
184
185 return netState;
186
187fail:
188 netShutdown(netState);
189 netFree(netState);
190 return NULL;
191}
192
193/*
194 * Shut down JDWP listener. Don't free state.
195 *
196 * Note that "netState" may be partially initialized if "startup" failed.
197 *
198 * This may be called from a non-JDWP thread as part of shutting the
199 * JDWP thread down.
200 *
201 * (This is currently called several times during startup as we probe
202 * for an open port.)
203 */
204static void netShutdown(JdwpNetState* netState) {
205 if (netState == NULL) {
206 return;
207 }
208
209 int listenSock = netState->listenSock;
210 int clientSock = netState->clientSock;
211
212 /* clear these out so it doesn't wake up and try to reuse them */
213 netState->listenSock = netState->clientSock = -1;
214
215 /* "shutdown" dislodges blocking read() and accept() calls */
216 if (listenSock >= 0) {
217 shutdown(listenSock, SHUT_RDWR);
218 close(listenSock);
219 }
220 if (clientSock >= 0) {
221 shutdown(clientSock, SHUT_RDWR);
222 close(clientSock);
223 }
224
225 /* if we might be sitting in select, kick us loose */
226 if (netState->wakePipe[1] >= 0) {
227 LOG(VERBOSE) << "+++ writing to wakePipe";
228 (void) write(netState->wakePipe[1], "", 1);
229 }
230}
231
232static void netShutdownExtern(JdwpState* state) {
233 netShutdown(state->netState);
234}
235
236/*
237 * Free JDWP state.
238 *
239 * Call this after shutting the network down with netShutdown().
240 */
241static void netFree(JdwpNetState* netState) {
242 if (netState == NULL) {
243 return;
244 }
245 CHECK_EQ(netState->listenSock, -1);
246 CHECK_EQ(netState->clientSock, -1);
247
248 if (netState->wakePipe[0] >= 0) {
249 close(netState->wakePipe[0]);
250 netState->wakePipe[0] = -1;
251 }
252 if (netState->wakePipe[1] >= 0) {
253 close(netState->wakePipe[1]);
254 netState->wakePipe[1] = -1;
255 }
256
257 delete netState;
258}
259
260static void netFreeExtern(JdwpState* state) {
261 netFree(state->netState);
262}
263
264/*
265 * Returns "true" if we're connected to a debugger.
266 */
267static bool isConnected(JdwpState* state) {
268 return (state->netState != NULL && state->netState->clientSock >= 0);
269}
270
271/*
272 * Returns "true" if the fd is ready, "false" if not.
273 */
274#if 0
275static bool isFdReadable(int sock)
276{
277 fd_set readfds;
278 struct timeval tv;
279 int count;
280
281 FD_ZERO(&readfds);
282 FD_SET(sock, &readfds);
283
284 tv.tv_sec = 0;
285 tv.tv_usec = 0;
286 count = select(sock+1, &readfds, NULL, NULL, &tv);
287 if (count <= 0)
288 return false;
289
290 if (FD_ISSET(sock, &readfds)) /* make sure it's our fd */
291 return true;
292
293 LOG(ERROR) << "WEIRD: odd behavior in select (count=" << count << ")";
294 return false;
295}
296#endif
297
298#if 0
299/*
300 * Check to see if we have a pending connection from the debugger.
301 *
302 * Returns true on success (meaning a connection is available).
303 */
304static bool checkConnection(JdwpState* state) {
305 JdwpNetState* netState = state->netState;
306
307 CHECK_GE(netState->listenSock, 0);
308 /* not expecting to be called when debugger is actively connected */
309 CHECK_LT(netState->clientSock, 0);
310
311 if (!isFdReadable(netState->listenSock))
312 return false;
313 return true;
314}
315#endif
316
317/*
318 * Disable the TCP Nagle algorithm, which delays transmission of outbound
319 * packets until the previous transmissions have been acked. JDWP does a
320 * lot of back-and-forth with small packets, so this may help.
321 */
322static int setNoDelay(int fd)
323{
324 int on = 1;
325 int cc = setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &on, sizeof(on));
326 CHECK_EQ(cc, 0);
327 return cc;
328}
329
330/*
331 * Accept a connection. This will block waiting for somebody to show up.
332 * If that's not desirable, use checkConnection() to make sure something
333 * is pending.
334 */
335static bool acceptConnection(JdwpState* state)
336{
337 JdwpNetState* netState = state->netState;
338 union {
339 struct sockaddr_in addrInet;
340 struct sockaddr addrPlain;
341 } addr;
342 socklen_t addrlen;
343 int sock;
344
345 if (netState->listenSock < 0) {
346 return false; /* you're not listening! */
347 }
348
349 CHECK_LT(netState->clientSock, 0); /* must not already be talking */
350
351 addrlen = sizeof(addr);
352 do {
353 sock = accept(netState->listenSock, &addr.addrPlain, &addrlen);
354 if (sock < 0 && errno != EINTR) {
355 // When we call shutdown() on the socket, accept() returns with
356 // EINVAL. Don't gripe about it.
357 if (errno == EINVAL) {
358 PLOG(VERBOSE) << "accept failed";
359 } else {
360 PLOG(ERROR) << "accept failed";
361 return false;
362 }
363 }
364 } while (sock < 0);
365
366 netState->remoteAddr = addr.addrInet.sin_addr;
367 netState->remotePort = ntohs(addr.addrInet.sin_port);
368 LOG(VERBOSE) << "+++ accepted connection from " << inet_ntoa(netState->remoteAddr) << ":" << netState->remotePort;
369
370 netState->clientSock = sock;
371 netState->awaitingHandshake = true;
372 netState->inputCount = 0;
373
374 LOG(VERBOSE) << "Setting TCP_NODELAY on accepted socket";
375 setNoDelay(netState->clientSock);
376
377 if (pipe(netState->wakePipe) < 0) {
378 PLOG(ERROR) << "pipe failed";
379 return false;
380 }
381
382 return true;
383}
384
385/*
386 * Create a connection to a waiting debugger.
387 */
388static bool establishConnection(JdwpState* state) {
389 union {
390 struct sockaddr_in addrInet;
391 struct sockaddr addrPlain;
392 } addr;
393 struct hostent* pEntry;
394
395 CHECK(state != NULL && state->netState != NULL);
Elliott Hughes376a7a02011-10-24 18:35:55 -0700396 CHECK(!state->options_->server);
397 CHECK(!state->options_->host.empty());
398 CHECK_NE(state->options_->port, 0);
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700399
400 /*
401 * Start by resolving the host name.
402 */
403//#undef HAVE_GETHOSTBYNAME_R
404//#warning "forcing non-R"
405#ifdef HAVE_GETHOSTBYNAME_R
406 struct hostent he;
407 char auxBuf[128];
408 int error;
Elliott Hughes376a7a02011-10-24 18:35:55 -0700409 int cc = gethostbyname_r(state->options_->host.c_str(), &he, auxBuf, sizeof(auxBuf), &pEntry, &error);
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700410 if (cc != 0) {
Elliott Hughes376a7a02011-10-24 18:35:55 -0700411 LOG(WARNING) << "gethostbyname_r('" << state->options_->host << "') failed: " << hstrerror(error);
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700412 return false;
413 }
414#else
415 h_errno = 0;
Elliott Hughes376a7a02011-10-24 18:35:55 -0700416 pEntry = gethostbyname(state->options_->host.c_str());
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700417 if (pEntry == NULL) {
Elliott Hughes376a7a02011-10-24 18:35:55 -0700418 PLOG(WARNING) << "gethostbyname('" << state->options_->host << "') failed";
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700419 return false;
420 }
421#endif
422
423 /* copy it out ASAP to minimize risk of multithreaded annoyances */
424 memcpy(&addr.addrInet.sin_addr, pEntry->h_addr, pEntry->h_length);
425 addr.addrInet.sin_family = pEntry->h_addrtype;
426
Elliott Hughes376a7a02011-10-24 18:35:55 -0700427 addr.addrInet.sin_port = htons(state->options_->port);
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700428
429 LOG(INFO) << "Connecting out to " << inet_ntoa(addr.addrInet.sin_addr) << ":" << ntohs(addr.addrInet.sin_port);
430
431 /*
432 * Create a socket.
433 */
434 JdwpNetState* netState;
435 netState = state->netState;
436 netState->clientSock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
437 if (netState->clientSock < 0) {
438 PLOG(ERROR) << "Unable to create socket";
439 return false;
440 }
441
442 /*
443 * Try to connect.
444 */
445 if (connect(netState->clientSock, &addr.addrPlain, sizeof(addr)) != 0) {
446 PLOG(ERROR) << "Unable to connect to " << inet_ntoa(addr.addrInet.sin_addr) << ":" << ntohs(addr.addrInet.sin_port);
447 close(netState->clientSock);
448 netState->clientSock = -1;
449 return false;
450 }
451
Elliott Hughes376a7a02011-10-24 18:35:55 -0700452 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 -0700453 netState->awaitingHandshake = true;
454 netState->inputCount = 0;
455
456 setNoDelay(netState->clientSock);
457
458 if (pipe(netState->wakePipe) < 0) {
459 PLOG(ERROR) << "pipe failed";
460 return false;
461 }
462
463 return true;
464}
465
466/*
467 * Close the connection to the debugger.
468 *
469 * Reset the state so we're ready to receive a new connection.
470 */
471static void closeConnection(JdwpState* state) {
472 JdwpNetState* netState;
473
474 CHECK(state != NULL && state->netState != NULL);
475
476 netState = state->netState;
477 if (netState->clientSock < 0) {
478 return;
479 }
480
481 LOG(VERBOSE) << "+++ closed connection to " << inet_ntoa(netState->remoteAddr) << ":" << netState->remotePort;
482
483 close(netState->clientSock);
484 netState->clientSock = -1;
485}
486
487/*
488 * Figure out if we have a full packet in the buffer.
489 */
490static bool haveFullPacket(JdwpNetState* netState) {
491 if (netState->awaitingHandshake) {
492 return (netState->inputCount >= (int) kMagicHandshakeLen);
493 }
494 if (netState->inputCount < 4) {
495 return false;
496 }
Elliott Hughesf7c3b662011-10-27 12:04:56 -0700497 long length = Get4BE(netState->inputBuffer);
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700498 return (netState->inputCount >= length);
499}
500
501/*
502 * Consume bytes from the buffer.
503 *
504 * This would be more efficient with a circular buffer. However, we're
505 * usually only going to find one packet, which is trivial to handle.
506 */
507static void consumeBytes(JdwpNetState* netState, int count) {
508 CHECK_GT(count, 0);
509 CHECK_LE(count, netState->inputCount);
510
511 if (count == netState->inputCount) {
512 netState->inputCount = 0;
513 return;
514 }
515
516 memmove(netState->inputBuffer, netState->inputBuffer + count, netState->inputCount - count);
517 netState->inputCount -= count;
518}
519
520/*
521 * Dump the contents of a packet to stdout.
522 */
523#if 0
Elliott Hughes376a7a02011-10-24 18:35:55 -0700524static void dumpPacket(const unsigned char* packetBuf) {
525 const unsigned char* buf = packetBuf;
526 uint32_t length, id;
527 uint8_t flags, cmdSet, cmd;
528 uint16_t error;
529 bool reply;
530 int dataLen;
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700531
Elliott Hughes376a7a02011-10-24 18:35:55 -0700532 cmd = cmdSet = 0xcc;
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700533
Elliott Hughesf7c3b662011-10-27 12:04:56 -0700534 length = Read4BE(&buf);
535 id = Read4BE(&buf);
536 flags = Read1(&buf);
Elliott Hughes376a7a02011-10-24 18:35:55 -0700537 if ((flags & kJDWPFlagReply) != 0) {
538 reply = true;
Elliott Hughesf7c3b662011-10-27 12:04:56 -0700539 error = Read2BE(&buf);
Elliott Hughes376a7a02011-10-24 18:35:55 -0700540 } else {
541 reply = false;
Elliott Hughesf7c3b662011-10-27 12:04:56 -0700542 cmdSet = Read1(&buf);
543 cmd = Read1(&buf);
Elliott Hughes376a7a02011-10-24 18:35:55 -0700544 }
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700545
Elliott Hughes376a7a02011-10-24 18:35:55 -0700546 dataLen = length - (buf - packetBuf);
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700547
Elliott Hughes376a7a02011-10-24 18:35:55 -0700548 LOG(VERBOSE) << StringPrintf("--- %s: dataLen=%u id=0x%08x flags=0x%02x cmd=%d/%d",
549 reply ? "reply" : "req", dataLen, id, flags, cmdSet, cmd);
550 if (dataLen > 0) {
551 HexDump(buf, dataLen);
552 }
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700553}
554#endif
555
556/*
557 * Handle a packet. Returns "false" if we encounter a connection-fatal error.
558 */
Elliott Hughes376a7a02011-10-24 18:35:55 -0700559static bool handlePacket(JdwpState* state) {
560 JdwpNetState* netState = state->netState;
561 const unsigned char* buf = netState->inputBuffer;
562 JdwpReqHeader hdr;
563 uint32_t length, id;
564 uint8_t flags, cmdSet, cmd;
565 uint16_t error;
566 bool reply;
567 int dataLen;
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700568
Elliott Hughes376a7a02011-10-24 18:35:55 -0700569 cmd = cmdSet = 0; // shut up gcc
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700570
Elliott Hughes376a7a02011-10-24 18:35:55 -0700571 /*dumpPacket(netState->inputBuffer);*/
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700572
Elliott Hughesf7c3b662011-10-27 12:04:56 -0700573 length = Read4BE(&buf);
574 id = Read4BE(&buf);
575 flags = Read1(&buf);
Elliott Hughes376a7a02011-10-24 18:35:55 -0700576 if ((flags & kJDWPFlagReply) != 0) {
577 reply = true;
Elliott Hughesf7c3b662011-10-27 12:04:56 -0700578 error = Read2BE(&buf);
Elliott Hughes376a7a02011-10-24 18:35:55 -0700579 } else {
580 reply = false;
Elliott Hughesf7c3b662011-10-27 12:04:56 -0700581 cmdSet = Read1(&buf);
582 cmd = Read1(&buf);
Elliott Hughes376a7a02011-10-24 18:35:55 -0700583 }
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700584
Elliott Hughes376a7a02011-10-24 18:35:55 -0700585 CHECK_LE((int) length, netState->inputCount);
586 dataLen = length - (buf - netState->inputBuffer);
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700587
Elliott Hughes376a7a02011-10-24 18:35:55 -0700588 if (!reply) {
589 ExpandBuf* pReply = expandBufAlloc();
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700590
Elliott Hughes376a7a02011-10-24 18:35:55 -0700591 hdr.length = length;
592 hdr.id = id;
593 hdr.cmdSet = cmdSet;
594 hdr.cmd = cmd;
595 state->ProcessRequest(&hdr, buf, dataLen, pReply);
596 if (expandBufGetLength(pReply) > 0) {
597 ssize_t cc = netState->writePacket(pReply);
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700598
Elliott Hughes376a7a02011-10-24 18:35:55 -0700599 if (cc != (ssize_t) expandBufGetLength(pReply)) {
600 PLOG(ERROR) << "Failed sending reply to debugger";
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700601 expandBufFree(pReply);
Elliott Hughes376a7a02011-10-24 18:35:55 -0700602 return false;
603 }
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700604 } else {
Elliott Hughes376a7a02011-10-24 18:35:55 -0700605 LOG(WARNING) << "No reply created for set=" << cmdSet << " cmd=" << cmd;
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700606 }
Elliott Hughes376a7a02011-10-24 18:35:55 -0700607 expandBufFree(pReply);
608 } else {
609 LOG(ERROR) << "reply?!";
610 DCHECK(false);
611 }
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700612
Elliott Hughes376a7a02011-10-24 18:35:55 -0700613 LOG(VERBOSE) << "----------";
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700614
Elliott Hughes376a7a02011-10-24 18:35:55 -0700615 consumeBytes(netState, length);
616 return true;
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700617}
618
619/*
620 * Process incoming data. If no data is available, this will block until
621 * some arrives.
622 *
623 * If we get a full packet, handle it.
624 *
625 * To take some of the mystery out of life, we want to reject incoming
626 * connections if we already have a debugger attached. If we don't, the
627 * debugger will just mysteriously hang until it times out. We could just
628 * close the listen socket, but there's a good chance we won't be able to
629 * bind to the same port again, which would confuse utilities.
630 *
631 * Returns "false" on error (indicating that the connection has been severed),
632 * "true" if things are still okay.
633 */
634static bool processIncoming(JdwpState* state) {
635 JdwpNetState* netState = state->netState;
636 int readCount;
637
638 CHECK_GE(netState->clientSock, 0);
639
640 if (!haveFullPacket(netState)) {
641 /* read some more, looping until we have data */
642 errno = 0;
643 while (1) {
644 int selCount;
645 fd_set readfds;
646 int maxfd;
647 int fd;
648
649 maxfd = netState->listenSock;
650 if (netState->clientSock > maxfd) {
651 maxfd = netState->clientSock;
652 }
653 if (netState->wakePipe[0] > maxfd) {
654 maxfd = netState->wakePipe[0];
655 }
656
657 if (maxfd < 0) {
658 LOG(VERBOSE) << "+++ all fds are closed";
659 return false;
660 }
661
662 FD_ZERO(&readfds);
663
664 /* configure fds; note these may get zapped by another thread */
665 fd = netState->listenSock;
666 if (fd >= 0) {
667 FD_SET(fd, &readfds);
668 }
669 fd = netState->clientSock;
670 if (fd >= 0) {
671 FD_SET(fd, &readfds);
672 }
673 fd = netState->wakePipe[0];
674 if (fd >= 0) {
675 FD_SET(fd, &readfds);
676 } else {
677 LOG(INFO) << "NOTE: entering select w/o wakepipe";
678 }
679
680 /*
681 * Select blocks until it sees activity on the file descriptors.
682 * Closing the local file descriptor does not count as activity,
683 * so we can't rely on that to wake us up (it works for read()
684 * and accept(), but not select()).
685 *
686 * We can do one of three things: (1) send a signal and catch
687 * EINTR, (2) open an additional fd ("wakePipe") and write to
688 * it when it's time to exit, or (3) time out periodically and
689 * re-issue the select. We're currently using #2, as it's more
690 * reliable than #1 and generally better than #3. Wastes two fds.
691 */
692 selCount = select(maxfd+1, &readfds, NULL, NULL, NULL);
693 if (selCount < 0) {
694 if (errno == EINTR) {
695 continue;
696 }
697 PLOG(ERROR) << "select failed";
698 goto fail;
699 }
700
701 if (netState->wakePipe[0] >= 0 && FD_ISSET(netState->wakePipe[0], &readfds)) {
702 if (netState->listenSock >= 0) {
703 LOG(ERROR) << "Exit wake set, but not exiting?";
704 } else {
705 LOG(DEBUG) << "Got wake-up signal, bailing out of select";
706 }
707 goto fail;
708 }
709 if (netState->listenSock >= 0 && FD_ISSET(netState->listenSock, &readfds)) {
710 LOG(INFO) << "Ignoring second debugger -- accepting and dropping";
711 union {
712 struct sockaddr_in addrInet;
713 struct sockaddr addrPlain;
714 } addr;
715 socklen_t addrlen;
716 int tmpSock;
717 tmpSock = accept(netState->listenSock, &addr.addrPlain, &addrlen);
718 if (tmpSock < 0) {
719 LOG(INFO) << "Weird -- accept failed";
720 } else {
721 close(tmpSock);
722 }
723 }
724 if (netState->clientSock >= 0 && FD_ISSET(netState->clientSock, &readfds)) {
725 readCount = read(netState->clientSock, netState->inputBuffer + netState->inputCount, sizeof(netState->inputBuffer) - netState->inputCount);
726 if (readCount < 0) {
727 /* read failed */
728 if (errno != EINTR) {
729 goto fail;
730 }
731 LOG(DEBUG) << "+++ EINTR hit";
732 return true;
733 } else if (readCount == 0) {
734 /* EOF hit -- far end went away */
735 LOG(DEBUG) << "+++ peer disconnected";
736 goto fail;
737 } else {
738 break;
739 }
740 }
741 }
742
743 netState->inputCount += readCount;
744 if (!haveFullPacket(netState)) {
745 return true; /* still not there yet */
746 }
747 }
748
749 /*
750 * Special-case the initial handshake. For some bizarre reason we're
751 * expected to emulate bad tty settings by echoing the request back
752 * exactly as it was sent. Note the handshake is always initiated by
753 * the debugger, no matter who connects to whom.
754 *
755 * Other than this one case, the protocol [claims to be] stateless.
756 */
757 if (netState->awaitingHandshake) {
758 int cc;
759
760 if (memcmp(netState->inputBuffer, kMagicHandshake, kMagicHandshakeLen) != 0) {
761 LOG(ERROR) << StringPrintf("ERROR: bad handshake '%.14s'", netState->inputBuffer);
762 goto fail;
763 }
764
765 errno = 0;
766 cc = write(netState->clientSock, netState->inputBuffer, kMagicHandshakeLen);
767 if (cc != kMagicHandshakeLen) {
768 PLOG(ERROR) << "Failed writing handshake bytes (" << cc << " of " << kMagicHandshakeLen << ")";
769 goto fail;
770 }
771
772 consumeBytes(netState, kMagicHandshakeLen);
773 netState->awaitingHandshake = false;
774 LOG(VERBOSE) << "+++ handshake complete";
775 return true;
776 }
777
778 /*
779 * Handle this packet.
780 */
781 return handlePacket(state);
782
783fail:
784 closeConnection(state);
785 return false;
786}
787
788/*
789 * Send a request.
790 *
791 * The entire packet must be sent with a single write() call to avoid
792 * threading issues.
793 *
794 * Returns "true" if it was sent successfully.
795 */
796static bool sendRequest(JdwpState* state, ExpandBuf* pReq) {
797 JdwpNetState* netState = state->netState;
798
799 /*dumpPacket(expandBufGetBuffer(pReq));*/
800 if (netState->clientSock < 0) {
801 /* can happen with some DDMS events */
802 LOG(VERBOSE) << "NOT sending request -- no debugger is attached";
803 return false;
804 }
805
806 errno = 0;
807 ssize_t cc = netState->writePacket(pReq);
808
809 if (cc != (ssize_t) expandBufGetLength(pReq)) {
810 PLOG(ERROR) << "Failed sending req to debugger (" << cc << " of " << expandBufGetLength(pReq) << ")";
811 return false;
812 }
813
814 return true;
815}
816
817/*
818 * Send a request that was split into multiple buffers.
819 *
820 * The entire packet must be sent with a single writev() call to avoid
821 * threading issues.
822 *
823 * Returns "true" if it was sent successfully.
824 */
825static bool sendBufferedRequest(JdwpState* state, const iovec* iov, int iovcnt) {
826 JdwpNetState* netState = state->netState;
827
828 if (netState->clientSock < 0) {
829 /* can happen with some DDMS events */
830 LOG(VERBOSE) << "NOT sending request -- no debugger is attached";
831 return false;
832 }
833
834 size_t expected = 0;
835 for (int i = 0; i < iovcnt; i++) {
836 expected += iov[i].iov_len;
837 }
838
839 ssize_t actual = netState->writeBufferedPacket(iov, iovcnt);
840
841 if ((size_t)actual != expected) {
842 PLOG(ERROR) << "Failed sending b-req to debugger (" << actual << " of " << expected << ")";
843 return false;
844 }
845
846 return true;
847}
848
849/*
850 * Our functions.
851 *
852 * We can't generally share the implementations with other transports,
853 * even if they're also socket-based, because our JdwpNetState will be
854 * different from theirs.
855 */
856static const JdwpTransport socketTransport = {
857 prepareSocket,
858 acceptConnection,
859 establishConnection,
860 closeConnection,
861 netShutdownExtern,
862 netFreeExtern,
863 isConnected,
864 awaitingHandshake,
865 processIncoming,
866 sendRequest,
867 sendBufferedRequest,
868};
869
870/*
871 * Return our set.
872 */
873const JdwpTransport* SocketTransport() {
874 return &socketTransport;
875}
876
877} // namespace JDWP
878
879} // namespace art