• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 #include <arpa/inet.h>
18 #include <errno.h>
19 #include <netdb.h>
20 #include <netinet/in.h>
21 #include <netinet/tcp.h>
22 #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"
30 #include "base/stringprintf.h"
31 #include "jdwp/jdwp_priv.h"
32 
33 namespace art {
34 
35 namespace JDWP {
36 
37 static constexpr uint16_t kBasePort = 8000;
38 static constexpr uint16_t kMaxPort = 8040;
39 
40 /*
41  * JDWP network state.
42  *
43  * We only talk to one debugger at a time.
44  */
45 struct JdwpSocketState : public JdwpNetStateBase {
46   uint16_t listenPort;
47   int     listenSock;         /* listen for connection from debugger */
48 
JdwpSocketStateart::JDWP::JdwpSocketState49   explicit JdwpSocketState(JdwpState* state)
50       : JdwpNetStateBase(state),
51         listenPort(0U),
52         listenSock(-1),
53         remote_port_(0U) {
54   }
55 
56   virtual bool Accept();
57   virtual bool Establish(const JdwpOptions*);
58   virtual void Shutdown();
59   virtual bool ProcessIncoming();
60 
61  private:
62   in_addr remote_addr_;
63   uint16_t remote_port_;
64 };
65 
66 static JdwpSocketState* SocketStartup(JdwpState* state, uint16_t port, bool probe);
67 
68 /*
69  * Set up some stuff for transport=dt_socket.
70  */
InitSocketTransport(JdwpState * state,const JdwpOptions * options)71 bool InitSocketTransport(JdwpState* state, const JdwpOptions* options) {
72   uint16_t port = options->port;
73 
74   if (options->server) {
75     if (options->port != 0) {
76       /* try only the specified port */
77       state->netState = SocketStartup(state, port, false);
78     } else {
79       /* scan through a range of ports, binding to the first available */
80       for (port = kBasePort; port <= kMaxPort; port++) {
81         state->netState = SocketStartup(state, port, true);
82         if (state->netState != nullptr) {
83           break;
84         }
85       }
86     }
87     if (state->netState == nullptr) {
88       LOG(ERROR) << "JDWP net startup failed (req port=" << options->port << ")";
89       return false;
90     }
91   } else {
92     state->netState = SocketStartup(state, 0, false);
93   }
94 
95   if (options->suspend) {
96     LOG(INFO) << "JDWP will wait for debugger on port " << port;
97   } else {
98     LOG(INFO) << "JDWP will " << (options->server ? "listen" : "connect") << " on port " << port;
99   }
100 
101   return true;
102 }
103 
104 /*
105  * Initialize JDWP stuff.
106  *
107  * Allocates a new state structure.  If "port" is non-zero, this also
108  * tries to bind to a listen port.  If "port" is zero, we assume
109  * we're preparing for an outbound connection, and return without binding
110  * to anything.
111  *
112  * This may be called several times if we're probing for a port.
113  *
114  * Returns 0 on success.
115  */
SocketStartup(JdwpState * state,uint16_t port,bool probe)116 static JdwpSocketState* SocketStartup(JdwpState* state, uint16_t port, bool probe) {
117   JdwpSocketState* netState = new JdwpSocketState(state);
118   if (port == 0) {
119     return netState;
120   }
121 
122   netState->listenSock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
123   if (netState->listenSock < 0) {
124     PLOG(probe ? ERROR : FATAL) << "Socket create failed";
125     goto fail;
126   }
127 
128   /* allow immediate re-use */
129   {
130     int one = 1;
131     if (setsockopt(netState->listenSock, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one)) < 0) {
132       PLOG(probe ? ERROR : FATAL) << "setsockopt(SO_REUSEADDR) failed";
133       goto fail;
134     }
135   }
136 
137   union {
138     sockaddr_in  addrInet;
139     sockaddr     addrPlain;
140   } addr;
141   addr.addrInet.sin_family = AF_INET;
142   addr.addrInet.sin_port = htons(port);
143   inet_aton("127.0.0.1", &addr.addrInet.sin_addr);
144 
145   if (bind(netState->listenSock, &addr.addrPlain, sizeof(addr)) != 0) {
146     PLOG(probe ? ERROR : FATAL) << "Attempt to bind to port " << port << " failed";
147     goto fail;
148   }
149 
150   netState->listenPort = port;
151 
152   if (listen(netState->listenSock, 5) != 0) {
153     PLOG(probe ? ERROR : FATAL) << "Listen failed";
154     goto fail;
155   }
156 
157   return netState;
158 
159  fail:
160   netState->Shutdown();
161   delete netState;
162   return nullptr;
163 }
164 
165 /*
166  * Shut down JDWP listener.  Don't free state.
167  *
168  * This may be called from a non-JDWP thread as part of shutting the
169  * JDWP thread down.
170  *
171  * (This is currently called several times during startup as we probe
172  * for an open port.)
173  */
Shutdown()174 void JdwpSocketState::Shutdown() {
175   int local_listenSock = this->listenSock;
176   int local_clientSock = this->clientSock;
177 
178   /* clear these out so it doesn't wake up and try to reuse them */
179   this->listenSock = this->clientSock = -1;
180 
181   /* "shutdown" dislodges blocking read() and accept() calls */
182   if (local_listenSock != -1) {
183     shutdown(local_listenSock, SHUT_RDWR);
184     close(local_listenSock);
185   }
186   if (local_clientSock != -1) {
187     shutdown(local_clientSock, SHUT_RDWR);
188     close(local_clientSock);
189   }
190 
191   WakePipe();
192 }
193 
194 /*
195  * Disable the TCP Nagle algorithm, which delays transmission of outbound
196  * packets until the previous transmissions have been acked.  JDWP does a
197  * lot of back-and-forth with small packets, so this may help.
198  */
SetNoDelay(int fd)199 static int SetNoDelay(int fd) {
200   int on = 1;
201   int cc = setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &on, sizeof(on));
202   CHECK_EQ(cc, 0);
203   return cc;
204 }
205 
206 /*
207  * Accept a connection.  This will block waiting for somebody to show up.
208  * If that's not desirable, use checkConnection() to make sure something
209  * is pending.
210  */
Accept()211 bool JdwpSocketState::Accept() {
212   union {
213     sockaddr_in  addrInet;
214     sockaddr     addrPlain;
215   } addr;
216   socklen_t addrlen;
217   int sock;
218 
219   if (listenSock < 0) {
220     return false;       /* you're not listening! */
221   }
222 
223   CHECK_EQ(clientSock, -1);      /* must not already be talking */
224 
225   addrlen = sizeof(addr);
226   do {
227     sock = accept(listenSock, &addr.addrPlain, &addrlen);
228     if (sock < 0 && errno != EINTR) {
229       // When we call shutdown() on the socket, accept() returns with
230       // EINVAL.  Don't gripe about it.
231       if (errno == EINVAL) {
232         if (VLOG_IS_ON(jdwp)) {
233           PLOG(ERROR) << "accept failed";
234         }
235       } else {
236         PLOG(ERROR) << "accept failed";
237         return false;
238       }
239     }
240   } while (sock < 0);
241 
242   remote_addr_ = addr.addrInet.sin_addr;
243   remote_port_ = ntohs(addr.addrInet.sin_port);
244   VLOG(jdwp) << "+++ accepted connection from " << inet_ntoa(remote_addr_) << ":" << remote_port_;
245 
246   clientSock = sock;
247   SetAwaitingHandshake(true);
248   input_count_ = 0;
249 
250   VLOG(jdwp) << "Setting TCP_NODELAY on accepted socket";
251   SetNoDelay(clientSock);
252 
253   if (!MakePipe()) {
254     return false;
255   }
256 
257   return true;
258 }
259 
260 /*
261  * Create a connection to a waiting debugger.
262  */
Establish(const JdwpOptions * options)263 bool JdwpSocketState::Establish(const JdwpOptions* options) {
264   union {
265     sockaddr_in  addrInet;
266     sockaddr     addrPlain;
267   } addr;
268   hostent* pEntry;
269 
270   CHECK(!options->server);
271   CHECK(!options->host.empty());
272   CHECK_NE(options->port, 0);
273 
274   /*
275    * Start by resolving the host name.
276    */
277 #if defined(__linux__)
278   // Initial size of the work buffer used in gethostbyname_r.
279   //
280   // The call to gethostbyname_r below requires a user-allocated buffer,
281   // the size of which depends on the system. The initial implementation
282   // used to use a 128-byte buffer, but that was not enough on some
283   // systems (maybe because of IPv6), causing failures in JDWP host
284   // testing; thus it was increased to 256.
285   //
286   // However, we should not use a fixed size: gethostbyname_r's
287   // documentation states that if the work buffer is too small (i.e. if
288   // gethostbyname_r returns `ERANGE`), then the function should be
289   // called again with a bigger buffer. Which we do now, starting with
290   // an initial 256-byte buffer, and doubling it until gethostbyname_r
291   // accepts this size.
292   static constexpr size_t kInitialAuxBufSize = 256;
293 
294   std::vector<char> auxBuf(kInitialAuxBufSize);
295   hostent he;
296   int error;
297   int cc;
298   while ((cc = gethostbyname_r(
299              options->host.c_str(), &he, auxBuf.data(), auxBuf.size(), &pEntry, &error))
300          == ERANGE) {
301     // The work buffer `auxBuf` is too small; enlarge it.
302     auxBuf.resize(auxBuf.size() * 2);
303   }
304   if (cc != 0 || pEntry == nullptr) {
305     LOG(WARNING) << "gethostbyname_r('" << options->host << "') failed: " << hstrerror(error);
306     return false;
307   }
308 #else
309   h_errno = 0;
310   pEntry = gethostbyname(options->host.c_str());
311   if (pEntry == nullptr) {
312     PLOG(WARNING) << "gethostbyname('" << options->host << "') failed";
313     return false;
314   }
315 #endif
316 
317   /* copy it out ASAP to minimize risk of multithreaded annoyances */
318   memcpy(&addr.addrInet.sin_addr, pEntry->h_addr, pEntry->h_length);
319   addr.addrInet.sin_family = pEntry->h_addrtype;
320 
321   addr.addrInet.sin_port = htons(options->port);
322 
323   LOG(INFO) << "Connecting out to " << inet_ntoa(addr.addrInet.sin_addr) << ":"
324             << ntohs(addr.addrInet.sin_port);
325 
326   /*
327    * Create a socket.
328    */
329   clientSock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
330   if (clientSock < 0) {
331     PLOG(ERROR) << "Unable to create socket";
332     return false;
333   }
334 
335   /*
336    * Try to connect.
337    */
338   if (connect(clientSock, &addr.addrPlain, sizeof(addr)) != 0) {
339     PLOG(ERROR) << "Unable to connect to " << inet_ntoa(addr.addrInet.sin_addr) << ":"
340                 << ntohs(addr.addrInet.sin_port);
341     close(clientSock);
342     clientSock = -1;
343     return false;
344   }
345 
346   LOG(INFO) << "Connection established to " << options->host << " ("
347             << inet_ntoa(addr.addrInet.sin_addr) << ":" << ntohs(addr.addrInet.sin_port) << ")";
348   SetAwaitingHandshake(true);
349   input_count_ = 0;
350 
351   SetNoDelay(clientSock);
352 
353   if (!MakePipe()) {
354     return false;
355   }
356 
357   return true;
358 }
359 
360 /*
361  * Process incoming data.  If no data is available, this will block until
362  * some arrives.
363  *
364  * If we get a full packet, handle it.
365  *
366  * To take some of the mystery out of life, we want to reject incoming
367  * connections if we already have a debugger attached.  If we don't, the
368  * debugger will just mysteriously hang until it times out.  We could just
369  * close the listen socket, but there's a good chance we won't be able to
370  * bind to the same port again, which would confuse utilities.
371  *
372  * Returns "false" on error (indicating that the connection has been severed),
373  * "true" if things are still okay.
374  */
ProcessIncoming()375 bool JdwpSocketState::ProcessIncoming() {
376   int readCount;
377 
378   CHECK_NE(clientSock, -1);
379 
380   if (!HaveFullPacket()) {
381     /* read some more, looping until we have data */
382     errno = 0;
383     while (1) {
384       int selCount;
385       fd_set readfds;
386       int maxfd = -1;
387       int fd;
388 
389       FD_ZERO(&readfds);
390 
391       /* configure fds; note these may get zapped by another thread */
392       fd = listenSock;
393       if (fd >= 0) {
394         FD_SET(fd, &readfds);
395         if (maxfd < fd) {
396           maxfd = fd;
397         }
398       }
399       fd = clientSock;
400       if (fd >= 0) {
401         FD_SET(fd, &readfds);
402         if (maxfd < fd) {
403           maxfd = fd;
404         }
405       }
406       fd = wake_pipe_[0];
407       if (fd >= 0) {
408         FD_SET(fd, &readfds);
409         if (maxfd < fd) {
410           maxfd = fd;
411         }
412       } else {
413         LOG(INFO) << "NOTE: entering select w/o wakepipe";
414       }
415 
416       if (maxfd < 0) {
417         VLOG(jdwp) << "+++ all fds are closed";
418         return false;
419       }
420 
421       /*
422        * Select blocks until it sees activity on the file descriptors.
423        * Closing the local file descriptor does not count as activity,
424        * so we can't rely on that to wake us up (it works for read()
425        * and accept(), but not select()).
426        *
427        * We can do one of three things: (1) send a signal and catch
428        * EINTR, (2) open an additional fd ("wake pipe") and write to
429        * it when it's time to exit, or (3) time out periodically and
430        * re-issue the select.  We're currently using #2, as it's more
431        * reliable than #1 and generally better than #3.  Wastes two fds.
432        */
433       selCount = select(maxfd + 1, &readfds, nullptr, nullptr, nullptr);
434       if (selCount < 0) {
435         if (errno == EINTR) {
436           continue;
437         }
438         PLOG(ERROR) << "select failed";
439         goto fail;
440       }
441 
442       if (wake_pipe_[0] >= 0 && FD_ISSET(wake_pipe_[0], &readfds)) {
443         if (listenSock >= 0) {
444           LOG(ERROR) << "Exit wake set, but not exiting?";
445         } else {
446           VLOG(jdwp) << "Got wake-up signal, bailing out of select";
447         }
448         goto fail;
449       }
450       if (listenSock >= 0 && FD_ISSET(listenSock, &readfds)) {
451         LOG(INFO) << "Ignoring second debugger -- accepting and dropping";
452         union {
453           sockaddr_in   addrInet;
454           sockaddr      addrPlain;
455         } addr;
456         socklen_t addrlen;
457         int tmpSock;
458         tmpSock = accept(listenSock, &addr.addrPlain, &addrlen);
459         if (tmpSock < 0) {
460           LOG(INFO) << "Weird -- accept failed";
461         } else {
462           close(tmpSock);
463         }
464       }
465       if (clientSock >= 0 && FD_ISSET(clientSock, &readfds)) {
466         readCount =
467             read(clientSock, input_buffer_ + input_count_, sizeof(input_buffer_) - input_count_);
468         if (readCount < 0) {
469           /* read failed */
470           if (errno != EINTR) {
471             goto fail;
472           }
473           VLOG(jdwp) << "+++ EINTR hit";
474           return true;
475         } else if (readCount == 0) {
476           /* EOF hit -- far end went away */
477           VLOG(jdwp) << "+++ peer disconnected";
478           goto fail;
479         } else {
480           break;
481         }
482       }
483     }
484 
485     input_count_ += readCount;
486     if (!HaveFullPacket()) {
487       return true;        /* still not there yet */
488     }
489   }
490 
491   /*
492    * Special-case the initial handshake.  For some bizarre reason we're
493    * expected to emulate bad tty settings by echoing the request back
494    * exactly as it was sent.  Note the handshake is always initiated by
495    * the debugger, no matter who connects to whom.
496    *
497    * Other than this one case, the protocol [claims to be] stateless.
498    */
499   if (IsAwaitingHandshake()) {
500     if (memcmp(input_buffer_, kMagicHandshake, kMagicHandshakeLen) != 0) {
501       LOG(ERROR) << StringPrintf("ERROR: bad handshake '%.14s'", input_buffer_);
502       goto fail;
503     }
504 
505     errno = 0;
506     int cc = TEMP_FAILURE_RETRY(write(clientSock, input_buffer_, kMagicHandshakeLen));
507     if (cc != kMagicHandshakeLen) {
508       PLOG(ERROR) << "Failed writing handshake bytes ("
509                   << cc << " of " << kMagicHandshakeLen << ")";
510       goto fail;
511     }
512 
513     ConsumeBytes(kMagicHandshakeLen);
514     SetAwaitingHandshake(false);
515     VLOG(jdwp) << "+++ handshake complete";
516     return true;
517   }
518 
519   /*
520    * Handle this packet.
521    */
522   return state_->HandlePacket();
523 
524  fail:
525   Close();
526   return false;
527 }
528 
529 }  // namespace JDWP
530 
531 }  // namespace art
532