Lines
80 %
Functions
83.3 %
#include "source/common/network/socket_impl.h"
#include "envoy/common/exception.h"
#include "envoy/network/socket_interface.h"
#include "source/common/api/os_sys_calls_impl.h"
#include "source/common/common/utility.h"
namespace Envoy {
namespace Network {
SocketImpl::SocketImpl(Socket::Type sock_type,
const Address::InstanceConstSharedPtr& address_for_io_handle,
const Address::InstanceConstSharedPtr& remote_address,
const SocketCreationOptions& options)
: io_handle_(ioHandleForAddr(sock_type, address_for_io_handle, options)),
connection_info_provider_(
std::make_shared<ConnectionInfoSetterImpl>(nullptr, remote_address)),
sock_type_(sock_type), addr_type_(address_for_io_handle->type()) {}
SocketImpl::SocketImpl(IoHandlePtr&& io_handle,
const Address::InstanceConstSharedPtr& local_address,
const Address::InstanceConstSharedPtr& remote_address)
: io_handle_(std::move(io_handle)),
std::make_shared<ConnectionInfoSetterImpl>(local_address, remote_address)),
sock_type_(Network::Socket::Type::Stream) {
if (connection_info_provider_->localAddress() != nullptr) {
addr_type_ = connection_info_provider_->localAddress()->type();
return;
}
if (connection_info_provider_->remoteAddress() != nullptr) {
addr_type_ = connection_info_provider_->remoteAddress()->type();
if (!io_handle_) {
// This can happen iff system socket creation fails.
ENVOY_LOG_MISC(warn, "Created socket with null io handle");
// Should not happen but some tests inject -1 fds
if (!io_handle_->isOpen()) {
auto domain = io_handle_->domain();
// This should never happen in practice but too many tests inject fake fds ...
if (!domain.has_value()) {
addr_type_ = *domain == AF_UNIX ? Address::Type::Pipe : Address::Type::Ip;
Api::SysCallIntResult SocketImpl::bind(Network::Address::InstanceConstSharedPtr address) {
Api::SysCallIntResult bind_result;
if (address->type() == Address::Type::Pipe) {
const Address::Pipe* pipe = address->pipe();
const auto* pipe_sa = reinterpret_cast<const sockaddr_un*>(address->sockAddr());
bool abstract_namespace = address->pipe()->abstractNamespace();
if (!abstract_namespace) {
// Try to unlink an existing filesystem object at the requested path. Ignore
// errors -- it's fine if the path doesn't exist, and if it exists but can't
// be unlinked then `::bind()` will generate a reasonable errno.
unlink(pipe_sa->sun_path);
// Not storing a reference to syscalls singleton because of unit test mocks
bind_result = io_handle_->bind(address);
if (pipe->mode() != 0 && !abstract_namespace && bind_result.return_value_ == 0) {
auto set_permissions = Api::OsSysCallsSingleton::get().chmod(pipe_sa->sun_path, pipe->mode());
if (set_permissions.return_value_ != 0) {
return set_permissions;
return bind_result;
if (bind_result.return_value_ == 0 && address->ip()->port() == 0) {
auto address_or_error = io_handle_->localAddress();
if (!address_or_error.status().ok()) {
return Api::SysCallIntResult{-1, HANDLE_ERROR_INVALID};
connection_info_provider_->setLocalAddress(*address_or_error);
Api::SysCallIntResult SocketImpl::listen(int backlog) { return io_handle_->listen(backlog); }
Api::SysCallIntResult SocketImpl::connect(const Network::Address::InstanceConstSharedPtr address) {
auto result = io_handle_->connect(address);
if (address->type() == Address::Type::Ip) {
return result;
Api::SysCallIntResult SocketImpl::setSocketOption(int level, int optname, const void* optval,
socklen_t optlen) {
return io_handle_->setOption(level, optname, optval, optlen);
Api::SysCallIntResult SocketImpl::getSocketOption(int level, int optname, void* optval,
socklen_t* optlen) const {
return io_handle_->getOption(level, optname, optval, optlen);
Api::SysCallIntResult SocketImpl::ioctl(unsigned long control_code, void* in_buffer,
unsigned long in_buffer_len, void* out_buffer,
unsigned long out_buffer_len,
unsigned long* bytes_returned) {
return io_handle_->ioctl(control_code, in_buffer, in_buffer_len, out_buffer, out_buffer_len,
bytes_returned);
Api::SysCallIntResult SocketImpl::setBlockingForTest(bool blocking) {
return io_handle_->setBlocking(blocking);
absl::optional<Address::IpVersion> SocketImpl::ipVersion() const {
if (addr_type_ == Address::Type::Ip) {
// Always hit after socket is initialized, i.e., accepted or connected
return connection_info_provider_->localAddress()->ip()->version();
} else {
return absl::nullopt;
if (*domain == AF_INET) {
return Address::IpVersion::v4;
} else if (*domain == AF_INET6) {
return Address::IpVersion::v6;
} // namespace Network
} // namespace Envoy