blob: 1cd610b71521d6139ffd66d0ab21bb4e09a6d49f [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
Elliott Hughes872d4ec2011-10-21 17:07:15 -070041namespace art {
42
43namespace JDWP {
44
45// fwd
46static void netShutdown(JdwpNetState* state);
47static void netFree(JdwpNetState* state);
48
49/*
50 * JDWP network state.
51 *
52 * We only talk to one debugger at a time.
53 */
54struct JdwpNetState : public JdwpNetStateBase {
Elliott Hughes74847412012-06-20 18:10:21 -070055 uint16_t listenPort;
56 int listenSock; /* listen for connection from debugger */
57 int wakePipe[2]; /* break out of select */
Elliott Hughes872d4ec2011-10-21 17:07:15 -070058
Elliott Hughes74847412012-06-20 18:10:21 -070059 in_addr remoteAddr;
60 uint16_t remotePort;
Elliott Hughes872d4ec2011-10-21 17:07:15 -070061
Elliott Hughes74847412012-06-20 18:10:21 -070062 bool awaitingHandshake; /* waiting for "JDWP-Handshake" */
Elliott Hughes872d4ec2011-10-21 17:07:15 -070063
Elliott Hughes74847412012-06-20 18:10:21 -070064 /* pending data from the network; would be more efficient as circular buf */
65 unsigned char inputBuffer[kInputBufferSize];
66 size_t inputCount;
Elliott Hughes872d4ec2011-10-21 17:07:15 -070067
Elliott Hughes74847412012-06-20 18:10:21 -070068 JdwpNetState() {
69 listenPort = 0;
70 listenSock = -1;
71 wakePipe[0] = -1;
72 wakePipe[1] = -1;
Elliott Hughes872d4ec2011-10-21 17:07:15 -070073
Elliott Hughes74847412012-06-20 18:10:21 -070074 awaitingHandshake = false;
Elliott Hughes872d4ec2011-10-21 17:07:15 -070075
Elliott Hughes74847412012-06-20 18:10:21 -070076 inputCount = 0;
77 }
Elliott Hughes872d4ec2011-10-21 17:07:15 -070078};
79
Elliott Hughes6d8dd472012-01-17 18:27:41 -080080static JdwpNetState* netStartup(uint16_t port, bool probe);
Elliott Hughes872d4ec2011-10-21 17:07:15 -070081
82/*
83 * Set up some stuff for transport=dt_socket.
84 */
Elliott Hughes376a7a02011-10-24 18:35:55 -070085static bool prepareSocket(JdwpState* state, const JdwpOptions* options) {
Elliott Hughes6d8dd472012-01-17 18:27:41 -080086 uint16_t port = options->port;
Elliott Hughes872d4ec2011-10-21 17:07:15 -070087
Elliott Hughes376a7a02011-10-24 18:35:55 -070088 if (options->server) {
89 if (options->port != 0) {
Elliott Hughes872d4ec2011-10-21 17:07:15 -070090 /* try only the specified port */
Elliott Hughes3d30d9b2011-12-07 17:35:48 -080091 state->netState = netStartup(port, false);
Elliott Hughes872d4ec2011-10-21 17:07:15 -070092 } else {
93 /* scan through a range of ports, binding to the first available */
94 for (port = kBasePort; port <= kMaxPort; port++) {
Elliott Hughes3d30d9b2011-12-07 17:35:48 -080095 state->netState = netStartup(port, true);
Elliott Hughes872d4ec2011-10-21 17:07:15 -070096 if (state->netState != NULL) {
97 break;
98 }
99 }
100 }
101 if (state->netState == NULL) {
Elliott Hughes376a7a02011-10-24 18:35:55 -0700102 LOG(ERROR) << "JDWP net startup failed (req port=" << options->port << ")";
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700103 return false;
104 }
105 } else {
Elliott Hughes6d8dd472012-01-17 18:27:41 -0800106 state->netState = netStartup(0, false);
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700107 }
108
Elliott Hughes376a7a02011-10-24 18:35:55 -0700109 if (options->suspend) {
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700110 LOG(INFO) << "JDWP will wait for debugger on port " << port;
111 } else {
Elliott Hughes376a7a02011-10-24 18:35:55 -0700112 LOG(INFO) << "JDWP will " << (options->server ? "listen" : "connect") << " on port " << port;
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700113 }
114
115 return true;
116}
117
118/*
119 * Are we still waiting for the handshake string?
120 */
121static bool awaitingHandshake(JdwpState* state) {
122 return state->netState->awaitingHandshake;
123}
124
125/*
126 * Initialize JDWP stuff.
127 *
Elliott Hughes6d8dd472012-01-17 18:27:41 -0800128 * Allocates a new state structure. If "port" is non-zero, this also
129 * tries to bind to a listen port. If "port" is zero, we assume
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700130 * we're preparing for an outbound connection, and return without binding
131 * to anything.
132 *
133 * This may be called several times if we're probing for a port.
134 *
135 * Returns 0 on success.
136 */
Elliott Hughes6d8dd472012-01-17 18:27:41 -0800137static JdwpNetState* netStartup(uint16_t port, bool probe) {
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700138 JdwpNetState* netState = new JdwpNetState;
Elliott Hughes6d8dd472012-01-17 18:27:41 -0800139 if (port == 0) {
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700140 return netState;
141 }
142
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700143 netState->listenSock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
144 if (netState->listenSock < 0) {
Elliott Hughes3d30d9b2011-12-07 17:35:48 -0800145 PLOG(probe ? ERROR : FATAL) << "Socket create failed";
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700146 goto fail;
147 }
148
149 /* allow immediate re-use */
Elliott Hughes6d8dd472012-01-17 18:27:41 -0800150 {
151 int one = 1;
152 if (setsockopt(netState->listenSock, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one)) < 0) {
153 PLOG(probe ? ERROR : FATAL) << "setsockopt(SO_REUSEADDR) failed";
154 goto fail;
155 }
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700156 }
157
158 union {
Elliott Hughes7b9d9962012-04-20 18:48:18 -0700159 sockaddr_in addrInet;
160 sockaddr addrPlain;
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700161 } addr;
162 addr.addrInet.sin_family = AF_INET;
163 addr.addrInet.sin_port = htons(port);
164 inet_aton("127.0.0.1", &addr.addrInet.sin_addr);
165
166 if (bind(netState->listenSock, &addr.addrPlain, sizeof(addr)) != 0) {
Elliott Hughes3d30d9b2011-12-07 17:35:48 -0800167 PLOG(probe ? ERROR : FATAL) << "Attempt to bind to port " << port << " failed";
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700168 goto fail;
169 }
170
171 netState->listenPort = port;
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700172
173 if (listen(netState->listenSock, 5) != 0) {
Elliott Hughes3d30d9b2011-12-07 17:35:48 -0800174 PLOG(probe ? ERROR : FATAL) << "Listen failed";
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700175 goto fail;
176 }
177
178 return netState;
179
Elliott Hughesa21039c2012-06-21 12:09:25 -0700180 fail:
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700181 netShutdown(netState);
182 netFree(netState);
183 return NULL;
184}
185
186/*
187 * Shut down JDWP listener. Don't free state.
188 *
189 * Note that "netState" may be partially initialized if "startup" failed.
190 *
191 * This may be called from a non-JDWP thread as part of shutting the
192 * JDWP thread down.
193 *
194 * (This is currently called several times during startup as we probe
195 * for an open port.)
196 */
197static void netShutdown(JdwpNetState* netState) {
198 if (netState == NULL) {
199 return;
200 }
201
202 int listenSock = netState->listenSock;
203 int clientSock = netState->clientSock;
204
205 /* clear these out so it doesn't wake up and try to reuse them */
206 netState->listenSock = netState->clientSock = -1;
207
208 /* "shutdown" dislodges blocking read() and accept() calls */
209 if (listenSock >= 0) {
210 shutdown(listenSock, SHUT_RDWR);
211 close(listenSock);
212 }
213 if (clientSock >= 0) {
214 shutdown(clientSock, SHUT_RDWR);
215 close(clientSock);
216 }
217
218 /* if we might be sitting in select, kick us loose */
219 if (netState->wakePipe[1] >= 0) {
Elliott Hughes4dd9b4d2011-12-12 18:29:24 -0800220 VLOG(jdwp) << "+++ writing to wakePipe";
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700221 (void) write(netState->wakePipe[1], "", 1);
222 }
223}
224
225static void netShutdownExtern(JdwpState* state) {
226 netShutdown(state->netState);
227}
228
229/*
230 * Free JDWP state.
231 *
232 * Call this after shutting the network down with netShutdown().
233 */
234static void netFree(JdwpNetState* netState) {
235 if (netState == NULL) {
236 return;
237 }
238 CHECK_EQ(netState->listenSock, -1);
239 CHECK_EQ(netState->clientSock, -1);
240
241 if (netState->wakePipe[0] >= 0) {
242 close(netState->wakePipe[0]);
243 netState->wakePipe[0] = -1;
244 }
245 if (netState->wakePipe[1] >= 0) {
246 close(netState->wakePipe[1]);
247 netState->wakePipe[1] = -1;
248 }
249
250 delete netState;
251}
252
253static void netFreeExtern(JdwpState* state) {
254 netFree(state->netState);
255}
256
257/*
258 * Returns "true" if we're connected to a debugger.
259 */
260static bool isConnected(JdwpState* state) {
261 return (state->netState != NULL && state->netState->clientSock >= 0);
262}
263
264/*
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700265 * Disable the TCP Nagle algorithm, which delays transmission of outbound
266 * packets until the previous transmissions have been acked. JDWP does a
267 * lot of back-and-forth with small packets, so this may help.
268 */
Elliott Hughes74847412012-06-20 18:10:21 -0700269static int setNoDelay(int fd) {
270 int on = 1;
271 int cc = setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &on, sizeof(on));
272 CHECK_EQ(cc, 0);
273 return cc;
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700274}
275
276/*
277 * Accept a connection. This will block waiting for somebody to show up.
278 * If that's not desirable, use checkConnection() to make sure something
279 * is pending.
280 */
Elliott Hughes74847412012-06-20 18:10:21 -0700281static bool acceptConnection(JdwpState* state) {
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700282 JdwpNetState* netState = state->netState;
283 union {
Elliott Hughes7b9d9962012-04-20 18:48:18 -0700284 sockaddr_in addrInet;
285 sockaddr addrPlain;
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700286 } addr;
287 socklen_t addrlen;
288 int sock;
289
290 if (netState->listenSock < 0) {
291 return false; /* you're not listening! */
292 }
293
294 CHECK_LT(netState->clientSock, 0); /* must not already be talking */
295
296 addrlen = sizeof(addr);
297 do {
298 sock = accept(netState->listenSock, &addr.addrPlain, &addrlen);
299 if (sock < 0 && errno != EINTR) {
300 // When we call shutdown() on the socket, accept() returns with
301 // EINVAL. Don't gripe about it.
302 if (errno == EINVAL) {
Elliott Hughes4dd9b4d2011-12-12 18:29:24 -0800303 if (VLOG_IS_ON(jdwp)) {
304 PLOG(ERROR) << "accept failed";
305 }
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700306 } else {
307 PLOG(ERROR) << "accept failed";
308 return false;
309 }
310 }
311 } while (sock < 0);
312
313 netState->remoteAddr = addr.addrInet.sin_addr;
314 netState->remotePort = ntohs(addr.addrInet.sin_port);
Elliott Hughes4dd9b4d2011-12-12 18:29:24 -0800315 VLOG(jdwp) << "+++ accepted connection from " << inet_ntoa(netState->remoteAddr) << ":" << netState->remotePort;
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700316
317 netState->clientSock = sock;
318 netState->awaitingHandshake = true;
319 netState->inputCount = 0;
320
Elliott Hughes4dd9b4d2011-12-12 18:29:24 -0800321 VLOG(jdwp) << "Setting TCP_NODELAY on accepted socket";
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700322 setNoDelay(netState->clientSock);
323
324 if (pipe(netState->wakePipe) < 0) {
325 PLOG(ERROR) << "pipe failed";
326 return false;
327 }
328
329 return true;
330}
331
332/*
333 * Create a connection to a waiting debugger.
334 */
Elliott Hughesa21039c2012-06-21 12:09:25 -0700335static bool establishConnection(JdwpState* state, const JdwpOptions* options) {
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700336 union {
Elliott Hughes7b9d9962012-04-20 18:48:18 -0700337 sockaddr_in addrInet;
338 sockaddr addrPlain;
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700339 } addr;
Elliott Hughes7b9d9962012-04-20 18:48:18 -0700340 hostent* pEntry;
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700341
342 CHECK(state != NULL && state->netState != NULL);
Elliott Hughesa21039c2012-06-21 12:09:25 -0700343 CHECK(!options->server);
344 CHECK(!options->host.empty());
345 CHECK_NE(options->port, 0);
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700346
347 /*
348 * Start by resolving the host name.
349 */
350//#undef HAVE_GETHOSTBYNAME_R
351//#warning "forcing non-R"
352#ifdef HAVE_GETHOSTBYNAME_R
Elliott Hughes7b9d9962012-04-20 18:48:18 -0700353 hostent he;
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700354 char auxBuf[128];
355 int error;
Elliott Hughesa21039c2012-06-21 12:09:25 -0700356 int cc = gethostbyname_r(options->host.c_str(), &he, auxBuf, sizeof(auxBuf), &pEntry, &error);
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700357 if (cc != 0) {
Elliott Hughesa21039c2012-06-21 12:09:25 -0700358 LOG(WARNING) << "gethostbyname_r('" << options->host << "') failed: " << hstrerror(error);
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700359 return false;
360 }
361#else
362 h_errno = 0;
Elliott Hughesa21039c2012-06-21 12:09:25 -0700363 pEntry = gethostbyname(options->host.c_str());
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700364 if (pEntry == NULL) {
Elliott Hughesa21039c2012-06-21 12:09:25 -0700365 PLOG(WARNING) << "gethostbyname('" << options->host << "') failed";
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700366 return false;
367 }
368#endif
369
370 /* copy it out ASAP to minimize risk of multithreaded annoyances */
371 memcpy(&addr.addrInet.sin_addr, pEntry->h_addr, pEntry->h_length);
372 addr.addrInet.sin_family = pEntry->h_addrtype;
373
Elliott Hughesa21039c2012-06-21 12:09:25 -0700374 addr.addrInet.sin_port = htons(options->port);
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700375
376 LOG(INFO) << "Connecting out to " << inet_ntoa(addr.addrInet.sin_addr) << ":" << ntohs(addr.addrInet.sin_port);
377
378 /*
379 * Create a socket.
380 */
381 JdwpNetState* netState;
382 netState = state->netState;
383 netState->clientSock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
384 if (netState->clientSock < 0) {
385 PLOG(ERROR) << "Unable to create socket";
386 return false;
387 }
388
389 /*
390 * Try to connect.
391 */
392 if (connect(netState->clientSock, &addr.addrPlain, sizeof(addr)) != 0) {
393 PLOG(ERROR) << "Unable to connect to " << inet_ntoa(addr.addrInet.sin_addr) << ":" << ntohs(addr.addrInet.sin_port);
394 close(netState->clientSock);
395 netState->clientSock = -1;
396 return false;
397 }
398
Elliott Hughesa21039c2012-06-21 12:09:25 -0700399 LOG(INFO) << "Connection established to " << options->host << " (" << inet_ntoa(addr.addrInet.sin_addr) << ":" << ntohs(addr.addrInet.sin_port) << ")";
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700400 netState->awaitingHandshake = true;
401 netState->inputCount = 0;
402
403 setNoDelay(netState->clientSock);
404
405 if (pipe(netState->wakePipe) < 0) {
406 PLOG(ERROR) << "pipe failed";
407 return false;
408 }
409
410 return true;
411}
412
413/*
414 * Close the connection to the debugger.
415 *
416 * Reset the state so we're ready to receive a new connection.
417 */
418static void closeConnection(JdwpState* state) {
419 JdwpNetState* netState;
420
421 CHECK(state != NULL && state->netState != NULL);
422
423 netState = state->netState;
424 if (netState->clientSock < 0) {
425 return;
426 }
427
Elliott Hughes4dd9b4d2011-12-12 18:29:24 -0800428 VLOG(jdwp) << "+++ closed connection to " << inet_ntoa(netState->remoteAddr) << ":" << netState->remotePort;
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700429
430 close(netState->clientSock);
431 netState->clientSock = -1;
432}
433
434/*
435 * Figure out if we have a full packet in the buffer.
436 */
437static bool haveFullPacket(JdwpNetState* netState) {
438 if (netState->awaitingHandshake) {
Elliott Hughes74847412012-06-20 18:10:21 -0700439 return (netState->inputCount >= kMagicHandshakeLen);
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700440 }
441 if (netState->inputCount < 4) {
442 return false;
443 }
Elliott Hughes74847412012-06-20 18:10:21 -0700444 uint32_t length = Get4BE(netState->inputBuffer);
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700445 return (netState->inputCount >= length);
446}
447
448/*
449 * Consume bytes from the buffer.
450 *
451 * This would be more efficient with a circular buffer. However, we're
452 * usually only going to find one packet, which is trivial to handle.
453 */
Elliott Hughes74847412012-06-20 18:10:21 -0700454static void consumeBytes(JdwpNetState* netState, size_t count) {
455 CHECK_GT(count, 0U);
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700456 CHECK_LE(count, netState->inputCount);
457
458 if (count == netState->inputCount) {
459 netState->inputCount = 0;
460 return;
461 }
462
463 memmove(netState->inputBuffer, netState->inputBuffer + count, netState->inputCount - count);
464 netState->inputCount -= count;
465}
466
467/*
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700468 * Handle a packet. Returns "false" if we encounter a connection-fatal error.
469 */
Elliott Hughes376a7a02011-10-24 18:35:55 -0700470static bool handlePacket(JdwpState* state) {
471 JdwpNetState* netState = state->netState;
472 const unsigned char* buf = netState->inputBuffer;
Elliott Hughes74847412012-06-20 18:10:21 -0700473 uint8_t cmdSet, cmd;
Elliott Hughes376a7a02011-10-24 18:35:55 -0700474 bool reply;
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700475
Elliott Hughes376a7a02011-10-24 18:35:55 -0700476 cmd = cmdSet = 0; // shut up gcc
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700477
Elliott Hughes74847412012-06-20 18:10:21 -0700478 uint32_t length = Read4BE(&buf);
479 uint32_t id = Read4BE(&buf);
480 int8_t flags = Read1(&buf);
Elliott Hughes376a7a02011-10-24 18:35:55 -0700481 if ((flags & kJDWPFlagReply) != 0) {
482 reply = true;
Brian Carlstromfd2ec542012-05-02 15:08:57 -0700483 Read2BE(&buf); // error
Elliott Hughes376a7a02011-10-24 18:35:55 -0700484 } else {
485 reply = false;
Elliott Hughesf7c3b662011-10-27 12:04:56 -0700486 cmdSet = Read1(&buf);
487 cmd = Read1(&buf);
Elliott Hughes376a7a02011-10-24 18:35:55 -0700488 }
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700489
Elliott Hughes74847412012-06-20 18:10:21 -0700490 CHECK_LE(length, netState->inputCount);
491 int dataLen = length - (buf - netState->inputBuffer);
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700492
Elliott Hughes376a7a02011-10-24 18:35:55 -0700493 if (!reply) {
494 ExpandBuf* pReply = expandBufAlloc();
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700495
Elliott Hughes74847412012-06-20 18:10:21 -0700496 JdwpReqHeader hdr;
Elliott Hughes376a7a02011-10-24 18:35:55 -0700497 hdr.length = length;
498 hdr.id = id;
499 hdr.cmdSet = cmdSet;
500 hdr.cmd = cmd;
501 state->ProcessRequest(&hdr, buf, dataLen, pReply);
502 if (expandBufGetLength(pReply) > 0) {
503 ssize_t cc = netState->writePacket(pReply);
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700504
Elliott Hughes376a7a02011-10-24 18:35:55 -0700505 if (cc != (ssize_t) expandBufGetLength(pReply)) {
506 PLOG(ERROR) << "Failed sending reply to debugger";
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700507 expandBufFree(pReply);
Elliott Hughes376a7a02011-10-24 18:35:55 -0700508 return false;
509 }
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700510 } else {
Elliott Hughes376a7a02011-10-24 18:35:55 -0700511 LOG(WARNING) << "No reply created for set=" << cmdSet << " cmd=" << cmd;
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700512 }
Elliott Hughes376a7a02011-10-24 18:35:55 -0700513 expandBufFree(pReply);
514 } else {
515 LOG(ERROR) << "reply?!";
516 DCHECK(false);
517 }
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700518
Elliott Hughes4dd9b4d2011-12-12 18:29:24 -0800519 VLOG(jdwp) << "----------";
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700520
Elliott Hughes376a7a02011-10-24 18:35:55 -0700521 consumeBytes(netState, length);
522 return true;
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700523}
524
525/*
526 * Process incoming data. If no data is available, this will block until
527 * some arrives.
528 *
529 * If we get a full packet, handle it.
530 *
531 * To take some of the mystery out of life, we want to reject incoming
532 * connections if we already have a debugger attached. If we don't, the
533 * debugger will just mysteriously hang until it times out. We could just
534 * close the listen socket, but there's a good chance we won't be able to
535 * bind to the same port again, which would confuse utilities.
536 *
537 * Returns "false" on error (indicating that the connection has been severed),
538 * "true" if things are still okay.
539 */
540static bool processIncoming(JdwpState* state) {
541 JdwpNetState* netState = state->netState;
542 int readCount;
543
544 CHECK_GE(netState->clientSock, 0);
545
546 if (!haveFullPacket(netState)) {
547 /* read some more, looping until we have data */
548 errno = 0;
549 while (1) {
550 int selCount;
551 fd_set readfds;
552 int maxfd;
553 int fd;
554
555 maxfd = netState->listenSock;
556 if (netState->clientSock > maxfd) {
557 maxfd = netState->clientSock;
558 }
559 if (netState->wakePipe[0] > maxfd) {
560 maxfd = netState->wakePipe[0];
561 }
562
563 if (maxfd < 0) {
Elliott Hughes4dd9b4d2011-12-12 18:29:24 -0800564 VLOG(jdwp) << "+++ all fds are closed";
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700565 return false;
566 }
567
568 FD_ZERO(&readfds);
569
570 /* configure fds; note these may get zapped by another thread */
571 fd = netState->listenSock;
572 if (fd >= 0) {
573 FD_SET(fd, &readfds);
574 }
575 fd = netState->clientSock;
576 if (fd >= 0) {
577 FD_SET(fd, &readfds);
578 }
579 fd = netState->wakePipe[0];
580 if (fd >= 0) {
581 FD_SET(fd, &readfds);
582 } else {
583 LOG(INFO) << "NOTE: entering select w/o wakepipe";
584 }
585
586 /*
587 * Select blocks until it sees activity on the file descriptors.
588 * Closing the local file descriptor does not count as activity,
589 * so we can't rely on that to wake us up (it works for read()
590 * and accept(), but not select()).
591 *
592 * We can do one of three things: (1) send a signal and catch
593 * EINTR, (2) open an additional fd ("wakePipe") and write to
594 * it when it's time to exit, or (3) time out periodically and
595 * re-issue the select. We're currently using #2, as it's more
596 * reliable than #1 and generally better than #3. Wastes two fds.
597 */
598 selCount = select(maxfd+1, &readfds, NULL, NULL, NULL);
599 if (selCount < 0) {
600 if (errno == EINTR) {
601 continue;
602 }
603 PLOG(ERROR) << "select failed";
604 goto fail;
605 }
606
607 if (netState->wakePipe[0] >= 0 && FD_ISSET(netState->wakePipe[0], &readfds)) {
608 if (netState->listenSock >= 0) {
609 LOG(ERROR) << "Exit wake set, but not exiting?";
610 } else {
611 LOG(DEBUG) << "Got wake-up signal, bailing out of select";
612 }
613 goto fail;
614 }
615 if (netState->listenSock >= 0 && FD_ISSET(netState->listenSock, &readfds)) {
616 LOG(INFO) << "Ignoring second debugger -- accepting and dropping";
617 union {
Elliott Hughes7b9d9962012-04-20 18:48:18 -0700618 sockaddr_in addrInet;
619 sockaddr addrPlain;
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700620 } addr;
621 socklen_t addrlen;
622 int tmpSock;
623 tmpSock = accept(netState->listenSock, &addr.addrPlain, &addrlen);
624 if (tmpSock < 0) {
625 LOG(INFO) << "Weird -- accept failed";
626 } else {
627 close(tmpSock);
628 }
629 }
630 if (netState->clientSock >= 0 && FD_ISSET(netState->clientSock, &readfds)) {
631 readCount = read(netState->clientSock, netState->inputBuffer + netState->inputCount, sizeof(netState->inputBuffer) - netState->inputCount);
632 if (readCount < 0) {
633 /* read failed */
634 if (errno != EINTR) {
635 goto fail;
636 }
637 LOG(DEBUG) << "+++ EINTR hit";
638 return true;
639 } else if (readCount == 0) {
640 /* EOF hit -- far end went away */
641 LOG(DEBUG) << "+++ peer disconnected";
642 goto fail;
643 } else {
644 break;
645 }
646 }
647 }
648
649 netState->inputCount += readCount;
650 if (!haveFullPacket(netState)) {
651 return true; /* still not there yet */
652 }
653 }
654
655 /*
656 * Special-case the initial handshake. For some bizarre reason we're
657 * expected to emulate bad tty settings by echoing the request back
658 * exactly as it was sent. Note the handshake is always initiated by
659 * the debugger, no matter who connects to whom.
660 *
661 * Other than this one case, the protocol [claims to be] stateless.
662 */
663 if (netState->awaitingHandshake) {
664 int cc;
665
666 if (memcmp(netState->inputBuffer, kMagicHandshake, kMagicHandshakeLen) != 0) {
667 LOG(ERROR) << StringPrintf("ERROR: bad handshake '%.14s'", netState->inputBuffer);
668 goto fail;
669 }
670
671 errno = 0;
672 cc = write(netState->clientSock, netState->inputBuffer, kMagicHandshakeLen);
673 if (cc != kMagicHandshakeLen) {
674 PLOG(ERROR) << "Failed writing handshake bytes (" << cc << " of " << kMagicHandshakeLen << ")";
675 goto fail;
676 }
677
678 consumeBytes(netState, kMagicHandshakeLen);
679 netState->awaitingHandshake = false;
Elliott Hughes4dd9b4d2011-12-12 18:29:24 -0800680 VLOG(jdwp) << "+++ handshake complete";
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700681 return true;
682 }
683
684 /*
685 * Handle this packet.
686 */
687 return handlePacket(state);
688
Elliott Hughesa21039c2012-06-21 12:09:25 -0700689 fail:
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700690 closeConnection(state);
691 return false;
692}
693
694/*
695 * Send a request.
696 *
697 * The entire packet must be sent with a single write() call to avoid
698 * threading issues.
699 *
700 * Returns "true" if it was sent successfully.
701 */
702static bool sendRequest(JdwpState* state, ExpandBuf* pReq) {
703 JdwpNetState* netState = state->netState;
704
705 /*dumpPacket(expandBufGetBuffer(pReq));*/
706 if (netState->clientSock < 0) {
707 /* can happen with some DDMS events */
Elliott Hughes4dd9b4d2011-12-12 18:29:24 -0800708 VLOG(jdwp) << "NOT sending request -- no debugger is attached";
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700709 return false;
710 }
711
712 errno = 0;
713 ssize_t cc = netState->writePacket(pReq);
714
715 if (cc != (ssize_t) expandBufGetLength(pReq)) {
716 PLOG(ERROR) << "Failed sending req to debugger (" << cc << " of " << expandBufGetLength(pReq) << ")";
717 return false;
718 }
719
720 return true;
721}
722
723/*
724 * Send a request that was split into multiple buffers.
725 *
726 * The entire packet must be sent with a single writev() call to avoid
727 * threading issues.
728 *
729 * Returns "true" if it was sent successfully.
730 */
Elliott Hughescccd84f2011-12-05 16:51:54 -0800731static bool sendBufferedRequest(JdwpState* state, const iovec* iov, int iov_count) {
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700732 JdwpNetState* netState = state->netState;
733
734 if (netState->clientSock < 0) {
735 /* can happen with some DDMS events */
Elliott Hughes4dd9b4d2011-12-12 18:29:24 -0800736 VLOG(jdwp) << "NOT sending request -- no debugger is attached";
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700737 return false;
738 }
739
740 size_t expected = 0;
Elliott Hughescccd84f2011-12-05 16:51:54 -0800741 for (int i = 0; i < iov_count; i++) {
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700742 expected += iov[i].iov_len;
743 }
744
Elliott Hughescccd84f2011-12-05 16:51:54 -0800745 ssize_t actual = netState->writeBufferedPacket(iov, iov_count);
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700746
747 if ((size_t)actual != expected) {
748 PLOG(ERROR) << "Failed sending b-req to debugger (" << actual << " of " << expected << ")";
749 return false;
750 }
751
752 return true;
753}
754
755/*
756 * Our functions.
757 *
758 * We can't generally share the implementations with other transports,
759 * even if they're also socket-based, because our JdwpNetState will be
760 * different from theirs.
761 */
762static const JdwpTransport socketTransport = {
763 prepareSocket,
764 acceptConnection,
765 establishConnection,
766 closeConnection,
767 netShutdownExtern,
768 netFreeExtern,
769 isConnected,
770 awaitingHandshake,
771 processIncoming,
772 sendRequest,
773 sendBufferedRequest,
774};
775
776/*
777 * Return our set.
778 */
779const JdwpTransport* SocketTransport() {
780 return &socketTransport;
781}
782
783} // namespace JDWP
784
785} // namespace art