Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
133 changes: 133 additions & 0 deletions iocore/net/I_NetVConnection.h
Original file line number Diff line number Diff line change
Expand Up @@ -507,7 +507,20 @@ class NetVConnection : public VConnection, public PluginUserArgs<TS_USER_ARGS_VC
bool has_proxy_protocol(IOBufferReader *);
bool has_proxy_protocol(char *, int64_t *);

template <typename S> S *get_service() const;

protected:
enum class Service : uint8_t {
TLS_ALPN,
TLS_Basic,
TLS_CertSwitch,
TLS_EarlyData,
TLS_SNI,
TLS_SessionResumption,
TLS_Tunnel,
N_SERVICES,
};

IpEndpoint local_addr;
IpEndpoint remote_addr;
ProxyProtocol pp_info;
Expand All @@ -526,6 +539,16 @@ class NetVConnection : public VConnection, public PluginUserArgs<TS_USER_ARGS_VC
int write_buffer_empty_event = 0;
/// NetVConnection Context.
NetVConnectionContext_t netvc_context = NET_VCONNECTION_UNSET;

template <typename S> void _set_service(S *instance);

private:
void *_services[static_cast<unsigned int>(Service::N_SERVICES)] = {
nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
};

void *_get_service(enum Service mixin_index) const;
void _set_service(enum Service mixin_index, void *instance);
};

inline NetVConnection::NetVConnection() : VConnection(nullptr)
Expand All @@ -540,3 +563,113 @@ NetVConnection::trapWriteBufferEmpty(int event)
{
write_buffer_empty_event = event;
}

inline void *
NetVConnection::_get_service(enum NetVConnection::Service service) const
{
return _services[static_cast<unsigned int>(service)];
}

inline void
NetVConnection::_set_service(enum NetVConnection::Service service, void *instance)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note that this isn't type-safe. I expect it would be possible to make it typesafe if you had a template that mapped the enum to the type directly.

{
this->_services[static_cast<unsigned int>(service)] = instance;
}

class ALPNSupport;
template <>
inline ALPNSupport *
NetVConnection::get_service() const
{
return static_cast<ALPNSupport *>(this->_get_service(NetVConnection::Service::TLS_ALPN));
}
template <>
inline void
NetVConnection::_set_service(ALPNSupport *instance)
{
this->_set_service(NetVConnection::Service::TLS_ALPN, instance);
}

class TLSBasicSupport;
template <>
inline TLSBasicSupport *
NetVConnection::get_service() const
{
return static_cast<TLSBasicSupport *>(this->_get_service(NetVConnection::Service::TLS_Basic));
}
template <>
inline void
NetVConnection::_set_service(TLSBasicSupport *instance)
{
this->_set_service(NetVConnection::Service::TLS_Basic, instance);
}

class TLSEarlyDataSupport;
template <>
inline TLSEarlyDataSupport *
NetVConnection::get_service() const
{
return static_cast<TLSEarlyDataSupport *>(this->_get_service(NetVConnection::Service::TLS_EarlyData));
}
template <>
inline void
NetVConnection::_set_service(TLSEarlyDataSupport *instance)
{
this->_set_service(NetVConnection::Service::TLS_EarlyData, instance);
}

class TLSCertSwitchSupport;
template <>
inline TLSCertSwitchSupport *
NetVConnection::get_service() const
{
return static_cast<TLSCertSwitchSupport *>(this->_get_service(NetVConnection::Service::TLS_CertSwitch));
}
template <>
inline void
NetVConnection::_set_service(TLSCertSwitchSupport *instance)
{
this->_set_service(NetVConnection::Service::TLS_CertSwitch, instance);
}

class TLSSNISupport;
template <>
inline TLSSNISupport *
NetVConnection::get_service() const
{
return static_cast<TLSSNISupport *>(this->_get_service(NetVConnection::Service::TLS_SNI));
}
template <>
inline void
NetVConnection::_set_service(TLSSNISupport *instance)
{
this->_set_service(NetVConnection::Service::TLS_SNI, instance);
}

class TLSSessionResumptionSupport;
template <>
inline TLSSessionResumptionSupport *
NetVConnection::get_service() const
{
return static_cast<TLSSessionResumptionSupport *>(this->_get_service(NetVConnection::Service::TLS_SessionResumption));
}
template <>
inline void
NetVConnection::_set_service(TLSSessionResumptionSupport *instance)
{
this->_set_service(NetVConnection::Service::TLS_SessionResumption, instance);
}

class TLSTunnelSupport;
template <>
inline TLSTunnelSupport *
NetVConnection::get_service() const
{
return static_cast<TLSTunnelSupport *>(this->_get_service(NetVConnection::Service::TLS_Tunnel));
}
template <>
inline void
NetVConnection::_set_service(TLSTunnelSupport *instance)
{
this->_set_service(NetVConnection::Service::TLS_Tunnel, instance);
}
9 changes: 8 additions & 1 deletion iocore/net/QUICNetVConnection_quiche.cc
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,14 @@ static constexpr ink_hrtime WRITE_READY_INTERVAL = HRTIME_MSECONDS(2);

ClassAllocator<QUICNetVConnection> quicNetVCAllocator("quicNetVCAllocator");

QUICNetVConnection::QUICNetVConnection() {}
QUICNetVConnection::QUICNetVConnection()
{
this->_set_service(static_cast<ALPNSupport *>(this));
this->_set_service(static_cast<TLSBasicSupport *>(this));
this->_set_service(static_cast<TLSCertSwitchSupport *>(this));
this->_set_service(static_cast<TLSSNISupport *>(this));
this->_set_service(static_cast<TLSSessionResumptionSupport *>(this));
}

QUICNetVConnection::~QUICNetVConnection() {}

Expand Down
11 changes: 10 additions & 1 deletion iocore/net/SSLNetVConnection.cc
Original file line number Diff line number Diff line change
Expand Up @@ -860,7 +860,16 @@ SSLNetVConnection::load_buffer_and_write(int64_t towrite, MIOBufferAccessor &buf
return num_really_written;
}

SSLNetVConnection::SSLNetVConnection() {}
SSLNetVConnection::SSLNetVConnection()
{
this->_set_service(static_cast<ALPNSupport *>(this));
this->_set_service(static_cast<TLSBasicSupport *>(this));
this->_set_service(static_cast<TLSCertSwitchSupport *>(this));
this->_set_service(static_cast<TLSEarlyDataSupport *>(this));
this->_set_service(static_cast<TLSSNISupport *>(this));
this->_set_service(static_cast<TLSSessionResumptionSupport *>(this));
this->_set_service(static_cast<TLSTunnelSupport *>(this));
}

void
SSLNetVConnection::do_io_close(int lerrno)
Expand Down
2 changes: 1 addition & 1 deletion proxy/ProxySession.cc
Original file line number Diff line number Diff line change
Expand Up @@ -287,7 +287,7 @@ ProxySession::get_local_addr()
void
ProxySession::_handle_if_ssl(NetVConnection *new_vc)
{
auto tbs = dynamic_cast<TLSBasicSupport *>(new_vc);
auto tbs = new_vc->get_service<TLSBasicSupport>();
if (tbs) {
_ssl = std::make_unique<SSLProxySession>();
_ssl.get()->init(*new_vc);
Expand Down
5 changes: 2 additions & 3 deletions proxy/http/Http1ClientSession.cc
Original file line number Diff line number Diff line change
Expand Up @@ -141,8 +141,7 @@ Http1ClientSession::new_connection(NetVConnection *new_vc, MIOBuffer *iobuf, IOB
trans.mutex = mutex; // Share this mutex with the transaction
in_destroy = false;

TLSEarlyDataSupport *eds = dynamic_cast<TLSEarlyDataSupport *>(new_vc);
if (eds != nullptr) {
if (TLSEarlyDataSupport *eds = new_vc->get_service<TLSEarlyDataSupport>()) {
read_from_early_data = eds->get_early_data_len();
Debug("ssl_early_data", "read_from_early_data = %" PRId64, read_from_early_data);
}
Expand Down Expand Up @@ -534,7 +533,7 @@ bool
Http1ClientSession::allow_half_open() const
{
// Only allow half open connections if the not over TLS
return (_vc && dynamic_cast<TLSBasicSupport *>(_vc) == nullptr);
return (_vc && _vc->get_service<TLSBasicSupport>() == nullptr);
}

void
Expand Down
49 changes: 24 additions & 25 deletions proxy/http/HttpSM.cc
Original file line number Diff line number Diff line change
Expand Up @@ -522,7 +522,7 @@ HttpSM::attach_client_session(ProxyTransaction *client_vc)
mptcp_state = netvc->get_mptcp_state();
client_tcp_reused = !(ua_txn->is_first_transaction());

if (auto tbs = dynamic_cast<TLSBasicSupport *>(netvc)) {
if (auto tbs = netvc->get_service<TLSBasicSupport>()) {
client_connection_is_ssl = true;
const char *protocol = tbs->get_tls_protocol_name();
client_sec_protocol = protocol ? protocol : "-";
Expand All @@ -538,11 +538,11 @@ HttpSM::attach_client_session(ProxyTransaction *client_vc)
}
}

if (auto as = dynamic_cast<ALPNSupport *>(netvc)) {
if (auto as = netvc->get_service<ALPNSupport>()) {
client_alpn_id = as->get_negotiated_protocol_id();
}

if (auto tsrs = dynamic_cast<TLSSessionResumptionSupport *>(netvc)) {
if (auto tsrs = netvc->get_service<TLSSessionResumptionSupport>()) {
client_ssl_reused = tsrs->getSSLSessionCacheHit();
}

Expand Down Expand Up @@ -585,7 +585,7 @@ HttpSM::attach_client_session(ProxyTransaction *client_vc)
t_state.hdr_info.client_request.create(HTTP_TYPE_REQUEST);

// Prepare raw reader which will live until we are sure this is HTTP indeed
auto *tts = dynamic_cast<TLSTunnelSupport *>(netvc);
auto tts = netvc->get_service<TLSTunnelSupport>();
if (is_transparent_passthrough_allowed() || (tts && tts->is_decryption_needed())) {
ua_raw_buffer_reader = ua_txn->get_remote_reader()->clone();
}
Expand Down Expand Up @@ -649,7 +649,7 @@ HttpSM::setup_blind_tunnel_port()
}

TLSTunnelSupport *tts = nullptr;
if (!ua_txn->is_outbound_transparent() && (tts = dynamic_cast<TLSTunnelSupport *>(netvc))) {
if (!ua_txn->is_outbound_transparent() && (tts = netvc->get_service<TLSTunnelSupport>())) {
if (!t_state.hdr_info.client_request.url_get()->host_get(&host_len)) {
if (tts->has_tunnel_destination()) {
auto tunnel_host = tts->get_tunnel_host();
Expand Down Expand Up @@ -1513,20 +1513,21 @@ plugins required to work with sni_routing.
t_state.hdr_info.client_request.url_set(&u);

NetVConnection *netvc = ua_txn->get_netvc();
auto *tts = dynamic_cast<TLSTunnelSupport *>(netvc);

if (tts && tts->has_tunnel_destination()) {
auto tunnel_host = tts->get_tunnel_host();
t_state.hdr_info.client_request.url_get()->host_set(tunnel_host.data(), tunnel_host.size());
ushort tunnel_port = tts->get_tunnel_port();
if (tunnel_port > 0) {
t_state.hdr_info.client_request.url_get()->port_set(tunnel_port);
if (auto tts = netvc->get_service<TLSTunnelSupport>(); tts) {
if (tts->has_tunnel_destination()) {
auto tunnel_host = tts->get_tunnel_host();
t_state.hdr_info.client_request.url_get()->host_set(tunnel_host.data(), tunnel_host.size());
ushort tunnel_port = tts->get_tunnel_port();
if (tunnel_port > 0) {
t_state.hdr_info.client_request.url_get()->port_set(tunnel_port);
} else {
t_state.hdr_info.client_request.url_get()->port_set(netvc->get_local_port());
}
} else {
t_state.hdr_info.client_request.url_get()->host_set(netvc->get_server_name(), strlen(netvc->get_server_name()));
t_state.hdr_info.client_request.url_get()->port_set(netvc->get_local_port());
}
} else if (tts) {
t_state.hdr_info.client_request.url_get()->host_set(netvc->get_server_name(), strlen(netvc->get_server_name()));
t_state.hdr_info.client_request.url_get()->port_set(netvc->get_local_port());
}
}
// FALLTHROUGH
Expand Down Expand Up @@ -1678,7 +1679,7 @@ HttpSM::handle_api_return()
switch (t_state.api_next_action) {
case HttpTransact::SM_ACTION_API_SM_START: {
NetVConnection *netvc = ua_txn->get_netvc();
auto *tts = dynamic_cast<TLSTunnelSupport *>(netvc);
auto *tts = netvc->get_service<TLSTunnelSupport>();
bool forward_dest = tts != nullptr && tts->is_decryption_needed();
if (t_state.client_info.port_attribute == HttpProxyPort::TRANSPORT_BLIND_TUNNEL || forward_dest) {
setup_blind_tunnel_port();
Expand Down Expand Up @@ -1821,10 +1822,9 @@ PoolableSession *
HttpSM::create_server_session(NetVConnection *netvc, MIOBuffer *netvc_read_buffer, IOBufferReader *netvc_reader)
{
// Figure out what protocol was negotiated
int proto_index = SessionProtocolNameRegistry::INVALID;
auto const *sslnetvc = dynamic_cast<ALPNSupport *>(netvc);
if (sslnetvc) {
proto_index = sslnetvc->get_negotiated_protocol_id();
int proto_index = SessionProtocolNameRegistry::INVALID;
if (auto const alpn = netvc->get_service<ALPNSupport>(); alpn) {
proto_index = alpn->get_negotiated_protocol_id();
}
// No ALPN occurred. Assume it was HTTP/1.x and hope for the best
if (proto_index == SessionProtocolNameRegistry::INVALID) {
Expand Down Expand Up @@ -5576,15 +5576,15 @@ HttpSM::do_http_server_open(bool raw, bool only_direct)
int scheme_to_use = t_state.scheme; // get initial scheme
bool tls_upstream = scheme_to_use == URL_WKSIDX_HTTPS;
if (ua_txn) {
auto *tts = dynamic_cast<TLSTunnelSupport *>(ua_txn->get_netvc());
auto tts = ua_txn->get_netvc()->get_service<TLSTunnelSupport>();
if (tts && raw) {
tls_upstream = tts->is_upstream_tls();
_tunnel_type = tts->get_tunnel_type();

// ALPN on TLS Partial Blind Tunnel - set negotiated ALPN id
int pid = SessionProtocolNameRegistry::INVALID;
if (tts->get_tunnel_type() == SNIRoutingType::PARTIAL_BLIND) {
auto *alpns = dynamic_cast<ALPNSupport *>(ua_txn->get_netvc());
auto alpns = ua_txn->get_netvc()->get_service<ALPNSupport>();
ink_assert(alpns);
pid = alpns->get_negotiated_protocol_id();
if (pid != SessionProtocolNameRegistry::INVALID) {
Expand Down Expand Up @@ -6605,12 +6605,11 @@ HttpSM::attach_server_session()
UnixNetVConnection *server_vc = static_cast<UnixNetVConnection *>(server_txn->get_netvc());

// set flag for server session is SSL
TLSBasicSupport *tbs = dynamic_cast<TLSBasicSupport *>(server_vc);
if (tbs) {
if (server_vc->get_service<TLSBasicSupport>()) {
server_connection_is_ssl = true;
}

if (auto tsrs = dynamic_cast<TLSSessionResumptionSupport *>(server_vc)) {
if (auto tsrs = server_vc->get_service<TLSSessionResumptionSupport>(); tsrs) {
server_ssl_reused = tsrs->getSSLOriginSessionCacheHit();
}

Expand Down
6 changes: 2 additions & 4 deletions proxy/http2/Http2ClientSession.cc
Original file line number Diff line number Diff line change
Expand Up @@ -101,8 +101,7 @@ Http2ClientSession::new_connection(NetVConnection *new_vc, MIOBuffer *iobuf, IOB

this->connection_state.mutex = this->mutex;

TLSEarlyDataSupport *eds = dynamic_cast<TLSEarlyDataSupport *>(new_vc);
if (eds != nullptr) {
if (auto eds = new_vc->get_service<TLSEarlyDataSupport>(); eds) {
this->read_from_early_data = eds->get_early_data_len();
Debug("ssl_early_data", "read_from_early_data = %" PRId64, this->read_from_early_data);
}
Expand All @@ -120,8 +119,7 @@ Http2ClientSession::new_connection(NetVConnection *new_vc, MIOBuffer *iobuf, IOB
this->write_buffer = new_MIOBuffer(buffer_block_size_index);

uint32_t buffer_water_mark;
TLSSNISupport *snis = dynamic_cast<TLSSNISupport *>(this->_vc);
if (snis && snis->hints_from_sni.http2_buffer_water_mark.has_value()) {
if (auto snis = this->_vc->get_service<TLSSNISupport>(); snis && snis->hints_from_sni.http2_buffer_water_mark.has_value()) {
buffer_water_mark = snis->hints_from_sni.http2_buffer_water_mark.value();
} else {
buffer_water_mark = Http2::buffer_water_mark;
Expand Down
2 changes: 1 addition & 1 deletion proxy/private/SSLProxySession.cc
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@
void
SSLProxySession::init(NetVConnection const &new_vc)
{
if (dynamic_cast<const TLSSNISupport *>(&new_vc) != nullptr) {
if (new_vc.get_service<TLSSNISupport>() != nullptr) {
if (char const *name = new_vc.get_server_name()) {
_client_sni_server_name.assign(name);
}
Expand Down
Loading