• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* Copyright (C) 2017 The Android Open Source Project
2  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
3  *
4  * This file implements interfaces from the file jdwpTransport.h. This
5  * implementation is licensed under the same terms as the file
6  * jdwpTransport.h. The copyright and license information for the file
7  * jdwpTransport.h follows.
8  *
9  * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved.
10  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
11  *
12  * This code is free software; you can redistribute it and/or modify it
13  * under the terms of the GNU General Public License version 2 only, as
14  * published by the Free Software Foundation.  Oracle designates this
15  * particular file as subject to the "Classpath" exception as provided
16  * by Oracle in the LICENSE file that accompanied this code.
17  *
18  * This code is distributed in the hope that it will be useful, but WITHOUT
19  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
20  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
21  * version 2 for more details (a copy is included in the LICENSE file that
22  * accompanied this code).
23  *
24  * You should have received a copy of the GNU General Public License version
25  * 2 along with this work; if not, write to the Free Software Foundation,
26  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
27  *
28  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
29  * or visit www.oracle.com if you need additional information or have any
30  * questions.
31  */
32 
33 #include "dt_fd_forward.h"
34 
35 #include <string>
36 #include <vector>
37 
38 #include <android-base/endian.h>
39 #include <android-base/logging.h>
40 #include <android-base/parseint.h>
41 #include <android-base/stringprintf.h>
42 
43 #include <sys/ioctl.h>
44 #include <sys/eventfd.h>
45 #include <sys/socket.h>
46 #include <sys/types.h>
47 #include <unistd.h>
48 #include <poll.h>
49 
50 #include <jni.h>
51 #include <jdwpTransport.h>
52 
53 #include <base/strlcpy.h>
54 
55 namespace dt_fd_forward {
56 
57 // Helper that puts line-number in error message.
58 #define DT_IO_ERROR(f) \
59     SetLastError(::android::base::StringPrintf("%s:%d - %s: %s", \
60                                                __FILE__, __LINE__, f, strerror(errno)))
61 
62 extern const jdwpTransportNativeInterface_ gTransportInterface;
63 
64 template <typename T> static T HostToNetwork(T in);
65 template <typename T> static T NetworkToHost(T in);
66 
HostToNetwork(int8_t in)67 template<> int8_t HostToNetwork(int8_t in) { return in; }
NetworkToHost(int8_t in)68 template<> int8_t NetworkToHost(int8_t in) { return in; }
HostToNetwork(int16_t in)69 template<> int16_t HostToNetwork(int16_t in) { return htons(in); }
NetworkToHost(int16_t in)70 template<> int16_t NetworkToHost(int16_t in) { return ntohs(in); }
HostToNetwork(int32_t in)71 template<> int32_t HostToNetwork(int32_t in) { return htonl(in); }
NetworkToHost(int32_t in)72 template<> int32_t NetworkToHost(int32_t in) { return ntohl(in); }
73 
FdForwardTransport(jdwpTransportCallback * cb)74 FdForwardTransport::FdForwardTransport(jdwpTransportCallback* cb)
75     : mem_(*cb),
76       read_fd_(-1),
77       write_fd_(-1),
78       wakeup_fd_(eventfd(0, EFD_NONBLOCK)),
79       listen_fd_(-1),
80       close_notify_fd_(-1),
81       state_(TransportState::kClosed),
82       current_seq_num_(0) {}
83 
~FdForwardTransport()84 FdForwardTransport::~FdForwardTransport() { }
85 
ChangeState(TransportState old_state,TransportState new_state)86 bool FdForwardTransport::ChangeState(TransportState old_state, TransportState new_state) {
87   if (old_state == state_) {
88     state_ = new_state;
89     state_cv_.notify_all();
90     return true;
91   } else {
92     return false;
93   }
94 }
95 
PerformAttach(int listen_fd)96 jdwpTransportError FdForwardTransport::PerformAttach(int listen_fd) {
97   jdwpTransportError err = SetupListen(listen_fd);
98   if (err != OK) {
99     return OK;
100   }
101   err = Accept();
102   StopListening();
103   return err;
104 }
105 
SendListenMessage(const android::base::unique_fd & fd)106 static void SendListenMessage(const android::base::unique_fd& fd) {
107   TEMP_FAILURE_RETRY(send(fd, kListenStartMessage, sizeof(kListenStartMessage), MSG_EOR));
108 }
109 
110 // Copy from file_utils, so we do not need to depend on libartbase.
DupCloexec(int fd)111 static int DupCloexec(int fd) {
112 #if defined(__linux__)
113   return fcntl(fd, F_DUPFD_CLOEXEC, 0);
114 #else
115   return dup(fd);
116 #endif
117 }
118 
SetupListen(int listen_fd)119 jdwpTransportError FdForwardTransport::SetupListen(int listen_fd) {
120   std::lock_guard<std::mutex> lk(state_mutex_);
121   if (!ChangeState(TransportState::kClosed, TransportState::kListenSetup)) {
122     return ERR(ILLEGAL_STATE);
123   } else {
124     listen_fd_.reset(DupCloexec(listen_fd));
125     SendListenMessage(listen_fd_);
126     CHECK(ChangeState(TransportState::kListenSetup, TransportState::kListening));
127     return OK;
128   }
129 }
130 
SendListenEndMessage(const android::base::unique_fd & fd)131 static void SendListenEndMessage(const android::base::unique_fd& fd) {
132   TEMP_FAILURE_RETRY(send(fd, kListenEndMessage, sizeof(kListenEndMessage), MSG_EOR));
133 }
134 
StopListening()135 jdwpTransportError FdForwardTransport::StopListening() {
136   std::lock_guard<std::mutex> lk(state_mutex_);
137   if (listen_fd_ != -1) {
138     SendListenEndMessage(listen_fd_);
139   }
140   // Don't close the listen_fd_ since we might need it for later calls to listen.
141   if (ChangeState(TransportState::kListening, TransportState::kClosed) ||
142       state_ == TransportState::kOpen) {
143     listen_fd_.reset();
144   }
145   return OK;
146 }
147 
148 // Last error message.
149 thread_local std::string global_last_error_;
150 
SetLastError(const std::string & desc)151 void FdForwardTransport::SetLastError(const std::string& desc) {
152   LOG(ERROR) << desc;
153   global_last_error_ = desc;
154 }
155 
ReadFullyWithoutChecks(void * data,size_t ndata)156 IOResult FdForwardTransport::ReadFullyWithoutChecks(void* data, size_t ndata) {
157   uint8_t* bdata = reinterpret_cast<uint8_t*>(data);
158   size_t nbytes = 0;
159   while (nbytes < ndata) {
160     int res = TEMP_FAILURE_RETRY(read(read_fd_, bdata + nbytes, ndata - nbytes));
161     if (res < 0) {
162       DT_IO_ERROR("Failed read()");
163       return IOResult::kError;
164     } else if (res == 0) {
165       return IOResult::kEOF;
166     } else {
167       nbytes += res;
168     }
169   }
170   return IOResult::kOk;
171 }
172 
ReadUpToMax(void * data,size_t ndata,size_t * read_amount)173 IOResult FdForwardTransport::ReadUpToMax(void* data, size_t ndata, /*out*/size_t* read_amount) {
174   CHECK_GE(read_fd_.get(), 0);
175   int avail;
176   int res = TEMP_FAILURE_RETRY(ioctl(read_fd_, FIONREAD, &avail));
177   if (res < 0) {
178     DT_IO_ERROR("Failed ioctl(read_fd_, FIONREAD, &avail)");
179     return IOResult::kError;
180   }
181   size_t to_read = std::min(static_cast<size_t>(avail), ndata);
182   *read_amount = to_read;
183   if (*read_amount == 0) {
184     // Check if the read would cause an EOF.
185     struct pollfd pollfd = { read_fd_, POLLRDHUP, 0 };
186     res = TEMP_FAILURE_RETRY(poll(&pollfd, /*nfds*/1, /*timeout*/0));
187     if (res < 0 || (pollfd.revents & POLLERR) == POLLERR) {
188       DT_IO_ERROR("Failed poll on read fd.");
189       return IOResult::kError;
190     }
191     return ((pollfd.revents & (POLLRDHUP | POLLHUP)) == 0) ? IOResult::kOk : IOResult::kEOF;
192   }
193 
194   return ReadFullyWithoutChecks(data, to_read);
195 }
196 
ReadFully(void * data,size_t ndata)197 IOResult FdForwardTransport::ReadFully(void* data, size_t ndata) {
198   uint64_t seq_num = current_seq_num_;
199   size_t nbytes = 0;
200   while (nbytes < ndata) {
201     size_t read_len;
202     struct pollfd pollfds[2];
203     {
204       std::lock_guard<std::mutex> lk(state_mutex_);
205       // Operations in this block must not cause an unbounded pause.
206       if (state_ != TransportState::kOpen || seq_num != current_seq_num_) {
207         // Async-close occurred!
208         return IOResult::kInterrupt;
209       } else {
210         CHECK_GE(read_fd_.get(), 0);
211       }
212       IOResult res = ReadUpToMax(reinterpret_cast<uint8_t*>(data) + nbytes,
213                                  ndata - nbytes,
214                                  /*out*/&read_len);
215       if (res != IOResult::kOk) {
216         return res;
217       } else {
218         nbytes += read_len;
219       }
220 
221       pollfds[0] = { read_fd_, POLLRDHUP | POLLIN, 0 };
222       pollfds[1] = { wakeup_fd_, POLLIN, 0 };
223     }
224     if (read_len == 0) {
225       // No more data. Sleep without locks until more is available. We don't actually check for any
226       // errors since possible ones are (1) the read_fd_ is closed or wakeup happens which are both
227       // fine since the wakeup_fd_ or the poll failing will wake us up.
228       int poll_res = TEMP_FAILURE_RETRY(poll(pollfds, 2, -1));
229       if (poll_res < 0) {
230         DT_IO_ERROR("Failed to poll!");
231       }
232       // Clear the wakeup_fd regardless.
233       uint64_t val;
234       int unused = TEMP_FAILURE_RETRY(read(wakeup_fd_, &val, sizeof(val)));
235       DCHECK(unused == sizeof(val) || errno == EAGAIN);
236       if (poll_res < 0) {
237         return IOResult::kError;
238       }
239     }
240   }
241   return IOResult::kOk;
242 }
243 
244 // A helper that allows us to lock the eventfd 'fd'.
245 class ScopedEventFdLock {
246  public:
ScopedEventFdLock(const android::base::unique_fd & fd)247   explicit ScopedEventFdLock(const android::base::unique_fd& fd) : fd_(fd), data_(0) {
248     TEMP_FAILURE_RETRY(read(fd_, &data_, sizeof(data_)));
249   }
250 
~ScopedEventFdLock()251   ~ScopedEventFdLock() {
252     TEMP_FAILURE_RETRY(write(fd_, &data_, sizeof(data_)));
253   }
254 
255  private:
256   const android::base::unique_fd& fd_;
257   uint64_t data_;
258 };
259 
WriteFullyWithoutChecks(const void * data,size_t ndata)260 IOResult FdForwardTransport::WriteFullyWithoutChecks(const void* data, size_t ndata) {
261   ScopedEventFdLock sefdl(write_lock_fd_);
262   const uint8_t* bdata = static_cast<const uint8_t*>(data);
263   size_t nbytes = 0;
264   while (nbytes < ndata) {
265     int res = TEMP_FAILURE_RETRY(write(write_fd_, bdata + nbytes, ndata - nbytes));
266     if (res < 0) {
267       DT_IO_ERROR("Failed write()");
268       return IOResult::kError;
269     } else if (res == 0) {
270       return IOResult::kEOF;
271     } else {
272       nbytes += res;
273     }
274   }
275   return IOResult::kOk;
276 }
277 
WriteFully(const void * data,size_t ndata)278 IOResult FdForwardTransport::WriteFully(const void* data, size_t ndata) {
279   std::lock_guard<std::mutex> lk(state_mutex_);
280   if (state_ != TransportState::kOpen) {
281     return IOResult::kInterrupt;
282   }
283   return WriteFullyWithoutChecks(data, ndata);
284 }
285 
SendAcceptMessage(int fd)286 static void SendAcceptMessage(int fd) {
287   TEMP_FAILURE_RETRY(send(fd, kAcceptMessage, sizeof(kAcceptMessage), MSG_EOR));
288 }
289 
ReceiveFdsFromSocket(bool * do_handshake)290 IOResult FdForwardTransport::ReceiveFdsFromSocket(bool* do_handshake) {
291   union {
292     cmsghdr cm;
293     uint8_t buffer[CMSG_SPACE(sizeof(FdSet))];
294   } msg_union;
295   // This lets us know if we need to do a handshake or not.
296   char message[128];
297   iovec iov;
298   iov.iov_base = message;
299   iov.iov_len  = sizeof(message);
300 
301   msghdr msg;
302   memset(&msg, 0, sizeof(msg));
303   msg.msg_iov = &iov;
304   msg.msg_iovlen = 1;
305   msg.msg_control = msg_union.buffer;
306   msg.msg_controllen = sizeof(msg_union.buffer);
307 
308   cmsghdr* cmsg = CMSG_FIRSTHDR(&msg);
309   cmsg->cmsg_len   = msg.msg_controllen;
310   cmsg->cmsg_level = SOL_SOCKET;
311   cmsg->cmsg_type  = SCM_RIGHTS;
312   memset(reinterpret_cast<int*>(CMSG_DATA(cmsg)), -1, FdSet::kDataLength);
313 
314   int res = TEMP_FAILURE_RETRY(recvmsg(listen_fd_, &msg, 0));
315   if (res <= 0) {
316     DT_IO_ERROR("Failed to receive fds!");
317     return IOResult::kError;
318   }
319   FdSet out_fds = FdSet::ReadData(CMSG_DATA(cmsg));
320   bool failed = false;
321   if (out_fds.read_fd_ < 0 ||
322       out_fds.write_fd_ < 0 ||
323       out_fds.write_lock_fd_ < 0) {
324     DT_IO_ERROR("Received fds were invalid!");
325     failed = true;
326   } else if (strcmp(kPerformHandshakeMessage, message) == 0) {
327     *do_handshake = true;
328   } else if (strcmp(kSkipHandshakeMessage, message) == 0) {
329     *do_handshake = false;
330   } else {
331     DT_IO_ERROR("Unknown message sent with fds.");
332     failed = true;
333   }
334 
335   if (failed) {
336     if (out_fds.read_fd_ >= 0) {
337       close(out_fds.read_fd_);
338     }
339     if (out_fds.write_fd_ >= 0) {
340       close(out_fds.write_fd_);
341     }
342     if (out_fds.write_lock_fd_ >= 0) {
343       close(out_fds.write_lock_fd_);
344     }
345     return IOResult::kError;
346   }
347 
348   read_fd_.reset(out_fds.read_fd_);
349   write_fd_.reset(out_fds.write_fd_);
350   write_lock_fd_.reset(out_fds.write_lock_fd_);
351 
352   // We got the fds. Send ack.
353   close_notify_fd_.reset(DupCloexec(listen_fd_));
354   SendAcceptMessage(close_notify_fd_);
355 
356   return IOResult::kOk;
357 }
358 
359 // Accept the connection. Note that we match the behavior of other transports which is to just close
360 // the connection and try again if we get a bad handshake.
Accept()361 jdwpTransportError FdForwardTransport::Accept() {
362   // TODO Work with timeouts.
363   while (true) {
364     std::unique_lock<std::mutex> lk(state_mutex_);
365     while (!ChangeState(TransportState::kListening, TransportState::kOpening)) {
366       if (state_ == TransportState::kClosed ||
367           state_ == TransportState::kOpen) {
368         return ERR(ILLEGAL_STATE);
369       }
370       state_cv_.wait(lk);
371     }
372 
373     bool do_handshake = false;
374     DCHECK_NE(listen_fd_.get(), -1);
375     if (ReceiveFdsFromSocket(&do_handshake) != IOResult::kOk) {
376       CHECK(ChangeState(TransportState::kOpening, TransportState::kListening));
377       return ERR(IO_ERROR);
378     }
379 
380     current_seq_num_++;
381 
382     // Moved to the opening state.
383     if (do_handshake) {
384       // Perform the handshake
385       char handshake_recv[sizeof(kJdwpHandshake)];
386       memset(handshake_recv, 0, sizeof(handshake_recv));
387       IOResult res = ReadFullyWithoutChecks(handshake_recv, sizeof(handshake_recv));
388       if (res != IOResult::kOk ||
389           strncmp(handshake_recv, kJdwpHandshake, sizeof(kJdwpHandshake)) != 0) {
390         DT_IO_ERROR("Failed to read handshake");
391         CHECK(ChangeState(TransportState::kOpening, TransportState::kListening));
392         CloseFdsLocked();
393         // Retry.
394         continue;
395       }
396       res = WriteFullyWithoutChecks(kJdwpHandshake, sizeof(kJdwpHandshake));
397       if (res != IOResult::kOk) {
398         DT_IO_ERROR("Failed to write handshake");
399         CHECK(ChangeState(TransportState::kOpening, TransportState::kListening));
400         CloseFdsLocked();
401         // Retry.
402         continue;
403       }
404     }
405     break;
406   }
407   CHECK(ChangeState(TransportState::kOpening, TransportState::kOpen));
408   return OK;
409 }
410 
SendClosingMessage(int fd)411 void SendClosingMessage(int fd) {
412   if (fd >= 0) {
413     TEMP_FAILURE_RETRY(send(fd, kCloseMessage, sizeof(kCloseMessage), MSG_EOR));
414   }
415 }
416 
417 // Actually close the fds associated with this transport.
CloseFdsLocked()418 void FdForwardTransport::CloseFdsLocked() {
419   // We have a different set of fd's now. Increase the seq number.
420   current_seq_num_++;
421 
422   // All access to these is locked under the state_mutex_ so we are safe to close these.
423   {
424     ScopedEventFdLock sefdl(write_lock_fd_);
425     if (close_notify_fd_ >= 0) {
426       SendClosingMessage(close_notify_fd_);
427     }
428     close_notify_fd_.reset();
429     read_fd_.reset();
430     write_fd_.reset();
431     close_notify_fd_.reset();
432   }
433   write_lock_fd_.reset();
434 
435   // Send a wakeup in case we have any in-progress reads/writes.
436   uint64_t data = 1;
437   TEMP_FAILURE_RETRY(write(wakeup_fd_, &data, sizeof(data)));
438 }
439 
Close()440 jdwpTransportError FdForwardTransport::Close() {
441   std::lock_guard<std::mutex> lk(state_mutex_);
442   jdwpTransportError res =
443       ChangeState(TransportState::kOpen, TransportState::kClosed) ? OK : ERR(ILLEGAL_STATE);
444   // Send a wakeup after changing the state even if nothing actually happened.
445   uint64_t data = 1;
446   TEMP_FAILURE_RETRY(write(wakeup_fd_, &data, sizeof(data)));
447   if (res == OK) {
448     CloseFdsLocked();
449   }
450   return res;
451 }
452 
453 // A helper class to read and parse the JDWP packet.
454 class PacketReader {
455  public:
PacketReader(FdForwardTransport * transport,jdwpPacket * pkt)456   PacketReader(FdForwardTransport* transport, jdwpPacket* pkt)
457       : transport_(transport),
458         pkt_(pkt),
459         is_eof_(false),
460         is_err_(false) {}
ReadFully()461   bool ReadFully() {
462     // Zero out.
463     memset(pkt_, 0, sizeof(jdwpPacket));
464     int32_t len = ReadInt32();         // read len
465     if (is_err_) {
466       return false;
467     } else if (is_eof_) {
468       return true;
469     } else if (len < 11) {
470       transport_->DT_IO_ERROR("Packet with len < 11 received!");
471       return false;
472     }
473     pkt_->type.cmd.len = len;
474     pkt_->type.cmd.id = ReadInt32();
475     pkt_->type.cmd.flags = ReadByte();
476     if (is_err_) {
477       return false;
478     } else if (is_eof_) {
479       return true;
480     } else if ((pkt_->type.reply.flags & JDWPTRANSPORT_FLAGS_REPLY) == JDWPTRANSPORT_FLAGS_REPLY) {
481       ReadReplyPacket();
482     } else {
483       ReadCmdPacket();
484     }
485     return !is_err_;
486   }
487 
488  private:
ReadReplyPacket()489   void ReadReplyPacket() {
490     pkt_->type.reply.errorCode = ReadInt16();
491     pkt_->type.reply.data = ReadRemaining();
492   }
493 
ReadCmdPacket()494   void ReadCmdPacket() {
495     pkt_->type.cmd.cmdSet = ReadByte();
496     pkt_->type.cmd.cmd = ReadByte();
497     pkt_->type.cmd.data = ReadRemaining();
498   }
499 
500   template <typename T>
HandleResult(IOResult res,T val,T fail)501   T HandleResult(IOResult res, T val, T fail) {
502     switch (res) {
503       case IOResult::kError:
504         is_err_ = true;
505         return fail;
506       case IOResult::kOk:
507         return val;
508       case IOResult::kEOF:
509         is_eof_ = true;
510         pkt_->type.cmd.len = 0;
511         return fail;
512       case IOResult::kInterrupt:
513         transport_->DT_IO_ERROR("Failed to read, concurrent close!");
514         is_err_ = true;
515         return fail;
516     }
517   }
518 
ReadRemaining()519   jbyte* ReadRemaining() {
520     if (is_eof_ || is_err_) {
521       return nullptr;
522     }
523     jbyte* out = nullptr;
524     jint rem = pkt_->type.cmd.len - 11;
525     CHECK_GE(rem, 0);
526     if (rem == 0) {
527       return nullptr;
528     } else {
529       out = reinterpret_cast<jbyte*>(transport_->Alloc(rem));
530       IOResult res = transport_->ReadFully(out, rem);
531       jbyte* ret = HandleResult(res, out, static_cast<jbyte*>(nullptr));
532       if (ret != out) {
533         transport_->Free(out);
534       }
535       return ret;
536     }
537   }
538 
ReadByte()539   jbyte ReadByte() {
540     if (is_eof_ || is_err_) {
541       return -1;
542     }
543     jbyte out;
544     IOResult res = transport_->ReadFully(&out, sizeof(out));
545     return HandleResult(res, NetworkToHost(out), static_cast<jbyte>(-1));
546   }
547 
ReadInt16()548   jshort ReadInt16() {
549     if (is_eof_ || is_err_) {
550       return -1;
551     }
552     jshort out;
553     IOResult res = transport_->ReadFully(&out, sizeof(out));
554     return HandleResult(res, NetworkToHost(out), static_cast<jshort>(-1));
555   }
556 
ReadInt32()557   jint ReadInt32() {
558     if (is_eof_ || is_err_) {
559       return -1;
560     }
561     jint out;
562     IOResult res = transport_->ReadFully(&out, sizeof(out));
563     return HandleResult(res, NetworkToHost(out), -1);
564   }
565 
566   FdForwardTransport* transport_;
567   jdwpPacket* pkt_;
568   bool is_eof_;
569   bool is_err_;
570 };
571 
ReadPacket(jdwpPacket * pkt)572 jdwpTransportError FdForwardTransport::ReadPacket(jdwpPacket* pkt) {
573   if (pkt == nullptr) {
574     return ERR(ILLEGAL_ARGUMENT);
575   }
576   PacketReader reader(this, pkt);
577   if (reader.ReadFully()) {
578     return OK;
579   } else {
580     return ERR(IO_ERROR);
581   }
582 }
583 
584 // A class that writes a packet to the transport.
585 class PacketWriter {
586  public:
PacketWriter(FdForwardTransport * transport,const jdwpPacket * pkt)587   PacketWriter(FdForwardTransport* transport, const jdwpPacket* pkt)
588       : transport_(transport), pkt_(pkt), data_() {}
589 
WriteFully()590   bool WriteFully() {
591     PushInt32(pkt_->type.cmd.len);
592     PushInt32(pkt_->type.cmd.id);
593     PushByte(pkt_->type.cmd.flags);
594     if ((pkt_->type.reply.flags & JDWPTRANSPORT_FLAGS_REPLY) == JDWPTRANSPORT_FLAGS_REPLY) {
595       PushInt16(pkt_->type.reply.errorCode);
596       PushData(pkt_->type.reply.data, pkt_->type.reply.len - 11);
597     } else {
598       PushByte(pkt_->type.cmd.cmdSet);
599       PushByte(pkt_->type.cmd.cmd);
600       PushData(pkt_->type.cmd.data, pkt_->type.cmd.len - 11);
601     }
602     IOResult res = transport_->WriteFully(data_.data(), data_.size());
603     return res == IOResult::kOk;
604   }
605 
606  private:
PushInt32(int32_t data)607   void PushInt32(int32_t data) {
608     data = HostToNetwork(data);
609     PushData(&data, sizeof(data));
610   }
PushInt16(int16_t data)611   void PushInt16(int16_t data) {
612     data = HostToNetwork(data);
613     PushData(&data, sizeof(data));
614   }
PushByte(jbyte data)615   void PushByte(jbyte data) {
616     data_.push_back(HostToNetwork(data));
617   }
618 
PushData(void * d,size_t size)619   void PushData(void* d, size_t size) {
620     uint8_t* bytes = reinterpret_cast<uint8_t*>(d);
621     data_.insert(data_.end(), bytes, bytes + size);
622   }
623 
624   FdForwardTransport* transport_;
625   const jdwpPacket* pkt_;
626   std::vector<uint8_t> data_;
627 };
628 
WritePacket(const jdwpPacket * pkt)629 jdwpTransportError FdForwardTransport::WritePacket(const jdwpPacket* pkt) {
630   if (pkt == nullptr) {
631     return ERR(ILLEGAL_ARGUMENT);
632   }
633   PacketWriter writer(this, pkt);
634   if (writer.WriteFully()) {
635     return OK;
636   } else {
637     return ERR(IO_ERROR);
638   }
639 }
640 
IsOpen()641 jboolean FdForwardTransport::IsOpen() {
642   return state_ == TransportState::kOpen;
643 }
644 
Alloc(size_t s)645 void* FdForwardTransport::Alloc(size_t s) {
646   return mem_.alloc(s);
647 }
648 
Free(void * data)649 void FdForwardTransport::Free(void* data) {
650   mem_.free(data);
651 }
652 
GetLastError(char ** err)653 jdwpTransportError FdForwardTransport::GetLastError(/*out*/char** err) {
654   std::string data = global_last_error_;
655   *err = reinterpret_cast<char*>(Alloc(data.size() + 1));
656   strlcpy(*err, data.c_str(), data.size() + 1);
657   return OK;
658 }
659 
AsFdForward(jdwpTransportEnv * env)660 static FdForwardTransport* AsFdForward(jdwpTransportEnv* env) {
661   return reinterpret_cast<FdForwardTransport*>(env);
662 }
663 
ParseAddress(const std::string & addr,int * listen_sock)664 static jdwpTransportError ParseAddress(const std::string& addr,
665                                        /*out*/int* listen_sock) {
666   if (!android::base::ParseInt(addr.c_str(), listen_sock) || *listen_sock < 0) {
667     LOG(ERROR) << "address format is <fd_num> not " << addr;
668     return ERR(ILLEGAL_ARGUMENT);
669   }
670   return OK;
671 }
672 
673 class JdwpTransportFunctions {
674  public:
GetCapabilities(jdwpTransportEnv * env ATTRIBUTE_UNUSED,JDWPTransportCapabilities * capabilities_ptr)675   static jdwpTransportError GetCapabilities(jdwpTransportEnv* env ATTRIBUTE_UNUSED,
676                                             /*out*/ JDWPTransportCapabilities* capabilities_ptr) {
677     // We don't support any of the optional capabilities (can_timeout_attach, can_timeout_accept,
678     // can_timeout_handshake) so just return a zeroed capabilities ptr.
679     // TODO We should maybe support these timeout options.
680     memset(capabilities_ptr, 0, sizeof(JDWPTransportCapabilities));
681     return OK;
682   }
683 
684   // Address is <sock_fd>
Attach(jdwpTransportEnv * env,const char * address,jlong attach_timeout ATTRIBUTE_UNUSED,jlong handshake_timeout ATTRIBUTE_UNUSED)685   static jdwpTransportError Attach(jdwpTransportEnv* env,
686                                    const char* address,
687                                    jlong attach_timeout ATTRIBUTE_UNUSED,
688                                    jlong handshake_timeout ATTRIBUTE_UNUSED) {
689     if (address == nullptr || *address == '\0') {
690       return ERR(ILLEGAL_ARGUMENT);
691     }
692     int listen_fd;
693     jdwpTransportError err = ParseAddress(address, &listen_fd);
694     if (err != OK) {
695       return err;
696     }
697     return AsFdForward(env)->PerformAttach(listen_fd);
698   }
699 
StartListening(jdwpTransportEnv * env,const char * address,char ** actual_address)700   static jdwpTransportError StartListening(jdwpTransportEnv* env,
701                                            const char* address,
702                                            /*out*/ char** actual_address) {
703     if (address == nullptr || *address == '\0') {
704       return ERR(ILLEGAL_ARGUMENT);
705     }
706     int listen_fd;
707     jdwpTransportError err = ParseAddress(address, &listen_fd);
708     if (err != OK) {
709       return err;
710     }
711     err = AsFdForward(env)->SetupListen(listen_fd);
712     if (err != OK) {
713       return err;
714     }
715     if (actual_address != nullptr) {
716       *actual_address = reinterpret_cast<char*>(AsFdForward(env)->Alloc(strlen(address) + 1));
717       memcpy(*actual_address, address, strlen(address) + 1);
718     }
719     return OK;
720   }
721 
StopListening(jdwpTransportEnv * env)722   static jdwpTransportError StopListening(jdwpTransportEnv* env) {
723     return AsFdForward(env)->StopListening();
724   }
725 
Accept(jdwpTransportEnv * env,jlong accept_timeout ATTRIBUTE_UNUSED,jlong handshake_timeout ATTRIBUTE_UNUSED)726   static jdwpTransportError Accept(jdwpTransportEnv* env,
727                                    jlong accept_timeout ATTRIBUTE_UNUSED,
728                                    jlong handshake_timeout ATTRIBUTE_UNUSED) {
729     return AsFdForward(env)->Accept();
730   }
731 
IsOpen(jdwpTransportEnv * env)732   static jboolean IsOpen(jdwpTransportEnv* env) {
733     return AsFdForward(env)->IsOpen();
734   }
735 
Close(jdwpTransportEnv * env)736   static jdwpTransportError Close(jdwpTransportEnv* env) {
737     return AsFdForward(env)->Close();
738   }
739 
ReadPacket(jdwpTransportEnv * env,jdwpPacket * pkt)740   static jdwpTransportError ReadPacket(jdwpTransportEnv* env, jdwpPacket *pkt) {
741     return AsFdForward(env)->ReadPacket(pkt);
742   }
743 
WritePacket(jdwpTransportEnv * env,const jdwpPacket * pkt)744   static jdwpTransportError WritePacket(jdwpTransportEnv* env, const jdwpPacket* pkt) {
745     return AsFdForward(env)->WritePacket(pkt);
746   }
747 
GetLastError(jdwpTransportEnv * env,char ** error)748   static jdwpTransportError GetLastError(jdwpTransportEnv* env, char** error) {
749     return AsFdForward(env)->GetLastError(error);
750   }
751 };
752 
753 // The actual struct holding all the entrypoints into the jdwpTransport interface.
754 const jdwpTransportNativeInterface_ gTransportInterface = {
755   nullptr,  // reserved1
756   JdwpTransportFunctions::GetCapabilities,
757   JdwpTransportFunctions::Attach,
758   JdwpTransportFunctions::StartListening,
759   JdwpTransportFunctions::StopListening,
760   JdwpTransportFunctions::Accept,
761   JdwpTransportFunctions::IsOpen,
762   JdwpTransportFunctions::Close,
763   JdwpTransportFunctions::ReadPacket,
764   JdwpTransportFunctions::WritePacket,
765   JdwpTransportFunctions::GetLastError,
766 };
767 
768 extern "C"
jdwpTransport_OnLoad(JavaVM * vm ATTRIBUTE_UNUSED,jdwpTransportCallback * cb,jint version,jdwpTransportEnv ** env)769 JNIEXPORT jint JNICALL jdwpTransport_OnLoad(JavaVM* vm ATTRIBUTE_UNUSED,
770                                             jdwpTransportCallback* cb,
771                                             jint version,
772                                             jdwpTransportEnv** /*out*/env) {
773   if (version != JDWPTRANSPORT_VERSION_1_0) {
774     LOG(ERROR) << "unknown version " << version;
775     return JNI_EVERSION;
776   }
777   void* data = cb->alloc(sizeof(FdForwardTransport));
778   if (data == nullptr) {
779     LOG(ERROR) << "Failed to allocate data for transport!";
780     return JNI_ENOMEM;
781   }
782   FdForwardTransport* transport =
783       new (data) FdForwardTransport(cb);
784   transport->functions = &gTransportInterface;
785   *env = transport;
786   return JNI_OK;
787 }
788 
789 }  // namespace dt_fd_forward
790