Skip to content

Commit

Permalink
address refactor (#429)
Browse files Browse the repository at this point in the history
This is a large refactor that moves away from representing addresses
internally as strings of "URL" form into proper objects. With this
change in place, it should be very straightforward to add IPv6
support, as most places in the code no longer need to understand
anything about the underlying address. Additionally, adding NT support
in the future should also be easier.

There are still some unfortunate legacy aspects, such as the fact that
when loading from configuration we still parse tcp:// as well as unix://
style addresses. In the future this should likely become ip:// as well
as pipe:// but we will probably need to continue to support both.

Note that although this change is huge in number of lines, most of it is
very straightforward, and certain portions of the code have become
substantially simpler such as listener handling and client connection
handling.

Fixes #390
  • Loading branch information
mattklein123 authored Feb 8, 2017
1 parent b8b1563 commit 86219a4
Show file tree
Hide file tree
Showing 96 changed files with 1,147 additions and 828 deletions.
12 changes: 7 additions & 5 deletions include/envoy/event/dispatcher.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,19 +33,21 @@ class Dispatcher {

/**
* Create a client connection.
* @param url supplies the URL to connect to.
* @param address supplies the address to connect to.
* @return Network::ClientConnectionPtr a client connection that is owned by the caller.
*/
virtual Network::ClientConnectionPtr createClientConnection(const std::string& url) PURE;
virtual Network::ClientConnectionPtr
createClientConnection(Network::Address::InstancePtr address) PURE;

/**
* Create an SSL client connection.
* @param ssl_ctx supplies the SSL context to use.
* @param url supplies the URL to connect to.
* @param address supplies the address to connect to.
* @return Network::ClientConnectionPtr a client connection that is owned by the caller.
*/
virtual Network::ClientConnectionPtr createSslClientConnection(Ssl::ClientContext& ssl_ctx,
const std::string& url) PURE;
virtual Network::ClientConnectionPtr
createSslClientConnection(Ssl::ClientContext& ssl_ctx,
Network::Address::InstancePtr address) PURE;

/**
* Create an async DNS resolver. Only a single resolver can exist in the process at a time and it
Expand Down
5 changes: 3 additions & 2 deletions include/envoy/local_info/local_info.h
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#pragma once

#include "envoy/common/pure.h"
#include "envoy/network/address.h"

namespace LocalInfo {

Expand All @@ -12,9 +13,9 @@ class LocalInfo {
virtual ~LocalInfo() {}

/**
* Human readable network address. E.g., "127.0.0.1".
* @return the local (non-loopback) address of the server.
*/
virtual const std::string& address() const PURE;
virtual Network::Address::InstancePtr address() const PURE;

/**
* Human readable zone name. E.g., "us-east-1a".
Expand Down
110 changes: 110 additions & 0 deletions include/envoy/network/address.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
#pragma once

#include "envoy/common/pure.h"

namespace Network {
namespace Address {

/**
* Interface for an Ipv4 address.
*/
class Ipv4 {
public:
virtual ~Ipv4() {}

/**
* @return the 32-bit IPv4 address in network byte order.
*/
virtual uint32_t address() const PURE;
};

enum class IpVersion { v4 };

/**
* Interface for a generic IP address.
*/
class Ip {
public:
virtual ~Ip() {}

/**
* @return the address as a string. E.g., "1.2.3.4" for an IPv4 address.
*/
virtual const std::string& addressAsString() const PURE;

/**
* @return Ipv4 address data IFF type() == IpVersion::v4, otherwise nullptr.
*/
virtual const Ipv4* ipv4() const PURE;

/**
* @return the port associated with the address. Port may be zero if not specified or applicable.
* The port is in host byte order.
*/
virtual uint32_t port() const PURE;

/**
* @return the version of IP address.
*/
virtual IpVersion version() const PURE;
};

enum class Type { Ip, Pipe };
enum class SocketType { Stream, Datagram };

/**
* Interface for all network addresses.
*/
class Instance {
public:
virtual ~Instance() {}

virtual bool operator==(const Instance& rhs) const PURE;

/**
* @return a human readable string for the address.
*
* This string will be in the following format:
* For IP addresses: "1.2.3.4:80"
* For pipe addresses: "/foo"
*/
virtual const std::string& asString() const PURE;

/**
* Bind a socket to this address. The socket should have been created with a call to socket() on
* this object.
* @param fd supplies the platform socket handle.
* @return the platform error code.
*/
virtual int bind(int fd) const PURE;

/**
* Connect a socket to this address. The socket should have been created with a call to socket()
* on this object.
* @param fd supplies the platform socket handle.
* @return the platform error code.
*/
virtual int connect(int fd) const PURE;

/**
* @return the IP address information IFF type() == Type::Ip, otherwise nullptr.
*/
virtual const Ip* ip() const PURE;

/**
* Create a socket for this address.
* @param type supplies the socket type to create.
* @return the platform error code.
*/
virtual int socket(SocketType type) const PURE;

/**
* @return the type of address.
*/
virtual Type type() const PURE;
};

typedef std::shared_ptr<const Instance> InstancePtr;

} // Address
} // Network
5 changes: 3 additions & 2 deletions include/envoy/network/connection.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
#include "envoy/buffer/buffer.h"
#include "envoy/common/pure.h"
#include "envoy/event/deferred_deletable.h"
#include "envoy/network/address.h"
#include "envoy/network/filter.h"
#include "envoy/ssl/connection.h"

Expand Down Expand Up @@ -113,15 +114,15 @@ class Connection : public Event::DeferredDeletable, public FilterManager {
/**
* @return The address of the remote client.
*/
virtual const std::string& remoteAddress() PURE;
virtual const Address::Instance& remoteAddress() PURE;

/**
* @return the local address of the connection. For client connections, this is the origin
* address. For server connections, this is the local destination address. For server connections
* it can be different from the proxy address if the downstream connection has been redirected or
* the proxy is operating in transparent mode.
*/
virtual const std::string& localAddress() PURE;
virtual const Address::Instance& localAddress() PURE;

/**
* Set the buffer stats to update when the connection's read/write buffers change. Note that
Expand Down
3 changes: 2 additions & 1 deletion include/envoy/network/dns.h
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#pragma once

#include "envoy/common/pure.h"
#include "envoy/network/address.h"

namespace Network {

Expand Down Expand Up @@ -29,7 +30,7 @@ class DnsResolver {
* @param address_list supplies the list of resolved IP addresses. The list will be empty if
* the resolution failed.
*/
typedef std::function<void(std::list<std::string>&& address_list)> ResolveCb;
typedef std::function<void(std::list<Address::InstancePtr>&& address_list)> ResolveCb;

/**
* Initiate an async DNS resolution.
Expand Down
5 changes: 3 additions & 2 deletions include/envoy/network/listen_socket.h
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#pragma once

#include "envoy/common/pure.h"
#include "envoy/network/address.h"

namespace Network {

Expand All @@ -12,9 +13,9 @@ class ListenSocket {
virtual ~ListenSocket() {}

/**
* @return a name used for stats. For TCP listen sockets, this is the port.
* @return the address that the socket is listening on.
*/
virtual const std::string name() PURE;
virtual Address::InstancePtr localAddress() PURE;

/**
* @return fd the listen socket's file descriptor.
Expand Down
5 changes: 3 additions & 2 deletions include/envoy/upstream/host_description.h
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#pragma once

#include "envoy/network/address.h"
#include "envoy/stats/stats_macros.h"
#include "envoy/upstream/outlier_detection.h"

Expand Down Expand Up @@ -50,9 +51,9 @@ class HostDescription {
virtual Outlier::DetectorHostSink& outlierDetector() const PURE;

/**
* @return the URL used to connect to the host.
* @return the address used to connect to the host.
*/
virtual const std::string& url() const PURE;
virtual Network::Address::InstancePtr address() const PURE;

/**
* @return host specific stats.
Expand Down
1 change: 1 addition & 0 deletions source/common/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ add_library(
mongo/codec_impl.cc
mongo/proxy.cc
mongo/utility.cc
network/address_impl.cc
network/connection_impl.cc
network/dns_impl.cc
network/filter_manager_impl.cc
Expand Down
12 changes: 7 additions & 5 deletions source/common/event/dispatcher_impl.cc
Original file line number Diff line number Diff line change
Expand Up @@ -55,13 +55,15 @@ void DispatcherImpl::clearDeferredDeleteList() {
deferred_deleting_ = false;
}

Network::ClientConnectionPtr DispatcherImpl::createClientConnection(const std::string& url) {
return Network::ClientConnectionImpl::create(*this, url);
Network::ClientConnectionPtr
DispatcherImpl::createClientConnection(Network::Address::InstancePtr address) {
return Network::ClientConnectionPtr{new Network::ClientConnectionImpl(*this, address)};
}

Network::ClientConnectionPtr DispatcherImpl::createSslClientConnection(Ssl::ClientContext& ssl_ctx,
const std::string& url) {
return Network::ClientConnectionPtr{new Ssl::ClientConnectionImpl(*this, ssl_ctx, url)};
Network::ClientConnectionPtr
DispatcherImpl::createSslClientConnection(Ssl::ClientContext& ssl_ctx,
Network::Address::InstancePtr address) {
return Network::ClientConnectionPtr{new Ssl::ClientConnectionImpl(*this, ssl_ctx, address)};
}

Network::DnsResolverPtr DispatcherImpl::createDnsResolver() {
Expand Down
8 changes: 5 additions & 3 deletions source/common/event/dispatcher_impl.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,11 @@ class DispatcherImpl : Logger::Loggable<Logger::Id::main>, public Dispatcher {

// Event::Dispatcher
void clearDeferredDeleteList() override;
Network::ClientConnectionPtr createClientConnection(const std::string& url) override;
Network::ClientConnectionPtr createSslClientConnection(Ssl::ClientContext& ssl_ctx,
const std::string& url) override;
Network::ClientConnectionPtr
createClientConnection(Network::Address::InstancePtr address) override;
Network::ClientConnectionPtr
createSslClientConnection(Ssl::ClientContext& ssl_ctx,
Network::Address::InstancePtr address) override;
Network::DnsResolverPtr createDnsResolver() override;
FileEventPtr createFileEvent(int fd, FileReadyCb cb) override;
Filesystem::WatcherPtr createFilesystemWatcher() override;
Expand Down
3 changes: 1 addition & 2 deletions source/common/filter/auth/client_ssl.cc
Original file line number Diff line number Diff line change
Expand Up @@ -98,8 +98,7 @@ void Instance::onEvent(uint32_t events) {
}

ASSERT(read_callbacks_->connection().ssl());
if (config_->ipWhiteList().contains(
Network::Utility::hostFromUrl(read_callbacks_->connection().remoteAddress()))) {
if (config_->ipWhiteList().contains(read_callbacks_->connection().remoteAddress())) {
config_->stats().auth_ip_white_list_.inc();
read_callbacks_->continueReading();
return;
Expand Down
25 changes: 7 additions & 18 deletions source/common/filter/tcp_proxy.cc
Original file line number Diff line number Diff line change
Expand Up @@ -61,34 +61,23 @@ TcpProxyConfig::TcpProxyConfig(const Json::Object& config,
const std::string& TcpProxyConfig::getRouteFromEntries(Network::Connection& connection) {
for (const TcpProxyConfig::Route& route : routes_) {
if (!route.source_port_ranges_.empty() &&
!Network::Utility::portInRangeList(
Network::Utility::portFromUrl(connection.remoteAddress()), route.source_port_ranges_)) {
continue; // no match, try next route
}

if (!route.source_ips_.empty() &&
!route.source_ips_.contains(Network::Utility::hostFromUrl(connection.remoteAddress()))) {
continue; // no match, try next route
!Network::Utility::portInRangeList(connection.remoteAddress(), route.source_port_ranges_)) {
continue;
}

// If the route needs to match on destination address and port but they are not available
// (localAddress is empty), we skip it. The connection has a chance to match a different
// route that does not depend on destination address and port.
if ((!route.destination_port_ranges_.empty() || !route.destination_ips_.empty()) &&
connection.localAddress().empty()) {
if (!route.source_ips_.empty() && !route.source_ips_.contains(connection.remoteAddress())) {
continue;
}

if (!route.destination_port_ranges_.empty() &&
!Network::Utility::portInRangeList(Network::Utility::portFromUrl(connection.localAddress()),
!Network::Utility::portInRangeList(connection.localAddress(),
route.destination_port_ranges_)) {
continue; // no match, try next route
continue;
}

if (!route.destination_ips_.empty() &&
!route.destination_ips_.contains(
Network::Utility::hostFromUrl(connection.localAddress()))) {
continue; // no match, try next route
!route.destination_ips_.contains(connection.localAddress())) {
continue;
}

// if we made it past all checks, the route matches
Expand Down
9 changes: 4 additions & 5 deletions source/common/http/access_log/access_log_formatter.cc
Original file line number Diff line number Diff line change
Expand Up @@ -251,12 +251,11 @@ RequestInfoFormatter::RequestInfoFormatter(const std::string& field_name) {
};
} else if (field_name == "UPSTREAM_HOST") {
field_extractor_ = [](const RequestInfo& request_info) {
std::string upstream_host_url;
if (nullptr != request_info.upstreamHost()) {
upstream_host_url = request_info.upstreamHost()->url();
if (request_info.upstreamHost()) {
return request_info.upstreamHost()->address()->asString();
} else {
return std::string("-");
}

return upstream_host_url.empty() ? "-" : upstream_host_url;
};
} else if (field_name == "UPSTREAM_CLUSTER") {
field_extractor_ = [](const RequestInfo& request_info) {
Expand Down
3 changes: 2 additions & 1 deletion source/common/http/async_client_impl.cc
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#include "async_client_impl.h"
#include "utility.h"

namespace Http {

Expand Down Expand Up @@ -94,7 +95,7 @@ void AsyncStreamImpl::encodeTrailers(HeaderMapPtr&& trailers) {

void AsyncStreamImpl::sendHeaders(HeaderMap& headers, bool end_stream) {
headers.insertEnvoyInternalRequest().value(Headers::get().EnvoyInternalRequestValues.True);
headers.insertForwardedFor().value(parent_.config_.local_info_.address());
Utility::appendXff(headers, *parent_.config_.local_info_.address());
router_.decodeHeaders(headers, end_stream);
closeLocal(end_stream);
}
Expand Down
2 changes: 1 addition & 1 deletion source/common/http/conn_manager_impl.h
Original file line number Diff line number Diff line change
Expand Up @@ -188,7 +188,7 @@ class ConnectionManagerConfig {
* @return local address.
* Gives richer information in case of internal requests.
*/
virtual const std::string& localAddress() PURE;
virtual const Network::Address::Instance& localAddress() PURE;

/**
* @return custom user agent for internal requests for better debugging. Must be configured to
Expand Down
Loading

0 comments on commit 86219a4

Please sign in to comment.