diff --git a/iocore/net/I_NetVConnection.h b/iocore/net/I_NetVConnection.h index f16b5e84d12..d99fbc9df59 100644 --- a/iocore/net/I_NetVConnection.h +++ b/iocore/net/I_NetVConnection.h @@ -507,7 +507,20 @@ class NetVConnection : public VConnection, public PluginUserArgs 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; @@ -526,6 +539,16 @@ class NetVConnection : public VConnection, public PluginUserArgs void _set_service(S *instance); + +private: + void *_services[static_cast(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) @@ -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(service)]; +} + +inline void +NetVConnection::_set_service(enum NetVConnection::Service service, void *instance) +{ + this->_services[static_cast(service)] = instance; +} + +class ALPNSupport; +template <> +inline ALPNSupport * +NetVConnection::get_service() const +{ + return static_cast(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(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(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(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(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(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(this->_get_service(NetVConnection::Service::TLS_Tunnel)); +} +template <> +inline void +NetVConnection::_set_service(TLSTunnelSupport *instance) +{ + this->_set_service(NetVConnection::Service::TLS_Tunnel, instance); +} diff --git a/iocore/net/QUICNetVConnection_quiche.cc b/iocore/net/QUICNetVConnection_quiche.cc index 2d638f99289..321e3569804 100644 --- a/iocore/net/QUICNetVConnection_quiche.cc +++ b/iocore/net/QUICNetVConnection_quiche.cc @@ -37,7 +37,14 @@ static constexpr ink_hrtime WRITE_READY_INTERVAL = HRTIME_MSECONDS(2); ClassAllocator quicNetVCAllocator("quicNetVCAllocator"); -QUICNetVConnection::QUICNetVConnection() {} +QUICNetVConnection::QUICNetVConnection() +{ + this->_set_service(static_cast(this)); + this->_set_service(static_cast(this)); + this->_set_service(static_cast(this)); + this->_set_service(static_cast(this)); + this->_set_service(static_cast(this)); +} QUICNetVConnection::~QUICNetVConnection() {} diff --git a/iocore/net/SSLNetVConnection.cc b/iocore/net/SSLNetVConnection.cc index c40fad61f8a..1bc73f296d0 100644 --- a/iocore/net/SSLNetVConnection.cc +++ b/iocore/net/SSLNetVConnection.cc @@ -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(this)); + this->_set_service(static_cast(this)); + this->_set_service(static_cast(this)); + this->_set_service(static_cast(this)); + this->_set_service(static_cast(this)); + this->_set_service(static_cast(this)); + this->_set_service(static_cast(this)); +} void SSLNetVConnection::do_io_close(int lerrno) diff --git a/proxy/ProxySession.cc b/proxy/ProxySession.cc index a4feee97ae7..ab4211cd3c9 100644 --- a/proxy/ProxySession.cc +++ b/proxy/ProxySession.cc @@ -287,7 +287,7 @@ ProxySession::get_local_addr() void ProxySession::_handle_if_ssl(NetVConnection *new_vc) { - auto tbs = dynamic_cast(new_vc); + auto tbs = new_vc->get_service(); if (tbs) { _ssl = std::make_unique(); _ssl.get()->init(*new_vc); diff --git a/proxy/http/Http1ClientSession.cc b/proxy/http/Http1ClientSession.cc index 23f7696ca3e..ff1f58bbfda 100644 --- a/proxy/http/Http1ClientSession.cc +++ b/proxy/http/Http1ClientSession.cc @@ -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(new_vc); - if (eds != nullptr) { + if (TLSEarlyDataSupport *eds = new_vc->get_service()) { read_from_early_data = eds->get_early_data_len(); Debug("ssl_early_data", "read_from_early_data = %" PRId64, read_from_early_data); } @@ -534,7 +533,7 @@ bool Http1ClientSession::allow_half_open() const { // Only allow half open connections if the not over TLS - return (_vc && dynamic_cast(_vc) == nullptr); + return (_vc && _vc->get_service() == nullptr); } void diff --git a/proxy/http/HttpSM.cc b/proxy/http/HttpSM.cc index 77be42d3d55..ef45360bb9b 100644 --- a/proxy/http/HttpSM.cc +++ b/proxy/http/HttpSM.cc @@ -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(netvc)) { + if (auto tbs = netvc->get_service()) { client_connection_is_ssl = true; const char *protocol = tbs->get_tls_protocol_name(); client_sec_protocol = protocol ? protocol : "-"; @@ -538,11 +538,11 @@ HttpSM::attach_client_session(ProxyTransaction *client_vc) } } - if (auto as = dynamic_cast(netvc)) { + if (auto as = netvc->get_service()) { client_alpn_id = as->get_negotiated_protocol_id(); } - if (auto tsrs = dynamic_cast(netvc)) { + if (auto tsrs = netvc->get_service()) { client_ssl_reused = tsrs->getSSLSessionCacheHit(); } @@ -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(netvc); + auto tts = netvc->get_service(); if (is_transparent_passthrough_allowed() || (tts && tts->is_decryption_needed())) { ua_raw_buffer_reader = ua_txn->get_remote_reader()->clone(); } @@ -649,7 +649,7 @@ HttpSM::setup_blind_tunnel_port() } TLSTunnelSupport *tts = nullptr; - if (!ua_txn->is_outbound_transparent() && (tts = dynamic_cast(netvc))) { + if (!ua_txn->is_outbound_transparent() && (tts = netvc->get_service())) { 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(); @@ -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(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(); 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 @@ -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(netvc); + auto *tts = netvc->get_service(); 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(); @@ -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(netvc); - if (sslnetvc) { - proto_index = sslnetvc->get_negotiated_protocol_id(); + int proto_index = SessionProtocolNameRegistry::INVALID; + if (auto const alpn = netvc->get_service(); 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) { @@ -5576,7 +5576,7 @@ 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(ua_txn->get_netvc()); + auto tts = ua_txn->get_netvc()->get_service(); if (tts && raw) { tls_upstream = tts->is_upstream_tls(); _tunnel_type = tts->get_tunnel_type(); @@ -5584,7 +5584,7 @@ HttpSM::do_http_server_open(bool raw, bool only_direct) // 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(ua_txn->get_netvc()); + auto alpns = ua_txn->get_netvc()->get_service(); ink_assert(alpns); pid = alpns->get_negotiated_protocol_id(); if (pid != SessionProtocolNameRegistry::INVALID) { @@ -6605,12 +6605,11 @@ HttpSM::attach_server_session() UnixNetVConnection *server_vc = static_cast(server_txn->get_netvc()); // set flag for server session is SSL - TLSBasicSupport *tbs = dynamic_cast(server_vc); - if (tbs) { + if (server_vc->get_service()) { server_connection_is_ssl = true; } - if (auto tsrs = dynamic_cast(server_vc)) { + if (auto tsrs = server_vc->get_service(); tsrs) { server_ssl_reused = tsrs->getSSLOriginSessionCacheHit(); } diff --git a/proxy/http2/Http2ClientSession.cc b/proxy/http2/Http2ClientSession.cc index 56ce64928f4..d7a43d773b1 100644 --- a/proxy/http2/Http2ClientSession.cc +++ b/proxy/http2/Http2ClientSession.cc @@ -101,8 +101,7 @@ Http2ClientSession::new_connection(NetVConnection *new_vc, MIOBuffer *iobuf, IOB this->connection_state.mutex = this->mutex; - TLSEarlyDataSupport *eds = dynamic_cast(new_vc); - if (eds != nullptr) { + if (auto eds = new_vc->get_service(); 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); } @@ -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(this->_vc); - if (snis && snis->hints_from_sni.http2_buffer_water_mark.has_value()) { + if (auto snis = this->_vc->get_service(); 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; diff --git a/proxy/private/SSLProxySession.cc b/proxy/private/SSLProxySession.cc index 32da935cf60..1838cb839f0 100644 --- a/proxy/private/SSLProxySession.cc +++ b/proxy/private/SSLProxySession.cc @@ -29,7 +29,7 @@ void SSLProxySession::init(NetVConnection const &new_vc) { - if (dynamic_cast(&new_vc) != nullptr) { + if (new_vc.get_service() != nullptr) { if (char const *name = new_vc.get_server_name()) { _client_sni_server_name.assign(name); } diff --git a/src/traffic_server/InkAPI.cc b/src/traffic_server/InkAPI.cc index a58bb29981c..3afca1e576f 100644 --- a/src/traffic_server/InkAPI.cc +++ b/src/traffic_server/InkAPI.cc @@ -6571,7 +6571,7 @@ const char * TSVConnSslCipherGet(TSVConn sslp) { NetVConnection *vc = reinterpret_cast(sslp); - TLSBasicSupport *tlsbs = dynamic_cast(vc); + TLSBasicSupport *tlsbs = vc->get_service(); return tlsbs ? tlsbs->get_tls_cipher_suite() : nullptr; } @@ -6580,7 +6580,7 @@ const char * TSVConnSslProtocolGet(TSVConn sslp) { NetVConnection *vc = reinterpret_cast(sslp); - TLSBasicSupport *tlsbs = dynamic_cast(vc); + TLSBasicSupport *tlsbs = vc->get_service(); return tlsbs ? tlsbs->get_tls_protocol_name() : nullptr; } @@ -6589,7 +6589,7 @@ const char * TSVConnSslCurveGet(TSVConn sslp) { NetVConnection *vc = reinterpret_cast(sslp); - TLSBasicSupport *tlsbs = dynamic_cast(vc); + TLSBasicSupport *tlsbs = vc->get_service(); return tlsbs ? tlsbs->get_tls_curve() : nullptr; } @@ -9674,9 +9674,8 @@ TSVConnProtocolEnable(TSVConn connp, const char *protocol_name) TSReturnCode retval = TS_ERROR; int protocol_idx = globalSessionProtocolNameRegistry.toIndexConst(std::string_view{protocol_name}); auto net_vc = reinterpret_cast(connp); - auto alpn_vc = dynamic_cast(net_vc); - if (alpn_vc) { - alpn_vc->enableProtocol(protocol_idx); + if (auto alpn = net_vc->get_service(); alpn) { + alpn->enableProtocol(protocol_idx); retval = TS_SUCCESS; } return retval; @@ -9688,9 +9687,8 @@ TSVConnProtocolDisable(TSVConn connp, const char *protocol_name) TSReturnCode retval = TS_ERROR; int protocol_idx = globalSessionProtocolNameRegistry.toIndexConst(std::string_view{protocol_name}); auto net_vc = reinterpret_cast(connp); - auto alpn_vc = dynamic_cast(net_vc); - if (alpn_vc) { - alpn_vc->disableProtocol(protocol_idx); + if (auto alpn = net_vc->get_service(); alpn) { + alpn->disableProtocol(protocol_idx); retval = TS_SUCCESS; } return retval;