1
#pragma once
2

            
3
#include "envoy/api/os_sys_calls.h"
4
#include "envoy/common/platform.h"
5
#include "envoy/config/core/v3/base.pb.h"
6
#include "envoy/network/address.h"
7
#include "envoy/network/listen_socket.h"
8

            
9
#include "source/common/common/assert.h"
10
#include "source/common/common/logger.h"
11
#include "source/common/memory/aligned_allocator.h"
12

            
13
namespace Envoy {
14
namespace Network {
15

            
16
class SocketOptionImpl : public Socket::Option, Logger::Loggable<Logger::Id::connection> {
17
public:
18
  SocketOptionImpl(envoy::config::core::v3::SocketOption::SocketState in_state,
19
                   Network::SocketOptionName optname,
20
                   int value, // Yup, int. See setsockopt(2).
21
                   absl::optional<Network::Socket::Type> socket_type = absl::nullopt,
22
                   absl::optional<Network::Address::IpVersion> socket_ip_version = absl::nullopt)
23
47323
      : SocketOptionImpl(in_state, optname,
24
47323
                         absl::string_view(reinterpret_cast<char*>(&value), sizeof(value)),
25
47323
                         socket_type, socket_ip_version) {}
26

            
27
  SocketOptionImpl(envoy::config::core::v3::SocketOption::SocketState in_state,
28
                   Network::SocketOptionName optname, absl::string_view value,
29
                   absl::optional<Network::Socket::Type> socket_type = absl::nullopt,
30
                   absl::optional<Network::Address::IpVersion> socket_ip_version = absl::nullopt)
31
47882
      : in_state_(in_state), optname_(optname), value_(value.begin(), value.end()),
32
47882
        socket_type_(socket_type), socket_ip_version_(socket_ip_version) {
33
47882
    ASSERT(reinterpret_cast<uintptr_t>(value_.data()) % alignof(void*) == 0);
34
47882
  }
35

            
36
  SocketOptionImpl(Network::SocketOptionName optname, absl::string_view value,
37
                   absl::optional<Network::Socket::Type> socket_type = absl::nullopt,
38
                   absl::optional<Network::Address::IpVersion> socket_ip_version = absl::nullopt)
39
2
      : in_state_(absl::nullopt), optname_(optname), value_(value.begin(), value.end()),
40
2
        socket_type_(socket_type), socket_ip_version_(socket_ip_version) {
41
2
    ASSERT(reinterpret_cast<uintptr_t>(value_.data()) % alignof(void*) == 0);
42
2
  }
43

            
44
  // Socket::Option
45
  bool setOption(Socket& socket,
46
                 envoy::config::core::v3::SocketOption::SocketState state) const override;
47
  void hashKey(std::vector<uint8_t>& hash_key) const override;
48
  absl::optional<Details>
49
  getOptionDetails(const Socket& socket,
50
                   envoy::config::core::v3::SocketOption::SocketState state) const override;
51
  bool isSupported() const override;
52

            
53
  /**
54
   * Gets the socket type for this socket option. Empty means, the socket option is not specific to
55
   * a particular socket type.
56
   *
57
   * @return the socket type
58
   */
59
  absl::optional<Network::Socket::Type> socketType() const;
60

            
61
  /**
62
   * Gets the socket IP version for this socket option. Empty means, the socket option is not
63
   * specific to a particular socket IP version.
64
   *
65
   * @return the socket IP version
66
   */
67
  absl::optional<Network::Address::IpVersion> socketIpVersion() const;
68

            
69
  /**
70
   * Set the option on the given socket.
71
   * @param socket the socket on which to apply the option.
72
   * @param optname the option name.
73
   * @param value the option value.
74
   * @param size the option value size.
75
   * @return a Api::SysCallIntResult with rc_ = 0 for success and rc = -1 for failure. If the call
76
   * is successful, errno_ shouldn't be used.
77
   */
78
  static Api::SysCallIntResult setSocketOption(Socket& socket,
79
                                               const Network::SocketOptionName& optname,
80
                                               const void* value, size_t size);
81

            
82
private:
83
  // The state this option expects the socket to be in when it is applied. If the state is not set,
84
  // then this option will be applied in any state.
85
  absl::optional<const envoy::config::core::v3::SocketOption::SocketState> in_state_;
86
  const Network::SocketOptionName optname_;
87
  // The vector's data() is used by the setsockopt syscall, which needs to be int-size-aligned on
88
  // some platforms, the AlignedAllocator here makes it pointer-size-aligned, which satisfies the
89
  // requirement, although it can be slightly over-aligned.
90
  const std::vector<uint8_t, Memory::AlignedAllocator<uint8_t, alignof(void*)>> value_;
91
  // If present, specifies the socket type that this option applies to. Attempting to set this
92
  // option on a socket of a different type will be a no-op.
93
  absl::optional<Network::Socket::Type> socket_type_;
94
  // If present, specifies the socket IP version that this option applies to. Attempting to set this
95
  // option on a socket of a different IP version will be a no-op.
96
  absl::optional<Network::Address::IpVersion> socket_ip_version_;
97
};
98

            
99
} // namespace Network
100
} // namespace Envoy