Skip to content

Commit

Permalink
socket options: add support for directly creating ipv4/ipv6 pairs (#1…
Browse files Browse the repository at this point in the history
…8769)

Signed-off-by: Mike Schore <mike.schore@gmail.com>
  • Loading branch information
goaway authored Oct 28, 2021
1 parent 4a2b01f commit 365900f
Show file tree
Hide file tree
Showing 7 changed files with 32 additions and 19 deletions.
10 changes: 10 additions & 0 deletions envoy/network/socket.h
Original file line number Diff line number Diff line change
Expand Up @@ -299,8 +299,18 @@ class Socket {
virtual absl::optional<Details>
getOptionDetails(const Socket& socket,
envoy::config::core::v3::SocketOption::SocketState state) const PURE;

/**
* Whether the socket implementation is supported. Real implementations should typically return
* true. Placeholder implementations may indicate such by returning false. Note this does NOT
* inherently prevent an option from being applied if it's passed to socket/connection
* interfaces.
* @return Whether this is a supported socket option.
*/
virtual bool isSupported() const PURE;
};

using OptionConstPtr = std::unique_ptr<const Option>;
using OptionConstSharedPtr = std::shared_ptr<const Option>;
using Options = std::vector<OptionConstSharedPtr>;
using OptionsSharedPtr = std::shared_ptr<Options>;
Expand Down
20 changes: 10 additions & 10 deletions source/common/network/addr_family_aware_socket_option_impl.cc
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
#include "source/common/network/addr_family_aware_socket_option_impl.h"

#include "envoy/common/exception.h"
#include "envoy/common/platform.h"
#include "envoy/common/optref.h"
#include "envoy/config/core/v3/base.pb.h"

#include "source/common/api/os_sys_calls_impl.h"
Expand All @@ -14,11 +14,12 @@ namespace Network {

namespace {

SocketOptionImplOptRef getOptionForSocket(const Socket& socket, SocketOptionImpl& ipv4_option,
SocketOptionImpl& ipv6_option) {
OptRef<const Socket::Option> getOptionForSocket(const Socket& socket,
const Socket::Option& ipv4_option,
const Socket::Option& ipv6_option) {
auto version = socket.ipVersion();
if (!version.has_value()) {
return absl::nullopt;
return {};
}

// If the FD is v4, we can only try the IPv4 variant.
Expand All @@ -38,7 +39,7 @@ SocketOptionImplOptRef getOptionForSocket(const Socket& socket, SocketOptionImpl

bool AddrFamilyAwareSocketOptionImpl::setOption(
Socket& socket, envoy::config::core::v3::SocketOption::SocketState state) const {
return setIpSocketOption(socket, state, ipv4_option_, ipv6_option_);
return setIpSocketOption(socket, state, *ipv4_option_, *ipv6_option_);
}

absl::optional<Socket::Option::Details> AddrFamilyAwareSocketOptionImpl::getOptionDetails(
Expand All @@ -49,21 +50,20 @@ absl::optional<Socket::Option::Details> AddrFamilyAwareSocketOptionImpl::getOpti
return absl::nullopt;
}

return option->get().getOptionDetails(socket, state);
return option.value().get().getOptionDetails(socket, state);
}

bool AddrFamilyAwareSocketOptionImpl::setIpSocketOption(
Socket& socket, envoy::config::core::v3::SocketOption::SocketState state,
const std::unique_ptr<SocketOptionImpl>& ipv4_option,
const std::unique_ptr<SocketOptionImpl>& ipv6_option) {
auto option = getOptionForSocket(socket, *ipv4_option, *ipv6_option);
const Socket::Option& ipv4_option, const Socket::Option& ipv6_option) {
auto option = getOptionForSocket(socket, ipv4_option, ipv6_option);

if (!option.has_value()) {
ENVOY_LOG(warn, "Failed to set IP socket option on non-IP socket");
return false;
}

return option->get().setOption(socket, state);
return option.value().get().setOption(socket, state);
}

} // namespace Network
Expand Down
12 changes: 8 additions & 4 deletions source/common/network/addr_family_aware_socket_option_impl.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,9 @@ class AddrFamilyAwareSocketOptionImpl : public Socket::Option,
SocketOptionName ipv6_optname, absl::string_view ipv6_value)
: ipv4_option_(std::make_unique<SocketOptionImpl>(in_state, ipv4_optname, ipv4_value)),
ipv6_option_(std::make_unique<SocketOptionImpl>(in_state, ipv6_optname, ipv6_value)) {}
AddrFamilyAwareSocketOptionImpl(Socket::OptionConstPtr&& ipv4_option,
Socket::OptionConstPtr&& ipv6_option)
: ipv4_option_(std::move(ipv4_option)), ipv6_option_(std::move(ipv6_option)) {}

// Socket::Option
bool setOption(Socket& socket,
Expand All @@ -41,6 +44,7 @@ class AddrFamilyAwareSocketOptionImpl : public Socket::Option,
absl::optional<Details>
getOptionDetails(const Socket& socket,
envoy::config::core::v3::SocketOption::SocketState state) const override;
bool isSupported() const override { return true; }

/**
* Set a socket option that applies at both IPv4 and IPv6 socket levels. When the underlying FD
Expand All @@ -59,12 +63,12 @@ class AddrFamilyAwareSocketOptionImpl : public Socket::Option,
*/
static bool setIpSocketOption(Socket& socket,
envoy::config::core::v3::SocketOption::SocketState state,
const std::unique_ptr<SocketOptionImpl>& ipv4_option,
const std::unique_ptr<SocketOptionImpl>& ipv6_option);
const Socket::Option& ipv4_option,
const Socket::Option& ipv6_option);

private:
const std::unique_ptr<SocketOptionImpl> ipv4_option_;
const std::unique_ptr<SocketOptionImpl> ipv6_option_;
const Socket::OptionConstPtr ipv4_option_;
const Socket::OptionConstPtr ipv6_option_;
};

} // namespace Network
Expand Down
5 changes: 1 addition & 4 deletions source/common/network/socket_option_impl.h
Original file line number Diff line number Diff line change
Expand Up @@ -138,8 +138,7 @@ class SocketOptionImpl : public Socket::Option, Logger::Loggable<Logger::Id::con
absl::optional<Details>
getOptionDetails(const Socket& socket,
envoy::config::core::v3::SocketOption::SocketState state) const override;

bool isSupported() const;
bool isSupported() const override;

/**
* Set the option on the given socket.
Expand All @@ -162,7 +161,5 @@ class SocketOptionImpl : public Socket::Option, Logger::Loggable<Logger::Id::con
const std::vector<uint8_t> value_;
};

using SocketOptionImplOptRef = absl::optional<std::reference_wrapper<SocketOptionImpl>>;

} // namespace Network
} // namespace Envoy
2 changes: 1 addition & 1 deletion source/common/network/win32_redirect_records_option_impl.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,8 @@ class Win32RedirectRecordsOptionImpl : public Socket::Option,
absl::optional<Details>
getOptionDetails(const Socket& socket,
envoy::config::core::v3::SocketOption::SocketState) const override;
bool isSupported() const override;

bool isSupported() const;
static const Network::SocketOptionName& optionName();

private:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ class OriginalSrcSocketOption : public Network::Socket::Option {
absl::optional<Details>
getOptionDetails(const Network::Socket& socket,
envoy::config::core::v3::SocketOption::SocketState state) const override;
bool isSupported() const override { return true; }

private:
Network::Address::InstanceConstSharedPtr src_address_;
Expand Down
1 change: 1 addition & 0 deletions test/mocks/network/mocks.h
Original file line number Diff line number Diff line change
Expand Up @@ -306,6 +306,7 @@ class MockSocketOption : public Socket::Option {
MOCK_METHOD(void, hashKey, (std::vector<uint8_t>&), (const));
MOCK_METHOD(absl::optional<Socket::Option::Details>, getOptionDetails,
(const Socket&, envoy::config::core::v3::SocketOption::SocketState state), (const));
MOCK_METHOD(bool, isSupported, (), (const));
};

class MockConnectionSocket : public ConnectionSocket {
Expand Down

0 comments on commit 365900f

Please sign in to comment.