Home | History | Annotate | Download | only in dt_fd_forward
      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 
     67 template<> int8_t HostToNetwork(int8_t in) { return in; }
     68 template<> int8_t NetworkToHost(int8_t in) { return in; }
     69 template<> int16_t HostToNetwork(int16_t in) { return htons(in); }
     70 template<> int16_t NetworkToHost(int16_t in) { return ntohs(in); }
     71 template<> int32_t HostToNetwork(int32_t in) { return htonl(in); }
     72 template<> int32_t NetworkToHost(int32_t in) { return ntohl(in); }
     73 
     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 
     84 FdForwardTransport::~FdForwardTransport() { }
     85 
     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 
     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 
    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.
    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 
    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 
    131 static void SendListenEndMessage(const android::base::unique_fd& fd) {
    132   TEMP_FAILURE_RETRY(send(fd, kListenEndMessage, sizeof(kListenEndMessage), MSG_EOR));
    133 }
    134 
    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 
    151 void FdForwardTransport::SetLastError(const std::string& desc) {
    152   LOG(ERROR) << desc;
    153   global_last_error_ = desc;
    154 }
    155 
    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 
    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 
    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:
    247   explicit ScopedEventFdLock(const android::base::unique_fd& fd) : fd_(fd), data_(0) {
    248     TEMP_FAILURE_RETRY(read(fd_, &data_, sizeof(data_)));
    249   }
    250 
    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 
    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 
    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 
    286 static void SendAcceptMessage(int fd) {
    287   TEMP_FAILURE_RETRY(send(fd, kAcceptMessage, sizeof(kAcceptMessage), MSG_EOR));
    288 }
    289 
    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.
    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 
    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.
    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 
    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:
    456   PacketReader(FdForwardTransport* transport, jdwpPacket* pkt)
    457       : transport_(transport),
    458         pkt_(pkt),
    459         is_eof_(false),
    460         is_err_(false) {}
    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:
    489   void ReadReplyPacket() {
    490     pkt_->type.reply.errorCode = ReadInt16();
    491     pkt_->type.reply.data = ReadRemaining();
    492   }
    493 
    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>
    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 
    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 
    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 
    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 
    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 
    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:
    587   PacketWriter(FdForwardTransport* transport, const jdwpPacket* pkt)
    588       : transport_(transport), pkt_(pkt), data_() {}
    589 
    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:
    607   void PushInt32(int32_t data) {
    608     data = HostToNetwork(data);
    609     PushData(&data, sizeof(data));
    610   }
    611   void PushInt16(int16_t data) {
    612     data = HostToNetwork(data);
    613     PushData(&data, sizeof(data));
    614   }
    615   void PushByte(jbyte data) {
    616     data_.push_back(HostToNetwork(data));
    617   }
    618 
    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 
    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 
    641 jboolean FdForwardTransport::IsOpen() {
    642   return state_ == TransportState::kOpen;
    643 }
    644 
    645 void* FdForwardTransport::Alloc(size_t s) {
    646   return mem_.alloc(s);
    647 }
    648 
    649 void FdForwardTransport::Free(void* data) {
    650   mem_.free(data);
    651 }
    652 
    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 
    660 static FdForwardTransport* AsFdForward(jdwpTransportEnv* env) {
    661   return reinterpret_cast<FdForwardTransport*>(env);
    662 }
    663 
    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:
    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>
    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 
    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 
    722   static jdwpTransportError StopListening(jdwpTransportEnv* env) {
    723     return AsFdForward(env)->StopListening();
    724   }
    725 
    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 
    732   static jboolean IsOpen(jdwpTransportEnv* env) {
    733     return AsFdForward(env)->IsOpen();
    734   }
    735 
    736   static jdwpTransportError Close(jdwpTransportEnv* env) {
    737     return AsFdForward(env)->Close();
    738   }
    739 
    740   static jdwpTransportError ReadPacket(jdwpTransportEnv* env, jdwpPacket *pkt) {
    741     return AsFdForward(env)->ReadPacket(pkt);
    742   }
    743 
    744   static jdwpTransportError WritePacket(jdwpTransportEnv* env, const jdwpPacket* pkt) {
    745     return AsFdForward(env)->WritePacket(pkt);
    746   }
    747 
    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"
    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