1
#pragma once
2

            
3
#include <memory>
4
#include <vector>
5

            
6
#include "envoy/api/io_error.h"
7
#include "envoy/api/os_sys_calls.h"
8
#include "envoy/common/platform.h"
9
#include "envoy/event/dispatcher.h"
10
#include "envoy/network/io_handle.h"
11

            
12
#include "source/common/common/logger.h"
13
#include "source/common/network/io_socket_error_impl.h"
14
#include "source/common/network/io_socket_handle_base_impl.h"
15
#include "source/common/runtime/runtime_features.h"
16

            
17
#include "quiche/quic/platform/api/quic_socket_address.h"
18

            
19
namespace Envoy {
20
namespace Network {
21

            
22
using QuicEnvoyAddressPair = std::pair<quic::QuicSocketAddress, Address::InstanceConstSharedPtr>;
23

            
24
/**
25
 * IoHandle derivative for sockets.
26
 */
27
class IoSocketHandleImpl : public IoSocketHandleBaseImpl {
28
public:
29
  explicit IoSocketHandleImpl(os_fd_t fd = INVALID_SOCKET, bool socket_v6only = false,
30
                              absl::optional<int> domain = absl::nullopt,
31
                              size_t address_cache_max_capacity = 0)
32
155455
      : IoSocketHandleBaseImpl(fd, socket_v6only, domain),
33
155455
        address_cache_max_capacity_(address_cache_max_capacity) {
34
155455
    if (address_cache_max_capacity > 0) {
35
3133
      recent_received_addresses_ = std::vector<QuicEnvoyAddressPair>();
36
3133
    }
37
155455
  }
38

            
39
  // Close underlying socket if close() hasn't been call yet.
40
  ~IoSocketHandleImpl() override;
41

            
42
  Api::IoCallUint64Result close() override;
43

            
44
  Api::IoCallUint64Result readv(uint64_t max_length, Buffer::RawSlice* slices,
45
                                uint64_t num_slice) override;
46
  Api::IoCallUint64Result read(Buffer::Instance& buffer,
47
                               absl::optional<uint64_t> max_length) override;
48

            
49
  Api::IoCallUint64Result writev(const Buffer::RawSlice* slices, uint64_t num_slice) override;
50

            
51
  Api::IoCallUint64Result write(Buffer::Instance& buffer) override;
52

            
53
  Api::IoCallUint64Result sendmsg(const Buffer::RawSlice* slices, uint64_t num_slice, int flags,
54
                                  const Address::Ip* self_ip,
55
                                  const Address::Instance& peer_address) override;
56

            
57
  Api::IoCallUint64Result recvmsg(Buffer::RawSlice* slices, const uint64_t num_slice,
58
                                  uint32_t self_port, const UdpSaveCmsgConfig& save_cmsg_config,
59
                                  RecvMsgOutput& output) override;
60

            
61
  Api::IoCallUint64Result recvmmsg(RawSliceArrays& slices, uint32_t self_port,
62
                                   const UdpSaveCmsgConfig& save_cmsg_config,
63
                                   RecvMsgOutput& output) override;
64
  Api::IoCallUint64Result recv(void* buffer, size_t length, int flags) override;
65

            
66
  Api::SysCallIntResult bind(Address::InstanceConstSharedPtr address) override;
67
  Api::SysCallIntResult listen(int backlog) override;
68
  IoHandlePtr accept(struct sockaddr* addr, socklen_t* addrlen) override;
69
  Api::SysCallIntResult connect(Address::InstanceConstSharedPtr address) override;
70
  void initializeFileEvent(Event::Dispatcher& dispatcher, Event::FileReadyCb cb,
71
                           Event::FileTriggerType trigger, uint32_t events) override;
72

            
73
  IoHandlePtr duplicate() override;
74

            
75
  void activateFileEvents(uint32_t events) override;
76
  void enableFileEvents(uint32_t events) override;
77

            
78
40172
  void resetFileEvents() override { file_event_.reset(); }
79

            
80
  Api::SysCallIntResult shutdown(int how) override;
81

            
82
protected:
83
  // Converts a SysCallSizeResult to IoCallUint64Result.
84
  template <typename T>
85
2960679
  Api::IoCallUint64Result sysCallResultToIoCallResult(const Api::SysCallResult<T>& result) {
86
2960679
    if (result.return_value_ >= 0) {
87
      // Return nullptr as IoError upon success.
88
2391894
      return Api::IoCallUint64Result(result.return_value_, Api::IoError::none());
89
2391894
    }
90
568785
    if (result.errno_ == SOCKET_ERROR_INVAL) {
91
1
      ENVOY_LOG(error, "Invalid argument passed in.");
92
1
    }
93
568785
    return Api::IoCallUint64Result(
94
568785
        /*rc=*/0, (result.errno_ == SOCKET_ERROR_AGAIN
95
                       // EAGAIN is frequent enough that its memory allocation should be avoided.
96
568797
                       ? IoSocketError::getIoSocketEagainError()
97
397463
                       : IoSocketError::create(result.errno_)));
98
2960679
  }
99

            
100
  Event::FileEventPtr file_event_{nullptr};
101

            
102
  // The minimum cmsg buffer size to filled in destination address, packets dropped and gso
103
  // size when receiving a packet. It is possible for a received packet to contain both IPv4
104
  // and IPV6 addresses.
105
  const size_t cmsg_space_{CMSG_SPACE(sizeof(int)) + CMSG_SPACE(sizeof(struct in_pktinfo)) +
106
                           CMSG_SPACE(sizeof(struct in6_pktinfo)) + CMSG_SPACE(sizeof(uint16_t))};
107

            
108
221
  size_t addressCacheMaxSize() const { return address_cache_max_capacity_; }
109

            
110
private:
111
  // Returns the destination address if the control message carries it.
112
  // Otherwise returns nullptr.
113
  Address::InstanceConstSharedPtr maybeGetDstAddressFromHeader(const cmsghdr& cmsg,
114
                                                               uint32_t self_port);
115

            
116
  Address::InstanceConstSharedPtr getOrCreateEnvoyAddressInstance(sockaddr_storage ss,
117
                                                                  socklen_t ss_len);
118

            
119
  // Caches the address instances of the most recently received packets on this socket.
120
  // Should only be used by QUIC client sockets to avoid creating multiple address instances for
121
  // the same address in each read operation. Since the QUIC client sockets are connected via a
122
  // connect() call, the total number of expected addresses are 2 (source and destination address),
123
  // and the cache size defaults to 4.
124
  size_t address_cache_max_capacity_;
125
  // Only non-null if address_cache_max_capacity_ is greater than 0.
126
  absl::optional<std::vector<QuicEnvoyAddressPair>> recent_received_addresses_ = absl::nullopt;
127

            
128
  // For testing and benchmarking non-public methods.
129
  friend class IoSocketHandleImplTestWrapper;
130
};
131
} // namespace Network
132
} // namespace Envoy