1
#pragma once
2

            
3
#include <chrono>
4
#include <iosfwd>
5

            
6
#include "envoy/network/io_handle.h"
7

            
8
#include "source/common/common/assert.h"
9
#include "source/common/network/io_socket_error_impl.h"
10

            
11
namespace Envoy {
12
namespace Quic {
13

            
14
// A wrapper class around IoHandle object which doesn't close() upon destruction. It is used to
15
// create ConnectionSocket as the actual IoHandle instance should out live connection socket.
16
class QuicIoHandleWrapper : public Network::IoHandle {
17
public:
18
7771
  QuicIoHandleWrapper(Network::IoHandle& io_handle) : io_handle_(io_handle) {}
19

            
20
  // Network::IoHandle
21
1
  os_fd_t fdDoNotUse() const override { return io_handle_.fdDoNotUse(); }
22
3041
  Api::IoCallUint64Result close() override {
23
3041
    closed_ = true;
24
3041
    return Api::ioCallUint64ResultNoError();
25
3041
  }
26
6029
  bool isOpen() const override { return !closed_; }
27
  bool wasConnected() const override { return io_handle_.wasConnected(); }
28
  Api::IoCallUint64Result readv(uint64_t max_length, Buffer::RawSlice* slices,
29
2
                                uint64_t num_slice) override {
30
2
    if (closed_) {
31
1
      return {0, Network::IoSocketError::getIoSocketEbadfError()};
32
1
    }
33
1
    return io_handle_.readv(max_length, slices, num_slice);
34
2
  }
35
  Api::IoCallUint64Result read(Buffer::Instance& buffer,
36
2
                               absl::optional<uint64_t> max_length) override {
37
2
    if (closed_) {
38
1
      return {0, Network::IoSocketError::getIoSocketEbadfError()};
39
1
    }
40
1
    return io_handle_.read(buffer, max_length);
41
2
  }
42
2
  Api::IoCallUint64Result writev(const Buffer::RawSlice* slices, uint64_t num_slice) override {
43
2
    if (closed_) {
44
1
      return {0, Network::IoSocketError::getIoSocketEbadfError()};
45
1
    }
46
1
    return io_handle_.writev(slices, num_slice);
47
2
  }
48
2
  Api::IoCallUint64Result write(Buffer::Instance& buffer) override {
49
2
    if (closed_) {
50
1
      return {0, Network::IoSocketError::getIoSocketEbadfError()};
51
1
    }
52
1
    return io_handle_.write(buffer);
53
2
  }
54
  Api::IoCallUint64Result sendmsg(const Buffer::RawSlice* slices, uint64_t num_slice, int flags,
55
                                  const Envoy::Network::Address::Ip* self_ip,
56
2
                                  const Network::Address::Instance& peer_address) override {
57
2
    if (closed_) {
58
1
      return {0, Network::IoSocketError::getIoSocketEbadfError()};
59
1
    }
60
1
    return io_handle_.sendmsg(slices, num_slice, flags, self_ip, peer_address);
61
2
  }
62
  Api::IoCallUint64Result recvmsg(Buffer::RawSlice* slices, const uint64_t num_slice,
63
                                  uint32_t self_port, const UdpSaveCmsgConfig& udp_save_cmsg_config,
64
2
                                  RecvMsgOutput& output) override {
65
2
    if (closed_) {
66
1
      ASSERT(false, "recvmmsg is called after close.");
67
1
      return {0, Network::IoSocketError::getIoSocketEbadfError()};
68
1
    }
69
1
    return io_handle_.recvmsg(slices, num_slice, self_port, udp_save_cmsg_config, output);
70
2
  }
71
  Api::IoCallUint64Result recvmmsg(RawSliceArrays& slices, uint32_t self_port,
72
                                   const UdpSaveCmsgConfig& udp_save_cmsg_config,
73
2
                                   RecvMsgOutput& output) override {
74
2
    if (closed_) {
75
1
      ASSERT(false, "recvmmsg is called after close.");
76
1
      return {0, Network::IoSocketError::getIoSocketEbadfError()};
77
1
    }
78
1
    return io_handle_.recvmmsg(slices, self_port, udp_save_cmsg_config, output);
79
2
  }
80
2
  Api::IoCallUint64Result recv(void* buffer, size_t length, int flags) override {
81
2
    if (closed_) {
82
1
      ASSERT(false, "recv called after close.");
83
1
      return {0, Network::IoSocketError::getIoSocketEbadfError()};
84
1
    }
85
1
    return io_handle_.recv(buffer, length, flags);
86
2
  }
87
1
  bool supportsMmsg() const override { return io_handle_.supportsMmsg(); }
88
1
  bool supportsUdpGro() const override { return io_handle_.supportsUdpGro(); }
89
1
  Api::SysCallIntResult bind(Network::Address::InstanceConstSharedPtr address) override {
90
1
    return io_handle_.bind(address);
91
1
  }
92
1
  Api::SysCallIntResult listen(int backlog) override { return io_handle_.listen(backlog); }
93
1
  Network::IoHandlePtr accept(struct sockaddr* addr, socklen_t* addrlen) override {
94
1
    return io_handle_.accept(addr, addrlen);
95
1
  }
96
1
  Api::SysCallIntResult connect(Network::Address::InstanceConstSharedPtr address) override {
97
1
    return io_handle_.connect(address);
98
1
  }
99
  Api::SysCallIntResult setOption(int level, int optname, const void* optval,
100
1
                                  socklen_t optlen) override {
101
1
    return io_handle_.setOption(level, optname, optval, optlen);
102
1
  }
103
  Api::SysCallIntResult getOption(int level, int optname, void* optval,
104
                                  socklen_t* optlen) override {
105
    return io_handle_.getOption(level, optname, optval, optlen);
106
  }
107

            
108
  Api::SysCallIntResult ioctl(unsigned long control_code, void* in_buffer,
109
                              unsigned long in_buffer_len, void* out_buffer,
110
                              unsigned long out_buffer_len,
111
1
                              unsigned long* bytes_returned) override {
112
1
    return io_handle_.ioctl(control_code, in_buffer, in_buffer_len, out_buffer, out_buffer_len,
113
1
                            bytes_returned);
114
1
  }
115

            
116
1
  Api::SysCallIntResult setBlocking(bool blocking) override {
117
1
    return io_handle_.setBlocking(blocking);
118
1
  }
119
1
  absl::optional<int> domain() override { return io_handle_.domain(); }
120
1
  absl::StatusOr<Network::Address::InstanceConstSharedPtr> localAddress() override {
121
1
    return io_handle_.localAddress();
122
1
  }
123
1
  absl::StatusOr<Network::Address::InstanceConstSharedPtr> peerAddress() override {
124
1
    return io_handle_.peerAddress();
125
1
  }
126

            
127
  void initializeFileEvent(Event::Dispatcher& dispatcher, Event::FileReadyCb cb,
128
1
                           Event::FileTriggerType trigger, uint32_t events) override {
129
1
    io_handle_.initializeFileEvent(dispatcher, cb, trigger, events);
130
1
  }
131

            
132
1
  Network::IoHandlePtr duplicate() override { return io_handle_.duplicate(); }
133

            
134
1
  void activateFileEvents(uint32_t events) override { io_handle_.activateFileEvents(events); }
135
1
  void enableFileEvents(uint32_t events) override { io_handle_.enableFileEvents(events); }
136
1
  void resetFileEvents() override { return io_handle_.resetFileEvents(); };
137
1
  absl::optional<std::string> interfaceName() override { return io_handle_.interfaceName(); }
138

            
139
1
  Api::SysCallIntResult shutdown(int how) override { return io_handle_.shutdown(how); }
140
1
  absl::optional<std::chrono::milliseconds> lastRoundTripTime() override { return {}; }
141
  absl::optional<uint64_t> congestionWindowInBytes() const override {
142
    // QUIC should get congestion window from QuicFilterManagerConnectionImpl, which implements the
143
    // Envoy::Network::Connection::congestionWindowInBytes interface.
144
    IS_ENVOY_BUG("QuicIoHandleWrapper does not implement congestionWindowInBytes.");
145
    return {};
146
  }
147

            
148
private:
149
  Network::IoHandle& io_handle_;
150
  bool closed_{false};
151
};
152

            
153
} // namespace Quic
154
} // namespace Envoy