blob: 13e150a217a7cab87f4b5b7d69712d65a6751955 [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 */
Elliott Hughes872d4ec2011-10-21 17:07:15 -070016
Elliott Hughes07ed66b2012-12-12 18:34:25 -080017#include <arpa/inet.h>
Elliott Hughes872d4ec2011-10-21 17:07:15 -070018#include <errno.h>
Elliott Hughes07ed66b2012-12-12 18:34:25 -080019#include <netdb.h>
Elliott Hughes872d4ec2011-10-21 17:07:15 -070020#include <netinet/in.h>
21#include <netinet/tcp.h>
Elliott Hughes07ed66b2012-12-12 18:34:25 -080022#include <stdio.h>
23#include <stdlib.h>
24#include <string.h>
25#include <sys/socket.h>
26#include <sys/types.h>
27#include <unistd.h>
28
29#include "base/logging.h"
Elliott Hughese222ee02012-12-13 14:41:43 -080030#include "base/stringprintf.h"
Elliott Hughes07ed66b2012-12-12 18:34:25 -080031#include "jdwp/jdwp_priv.h"
Elliott Hughes872d4ec2011-10-21 17:07:15 -070032
33#define kBasePort 8000
34#define kMaxPort 8040
35
Elliott Hughes872d4ec2011-10-21 17:07:15 -070036namespace art {
37
38namespace JDWP {
39
40// fwd
41static void netShutdown(JdwpNetState* state);
42static void netFree(JdwpNetState* state);
43
44/*
45 * JDWP network state.
46 *
47 * We only talk to one debugger at a time.
48 */
49struct JdwpNetState : public JdwpNetStateBase {
Elliott Hughes74847412012-06-20 18:10:21 -070050 uint16_t listenPort;
51 int listenSock; /* listen for connection from debugger */
52 int wakePipe[2]; /* break out of select */
Elliott Hughes872d4ec2011-10-21 17:07:15 -070053
Elliott Hughes74847412012-06-20 18:10:21 -070054 in_addr remoteAddr;
55 uint16_t remotePort;
Elliott Hughes872d4ec2011-10-21 17:07:15 -070056
Elliott Hughes74847412012-06-20 18:10:21 -070057 bool awaitingHandshake; /* waiting for "JDWP-Handshake" */
Elliott Hughes872d4ec2011-10-21 17:07:15 -070058
Elliott Hughes74847412012-06-20 18:10:21 -070059 JdwpNetState() {
60 listenPort = 0;
61 listenSock = -1;
62 wakePipe[0] = -1;
63 wakePipe[1] = -1;
Elliott Hughes872d4ec2011-10-21 17:07:15 -070064
Elliott Hughes74847412012-06-20 18:10:21 -070065 awaitingHandshake = false;
Elliott Hughes74847412012-06-20 18:10:21 -070066 }
Elliott Hughes872d4ec2011-10-21 17:07:15 -070067};
68
Elliott Hughes6d8dd472012-01-17 18:27:41 -080069static JdwpNetState* netStartup(uint16_t port, bool probe);
Elliott Hughes872d4ec2011-10-21 17:07:15 -070070
71/*
72 * Set up some stuff for transport=dt_socket.
73 */
Elliott Hughes376a7a02011-10-24 18:35:55 -070074static bool prepareSocket(JdwpState* state, const JdwpOptions* options) {
Elliott Hughes6d8dd472012-01-17 18:27:41 -080075 uint16_t port = options->port;
Elliott Hughes872d4ec2011-10-21 17:07:15 -070076
Elliott Hughes376a7a02011-10-24 18:35:55 -070077 if (options->server) {
78 if (options->port != 0) {
Elliott Hughes872d4ec2011-10-21 17:07:15 -070079 /* try only the specified port */
Elliott Hughes3d30d9b2011-12-07 17:35:48 -080080 state->netState = netStartup(port, false);
Elliott Hughes872d4ec2011-10-21 17:07:15 -070081 } else {
82 /* scan through a range of ports, binding to the first available */
83 for (port = kBasePort; port <= kMaxPort; port++) {
Elliott Hughes3d30d9b2011-12-07 17:35:48 -080084 state->netState = netStartup(port, true);
Elliott Hughes872d4ec2011-10-21 17:07:15 -070085 if (state->netState != NULL) {
86 break;
87 }
88 }
89 }
90 if (state->netState == NULL) {
Elliott Hughes376a7a02011-10-24 18:35:55 -070091 LOG(ERROR) << "JDWP net startup failed (req port=" << options->port << ")";
Elliott Hughes872d4ec2011-10-21 17:07:15 -070092 return false;
93 }
94 } else {
Elliott Hughes6d8dd472012-01-17 18:27:41 -080095 state->netState = netStartup(0, false);
Elliott Hughes872d4ec2011-10-21 17:07:15 -070096 }
97
Elliott Hughes376a7a02011-10-24 18:35:55 -070098 if (options->suspend) {
Elliott Hughes872d4ec2011-10-21 17:07:15 -070099 LOG(INFO) << "JDWP will wait for debugger on port " << port;
100 } else {
Elliott Hughes376a7a02011-10-24 18:35:55 -0700101 LOG(INFO) << "JDWP will " << (options->server ? "listen" : "connect") << " on port " << port;
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700102 }
103
104 return true;
105}
106
107/*
108 * Are we still waiting for the handshake string?
109 */
110static bool awaitingHandshake(JdwpState* state) {
111 return state->netState->awaitingHandshake;
112}
113
114/*
115 * Initialize JDWP stuff.
116 *
Elliott Hughes6d8dd472012-01-17 18:27:41 -0800117 * Allocates a new state structure. If "port" is non-zero, this also
118 * tries to bind to a listen port. If "port" is zero, we assume
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700119 * we're preparing for an outbound connection, and return without binding
120 * to anything.
121 *
122 * This may be called several times if we're probing for a port.
123 *
124 * Returns 0 on success.
125 */
Elliott Hughes6d8dd472012-01-17 18:27:41 -0800126static JdwpNetState* netStartup(uint16_t port, bool probe) {
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700127 JdwpNetState* netState = new JdwpNetState;
Elliott Hughes6d8dd472012-01-17 18:27:41 -0800128 if (port == 0) {
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700129 return netState;
130 }
131
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700132 netState->listenSock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
133 if (netState->listenSock < 0) {
Elliott Hughes3d30d9b2011-12-07 17:35:48 -0800134 PLOG(probe ? ERROR : FATAL) << "Socket create failed";
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700135 goto fail;
136 }
137
138 /* allow immediate re-use */
Elliott Hughes6d8dd472012-01-17 18:27:41 -0800139 {
140 int one = 1;
141 if (setsockopt(netState->listenSock, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one)) < 0) {
142 PLOG(probe ? ERROR : FATAL) << "setsockopt(SO_REUSEADDR) failed";
143 goto fail;
144 }
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700145 }
146
147 union {
Elliott Hughes7b9d9962012-04-20 18:48:18 -0700148 sockaddr_in addrInet;
149 sockaddr addrPlain;
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700150 } addr;
151 addr.addrInet.sin_family = AF_INET;
152 addr.addrInet.sin_port = htons(port);
153 inet_aton("127.0.0.1", &addr.addrInet.sin_addr);
154
155 if (bind(netState->listenSock, &addr.addrPlain, sizeof(addr)) != 0) {
Elliott Hughes3d30d9b2011-12-07 17:35:48 -0800156 PLOG(probe ? ERROR : FATAL) << "Attempt to bind to port " << port << " failed";
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700157 goto fail;
158 }
159
160 netState->listenPort = port;
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700161
162 if (listen(netState->listenSock, 5) != 0) {
Elliott Hughes3d30d9b2011-12-07 17:35:48 -0800163 PLOG(probe ? ERROR : FATAL) << "Listen failed";
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700164 goto fail;
165 }
166
167 return netState;
168
Elliott Hughesa21039c2012-06-21 12:09:25 -0700169 fail:
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700170 netShutdown(netState);
171 netFree(netState);
172 return NULL;
173}
174
175/*
176 * Shut down JDWP listener. Don't free state.
177 *
178 * Note that "netState" may be partially initialized if "startup" failed.
179 *
180 * This may be called from a non-JDWP thread as part of shutting the
181 * JDWP thread down.
182 *
183 * (This is currently called several times during startup as we probe
184 * for an open port.)
185 */
186static void netShutdown(JdwpNetState* netState) {
187 if (netState == NULL) {
188 return;
189 }
190
191 int listenSock = netState->listenSock;
192 int clientSock = netState->clientSock;
193
194 /* clear these out so it doesn't wake up and try to reuse them */
195 netState->listenSock = netState->clientSock = -1;
196
197 /* "shutdown" dislodges blocking read() and accept() calls */
198 if (listenSock >= 0) {
199 shutdown(listenSock, SHUT_RDWR);
200 close(listenSock);
201 }
202 if (clientSock >= 0) {
203 shutdown(clientSock, SHUT_RDWR);
204 close(clientSock);
205 }
206
207 /* if we might be sitting in select, kick us loose */
208 if (netState->wakePipe[1] >= 0) {
Elliott Hughes4dd9b4d2011-12-12 18:29:24 -0800209 VLOG(jdwp) << "+++ writing to wakePipe";
Elliott Hughes068193c2013-04-15 16:05:28 -0700210 TEMP_FAILURE_RETRY(write(netState->wakePipe[1], "", 1));
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700211 }
212}
213
214static void netShutdownExtern(JdwpState* state) {
215 netShutdown(state->netState);
216}
217
218/*
219 * Free JDWP state.
220 *
221 * Call this after shutting the network down with netShutdown().
222 */
223static void netFree(JdwpNetState* netState) {
224 if (netState == NULL) {
225 return;
226 }
227 CHECK_EQ(netState->listenSock, -1);
228 CHECK_EQ(netState->clientSock, -1);
229
230 if (netState->wakePipe[0] >= 0) {
231 close(netState->wakePipe[0]);
232 netState->wakePipe[0] = -1;
233 }
234 if (netState->wakePipe[1] >= 0) {
235 close(netState->wakePipe[1]);
236 netState->wakePipe[1] = -1;
237 }
238
239 delete netState;
240}
241
242static void netFreeExtern(JdwpState* state) {
243 netFree(state->netState);
244}
245
246/*
247 * Returns "true" if we're connected to a debugger.
248 */
249static bool isConnected(JdwpState* state) {
250 return (state->netState != NULL && state->netState->clientSock >= 0);
251}
252
253/*
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700254 * Disable the TCP Nagle algorithm, which delays transmission of outbound
255 * packets until the previous transmissions have been acked. JDWP does a
256 * lot of back-and-forth with small packets, so this may help.
257 */
Elliott Hughes74847412012-06-20 18:10:21 -0700258static int setNoDelay(int fd) {
259 int on = 1;
260 int cc = setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &on, sizeof(on));
261 CHECK_EQ(cc, 0);
262 return cc;
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700263}
264
265/*
266 * Accept a connection. This will block waiting for somebody to show up.
267 * If that's not desirable, use checkConnection() to make sure something
268 * is pending.
269 */
Elliott Hughes74847412012-06-20 18:10:21 -0700270static bool acceptConnection(JdwpState* state) {
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700271 JdwpNetState* netState = state->netState;
272 union {
Elliott Hughes7b9d9962012-04-20 18:48:18 -0700273 sockaddr_in addrInet;
274 sockaddr addrPlain;
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700275 } addr;
276 socklen_t addrlen;
277 int sock;
278
279 if (netState->listenSock < 0) {
280 return false; /* you're not listening! */
281 }
282
283 CHECK_LT(netState->clientSock, 0); /* must not already be talking */
284
285 addrlen = sizeof(addr);
286 do {
287 sock = accept(netState->listenSock, &addr.addrPlain, &addrlen);
288 if (sock < 0 && errno != EINTR) {
289 // When we call shutdown() on the socket, accept() returns with
290 // EINVAL. Don't gripe about it.
291 if (errno == EINVAL) {
Elliott Hughes4dd9b4d2011-12-12 18:29:24 -0800292 if (VLOG_IS_ON(jdwp)) {
293 PLOG(ERROR) << "accept failed";
294 }
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700295 } else {
296 PLOG(ERROR) << "accept failed";
297 return false;
298 }
299 }
300 } while (sock < 0);
301
302 netState->remoteAddr = addr.addrInet.sin_addr;
303 netState->remotePort = ntohs(addr.addrInet.sin_port);
Elliott Hughes4dd9b4d2011-12-12 18:29:24 -0800304 VLOG(jdwp) << "+++ accepted connection from " << inet_ntoa(netState->remoteAddr) << ":" << netState->remotePort;
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700305
306 netState->clientSock = sock;
307 netState->awaitingHandshake = true;
308 netState->inputCount = 0;
309
Elliott Hughes4dd9b4d2011-12-12 18:29:24 -0800310 VLOG(jdwp) << "Setting TCP_NODELAY on accepted socket";
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700311 setNoDelay(netState->clientSock);
312
313 if (pipe(netState->wakePipe) < 0) {
314 PLOG(ERROR) << "pipe failed";
315 return false;
316 }
317
318 return true;
319}
320
321/*
322 * Create a connection to a waiting debugger.
323 */
Elliott Hughesa21039c2012-06-21 12:09:25 -0700324static bool establishConnection(JdwpState* state, const JdwpOptions* options) {
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700325 union {
Elliott Hughes7b9d9962012-04-20 18:48:18 -0700326 sockaddr_in addrInet;
327 sockaddr addrPlain;
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700328 } addr;
Elliott Hughes7b9d9962012-04-20 18:48:18 -0700329 hostent* pEntry;
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700330
331 CHECK(state != NULL && state->netState != NULL);
Elliott Hughesa21039c2012-06-21 12:09:25 -0700332 CHECK(!options->server);
333 CHECK(!options->host.empty());
334 CHECK_NE(options->port, 0);
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700335
336 /*
337 * Start by resolving the host name.
338 */
339//#undef HAVE_GETHOSTBYNAME_R
340//#warning "forcing non-R"
341#ifdef HAVE_GETHOSTBYNAME_R
Elliott Hughes7b9d9962012-04-20 18:48:18 -0700342 hostent he;
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700343 char auxBuf[128];
344 int error;
Elliott Hughesa21039c2012-06-21 12:09:25 -0700345 int cc = gethostbyname_r(options->host.c_str(), &he, auxBuf, sizeof(auxBuf), &pEntry, &error);
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700346 if (cc != 0) {
Elliott Hughesa21039c2012-06-21 12:09:25 -0700347 LOG(WARNING) << "gethostbyname_r('" << options->host << "') failed: " << hstrerror(error);
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700348 return false;
349 }
350#else
351 h_errno = 0;
Elliott Hughesa21039c2012-06-21 12:09:25 -0700352 pEntry = gethostbyname(options->host.c_str());
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700353 if (pEntry == NULL) {
Elliott Hughesa21039c2012-06-21 12:09:25 -0700354 PLOG(WARNING) << "gethostbyname('" << options->host << "') failed";
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700355 return false;
356 }
357#endif
358
359 /* copy it out ASAP to minimize risk of multithreaded annoyances */
360 memcpy(&addr.addrInet.sin_addr, pEntry->h_addr, pEntry->h_length);
361 addr.addrInet.sin_family = pEntry->h_addrtype;
362
Elliott Hughesa21039c2012-06-21 12:09:25 -0700363 addr.addrInet.sin_port = htons(options->port);
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700364
365 LOG(INFO) << "Connecting out to " << inet_ntoa(addr.addrInet.sin_addr) << ":" << ntohs(addr.addrInet.sin_port);
366
367 /*
368 * Create a socket.
369 */
370 JdwpNetState* netState;
371 netState = state->netState;
372 netState->clientSock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
373 if (netState->clientSock < 0) {
374 PLOG(ERROR) << "Unable to create socket";
375 return false;
376 }
377
378 /*
379 * Try to connect.
380 */
381 if (connect(netState->clientSock, &addr.addrPlain, sizeof(addr)) != 0) {
382 PLOG(ERROR) << "Unable to connect to " << inet_ntoa(addr.addrInet.sin_addr) << ":" << ntohs(addr.addrInet.sin_port);
383 close(netState->clientSock);
384 netState->clientSock = -1;
385 return false;
386 }
387
Elliott Hughesa21039c2012-06-21 12:09:25 -0700388 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 -0700389 netState->awaitingHandshake = true;
390 netState->inputCount = 0;
391
392 setNoDelay(netState->clientSock);
393
394 if (pipe(netState->wakePipe) < 0) {
395 PLOG(ERROR) << "pipe failed";
396 return false;
397 }
398
399 return true;
400}
401
402/*
403 * Close the connection to the debugger.
404 *
405 * Reset the state so we're ready to receive a new connection.
406 */
407static void closeConnection(JdwpState* state) {
408 JdwpNetState* netState;
409
410 CHECK(state != NULL && state->netState != NULL);
411
412 netState = state->netState;
413 if (netState->clientSock < 0) {
414 return;
415 }
416
Elliott Hughes4dd9b4d2011-12-12 18:29:24 -0800417 VLOG(jdwp) << "+++ closed connection to " << inet_ntoa(netState->remoteAddr) << ":" << netState->remotePort;
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700418
419 close(netState->clientSock);
420 netState->clientSock = -1;
421}
422
423/*
424 * Figure out if we have a full packet in the buffer.
425 */
426static bool haveFullPacket(JdwpNetState* netState) {
427 if (netState->awaitingHandshake) {
Elliott Hughes74847412012-06-20 18:10:21 -0700428 return (netState->inputCount >= kMagicHandshakeLen);
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700429 }
430 if (netState->inputCount < 4) {
431 return false;
432 }
Elliott Hughes74847412012-06-20 18:10:21 -0700433 uint32_t length = Get4BE(netState->inputBuffer);
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700434 return (netState->inputCount >= length);
435}
436
437/*
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700438 * Process incoming data. If no data is available, this will block until
439 * some arrives.
440 *
441 * If we get a full packet, handle it.
442 *
443 * To take some of the mystery out of life, we want to reject incoming
444 * connections if we already have a debugger attached. If we don't, the
445 * debugger will just mysteriously hang until it times out. We could just
446 * close the listen socket, but there's a good chance we won't be able to
447 * bind to the same port again, which would confuse utilities.
448 *
449 * Returns "false" on error (indicating that the connection has been severed),
450 * "true" if things are still okay.
451 */
452static bool processIncoming(JdwpState* state) {
453 JdwpNetState* netState = state->netState;
454 int readCount;
455
456 CHECK_GE(netState->clientSock, 0);
457
458 if (!haveFullPacket(netState)) {
459 /* read some more, looping until we have data */
460 errno = 0;
461 while (1) {
462 int selCount;
463 fd_set readfds;
464 int maxfd;
465 int fd;
466
467 maxfd = netState->listenSock;
468 if (netState->clientSock > maxfd) {
469 maxfd = netState->clientSock;
470 }
471 if (netState->wakePipe[0] > maxfd) {
472 maxfd = netState->wakePipe[0];
473 }
474
475 if (maxfd < 0) {
Elliott Hughes4dd9b4d2011-12-12 18:29:24 -0800476 VLOG(jdwp) << "+++ all fds are closed";
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700477 return false;
478 }
479
480 FD_ZERO(&readfds);
481
482 /* configure fds; note these may get zapped by another thread */
483 fd = netState->listenSock;
484 if (fd >= 0) {
485 FD_SET(fd, &readfds);
486 }
487 fd = netState->clientSock;
488 if (fd >= 0) {
489 FD_SET(fd, &readfds);
490 }
491 fd = netState->wakePipe[0];
492 if (fd >= 0) {
493 FD_SET(fd, &readfds);
494 } else {
495 LOG(INFO) << "NOTE: entering select w/o wakepipe";
496 }
497
498 /*
499 * Select blocks until it sees activity on the file descriptors.
500 * Closing the local file descriptor does not count as activity,
501 * so we can't rely on that to wake us up (it works for read()
502 * and accept(), but not select()).
503 *
504 * We can do one of three things: (1) send a signal and catch
505 * EINTR, (2) open an additional fd ("wakePipe") and write to
506 * it when it's time to exit, or (3) time out periodically and
507 * re-issue the select. We're currently using #2, as it's more
508 * reliable than #1 and generally better than #3. Wastes two fds.
509 */
510 selCount = select(maxfd+1, &readfds, NULL, NULL, NULL);
511 if (selCount < 0) {
512 if (errno == EINTR) {
513 continue;
514 }
515 PLOG(ERROR) << "select failed";
516 goto fail;
517 }
518
519 if (netState->wakePipe[0] >= 0 && FD_ISSET(netState->wakePipe[0], &readfds)) {
520 if (netState->listenSock >= 0) {
521 LOG(ERROR) << "Exit wake set, but not exiting?";
522 } else {
523 LOG(DEBUG) << "Got wake-up signal, bailing out of select";
524 }
525 goto fail;
526 }
527 if (netState->listenSock >= 0 && FD_ISSET(netState->listenSock, &readfds)) {
528 LOG(INFO) << "Ignoring second debugger -- accepting and dropping";
529 union {
Elliott Hughes7b9d9962012-04-20 18:48:18 -0700530 sockaddr_in addrInet;
531 sockaddr addrPlain;
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700532 } addr;
533 socklen_t addrlen;
534 int tmpSock;
535 tmpSock = accept(netState->listenSock, &addr.addrPlain, &addrlen);
536 if (tmpSock < 0) {
537 LOG(INFO) << "Weird -- accept failed";
538 } else {
539 close(tmpSock);
540 }
541 }
542 if (netState->clientSock >= 0 && FD_ISSET(netState->clientSock, &readfds)) {
543 readCount = read(netState->clientSock, netState->inputBuffer + netState->inputCount, sizeof(netState->inputBuffer) - netState->inputCount);
544 if (readCount < 0) {
545 /* read failed */
546 if (errno != EINTR) {
547 goto fail;
548 }
549 LOG(DEBUG) << "+++ EINTR hit";
550 return true;
551 } else if (readCount == 0) {
552 /* EOF hit -- far end went away */
553 LOG(DEBUG) << "+++ peer disconnected";
554 goto fail;
555 } else {
556 break;
557 }
558 }
559 }
560
561 netState->inputCount += readCount;
562 if (!haveFullPacket(netState)) {
563 return true; /* still not there yet */
564 }
565 }
566
567 /*
568 * Special-case the initial handshake. For some bizarre reason we're
569 * expected to emulate bad tty settings by echoing the request back
570 * exactly as it was sent. Note the handshake is always initiated by
571 * the debugger, no matter who connects to whom.
572 *
573 * Other than this one case, the protocol [claims to be] stateless.
574 */
575 if (netState->awaitingHandshake) {
576 int cc;
577
578 if (memcmp(netState->inputBuffer, kMagicHandshake, kMagicHandshakeLen) != 0) {
579 LOG(ERROR) << StringPrintf("ERROR: bad handshake '%.14s'", netState->inputBuffer);
580 goto fail;
581 }
582
583 errno = 0;
Elliott Hughes068193c2013-04-15 16:05:28 -0700584 cc = TEMP_FAILURE_RETRY(write(netState->clientSock, netState->inputBuffer, kMagicHandshakeLen));
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700585 if (cc != kMagicHandshakeLen) {
586 PLOG(ERROR) << "Failed writing handshake bytes (" << cc << " of " << kMagicHandshakeLen << ")";
587 goto fail;
588 }
589
Elliott Hughescb693062013-02-21 09:48:08 -0800590 netState->ConsumeBytes(kMagicHandshakeLen);
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700591 netState->awaitingHandshake = false;
Elliott Hughes4dd9b4d2011-12-12 18:29:24 -0800592 VLOG(jdwp) << "+++ handshake complete";
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700593 return true;
594 }
595
596 /*
597 * Handle this packet.
598 */
Elliott Hughescb693062013-02-21 09:48:08 -0800599 return state->HandlePacket();
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700600
Elliott Hughesa21039c2012-06-21 12:09:25 -0700601 fail:
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700602 closeConnection(state);
603 return false;
604}
605
606/*
607 * Send a request.
608 *
609 * The entire packet must be sent with a single write() call to avoid
610 * threading issues.
611 *
612 * Returns "true" if it was sent successfully.
613 */
614static bool sendRequest(JdwpState* state, ExpandBuf* pReq) {
615 JdwpNetState* netState = state->netState;
616
617 /*dumpPacket(expandBufGetBuffer(pReq));*/
618 if (netState->clientSock < 0) {
619 /* can happen with some DDMS events */
Elliott Hughes4dd9b4d2011-12-12 18:29:24 -0800620 VLOG(jdwp) << "NOT sending request -- no debugger is attached";
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700621 return false;
622 }
623
624 errno = 0;
Elliott Hughescb693062013-02-21 09:48:08 -0800625 ssize_t cc = netState->WritePacket(pReq);
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700626
627 if (cc != (ssize_t) expandBufGetLength(pReq)) {
628 PLOG(ERROR) << "Failed sending req to debugger (" << cc << " of " << expandBufGetLength(pReq) << ")";
629 return false;
630 }
631
632 return true;
633}
634
635/*
636 * Send a request that was split into multiple buffers.
637 *
638 * The entire packet must be sent with a single writev() call to avoid
639 * threading issues.
640 *
641 * Returns "true" if it was sent successfully.
642 */
Elliott Hughescccd84f2011-12-05 16:51:54 -0800643static bool sendBufferedRequest(JdwpState* state, const iovec* iov, int iov_count) {
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700644 JdwpNetState* netState = state->netState;
645
646 if (netState->clientSock < 0) {
647 /* can happen with some DDMS events */
Elliott Hughes4dd9b4d2011-12-12 18:29:24 -0800648 VLOG(jdwp) << "NOT sending request -- no debugger is attached";
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700649 return false;
650 }
651
652 size_t expected = 0;
Elliott Hughescccd84f2011-12-05 16:51:54 -0800653 for (int i = 0; i < iov_count; i++) {
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700654 expected += iov[i].iov_len;
655 }
656
Elliott Hughescb693062013-02-21 09:48:08 -0800657 ssize_t actual = netState->WriteBufferedPacket(iov, iov_count);
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700658
659 if ((size_t)actual != expected) {
660 PLOG(ERROR) << "Failed sending b-req to debugger (" << actual << " of " << expected << ")";
661 return false;
662 }
663
664 return true;
665}
666
667/*
668 * Our functions.
669 *
670 * We can't generally share the implementations with other transports,
671 * even if they're also socket-based, because our JdwpNetState will be
672 * different from theirs.
673 */
674static const JdwpTransport socketTransport = {
675 prepareSocket,
676 acceptConnection,
677 establishConnection,
678 closeConnection,
679 netShutdownExtern,
680 netFreeExtern,
681 isConnected,
682 awaitingHandshake,
683 processIncoming,
684 sendRequest,
685 sendBufferedRequest,
686};
687
688/*
689 * Return our set.
690 */
691const JdwpTransport* SocketTransport() {
692 return &socketTransport;
693}
694
695} // namespace JDWP
696
697} // namespace art