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