blob: 01eba12bb7193af19a9054c3cc2d1a4859db7330 [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;
Elliott Hughes376a7a02011-10-24 18:35:55 -0700561 bool reply;
562 int dataLen;
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700563
Elliott Hughes376a7a02011-10-24 18:35:55 -0700564 cmd = cmdSet = 0; // shut up gcc
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700565
Elliott Hughes376a7a02011-10-24 18:35:55 -0700566 /*dumpPacket(netState->inputBuffer);*/
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700567
Elliott Hughesf7c3b662011-10-27 12:04:56 -0700568 length = Read4BE(&buf);
569 id = Read4BE(&buf);
570 flags = Read1(&buf);
Elliott Hughes376a7a02011-10-24 18:35:55 -0700571 if ((flags & kJDWPFlagReply) != 0) {
572 reply = true;
Brian Carlstromfd2ec542012-05-02 15:08:57 -0700573 Read2BE(&buf); // error
Elliott Hughes376a7a02011-10-24 18:35:55 -0700574 } else {
575 reply = false;
Elliott Hughesf7c3b662011-10-27 12:04:56 -0700576 cmdSet = Read1(&buf);
577 cmd = Read1(&buf);
Elliott Hughes376a7a02011-10-24 18:35:55 -0700578 }
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700579
Elliott Hughes376a7a02011-10-24 18:35:55 -0700580 CHECK_LE((int) length, netState->inputCount);
581 dataLen = length - (buf - netState->inputBuffer);
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700582
Elliott Hughes376a7a02011-10-24 18:35:55 -0700583 if (!reply) {
584 ExpandBuf* pReply = expandBufAlloc();
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700585
Elliott Hughes376a7a02011-10-24 18:35:55 -0700586 hdr.length = length;
587 hdr.id = id;
588 hdr.cmdSet = cmdSet;
589 hdr.cmd = cmd;
590 state->ProcessRequest(&hdr, buf, dataLen, pReply);
591 if (expandBufGetLength(pReply) > 0) {
592 ssize_t cc = netState->writePacket(pReply);
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700593
Elliott Hughes376a7a02011-10-24 18:35:55 -0700594 if (cc != (ssize_t) expandBufGetLength(pReply)) {
595 PLOG(ERROR) << "Failed sending reply to debugger";
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700596 expandBufFree(pReply);
Elliott Hughes376a7a02011-10-24 18:35:55 -0700597 return false;
598 }
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700599 } else {
Elliott Hughes376a7a02011-10-24 18:35:55 -0700600 LOG(WARNING) << "No reply created for set=" << cmdSet << " cmd=" << cmd;
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700601 }
Elliott Hughes376a7a02011-10-24 18:35:55 -0700602 expandBufFree(pReply);
603 } else {
604 LOG(ERROR) << "reply?!";
605 DCHECK(false);
606 }
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700607
Elliott Hughes4dd9b4d2011-12-12 18:29:24 -0800608 VLOG(jdwp) << "----------";
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700609
Elliott Hughes376a7a02011-10-24 18:35:55 -0700610 consumeBytes(netState, length);
611 return true;
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700612}
613
614/*
615 * Process incoming data. If no data is available, this will block until
616 * some arrives.
617 *
618 * If we get a full packet, handle it.
619 *
620 * To take some of the mystery out of life, we want to reject incoming
621 * connections if we already have a debugger attached. If we don't, the
622 * debugger will just mysteriously hang until it times out. We could just
623 * close the listen socket, but there's a good chance we won't be able to
624 * bind to the same port again, which would confuse utilities.
625 *
626 * Returns "false" on error (indicating that the connection has been severed),
627 * "true" if things are still okay.
628 */
629static bool processIncoming(JdwpState* state) {
630 JdwpNetState* netState = state->netState;
631 int readCount;
632
633 CHECK_GE(netState->clientSock, 0);
634
635 if (!haveFullPacket(netState)) {
636 /* read some more, looping until we have data */
637 errno = 0;
638 while (1) {
639 int selCount;
640 fd_set readfds;
641 int maxfd;
642 int fd;
643
644 maxfd = netState->listenSock;
645 if (netState->clientSock > maxfd) {
646 maxfd = netState->clientSock;
647 }
648 if (netState->wakePipe[0] > maxfd) {
649 maxfd = netState->wakePipe[0];
650 }
651
652 if (maxfd < 0) {
Elliott Hughes4dd9b4d2011-12-12 18:29:24 -0800653 VLOG(jdwp) << "+++ all fds are closed";
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700654 return false;
655 }
656
657 FD_ZERO(&readfds);
658
659 /* configure fds; note these may get zapped by another thread */
660 fd = netState->listenSock;
661 if (fd >= 0) {
662 FD_SET(fd, &readfds);
663 }
664 fd = netState->clientSock;
665 if (fd >= 0) {
666 FD_SET(fd, &readfds);
667 }
668 fd = netState->wakePipe[0];
669 if (fd >= 0) {
670 FD_SET(fd, &readfds);
671 } else {
672 LOG(INFO) << "NOTE: entering select w/o wakepipe";
673 }
674
675 /*
676 * Select blocks until it sees activity on the file descriptors.
677 * Closing the local file descriptor does not count as activity,
678 * so we can't rely on that to wake us up (it works for read()
679 * and accept(), but not select()).
680 *
681 * We can do one of three things: (1) send a signal and catch
682 * EINTR, (2) open an additional fd ("wakePipe") and write to
683 * it when it's time to exit, or (3) time out periodically and
684 * re-issue the select. We're currently using #2, as it's more
685 * reliable than #1 and generally better than #3. Wastes two fds.
686 */
687 selCount = select(maxfd+1, &readfds, NULL, NULL, NULL);
688 if (selCount < 0) {
689 if (errno == EINTR) {
690 continue;
691 }
692 PLOG(ERROR) << "select failed";
693 goto fail;
694 }
695
696 if (netState->wakePipe[0] >= 0 && FD_ISSET(netState->wakePipe[0], &readfds)) {
697 if (netState->listenSock >= 0) {
698 LOG(ERROR) << "Exit wake set, but not exiting?";
699 } else {
700 LOG(DEBUG) << "Got wake-up signal, bailing out of select";
701 }
702 goto fail;
703 }
704 if (netState->listenSock >= 0 && FD_ISSET(netState->listenSock, &readfds)) {
705 LOG(INFO) << "Ignoring second debugger -- accepting and dropping";
706 union {
Elliott Hughes7b9d9962012-04-20 18:48:18 -0700707 sockaddr_in addrInet;
708 sockaddr addrPlain;
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700709 } addr;
710 socklen_t addrlen;
711 int tmpSock;
712 tmpSock = accept(netState->listenSock, &addr.addrPlain, &addrlen);
713 if (tmpSock < 0) {
714 LOG(INFO) << "Weird -- accept failed";
715 } else {
716 close(tmpSock);
717 }
718 }
719 if (netState->clientSock >= 0 && FD_ISSET(netState->clientSock, &readfds)) {
720 readCount = read(netState->clientSock, netState->inputBuffer + netState->inputCount, sizeof(netState->inputBuffer) - netState->inputCount);
721 if (readCount < 0) {
722 /* read failed */
723 if (errno != EINTR) {
724 goto fail;
725 }
726 LOG(DEBUG) << "+++ EINTR hit";
727 return true;
728 } else if (readCount == 0) {
729 /* EOF hit -- far end went away */
730 LOG(DEBUG) << "+++ peer disconnected";
731 goto fail;
732 } else {
733 break;
734 }
735 }
736 }
737
738 netState->inputCount += readCount;
739 if (!haveFullPacket(netState)) {
740 return true; /* still not there yet */
741 }
742 }
743
744 /*
745 * Special-case the initial handshake. For some bizarre reason we're
746 * expected to emulate bad tty settings by echoing the request back
747 * exactly as it was sent. Note the handshake is always initiated by
748 * the debugger, no matter who connects to whom.
749 *
750 * Other than this one case, the protocol [claims to be] stateless.
751 */
752 if (netState->awaitingHandshake) {
753 int cc;
754
755 if (memcmp(netState->inputBuffer, kMagicHandshake, kMagicHandshakeLen) != 0) {
756 LOG(ERROR) << StringPrintf("ERROR: bad handshake '%.14s'", netState->inputBuffer);
757 goto fail;
758 }
759
760 errno = 0;
761 cc = write(netState->clientSock, netState->inputBuffer, kMagicHandshakeLen);
762 if (cc != kMagicHandshakeLen) {
763 PLOG(ERROR) << "Failed writing handshake bytes (" << cc << " of " << kMagicHandshakeLen << ")";
764 goto fail;
765 }
766
767 consumeBytes(netState, kMagicHandshakeLen);
768 netState->awaitingHandshake = false;
Elliott Hughes4dd9b4d2011-12-12 18:29:24 -0800769 VLOG(jdwp) << "+++ handshake complete";
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700770 return true;
771 }
772
773 /*
774 * Handle this packet.
775 */
776 return handlePacket(state);
777
778fail:
779 closeConnection(state);
780 return false;
781}
782
783/*
784 * Send a request.
785 *
786 * The entire packet must be sent with a single write() call to avoid
787 * threading issues.
788 *
789 * Returns "true" if it was sent successfully.
790 */
791static bool sendRequest(JdwpState* state, ExpandBuf* pReq) {
792 JdwpNetState* netState = state->netState;
793
794 /*dumpPacket(expandBufGetBuffer(pReq));*/
795 if (netState->clientSock < 0) {
796 /* can happen with some DDMS events */
Elliott Hughes4dd9b4d2011-12-12 18:29:24 -0800797 VLOG(jdwp) << "NOT sending request -- no debugger is attached";
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700798 return false;
799 }
800
801 errno = 0;
802 ssize_t cc = netState->writePacket(pReq);
803
804 if (cc != (ssize_t) expandBufGetLength(pReq)) {
805 PLOG(ERROR) << "Failed sending req to debugger (" << cc << " of " << expandBufGetLength(pReq) << ")";
806 return false;
807 }
808
809 return true;
810}
811
812/*
813 * Send a request that was split into multiple buffers.
814 *
815 * The entire packet must be sent with a single writev() call to avoid
816 * threading issues.
817 *
818 * Returns "true" if it was sent successfully.
819 */
Elliott Hughescccd84f2011-12-05 16:51:54 -0800820static bool sendBufferedRequest(JdwpState* state, const iovec* iov, int iov_count) {
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700821 JdwpNetState* netState = state->netState;
822
823 if (netState->clientSock < 0) {
824 /* can happen with some DDMS events */
Elliott Hughes4dd9b4d2011-12-12 18:29:24 -0800825 VLOG(jdwp) << "NOT sending request -- no debugger is attached";
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700826 return false;
827 }
828
829 size_t expected = 0;
Elliott Hughescccd84f2011-12-05 16:51:54 -0800830 for (int i = 0; i < iov_count; i++) {
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700831 expected += iov[i].iov_len;
832 }
833
Elliott Hughescccd84f2011-12-05 16:51:54 -0800834 ssize_t actual = netState->writeBufferedPacket(iov, iov_count);
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700835
836 if ((size_t)actual != expected) {
837 PLOG(ERROR) << "Failed sending b-req to debugger (" << actual << " of " << expected << ")";
838 return false;
839 }
840
841 return true;
842}
843
844/*
845 * Our functions.
846 *
847 * We can't generally share the implementations with other transports,
848 * even if they're also socket-based, because our JdwpNetState will be
849 * different from theirs.
850 */
851static const JdwpTransport socketTransport = {
852 prepareSocket,
853 acceptConnection,
854 establishConnection,
855 closeConnection,
856 netShutdownExtern,
857 netFreeExtern,
858 isConnected,
859 awaitingHandshake,
860 processIncoming,
861 sendRequest,
862 sendBufferedRequest,
863};
864
865/*
866 * Return our set.
867 */
868const JdwpTransport* SocketTransport() {
869 return &socketTransport;
870}
871
872} // namespace JDWP
873
874} // namespace art