JdwpSocket.cpp revision 60fc806b679a3655c228b4093058c59941a49cfe
1/* 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/JdwpPriv.h" 20#include "jdwp/JdwpHandler.h" 21#include "Bits.h" 22 23#include <stdlib.h> 24#include <unistd.h> 25#include <stdio.h> 26#include <string.h> 27#include <errno.h> 28#include <sys/types.h> 29#include <sys/socket.h> 30#include <netinet/in.h> 31#include <netinet/tcp.h> 32#include <arpa/inet.h> 33#include <netdb.h> 34 35#define kBasePort 8000 36#define kMaxPort 8040 37 38#define kInputBufferSize 8192 39 40#define kMagicHandshake "JDWP-Handshake" 41#define kMagicHandshakeLen (sizeof(kMagicHandshake)-1) 42 43// fwd 44static void netShutdown(JdwpNetState* state); 45static void netFree(JdwpNetState* state); 46 47 48/* 49 * JDWP network state. 50 * 51 * We only talk to one debugger at a time. 52 */ 53struct JdwpNetState { 54 short listenPort; 55 int listenSock; /* listen for connection from debugger */ 56 int clientSock; /* active connection to debugger */ 57 int wakePipe[2]; /* break out of select */ 58 59 struct in_addr remoteAddr; 60 unsigned short remotePort; 61 62 bool awaitingHandshake; /* waiting for "JDWP-Handshake" */ 63 64 /* pending data from the network; would be more efficient as circular buf */ 65 unsigned char inputBuffer[kInputBufferSize]; 66 int inputCount; 67}; 68 69static JdwpNetState* netStartup(short port); 70 71/* 72 * Set up some stuff for transport=dt_socket. 73 */ 74static bool prepareSocket(JdwpState* state, const JdwpStartupParams* pParams) 75{ 76 unsigned short port; 77 78 if (pParams->server) { 79 if (pParams->port != 0) { 80 /* try only the specified port */ 81 port = pParams->port; 82 state->netState = netStartup(port); 83 } else { 84 /* scan through a range of ports, binding to the first available */ 85 for (port = kBasePort; port <= kMaxPort; port++) { 86 state->netState = netStartup(port); 87 if (state->netState != NULL) 88 break; 89 } 90 } 91 if (state->netState == NULL) { 92 LOGE("JDWP net startup failed (req port=%d)", pParams->port); 93 return false; 94 } 95 } else { 96 port = pParams->port; // used in a debug msg later 97 state->netState = netStartup(-1); 98 } 99 100 if (pParams->suspend) 101 LOGI("JDWP will wait for debugger on port %d", port); 102 else 103 LOGD("JDWP will %s on port %d", 104 pParams->server ? "listen" : "connect", port); 105 106 return true; 107} 108 109 110/* 111 * Are we still waiting for the handshake string? 112 */ 113static bool awaitingHandshake(JdwpState* state) 114{ 115 return state->netState->awaitingHandshake; 116} 117 118/* 119 * Initialize JDWP stuff. 120 * 121 * Allocates a new state structure. If "port" is non-negative, this also 122 * tries to bind to a listen port. If "port" is less than zero, we assume 123 * we're preparing for an outbound connection, and return without binding 124 * to anything. 125 * 126 * This may be called several times if we're probing for a port. 127 * 128 * Returns 0 on success. 129 */ 130static JdwpNetState* netStartup(short port) 131{ 132 JdwpNetState* netState; 133 int one = 1; 134 135 netState = (JdwpNetState*) malloc(sizeof(*netState)); 136 memset(netState, 0, sizeof(*netState)); 137 netState->listenSock = -1; 138 netState->clientSock = -1; 139 netState->wakePipe[0] = -1; 140 netState->wakePipe[1] = -1; 141 142 if (port < 0) 143 return netState; 144 145 assert(port != 0); 146 147 netState->listenSock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP); 148 if (netState->listenSock < 0) { 149 LOGE("Socket create failed: %s", strerror(errno)); 150 goto fail; 151 } 152 153 /* allow immediate re-use */ 154 if (setsockopt(netState->listenSock, SOL_SOCKET, SO_REUSEADDR, &one, 155 sizeof(one)) < 0) 156 { 157 LOGE("setsockopt(SO_REUSEADDR) failed: %s", strerror(errno)); 158 goto fail; 159 } 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) { 170 LOGV("attempt to bind to port %u failed: %s", port, strerror(errno)); 171 goto fail; 172 } 173 174 netState->listenPort = port; 175 LOGVV("+++ bound to port %d", netState->listenPort); 176 177 if (listen(netState->listenSock, 5) != 0) { 178 LOGE("Listen failed: %s", strerror(errno)); 179 goto fail; 180 } 181 182 return netState; 183 184fail: 185 netShutdown(netState); 186 netFree(netState); 187 return NULL; 188} 189 190/* 191 * Shut down JDWP listener. Don't free state. 192 * 193 * Note that "netState" may be partially initialized if "startup" failed. 194 * 195 * This may be called from a non-JDWP thread as part of shutting the 196 * JDWP thread down. 197 * 198 * (This is currently called several times during startup as we probe 199 * for an open port.) 200 */ 201static void netShutdown(JdwpNetState* netState) 202{ 203 if (netState == NULL) 204 return; 205 206 int listenSock = netState->listenSock; 207 int clientSock = netState->clientSock; 208 209 /* clear these out so it doesn't wake up and try to reuse them */ 210 netState->listenSock = netState->clientSock = -1; 211 212 /* "shutdown" dislodges blocking read() and accept() calls */ 213 if (listenSock >= 0) { 214 shutdown(listenSock, SHUT_RDWR); 215 close(listenSock); 216 } 217 if (clientSock >= 0) { 218 shutdown(clientSock, SHUT_RDWR); 219 close(clientSock); 220 } 221 222 /* if we might be sitting in select, kick us loose */ 223 if (netState->wakePipe[1] >= 0) { 224 LOGV("+++ writing to wakePipe"); 225 (void) write(netState->wakePipe[1], "", 1); 226 } 227} 228static void netShutdownExtern(JdwpState* state) 229{ 230 netShutdown(state->netState); 231} 232 233/* 234 * Free JDWP state. 235 * 236 * Call this after shutting the network down with netShutdown(). 237 */ 238static void netFree(JdwpNetState* netState) 239{ 240 if (netState == NULL) 241 return; 242 assert(netState->listenSock == -1); 243 assert(netState->clientSock == -1); 244 245 if (netState->wakePipe[0] >= 0) { 246 close(netState->wakePipe[0]); 247 netState->wakePipe[0] = -1; 248 } 249 if (netState->wakePipe[1] >= 0) { 250 close(netState->wakePipe[1]); 251 netState->wakePipe[1] = -1; 252 } 253 254 free(netState); 255} 256static void netFreeExtern(JdwpState* state) 257{ 258 netFree(state->netState); 259} 260 261/* 262 * Returns "true" if we're connected to a debugger. 263 */ 264static bool isConnected(JdwpState* state) 265{ 266 return (state->netState != NULL && 267 state->netState->clientSock >= 0); 268} 269 270/* 271 * Returns "true" if the fd is ready, "false" if not. 272 */ 273#if 0 274static bool isFdReadable(int sock) 275{ 276 fd_set readfds; 277 struct timeval tv; 278 int count; 279 280 FD_ZERO(&readfds); 281 FD_SET(sock, &readfds); 282 283 tv.tv_sec = 0; 284 tv.tv_usec = 0; 285 count = select(sock+1, &readfds, NULL, NULL, &tv); 286 if (count <= 0) 287 return false; 288 289 if (FD_ISSET(sock, &readfds)) /* make sure it's our fd */ 290 return true; 291 292 LOGE("WEIRD: odd behavior in select (count=%d)", count); 293 return false; 294} 295#endif 296 297#if 0 298/* 299 * Check to see if we have a pending connection from the debugger. 300 * 301 * Returns true on success (meaning a connection is available). 302 */ 303static bool checkConnection(JdwpState* state) 304{ 305 JdwpNetState* netState = state->netState; 306 307 assert(netState->listenSock >= 0); 308 /* not expecting to be called when debugger is actively connected */ 309 assert(netState->clientSock < 0); 310 311 if (!isFdReadable(netState->listenSock)) 312 return false; 313 return true; 314} 315#endif 316 317/* 318 * Disable the TCP Nagle algorithm, which delays transmission of outbound 319 * packets until the previous transmissions have been acked. JDWP does a 320 * lot of back-and-forth with small packets, so this may help. 321 */ 322static int setNoDelay(int fd) 323{ 324 int cc, on = 1; 325 326 cc = setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &on, sizeof(on)); 327 assert(cc == 0); 328 return cc; 329} 330 331/* 332 * Accept a connection. This will block waiting for somebody to show up. 333 * If that's not desirable, use checkConnection() to make sure something 334 * is pending. 335 */ 336static bool acceptConnection(JdwpState* state) 337{ 338 JdwpNetState* netState = state->netState; 339 union { 340 struct sockaddr_in addrInet; 341 struct sockaddr addrPlain; 342 } addr; 343 socklen_t addrlen; 344 int sock; 345 346 if (netState->listenSock < 0) 347 return false; /* you're not listening! */ 348 349 assert(netState->clientSock < 0); /* must not already be talking */ 350 351 addrlen = sizeof(addr); 352 do { 353 sock = accept(netState->listenSock, &addr.addrPlain, &addrlen); 354 if (sock < 0 && errno != EINTR) { 355 // When we call shutdown() on the socket, accept() returns with 356 // EINVAL. Don't gripe about it. 357 if (errno == EINVAL) 358 LOGVV("accept failed: %s", strerror(errno)); 359 else 360 LOGE("accept failed: %s", strerror(errno)); 361 return false; 362 } 363 } while (sock < 0); 364 365 netState->remoteAddr = addr.addrInet.sin_addr; 366 netState->remotePort = ntohs(addr.addrInet.sin_port); 367 LOGV("+++ accepted connection from %s:%u", 368 inet_ntoa(netState->remoteAddr), netState->remotePort); 369 370 netState->clientSock = sock; 371 netState->awaitingHandshake = true; 372 netState->inputCount = 0; 373 374 LOGV("Setting TCP_NODELAY on accepted socket"); 375 setNoDelay(netState->clientSock); 376 377 if (pipe(netState->wakePipe) < 0) { 378 LOGE("pipe failed"); 379 return false; 380 } 381 382 return true; 383} 384 385/* 386 * Create a connection to a waiting debugger. 387 */ 388static bool establishConnection(JdwpState* state) 389{ 390 union { 391 struct sockaddr_in addrInet; 392 struct sockaddr addrPlain; 393 } addr; 394 struct hostent* pEntry; 395 int h_errno; 396 397 assert(state != NULL && state->netState != NULL); 398 assert(!state->params.server); 399 assert(state->params.host[0] != '\0'); 400 assert(state->params.port != 0); 401 402 /* 403 * Start by resolving the host name. 404 */ 405//#undef HAVE_GETHOSTBYNAME_R 406//#warning "forcing non-R" 407#ifdef HAVE_GETHOSTBYNAME_R 408 struct hostent he; 409 char auxBuf[128]; 410 int cc = gethostbyname_r(state->params.host, &he, auxBuf, sizeof(auxBuf), 411 &pEntry, &h_errno); 412 if (cc != 0) { 413 LOGW("gethostbyname_r('%s') failed: %s", 414 state->params.host, strerror(errno)); 415 return false; 416 } 417 418#else 419 h_errno = 0; 420 pEntry = gethostbyname(state->params.host); 421 if (pEntry == NULL) { 422 LOGW("gethostbyname('%s') failed: %s", 423 state->params.host, strerror(h_errno)); 424 return false; 425 } 426#endif 427 428 /* copy it out ASAP to minimize risk of multithreaded annoyances */ 429 memcpy(&addr.addrInet.sin_addr, pEntry->h_addr, pEntry->h_length); 430 addr.addrInet.sin_family = pEntry->h_addrtype; 431 432 addr.addrInet.sin_port = htons(state->params.port); 433 434 LOGI("Connecting out to '%s' %d", 435 inet_ntoa(addr.addrInet.sin_addr), ntohs(addr.addrInet.sin_port)); 436 437 /* 438 * Create a socket. 439 */ 440 JdwpNetState* netState; 441 netState = state->netState; 442 netState->clientSock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP); 443 if (netState->clientSock < 0) { 444 LOGE("Unable to create socket: %s", strerror(errno)); 445 return false; 446 } 447 448 /* 449 * Try to connect. 450 */ 451 if (connect(netState->clientSock, &addr.addrPlain, sizeof(addr)) != 0) { 452 LOGE("Unable to connect to %s:%d: %s", 453 inet_ntoa(addr.addrInet.sin_addr), ntohs(addr.addrInet.sin_port), 454 strerror(errno)); 455 close(netState->clientSock); 456 netState->clientSock = -1; 457 return false; 458 } 459 460 LOGI("Connection established to %s (%s:%d)", 461 state->params.host, inet_ntoa(addr.addrInet.sin_addr), 462 ntohs(addr.addrInet.sin_port)); 463 netState->awaitingHandshake = true; 464 netState->inputCount = 0; 465 466 setNoDelay(netState->clientSock); 467 468 if (pipe(netState->wakePipe) < 0) { 469 LOGE("pipe failed"); 470 return false; 471 } 472 473 return true; 474} 475 476/* 477 * Close the connection to the debugger. 478 * 479 * Reset the state so we're ready to receive a new connection. 480 */ 481static void closeConnection(JdwpState* state) 482{ 483 JdwpNetState* netState; 484 485 assert(state != NULL && state->netState != NULL); 486 487 netState = state->netState; 488 if (netState->clientSock < 0) 489 return; 490 491 LOGV("+++ closed connection to %s:%u", 492 inet_ntoa(netState->remoteAddr), netState->remotePort); 493 494 close(netState->clientSock); 495 netState->clientSock = -1; 496 497 return; 498} 499 500/* 501 * Figure out if we have a full packet in the buffer. 502 */ 503static bool haveFullPacket(JdwpNetState* netState) 504{ 505 long length; 506 507 if (netState->awaitingHandshake) 508 return (netState->inputCount >= (int) kMagicHandshakeLen); 509 510 if (netState->inputCount < 4) 511 return false; 512 513 length = get4BE(netState->inputBuffer); 514 return (netState->inputCount >= length); 515} 516 517/* 518 * Consume bytes from the buffer. 519 * 520 * This would be more efficient with a circular buffer. However, we're 521 * usually only going to find one packet, which is trivial to handle. 522 */ 523static void consumeBytes(JdwpNetState* netState, int count) 524{ 525 assert(count > 0); 526 assert(count <= netState->inputCount); 527 528 if (count == netState->inputCount) { 529 netState->inputCount = 0; 530 return; 531 } 532 533 memmove(netState->inputBuffer, netState->inputBuffer + count, 534 netState->inputCount - count); 535 netState->inputCount -= count; 536} 537 538/* 539 * Dump the contents of a packet to stdout. 540 */ 541#if 0 542static void dumpPacket(const unsigned char* packetBuf) 543{ 544 const unsigned char* buf = packetBuf; 545 u4 length, id; 546 u1 flags, cmdSet, cmd; 547 u2 error; 548 bool reply; 549 int dataLen; 550 551 cmd = cmdSet = 0xcc; 552 553 length = read4BE(&buf); 554 id = read4BE(&buf); 555 flags = read1(&buf); 556 if ((flags & kJDWPFlagReply) != 0) { 557 reply = true; 558 error = read2BE(&buf); 559 } else { 560 reply = false; 561 cmdSet = read1(&buf); 562 cmd = read1(&buf); 563 } 564 565 dataLen = length - (buf - packetBuf); 566 567 LOGV("--- %s: dataLen=%u id=0x%08x flags=0x%02x cmd=%d/%d", 568 reply ? "reply" : "req", 569 dataLen, id, flags, cmdSet, cmd); 570 if (dataLen > 0) 571 dvmPrintHexDumpDbg(buf, dataLen, LOG_TAG); 572} 573#endif 574 575/* 576 * Handle a packet. Returns "false" if we encounter a connection-fatal error. 577 */ 578static bool handlePacket(JdwpState* state) 579{ 580 JdwpNetState* netState = state->netState; 581 const unsigned char* buf = netState->inputBuffer; 582 JdwpReqHeader hdr; 583 u4 length, id; 584 u1 flags, cmdSet, cmd; 585 u2 error; 586 bool reply; 587 int dataLen; 588 589 cmd = cmdSet = 0; // shut up gcc 590 591 /*dumpPacket(netState->inputBuffer);*/ 592 593 length = read4BE(&buf); 594 id = read4BE(&buf); 595 flags = read1(&buf); 596 if ((flags & kJDWPFlagReply) != 0) { 597 reply = true; 598 error = read2BE(&buf); 599 } else { 600 reply = false; 601 cmdSet = read1(&buf); 602 cmd = read1(&buf); 603 } 604 605 assert((int) length <= netState->inputCount); 606 dataLen = length - (buf - netState->inputBuffer); 607 608 if (!reply) { 609 ExpandBuf* pReply = expandBufAlloc(); 610 611 hdr.length = length; 612 hdr.id = id; 613 hdr.cmdSet = cmdSet; 614 hdr.cmd = cmd; 615 dvmJdwpProcessRequest(state, &hdr, buf, dataLen, pReply); 616 if (expandBufGetLength(pReply) > 0) { 617 int cc; 618 619 /* 620 * TODO: we currently assume the write() will complete in one 621 * go, which may not be safe for a network socket. We may need 622 * to mutex this against sendRequest(). 623 */ 624 cc = write(netState->clientSock, expandBufGetBuffer(pReply), 625 expandBufGetLength(pReply)); 626 if (cc != (int) expandBufGetLength(pReply)) { 627 LOGE("Failed sending reply to debugger: %s", strerror(errno)); 628 expandBufFree(pReply); 629 return false; 630 } 631 } else { 632 LOGW("No reply created for set=%d cmd=%d", cmdSet, cmd); 633 } 634 expandBufFree(pReply); 635 } else { 636 LOGV("reply?!"); 637 assert(false); 638 } 639 640 LOGV("----------"); 641 642 consumeBytes(netState, length); 643 return true; 644} 645 646/* 647 * Process incoming data. If no data is available, this will block until 648 * some arrives. 649 * 650 * If we get a full packet, handle it. 651 * 652 * To take some of the mystery out of life, we want to reject incoming 653 * connections if we already have a debugger attached. If we don't, the 654 * debugger will just mysteriously hang until it times out. We could just 655 * close the listen socket, but there's a good chance we won't be able to 656 * bind to the same port again, which would confuse utilities. 657 * 658 * Returns "false" on error (indicating that the connection has been severed), 659 * "true" if things are still okay. 660 */ 661static bool processIncoming(JdwpState* state) 662{ 663 JdwpNetState* netState = state->netState; 664 int readCount; 665 666 assert(netState->clientSock >= 0); 667 668 if (!haveFullPacket(netState)) { 669 /* read some more, looping until we have data */ 670 errno = 0; 671 while (1) { 672 int selCount; 673 fd_set readfds; 674 int maxfd; 675 int fd; 676 677 maxfd = netState->listenSock; 678 if (netState->clientSock > maxfd) 679 maxfd = netState->clientSock; 680 if (netState->wakePipe[0] > maxfd) 681 maxfd = netState->wakePipe[0]; 682 683 if (maxfd < 0) { 684 LOGV("+++ all fds are closed"); 685 return false; 686 } 687 688 FD_ZERO(&readfds); 689 690 /* configure fds; note these may get zapped by another thread */ 691 fd = netState->listenSock; 692 if (fd >= 0) 693 FD_SET(fd, &readfds); 694 fd = netState->clientSock; 695 if (fd >= 0) 696 FD_SET(fd, &readfds); 697 fd = netState->wakePipe[0]; 698 if (fd >= 0) { 699 FD_SET(fd, &readfds); 700 } else { 701 LOGI("NOTE: entering select w/o wakepipe"); 702 } 703 704 /* 705 * Select blocks until it sees activity on the file descriptors. 706 * Closing the local file descriptor does not count as activity, 707 * so we can't rely on that to wake us up (it works for read() 708 * and accept(), but not select()). 709 * 710 * We can do one of three things: (1) send a signal and catch 711 * EINTR, (2) open an additional fd ("wakePipe") and write to 712 * it when it's time to exit, or (3) time out periodically and 713 * re-issue the select. We're currently using #2, as it's more 714 * reliable than #1 and generally better than #3. Wastes two fds. 715 */ 716 selCount = select(maxfd+1, &readfds, NULL, NULL, NULL); 717 if (selCount < 0) { 718 if (errno == EINTR) 719 continue; 720 LOGE("select failed: %s", strerror(errno)); 721 goto fail; 722 } 723 724 if (netState->wakePipe[0] >= 0 && 725 FD_ISSET(netState->wakePipe[0], &readfds)) 726 { 727 if (netState->listenSock >= 0) 728 LOGE("Exit wake set, but not exiting?"); 729 else 730 LOGD("Got wake-up signal, bailing out of select"); 731 goto fail; 732 } 733 if (netState->listenSock >= 0 && 734 FD_ISSET(netState->listenSock, &readfds)) 735 { 736 LOGI("Ignoring second debugger -- accepting and dropping"); 737 union { 738 struct sockaddr_in addrInet; 739 struct sockaddr addrPlain; 740 } addr; 741 socklen_t addrlen; 742 int tmpSock; 743 tmpSock = accept(netState->listenSock, &addr.addrPlain, 744 &addrlen); 745 if (tmpSock < 0) 746 LOGI("Weird -- accept failed"); 747 else 748 close(tmpSock); 749 } 750 if (netState->clientSock >= 0 && 751 FD_ISSET(netState->clientSock, &readfds)) 752 { 753 readCount = read(netState->clientSock, 754 netState->inputBuffer + netState->inputCount, 755 sizeof(netState->inputBuffer) - netState->inputCount); 756 if (readCount < 0) { 757 /* read failed */ 758 if (errno != EINTR) 759 goto fail; 760 LOGD("+++ EINTR hit"); 761 return true; 762 } else if (readCount == 0) { 763 /* EOF hit -- far end went away */ 764 LOGD("+++ peer disconnected"); 765 goto fail; 766 } else 767 break; 768 } 769 } 770 771 netState->inputCount += readCount; 772 if (!haveFullPacket(netState)) 773 return true; /* still not there yet */ 774 } 775 776 /* 777 * Special-case the initial handshake. For some bizarre reason we're 778 * expected to emulate bad tty settings by echoing the request back 779 * exactly as it was sent. Note the handshake is always initiated by 780 * the debugger, no matter who connects to whom. 781 * 782 * Other than this one case, the protocol [claims to be] stateless. 783 */ 784 if (netState->awaitingHandshake) { 785 int cc; 786 787 if (memcmp(netState->inputBuffer, 788 kMagicHandshake, kMagicHandshakeLen) != 0) 789 { 790 LOGE("ERROR: bad handshake '%.14s'", netState->inputBuffer); 791 goto fail; 792 } 793 794 errno = 0; 795 cc = write(netState->clientSock, netState->inputBuffer, 796 kMagicHandshakeLen); 797 if (cc != kMagicHandshakeLen) { 798 LOGE("Failed writing handshake bytes: %s (%d of %d)", 799 strerror(errno), cc, (int) kMagicHandshakeLen); 800 goto fail; 801 } 802 803 consumeBytes(netState, kMagicHandshakeLen); 804 netState->awaitingHandshake = false; 805 LOGV("+++ handshake complete"); 806 return true; 807 } 808 809 /* 810 * Handle this packet. 811 */ 812 return handlePacket(state); 813 814fail: 815 closeConnection(state); 816 return false; 817} 818 819/* 820 * Send a request. 821 * 822 * The entire packet must be sent with a single write() call to avoid 823 * threading issues. 824 * 825 * Returns "true" if it was sent successfully. 826 */ 827static bool sendRequest(JdwpState* state, ExpandBuf* pReq) 828{ 829 JdwpNetState* netState = state->netState; 830 int cc; 831 832 /*dumpPacket(expandBufGetBuffer(pReq));*/ 833 if (netState->clientSock < 0) { 834 /* can happen with some DDMS events */ 835 LOGV("NOT sending request -- no debugger is attached"); 836 return false; 837 } 838 839 /* 840 * TODO: we currently assume the write() will complete in one 841 * go, which may not be safe for a network socket. We may need 842 * to mutex this against handlePacket(). 843 */ 844 errno = 0; 845 cc = write(netState->clientSock, expandBufGetBuffer(pReq), 846 expandBufGetLength(pReq)); 847 if (cc != (int) expandBufGetLength(pReq)) { 848 LOGE("Failed sending req to debugger: %s (%d of %d)", 849 strerror(errno), cc, (int) expandBufGetLength(pReq)); 850 return false; 851 } 852 853 return true; 854} 855 856/* 857 * Send a request that was split into multiple buffers. 858 * 859 * The entire packet must be sent with a single writev() call to avoid 860 * threading issues. 861 * 862 * Returns "true" if it was sent successfully. 863 */ 864static bool sendBufferedRequest(JdwpState* state, const struct iovec* iov, 865 int iovcnt) 866{ 867 JdwpNetState* netState = state->netState; 868 869 if (netState->clientSock < 0) { 870 /* can happen with some DDMS events */ 871 LOGV("NOT sending request -- no debugger is attached"); 872 return false; 873 } 874 875 size_t expected = 0; 876 int i; 877 for (i = 0; i < iovcnt; i++) 878 expected += iov[i].iov_len; 879 880 /* 881 * TODO: we currently assume the writev() will complete in one 882 * go, which may not be safe for a network socket. We may need 883 * to mutex this against handlePacket(). 884 */ 885 ssize_t actual; 886 actual = writev(netState->clientSock, iov, iovcnt); 887 if ((size_t)actual != expected) { 888 LOGE("Failed sending b-req to debugger: %s (%d of %zu)", 889 strerror(errno), (int) actual, expected); 890 return false; 891 } 892 893 return true; 894} 895 896 897/* 898 * Our functions. 899 * 900 * We can't generally share the implementations with other transports, 901 * even if they're also socket-based, because our JdwpNetState will be 902 * different from theirs. 903 */ 904static const JdwpTransport socketTransport = { 905 prepareSocket, 906 acceptConnection, 907 establishConnection, 908 closeConnection, 909 netShutdownExtern, 910 netFreeExtern, 911 isConnected, 912 awaitingHandshake, 913 processIncoming, 914 sendRequest, 915 sendBufferedRequest, 916}; 917 918/* 919 * Return our set. 920 */ 921const JdwpTransport* dvmJdwpSocketTransport() 922{ 923 return &socketTransport; 924} 925