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