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