1872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes/* 2872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * Copyright (C) 2008 The Android Open Source Project 3872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * 4872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * Licensed under the Apache License, Version 2.0 (the "License"); 5872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * you may not use this file except in compliance with the License. 6872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * You may obtain a copy of the License at 7872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * 8872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * http://www.apache.org/licenses/LICENSE-2.0 9872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * 10872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * Unless required by applicable law or agreed to in writing, software 11872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * distributed under the License is distributed on an "AS IS" BASIS, 12872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * See the License for the specific language governing permissions and 14872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * limitations under the License. 15872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes */ 16872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes 1707ed66b5ae659c452cbe1ab20c3dbf1d6f546461Elliott Hughes#include <arpa/inet.h> 18872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes#include <errno.h> 1907ed66b5ae659c452cbe1ab20c3dbf1d6f546461Elliott Hughes#include <netdb.h> 20872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes#include <netinet/in.h> 21872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes#include <netinet/tcp.h> 2207ed66b5ae659c452cbe1ab20c3dbf1d6f546461Elliott Hughes#include <stdio.h> 2307ed66b5ae659c452cbe1ab20c3dbf1d6f546461Elliott Hughes#include <stdlib.h> 2407ed66b5ae659c452cbe1ab20c3dbf1d6f546461Elliott Hughes#include <string.h> 2507ed66b5ae659c452cbe1ab20c3dbf1d6f546461Elliott Hughes#include <sys/socket.h> 2607ed66b5ae659c452cbe1ab20c3dbf1d6f546461Elliott Hughes#include <sys/types.h> 2707ed66b5ae659c452cbe1ab20c3dbf1d6f546461Elliott Hughes#include <unistd.h> 2807ed66b5ae659c452cbe1ab20c3dbf1d6f546461Elliott Hughes 2907ed66b5ae659c452cbe1ab20c3dbf1d6f546461Elliott Hughes#include "base/logging.h" 30e222ee0b794f941af4fb1b32fb8224e32942ea7bElliott Hughes#include "base/stringprintf.h" 3107ed66b5ae659c452cbe1ab20c3dbf1d6f546461Elliott Hughes#include "jdwp/jdwp_priv.h" 32872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes 33872d4ec7225444d9400d30f9027247deb91012fdElliott Hughesnamespace art { 34872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes 35872d4ec7225444d9400d30f9027247deb91012fdElliott Hughesnamespace JDWP { 36872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes 373cbad24f0ee3639ac2ce2d06d61e97386df6f94bRoland Levillainstatic constexpr uint16_t kBasePort = 8000; 383cbad24f0ee3639ac2ce2d06d61e97386df6f94bRoland Levillainstatic constexpr uint16_t kMaxPort = 8040; 393cbad24f0ee3639ac2ce2d06d61e97386df6f94bRoland Levillain 40872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes/* 41872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * JDWP network state. 42872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * 43872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * We only talk to one debugger at a time. 44872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes */ 455d10a87ea630b22180d3731018a70b77270c726eElliott Hughesstruct JdwpSocketState : public JdwpNetStateBase { 46748474146da0c6484fa3dca0a700f612d47550c3Elliott Hughes uint16_t listenPort; 47748474146da0c6484fa3dca0a700f612d47550c3Elliott Hughes int listenSock; /* listen for connection from debugger */ 48872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes 49aa50d3a01a4137cd89c152be5487fed23683d0ffSebastien Hertz explicit JdwpSocketState(JdwpState* state) 50aa50d3a01a4137cd89c152be5487fed23683d0ffSebastien Hertz : JdwpNetStateBase(state), 51aa50d3a01a4137cd89c152be5487fed23683d0ffSebastien Hertz listenPort(0U), 52aa50d3a01a4137cd89c152be5487fed23683d0ffSebastien Hertz listenSock(-1), 53aa50d3a01a4137cd89c152be5487fed23683d0ffSebastien Hertz remote_port_(0U) { 54748474146da0c6484fa3dca0a700f612d47550c3Elliott Hughes } 55872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes 565d10a87ea630b22180d3731018a70b77270c726eElliott Hughes virtual bool Accept(); 575d10a87ea630b22180d3731018a70b77270c726eElliott Hughes virtual bool Establish(const JdwpOptions*); 585d10a87ea630b22180d3731018a70b77270c726eElliott Hughes virtual void Shutdown(); 595d10a87ea630b22180d3731018a70b77270c726eElliott Hughes virtual bool ProcessIncoming(); 6068a5e3c9115f9ba396563ce3b72df9cb036bc665Elliott Hughes 615d10a87ea630b22180d3731018a70b77270c726eElliott Hughes private: 625d10a87ea630b22180d3731018a70b77270c726eElliott Hughes in_addr remote_addr_; 635d10a87ea630b22180d3731018a70b77270c726eElliott Hughes uint16_t remote_port_; 645d10a87ea630b22180d3731018a70b77270c726eElliott Hughes}; 6568a5e3c9115f9ba396563ce3b72df9cb036bc665Elliott Hughes 665d10a87ea630b22180d3731018a70b77270c726eElliott Hughesstatic JdwpSocketState* SocketStartup(JdwpState* state, uint16_t port, bool probe); 67872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes 68872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes/* 69872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * Set up some stuff for transport=dt_socket. 70872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes */ 715d10a87ea630b22180d3731018a70b77270c726eElliott Hughesbool InitSocketTransport(JdwpState* state, const JdwpOptions* options) { 726d8dd47f2f65c4476b31672b6f2c7bbf9020fe3aElliott Hughes uint16_t port = options->port; 73872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes 74376a7a033d29d5f2b6e16574a340c999ff2999a0Elliott Hughes if (options->server) { 75376a7a033d29d5f2b6e16574a340c999ff2999a0Elliott Hughes if (options->port != 0) { 76872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes /* try only the specified port */ 775d10a87ea630b22180d3731018a70b77270c726eElliott Hughes state->netState = SocketStartup(state, port, false); 78872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes } else { 79872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes /* scan through a range of ports, binding to the first available */ 80872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes for (port = kBasePort; port <= kMaxPort; port++) { 815d10a87ea630b22180d3731018a70b77270c726eElliott Hughes state->netState = SocketStartup(state, port, true); 827d95565c84d91ae5dcec4b89728ada208633de0cSebastien Hertz if (state->netState != nullptr) { 83872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes break; 84872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes } 85872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes } 86872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes } 877d95565c84d91ae5dcec4b89728ada208633de0cSebastien Hertz if (state->netState == nullptr) { 88376a7a033d29d5f2b6e16574a340c999ff2999a0Elliott Hughes LOG(ERROR) << "JDWP net startup failed (req port=" << options->port << ")"; 89872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes return false; 90872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes } 91872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes } else { 925d10a87ea630b22180d3731018a70b77270c726eElliott Hughes state->netState = SocketStartup(state, 0, false); 93872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes } 94872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes 95376a7a033d29d5f2b6e16574a340c999ff2999a0Elliott Hughes if (options->suspend) { 96872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes LOG(INFO) << "JDWP will wait for debugger on port " << port; 97872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes } else { 98376a7a033d29d5f2b6e16574a340c999ff2999a0Elliott Hughes LOG(INFO) << "JDWP will " << (options->server ? "listen" : "connect") << " on port " << port; 99872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes } 100872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes 101872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes return true; 102872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes} 103872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes 104872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes/* 105872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * Initialize JDWP stuff. 106872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * 1076d8dd47f2f65c4476b31672b6f2c7bbf9020fe3aElliott Hughes * Allocates a new state structure. If "port" is non-zero, this also 1086d8dd47f2f65c4476b31672b6f2c7bbf9020fe3aElliott Hughes * tries to bind to a listen port. If "port" is zero, we assume 109872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * we're preparing for an outbound connection, and return without binding 110872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * to anything. 111872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * 112872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * This may be called several times if we're probing for a port. 113872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * 114872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * Returns 0 on success. 115872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes */ 1165d10a87ea630b22180d3731018a70b77270c726eElliott Hughesstatic JdwpSocketState* SocketStartup(JdwpState* state, uint16_t port, bool probe) { 1175d10a87ea630b22180d3731018a70b77270c726eElliott Hughes JdwpSocketState* netState = new JdwpSocketState(state); 1186d8dd47f2f65c4476b31672b6f2c7bbf9020fe3aElliott Hughes if (port == 0) { 119872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes return netState; 120872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes } 121872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes 122872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes netState->listenSock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP); 123872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes if (netState->listenSock < 0) { 1243d30d9b09c16542d41554aad9f46ec9109ba5cb5Elliott Hughes PLOG(probe ? ERROR : FATAL) << "Socket create failed"; 125872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes goto fail; 126872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes } 127872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes 128872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes /* allow immediate re-use */ 1296d8dd47f2f65c4476b31672b6f2c7bbf9020fe3aElliott Hughes { 1306d8dd47f2f65c4476b31672b6f2c7bbf9020fe3aElliott Hughes int one = 1; 1316d8dd47f2f65c4476b31672b6f2c7bbf9020fe3aElliott Hughes if (setsockopt(netState->listenSock, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one)) < 0) { 1326d8dd47f2f65c4476b31672b6f2c7bbf9020fe3aElliott Hughes PLOG(probe ? ERROR : FATAL) << "setsockopt(SO_REUSEADDR) failed"; 1336d8dd47f2f65c4476b31672b6f2c7bbf9020fe3aElliott Hughes goto fail; 1346d8dd47f2f65c4476b31672b6f2c7bbf9020fe3aElliott Hughes } 135872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes } 136872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes 137872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes union { 1387b9d996e4cd7d154bb1a244d67139aff0c363cf2Elliott Hughes sockaddr_in addrInet; 1397b9d996e4cd7d154bb1a244d67139aff0c363cf2Elliott Hughes sockaddr addrPlain; 140872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes } addr; 141872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes addr.addrInet.sin_family = AF_INET; 142872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes addr.addrInet.sin_port = htons(port); 143872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes inet_aton("127.0.0.1", &addr.addrInet.sin_addr); 144872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes 145872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes if (bind(netState->listenSock, &addr.addrPlain, sizeof(addr)) != 0) { 1463d30d9b09c16542d41554aad9f46ec9109ba5cb5Elliott Hughes PLOG(probe ? ERROR : FATAL) << "Attempt to bind to port " << port << " failed"; 147872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes goto fail; 148872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes } 149872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes 150872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes netState->listenPort = port; 151872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes 152872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes if (listen(netState->listenSock, 5) != 0) { 1533d30d9b09c16542d41554aad9f46ec9109ba5cb5Elliott Hughes PLOG(probe ? ERROR : FATAL) << "Listen failed"; 154872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes goto fail; 155872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes } 156872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes 157872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes return netState; 158872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes 159a21039c3ae2b20e44ceb2735251c04d0aac89afdElliott Hughes fail: 1605d10a87ea630b22180d3731018a70b77270c726eElliott Hughes netState->Shutdown(); 1615d10a87ea630b22180d3731018a70b77270c726eElliott Hughes delete netState; 1627d95565c84d91ae5dcec4b89728ada208633de0cSebastien Hertz return nullptr; 163872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes} 164872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes 165872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes/* 166872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * Shut down JDWP listener. Don't free state. 167872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * 168872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * This may be called from a non-JDWP thread as part of shutting the 169872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * JDWP thread down. 170872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * 171872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * (This is currently called several times during startup as we probe 172872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * for an open port.) 173872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes */ 1745d10a87ea630b22180d3731018a70b77270c726eElliott Hughesvoid JdwpSocketState::Shutdown() { 175277ccbd200ea43590dfc06a93ae184a765327ad0Andreas Gampe int local_listenSock = this->listenSock; 176277ccbd200ea43590dfc06a93ae184a765327ad0Andreas Gampe int local_clientSock = this->clientSock; 177872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes 178872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes /* clear these out so it doesn't wake up and try to reuse them */ 1795d10a87ea630b22180d3731018a70b77270c726eElliott Hughes this->listenSock = this->clientSock = -1; 180872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes 181872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes /* "shutdown" dislodges blocking read() and accept() calls */ 182277ccbd200ea43590dfc06a93ae184a765327ad0Andreas Gampe if (local_listenSock != -1) { 183277ccbd200ea43590dfc06a93ae184a765327ad0Andreas Gampe shutdown(local_listenSock, SHUT_RDWR); 184277ccbd200ea43590dfc06a93ae184a765327ad0Andreas Gampe close(local_listenSock); 185872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes } 186277ccbd200ea43590dfc06a93ae184a765327ad0Andreas Gampe if (local_clientSock != -1) { 187277ccbd200ea43590dfc06a93ae184a765327ad0Andreas Gampe shutdown(local_clientSock, SHUT_RDWR); 188277ccbd200ea43590dfc06a93ae184a765327ad0Andreas Gampe close(local_clientSock); 189872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes } 190872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes 1915d10a87ea630b22180d3731018a70b77270c726eElliott Hughes WakePipe(); 192872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes} 193872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes 194872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes/* 195872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * Disable the TCP Nagle algorithm, which delays transmission of outbound 196872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * packets until the previous transmissions have been acked. JDWP does a 197872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * lot of back-and-forth with small packets, so this may help. 198872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes */ 1995d10a87ea630b22180d3731018a70b77270c726eElliott Hughesstatic int SetNoDelay(int fd) { 200748474146da0c6484fa3dca0a700f612d47550c3Elliott Hughes int on = 1; 201748474146da0c6484fa3dca0a700f612d47550c3Elliott Hughes int cc = setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &on, sizeof(on)); 202748474146da0c6484fa3dca0a700f612d47550c3Elliott Hughes CHECK_EQ(cc, 0); 203748474146da0c6484fa3dca0a700f612d47550c3Elliott Hughes return cc; 204872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes} 205872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes 206872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes/* 207872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * Accept a connection. This will block waiting for somebody to show up. 208872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * If that's not desirable, use checkConnection() to make sure something 209872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * is pending. 210872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes */ 2115d10a87ea630b22180d3731018a70b77270c726eElliott Hughesbool JdwpSocketState::Accept() { 212872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes union { 2137b9d996e4cd7d154bb1a244d67139aff0c363cf2Elliott Hughes sockaddr_in addrInet; 2147b9d996e4cd7d154bb1a244d67139aff0c363cf2Elliott Hughes sockaddr addrPlain; 215872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes } addr; 216872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes socklen_t addrlen; 217872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes int sock; 218872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes 2195d10a87ea630b22180d3731018a70b77270c726eElliott Hughes if (listenSock < 0) { 220872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes return false; /* you're not listening! */ 221872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes } 222872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes 2234274889d48ef82369bf2c1ca70d84689b4f9e93aBrian Carlstrom CHECK_EQ(clientSock, -1); /* must not already be talking */ 224872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes 225872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes addrlen = sizeof(addr); 226872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes do { 2275d10a87ea630b22180d3731018a70b77270c726eElliott Hughes sock = accept(listenSock, &addr.addrPlain, &addrlen); 228872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes if (sock < 0 && errno != EINTR) { 229872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes // When we call shutdown() on the socket, accept() returns with 230872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes // EINVAL. Don't gripe about it. 231872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes if (errno == EINVAL) { 2324dd9b4d95eec9db5338fb9bf132f9bb8facf6cf4Elliott Hughes if (VLOG_IS_ON(jdwp)) { 2334dd9b4d95eec9db5338fb9bf132f9bb8facf6cf4Elliott Hughes PLOG(ERROR) << "accept failed"; 2344dd9b4d95eec9db5338fb9bf132f9bb8facf6cf4Elliott Hughes } 235872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes } else { 236872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes PLOG(ERROR) << "accept failed"; 237872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes return false; 238872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes } 239872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes } 240872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes } while (sock < 0); 241872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes 2425d10a87ea630b22180d3731018a70b77270c726eElliott Hughes remote_addr_ = addr.addrInet.sin_addr; 2435d10a87ea630b22180d3731018a70b77270c726eElliott Hughes remote_port_ = ntohs(addr.addrInet.sin_port); 2445d10a87ea630b22180d3731018a70b77270c726eElliott Hughes VLOG(jdwp) << "+++ accepted connection from " << inet_ntoa(remote_addr_) << ":" << remote_port_; 245872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes 2465d10a87ea630b22180d3731018a70b77270c726eElliott Hughes clientSock = sock; 2475d10a87ea630b22180d3731018a70b77270c726eElliott Hughes SetAwaitingHandshake(true); 2485d10a87ea630b22180d3731018a70b77270c726eElliott Hughes input_count_ = 0; 249872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes 2504dd9b4d95eec9db5338fb9bf132f9bb8facf6cf4Elliott Hughes VLOG(jdwp) << "Setting TCP_NODELAY on accepted socket"; 2515d10a87ea630b22180d3731018a70b77270c726eElliott Hughes SetNoDelay(clientSock); 252872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes 2535d10a87ea630b22180d3731018a70b77270c726eElliott Hughes if (!MakePipe()) { 254872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes return false; 255872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes } 256872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes 257872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes return true; 258872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes} 259872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes 260872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes/* 261872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * Create a connection to a waiting debugger. 262872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes */ 2635d10a87ea630b22180d3731018a70b77270c726eElliott Hughesbool JdwpSocketState::Establish(const JdwpOptions* options) { 264872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes union { 2657b9d996e4cd7d154bb1a244d67139aff0c363cf2Elliott Hughes sockaddr_in addrInet; 2667b9d996e4cd7d154bb1a244d67139aff0c363cf2Elliott Hughes sockaddr addrPlain; 267872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes } addr; 2687b9d996e4cd7d154bb1a244d67139aff0c363cf2Elliott Hughes hostent* pEntry; 269872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes 270a21039c3ae2b20e44ceb2735251c04d0aac89afdElliott Hughes CHECK(!options->server); 271a21039c3ae2b20e44ceb2735251c04d0aac89afdElliott Hughes CHECK(!options->host.empty()); 272a21039c3ae2b20e44ceb2735251c04d0aac89afdElliott Hughes CHECK_NE(options->port, 0); 273872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes 274872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes /* 275872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * Start by resolving the host name. 276872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes */ 277ec17f98e7a4efecc93a7d75fd17d5b45cf1576faYabin Cui#if defined(__linux__) 278d817560c697508df0d941071c8e96152c9404defRoland Levillain // Initial size of the work buffer used in gethostbyname_r. 279d817560c697508df0d941071c8e96152c9404defRoland Levillain // 280d817560c697508df0d941071c8e96152c9404defRoland Levillain // The call to gethostbyname_r below requires a user-allocated buffer, 281d817560c697508df0d941071c8e96152c9404defRoland Levillain // the size of which depends on the system. The initial implementation 282d817560c697508df0d941071c8e96152c9404defRoland Levillain // used to use a 128-byte buffer, but that was not enough on some 283d817560c697508df0d941071c8e96152c9404defRoland Levillain // systems (maybe because of IPv6), causing failures in JDWP host 284d817560c697508df0d941071c8e96152c9404defRoland Levillain // testing; thus it was increased to 256. 285d817560c697508df0d941071c8e96152c9404defRoland Levillain // 286d817560c697508df0d941071c8e96152c9404defRoland Levillain // However, we should not use a fixed size: gethostbyname_r's 287d817560c697508df0d941071c8e96152c9404defRoland Levillain // documentation states that if the work buffer is too small (i.e. if 288d817560c697508df0d941071c8e96152c9404defRoland Levillain // gethostbyname_r returns `ERANGE`), then the function should be 289d817560c697508df0d941071c8e96152c9404defRoland Levillain // called again with a bigger buffer. Which we do now, starting with 290d817560c697508df0d941071c8e96152c9404defRoland Levillain // an initial 256-byte buffer, and doubling it until gethostbyname_r 291d817560c697508df0d941071c8e96152c9404defRoland Levillain // accepts this size. 292d817560c697508df0d941071c8e96152c9404defRoland Levillain static constexpr size_t kInitialAuxBufSize = 256; 293d817560c697508df0d941071c8e96152c9404defRoland Levillain 2943cbad24f0ee3639ac2ce2d06d61e97386df6f94bRoland Levillain std::vector<char> auxBuf(kInitialAuxBufSize); 295d817560c697508df0d941071c8e96152c9404defRoland Levillain hostent he; 296872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes int error; 2973cbad24f0ee3639ac2ce2d06d61e97386df6f94bRoland Levillain int cc; 2983cbad24f0ee3639ac2ce2d06d61e97386df6f94bRoland Levillain while ((cc = gethostbyname_r( 2993cbad24f0ee3639ac2ce2d06d61e97386df6f94bRoland Levillain options->host.c_str(), &he, auxBuf.data(), auxBuf.size(), &pEntry, &error)) 3003cbad24f0ee3639ac2ce2d06d61e97386df6f94bRoland Levillain == ERANGE) { 3013cbad24f0ee3639ac2ce2d06d61e97386df6f94bRoland Levillain // The work buffer `auxBuf` is too small; enlarge it. 3023cbad24f0ee3639ac2ce2d06d61e97386df6f94bRoland Levillain auxBuf.resize(auxBuf.size() * 2); 3033cbad24f0ee3639ac2ce2d06d61e97386df6f94bRoland Levillain } 3043cbad24f0ee3639ac2ce2d06d61e97386df6f94bRoland Levillain if (cc != 0 || pEntry == nullptr) { 305a21039c3ae2b20e44ceb2735251c04d0aac89afdElliott Hughes LOG(WARNING) << "gethostbyname_r('" << options->host << "') failed: " << hstrerror(error); 306872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes return false; 307872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes } 308872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes#else 309872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes h_errno = 0; 310a21039c3ae2b20e44ceb2735251c04d0aac89afdElliott Hughes pEntry = gethostbyname(options->host.c_str()); 3117d95565c84d91ae5dcec4b89728ada208633de0cSebastien Hertz if (pEntry == nullptr) { 312a21039c3ae2b20e44ceb2735251c04d0aac89afdElliott Hughes PLOG(WARNING) << "gethostbyname('" << options->host << "') failed"; 313872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes return false; 314872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes } 315872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes#endif 316872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes 317872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes /* copy it out ASAP to minimize risk of multithreaded annoyances */ 318872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes memcpy(&addr.addrInet.sin_addr, pEntry->h_addr, pEntry->h_length); 319872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes addr.addrInet.sin_family = pEntry->h_addrtype; 320872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes 321a21039c3ae2b20e44ceb2735251c04d0aac89afdElliott Hughes addr.addrInet.sin_port = htons(options->port); 322872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes 32315f9b27adf1e1eb64a42d872f88e95ba637ce775Roland Levillain LOG(INFO) << "Connecting out to " << inet_ntoa(addr.addrInet.sin_addr) << ":" 32415f9b27adf1e1eb64a42d872f88e95ba637ce775Roland Levillain << ntohs(addr.addrInet.sin_port); 325872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes 326872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes /* 327872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * Create a socket. 328872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes */ 3295d10a87ea630b22180d3731018a70b77270c726eElliott Hughes clientSock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP); 3305d10a87ea630b22180d3731018a70b77270c726eElliott Hughes if (clientSock < 0) { 331872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes PLOG(ERROR) << "Unable to create socket"; 332872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes return false; 333872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes } 334872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes 335872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes /* 336872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * Try to connect. 337872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes */ 3385d10a87ea630b22180d3731018a70b77270c726eElliott Hughes if (connect(clientSock, &addr.addrPlain, sizeof(addr)) != 0) { 33915f9b27adf1e1eb64a42d872f88e95ba637ce775Roland Levillain PLOG(ERROR) << "Unable to connect to " << inet_ntoa(addr.addrInet.sin_addr) << ":" 34015f9b27adf1e1eb64a42d872f88e95ba637ce775Roland Levillain << ntohs(addr.addrInet.sin_port); 3415d10a87ea630b22180d3731018a70b77270c726eElliott Hughes close(clientSock); 3425d10a87ea630b22180d3731018a70b77270c726eElliott Hughes clientSock = -1; 343872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes return false; 344872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes } 345872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes 34615f9b27adf1e1eb64a42d872f88e95ba637ce775Roland Levillain LOG(INFO) << "Connection established to " << options->host << " (" 34715f9b27adf1e1eb64a42d872f88e95ba637ce775Roland Levillain << inet_ntoa(addr.addrInet.sin_addr) << ":" << ntohs(addr.addrInet.sin_port) << ")"; 3485d10a87ea630b22180d3731018a70b77270c726eElliott Hughes SetAwaitingHandshake(true); 3495d10a87ea630b22180d3731018a70b77270c726eElliott Hughes input_count_ = 0; 350872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes 3515d10a87ea630b22180d3731018a70b77270c726eElliott Hughes SetNoDelay(clientSock); 352872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes 3535d10a87ea630b22180d3731018a70b77270c726eElliott Hughes if (!MakePipe()) { 354872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes return false; 355872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes } 356872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes 357872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes return true; 358872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes} 359872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes 360872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes/* 361872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * Process incoming data. If no data is available, this will block until 362872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * some arrives. 363872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * 364872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * If we get a full packet, handle it. 365872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * 366872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * To take some of the mystery out of life, we want to reject incoming 367872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * connections if we already have a debugger attached. If we don't, the 368872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * debugger will just mysteriously hang until it times out. We could just 369872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * close the listen socket, but there's a good chance we won't be able to 370872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * bind to the same port again, which would confuse utilities. 371872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * 372872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * Returns "false" on error (indicating that the connection has been severed), 373872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * "true" if things are still okay. 374872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes */ 3755d10a87ea630b22180d3731018a70b77270c726eElliott Hughesbool JdwpSocketState::ProcessIncoming() { 376872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes int readCount; 377872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes 3784274889d48ef82369bf2c1ca70d84689b4f9e93aBrian Carlstrom CHECK_NE(clientSock, -1); 379872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes 3805d10a87ea630b22180d3731018a70b77270c726eElliott Hughes if (!HaveFullPacket()) { 381872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes /* read some more, looping until we have data */ 382872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes errno = 0; 383872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes while (1) { 384872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes int selCount; 385872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes fd_set readfds; 3865d10a87ea630b22180d3731018a70b77270c726eElliott Hughes int maxfd = -1; 387872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes int fd; 388872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes 389872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes FD_ZERO(&readfds); 390872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes 391872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes /* configure fds; note these may get zapped by another thread */ 3925d10a87ea630b22180d3731018a70b77270c726eElliott Hughes fd = listenSock; 393872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes if (fd >= 0) { 394872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes FD_SET(fd, &readfds); 3955d10a87ea630b22180d3731018a70b77270c726eElliott Hughes if (maxfd < fd) { 3965d10a87ea630b22180d3731018a70b77270c726eElliott Hughes maxfd = fd; 3975d10a87ea630b22180d3731018a70b77270c726eElliott Hughes } 398872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes } 3995d10a87ea630b22180d3731018a70b77270c726eElliott Hughes fd = clientSock; 400872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes if (fd >= 0) { 401872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes FD_SET(fd, &readfds); 4025d10a87ea630b22180d3731018a70b77270c726eElliott Hughes if (maxfd < fd) { 4035d10a87ea630b22180d3731018a70b77270c726eElliott Hughes maxfd = fd; 4045d10a87ea630b22180d3731018a70b77270c726eElliott Hughes } 405872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes } 4065d10a87ea630b22180d3731018a70b77270c726eElliott Hughes fd = wake_pipe_[0]; 407872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes if (fd >= 0) { 408872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes FD_SET(fd, &readfds); 4095d10a87ea630b22180d3731018a70b77270c726eElliott Hughes if (maxfd < fd) { 4105d10a87ea630b22180d3731018a70b77270c726eElliott Hughes maxfd = fd; 4115d10a87ea630b22180d3731018a70b77270c726eElliott Hughes } 412872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes } else { 413872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes LOG(INFO) << "NOTE: entering select w/o wakepipe"; 414872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes } 415872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes 4165d10a87ea630b22180d3731018a70b77270c726eElliott Hughes if (maxfd < 0) { 4175d10a87ea630b22180d3731018a70b77270c726eElliott Hughes VLOG(jdwp) << "+++ all fds are closed"; 4185d10a87ea630b22180d3731018a70b77270c726eElliott Hughes return false; 4195d10a87ea630b22180d3731018a70b77270c726eElliott Hughes } 4205d10a87ea630b22180d3731018a70b77270c726eElliott Hughes 421872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes /* 422872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * Select blocks until it sees activity on the file descriptors. 423872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * Closing the local file descriptor does not count as activity, 424872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * so we can't rely on that to wake us up (it works for read() 425872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * and accept(), but not select()). 426872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * 427872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * We can do one of three things: (1) send a signal and catch 4285d10a87ea630b22180d3731018a70b77270c726eElliott Hughes * EINTR, (2) open an additional fd ("wake pipe") and write to 429872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * it when it's time to exit, or (3) time out periodically and 430872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * re-issue the select. We're currently using #2, as it's more 431872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * reliable than #1 and generally better than #3. Wastes two fds. 432872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes */ 4337d95565c84d91ae5dcec4b89728ada208633de0cSebastien Hertz selCount = select(maxfd + 1, &readfds, nullptr, nullptr, nullptr); 434872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes if (selCount < 0) { 435872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes if (errno == EINTR) { 436872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes continue; 437872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes } 438872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes PLOG(ERROR) << "select failed"; 439872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes goto fail; 440872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes } 441872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes 4425d10a87ea630b22180d3731018a70b77270c726eElliott Hughes if (wake_pipe_[0] >= 0 && FD_ISSET(wake_pipe_[0], &readfds)) { 4435d10a87ea630b22180d3731018a70b77270c726eElliott Hughes if (listenSock >= 0) { 444872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes LOG(ERROR) << "Exit wake set, but not exiting?"; 445872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes } else { 4464d466a8e4587422c989705dce3b2a19e7f0137f5Brian Carlstrom VLOG(jdwp) << "Got wake-up signal, bailing out of select"; 447872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes } 448872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes goto fail; 449872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes } 4505d10a87ea630b22180d3731018a70b77270c726eElliott Hughes if (listenSock >= 0 && FD_ISSET(listenSock, &readfds)) { 451872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes LOG(INFO) << "Ignoring second debugger -- accepting and dropping"; 452872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes union { 4537b9d996e4cd7d154bb1a244d67139aff0c363cf2Elliott Hughes sockaddr_in addrInet; 4547b9d996e4cd7d154bb1a244d67139aff0c363cf2Elliott Hughes sockaddr addrPlain; 455872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes } addr; 456872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes socklen_t addrlen; 457872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes int tmpSock; 4585d10a87ea630b22180d3731018a70b77270c726eElliott Hughes tmpSock = accept(listenSock, &addr.addrPlain, &addrlen); 459872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes if (tmpSock < 0) { 460872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes LOG(INFO) << "Weird -- accept failed"; 461872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes } else { 462872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes close(tmpSock); 463872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes } 464872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes } 4655d10a87ea630b22180d3731018a70b77270c726eElliott Hughes if (clientSock >= 0 && FD_ISSET(clientSock, &readfds)) { 46615f9b27adf1e1eb64a42d872f88e95ba637ce775Roland Levillain readCount = 46715f9b27adf1e1eb64a42d872f88e95ba637ce775Roland Levillain read(clientSock, input_buffer_ + input_count_, sizeof(input_buffer_) - input_count_); 468872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes if (readCount < 0) { 469872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes /* read failed */ 470872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes if (errno != EINTR) { 471872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes goto fail; 472872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes } 4734d466a8e4587422c989705dce3b2a19e7f0137f5Brian Carlstrom VLOG(jdwp) << "+++ EINTR hit"; 474872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes return true; 475872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes } else if (readCount == 0) { 476872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes /* EOF hit -- far end went away */ 47768a5e3c9115f9ba396563ce3b72df9cb036bc665Elliott Hughes VLOG(jdwp) << "+++ peer disconnected"; 478872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes goto fail; 479872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes } else { 480872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes break; 481872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes } 482872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes } 483872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes } 484872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes 4855d10a87ea630b22180d3731018a70b77270c726eElliott Hughes input_count_ += readCount; 4865d10a87ea630b22180d3731018a70b77270c726eElliott Hughes if (!HaveFullPacket()) { 487872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes return true; /* still not there yet */ 488872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes } 489872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes } 490872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes 491872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes /* 492872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * Special-case the initial handshake. For some bizarre reason we're 493872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * expected to emulate bad tty settings by echoing the request back 494872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * exactly as it was sent. Note the handshake is always initiated by 495872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * the debugger, no matter who connects to whom. 496872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * 497872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * Other than this one case, the protocol [claims to be] stateless. 498872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes */ 4995d10a87ea630b22180d3731018a70b77270c726eElliott Hughes if (IsAwaitingHandshake()) { 5005d10a87ea630b22180d3731018a70b77270c726eElliott Hughes if (memcmp(input_buffer_, kMagicHandshake, kMagicHandshakeLen) != 0) { 5015d10a87ea630b22180d3731018a70b77270c726eElliott Hughes LOG(ERROR) << StringPrintf("ERROR: bad handshake '%.14s'", input_buffer_); 502872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes goto fail; 503872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes } 504872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes 505872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes errno = 0; 5065d10a87ea630b22180d3731018a70b77270c726eElliott Hughes int cc = TEMP_FAILURE_RETRY(write(clientSock, input_buffer_, kMagicHandshakeLen)); 507872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes if (cc != kMagicHandshakeLen) { 50815f9b27adf1e1eb64a42d872f88e95ba637ce775Roland Levillain PLOG(ERROR) << "Failed writing handshake bytes (" 50915f9b27adf1e1eb64a42d872f88e95ba637ce775Roland Levillain << cc << " of " << kMagicHandshakeLen << ")"; 510872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes goto fail; 511872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes } 512872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes 5135d10a87ea630b22180d3731018a70b77270c726eElliott Hughes ConsumeBytes(kMagicHandshakeLen); 5145d10a87ea630b22180d3731018a70b77270c726eElliott Hughes SetAwaitingHandshake(false); 5154dd9b4d95eec9db5338fb9bf132f9bb8facf6cf4Elliott Hughes VLOG(jdwp) << "+++ handshake complete"; 516872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes return true; 517872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes } 518872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes 519872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes /* 520872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * Handle this packet. 521872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes */ 5225d10a87ea630b22180d3731018a70b77270c726eElliott Hughes return state_->HandlePacket(); 523872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes 524a21039c3ae2b20e44ceb2735251c04d0aac89afdElliott Hughes fail: 5255d10a87ea630b22180d3731018a70b77270c726eElliott Hughes Close(); 526872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes return false; 527872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes} 528872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes 529872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes} // namespace JDWP 530872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes 531872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes} // namespace art 532