blob: 116cdf84ed2ce4943c74e25375ee355e090ccb90 [file] [log] [blame]
Alex Light39795712017-12-14 11:58:21 -08001/* 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
53namespace 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
60extern const jdwpTransportNativeInterface_ gTransportInterface;
61
62template <typename T> static T HostToNetwork(T in);
63template <typename T> static T NetworkToHost(T in);
64
65template<> int8_t HostToNetwork(int8_t in) { return in; }
66template<> int8_t NetworkToHost(int8_t in) { return in; }
67template<> int16_t HostToNetwork(int16_t in) { return htons(in); }
68template<> int16_t NetworkToHost(int16_t in) { return ntohs(in); }
69template<> int32_t HostToNetwork(int32_t in) { return htonl(in); }
70template<> int32_t NetworkToHost(int32_t in) { return ntohl(in); }
71
72FdForwardTransport::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
82FdForwardTransport::~FdForwardTransport() { }
83
84bool 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
94jdwpTransportError 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
104static void SendListenMessage(const android::base::unique_fd& fd) {
105 TEMP_FAILURE_RETRY(send(fd, kListenStartMessage, sizeof(kListenStartMessage), MSG_EOR));
106}
107
108jdwpTransportError 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
120static void SendListenEndMessage(const android::base::unique_fd& fd) {
121 TEMP_FAILURE_RETRY(send(fd, kListenEndMessage, sizeof(kListenEndMessage), MSG_EOR));
122}
123
124jdwpTransportError 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.
138thread_local std::string global_last_error_;
139
140void FdForwardTransport::SetLastError(const std::string& desc) {
141 LOG(ERROR) << desc;
142 global_last_error_ = desc;
143}
144
145IOResult 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
162IOResult FdForwardTransport::ReadUpToMax(void* data, size_t ndata, /*out*/size_t* read_amount) {
163 CHECK_GE(read_fd_.get(), 0);
164 int avail;
Alex Light96f4dc42018-01-23 14:06:58 -0800165 int res = TEMP_FAILURE_RETRY(ioctl(read_fd_, FIONREAD, &avail));
Alex Light39795712017-12-14 11:58:21 -0800166 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 };
Alex Light96f4dc42018-01-23 14:06:58 -0800175 res = TEMP_FAILURE_RETRY(poll(&pollfd, /*nfds*/1, /*timeout*/0));
Alex Light39795712017-12-14 11:58:21 -0800176 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
186IOResult 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.
Alex Light96f4dc42018-01-23 14:06:58 -0800217 int poll_res = TEMP_FAILURE_RETRY(poll(pollfds, 2, -1));
Alex Light39795712017-12-14 11:58:21 -0800218 if (poll_res < 0) {
219 DT_IO_ERROR("Failed to poll!");
220 }
221 // Clear the wakeup_fd regardless.
222 uint64_t val;
Alex Light96f4dc42018-01-23 14:06:58 -0800223 int unused = TEMP_FAILURE_RETRY(read(wakeup_fd_, &val, sizeof(val)));
Alex Light39795712017-12-14 11:58:21 -0800224 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'.
234class 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
249IOResult 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
267IOResult 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
275static void SendAcceptMessage(int fd) {
276 TEMP_FAILURE_RETRY(send(fd, kAcceptMessage, sizeof(kAcceptMessage), MSG_EOR));
277}
278
Alex Light15b81132018-01-24 13:29:07 -0800279IOResult FdForwardTransport::ReceiveFdsFromSocket(bool* do_handshake) {
Alex Light39795712017-12-14 11:58:21 -0800280 union {
281 cmsghdr cm;
282 uint8_t buffer[CMSG_SPACE(sizeof(FdSet))];
283 } msg_union;
Alex Light15b81132018-01-24 13:29:07 -0800284 // This lets us know if we need to do a handshake or not.
285 char message[128];
Alex Light39795712017-12-14 11:58:21 -0800286 iovec iov;
Alex Light15b81132018-01-24 13:29:07 -0800287 iov.iov_base = message;
288 iov.iov_len = sizeof(message);
Alex Light39795712017-12-14 11:58:21 -0800289
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));
Alex Light15b81132018-01-24 13:29:07 -0800309 bool failed = false;
310 if (out_fds.read_fd_ < 0 ||
311 out_fds.write_fd_ < 0 ||
312 out_fds.write_lock_fd_ < 0) {
Alex Light39795712017-12-14 11:58:21 -0800313 DT_IO_ERROR("Received fds were invalid!");
Alex Light15b81132018-01-24 13:29:07 -0800314 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) {
Alex Light39795712017-12-14 11:58:21 -0800325 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.
350jdwpTransportError 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
Alex Light15b81132018-01-24 13:29:07 -0800362 bool do_handshake = false;
Alex Light39795712017-12-14 11:58:21 -0800363 DCHECK_NE(listen_fd_.get(), -1);
Alex Light15b81132018-01-24 13:29:07 -0800364 if (ReceiveFdsFromSocket(&do_handshake) != IOResult::kOk) {
Alex Light39795712017-12-14 11:58:21 -0800365 CHECK(ChangeState(TransportState::kOpening, TransportState::kListening));
366 return ERR(IO_ERROR);
367 }
368
369 current_seq_num_++;
370
371 // Moved to the opening state.
Alex Light15b81132018-01-24 13:29:07 -0800372 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 }
Alex Light39795712017-12-14 11:58:21 -0800393 }
394 break;
395 }
396 CHECK(ChangeState(TransportState::kOpening, TransportState::kOpen));
397 return OK;
398}
399
400void 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.
407void 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
429jdwpTransportError 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.
443class 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
561jdwpTransportError 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.
574class 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
618jdwpTransportError 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
630jboolean FdForwardTransport::IsOpen() {
631 return state_ == TransportState::kOpen;
632}
633
634void* FdForwardTransport::Alloc(size_t s) {
635 return mem_.alloc(s);
636}
637
638void FdForwardTransport::Free(void* data) {
639 mem_.free(data);
640}
641
642jdwpTransportError 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
649static FdForwardTransport* AsFdForward(jdwpTransportEnv* env) {
650 return reinterpret_cast<FdForwardTransport*>(env);
651}
652
653static 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
662class 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.
743const 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
757extern "C"
758JNIEXPORT 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