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