blob: 37fd2c0163b482ec532d13564c65072e01810d9e [file] [log] [blame]
wubf975eac2019-08-19 19:41:01 -07001// Copyright (c) 2019 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "net/third_party/quiche/src/quic/qbone/bonnet/tun_device_packet_exchanger.h"
6
bnc463f2352019-10-10 04:49:34 -07007#include <utility>
8
wubf975eac2019-08-19 19:41:01 -07009#include "net/third_party/quiche/src/quic/platform/api/quic_str_cat.h"
10
11namespace quic {
12
13TunDevicePacketExchanger::TunDevicePacketExchanger(
14 int fd,
15 size_t mtu,
16 KernelInterface* kernel,
17 QbonePacketExchanger::Visitor* visitor,
vasilvv0fc587f2019-09-06 13:33:08 -070018 size_t max_pending_packets,
19 StatsInterface* stats)
wubf975eac2019-08-19 19:41:01 -070020 : QbonePacketExchanger(visitor, max_pending_packets),
21 fd_(fd),
22 mtu_(mtu),
23 kernel_(kernel),
24 stats_(stats) {}
25
26bool TunDevicePacketExchanger::WritePacket(const char* packet,
27 size_t size,
28 bool* blocked,
29 string* error) {
30 *blocked = false;
31 if (fd_ < 0) {
32 *error = QuicStrCat("Invalid file descriptor of the TUN device: ", fd_);
33 stats_->OnWriteError(error);
34 return false;
35 }
36
37 int result = kernel_->write(fd_, packet, size);
38 if (result == -1) {
39 if (errno == EWOULDBLOCK || errno == EAGAIN) {
40 // The tunnel is blocked. Note that this does not mean the receive buffer
41 // of a TCP connection is filled. This simply means the TUN device itself
42 // is blocked on handing packets to the rest part of the kernel.
43 *error = QuicStrCat("Write to the TUN device was blocked: ", errno);
44 *blocked = true;
45 stats_->OnWriteError(error);
46 }
47 return false;
48 }
49 stats_->OnPacketWritten();
50
51 return true;
52}
53
54std::unique_ptr<QuicData> TunDevicePacketExchanger::ReadPacket(bool* blocked,
55 string* error) {
56 *blocked = false;
57 if (fd_ < 0) {
58 *error = QuicStrCat("Invalid file descriptor of the TUN device: ", fd_);
59 stats_->OnReadError(error);
60 return nullptr;
61 }
62 // Reading on a TUN device returns a packet at a time. If the packet is longer
63 // than the buffer, it's truncated.
vasilvv0fc587f2019-09-06 13:33:08 -070064 auto read_buffer = std::make_unique<char[]>(mtu_);
wubf975eac2019-08-19 19:41:01 -070065 int result = kernel_->read(fd_, read_buffer.get(), mtu_);
66 // Note that 0 means end of file, but we're talking about a TUN device - there
67 // is no end of file. Therefore 0 also indicates error.
68 if (result <= 0) {
69 if (errno == EAGAIN || errno == EWOULDBLOCK) {
70 *error = QuicStrCat("Read from the TUN device was blocked: ", errno);
71 *blocked = true;
72 stats_->OnReadError(error);
73 }
74 return nullptr;
75 }
76 stats_->OnPacketRead();
vasilvv0fc587f2019-09-06 13:33:08 -070077 return std::make_unique<QuicData>(read_buffer.release(), result, true);
wubf975eac2019-08-19 19:41:01 -070078}
79
80int TunDevicePacketExchanger::file_descriptor() const {
81 return fd_;
82}
83
QUICHE team25de4472019-10-18 08:13:30 -070084const TunDevicePacketExchanger::StatsInterface*
85TunDevicePacketExchanger::stats_interface() const {
86 return stats_;
87}
88
wubf975eac2019-08-19 19:41:01 -070089} // namespace quic