You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@trafficserver.apache.org by ac...@apache.org on 2021/01/20 17:27:33 UTC

[trafficserver] branch master updated: PoolableSession (#6828)

This is an automated email from the ASF dual-hosted git repository.

acanary pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/trafficserver.git


The following commit(s) were added to refs/heads/master by this push:
     new d4f202c  PoolableSession (#6828)
d4f202c is described below

commit d4f202c808dd1b76255ce8991960ff83c07a9c46
Author: a-a-ron <ac...@verizonmedia.com>
AuthorDate: Wed Jan 20 11:27:21 2021 -0600

    PoolableSession (#6828)
    
    Http1ServerSessions now inherit from an abstract PoolableSession which adds following for outbound pooling:
    + linkage for intrusive dlist
    + KA status
    + OutboundConnTrack::Group
    
    Its is expected that H2 and H3 session will also need to inherit from this, or something similar.
---
 proxy/Makefile.am                                 |   1 +
 proxy/PoolableSession.h                           | 192 ++++++++++++++++++++++
 proxy/ProxySession.cc                             |  18 +-
 proxy/ProxySession.h                              |  15 +-
 proxy/ProxyTransaction.cc                         |  34 +++-
 proxy/ProxyTransaction.h                          |  57 ++++++-
 proxy/http/Http1ClientSession.cc                  |  37 ++---
 proxy/http/Http1ClientSession.h                   |  19 ++-
 proxy/http/Http1ServerSession.cc                  | 110 +++++--------
 proxy/http/Http1ServerSession.h                   | 159 ++----------------
 proxy/http/Http1Transaction.cc                    |  52 ------
 proxy/http/Http1Transaction.h                     |  11 --
 proxy/http/HttpSM.cc                              | 146 ++++++++--------
 proxy/http/HttpSM.h                               |  14 +-
 proxy/http/HttpSessionManager.cc                  |  75 +++++----
 proxy/http/HttpSessionManager.h                   |  14 +-
 proxy/http/HttpTransactHeaders.cc                 |   1 +
 proxy/http2/Http2ClientSession.cc                 |  10 +-
 proxy/http2/Http2ClientSession.h                  |   6 +-
 proxy/http2/Http2ConnectionState.cc               |   2 +-
 proxy/http2/Http2Stream.h                         |   2 +-
 proxy/http3/Http3Session.cc                       |   8 +-
 proxy/http3/Http3Session.h                        |   8 +-
 src/traffic_server/InkAPI.cc                      |  54 +++---
 tests/gold_tests/continuations/session_id.test.py |  15 +-
 25 files changed, 563 insertions(+), 497 deletions(-)

diff --git a/proxy/Makefile.am b/proxy/Makefile.am
index 33a2ad1..4eec154 100644
--- a/proxy/Makefile.am
+++ b/proxy/Makefile.am
@@ -70,6 +70,7 @@ libproxy_a_SOURCES = \
 	ProtocolProbeSessionAccept.h \
 	ProxySession.cc \
 	ProxySession.h \
+	PoolableSession.h \
 	ProxyTransaction.cc \
 	ProxyTransaction.h \
 	ReverseProxy.cc \
diff --git a/proxy/PoolableSession.h b/proxy/PoolableSession.h
new file mode 100644
index 0000000..76946ef
--- /dev/null
+++ b/proxy/PoolableSession.h
@@ -0,0 +1,192 @@
+/** @file
+
+  PoolableSession - class that extends ProxySession so that they can be cataloged for reuse.
+
+  @section license License
+
+  Licensed to the Apache Software Foundation (ASF) under one
+  or more contributor license agreements.  See the NOTICE file
+  distributed with this work for additional information
+  regarding copyright ownership.  The ASF licenses this file
+  to you under the Apache License, Version 2.0 (the
+  "License"); you may not use this file except in compliance
+  with the License.  You may obtain a copy of the License at
+
+      http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+ */
+
+#pragma once
+
+#include "ProxySession.h"
+
+class PoolableSession : public ProxySession
+{
+  using self_type  = PoolableSession;
+  using super_type = ProxySession;
+
+public:
+  enum PooledState {
+    INIT,
+    SSN_IN_USE,  // actively in use
+    KA_RESERVED, // stuck to client
+    KA_POOLED,   // free for reuse
+  };
+
+  /// Hash map descriptor class for IP map.
+  struct IPLinkage {
+    self_type *_next = nullptr;
+    self_type *_prev = nullptr;
+
+    static self_type *&next_ptr(self_type *);
+    static self_type *&prev_ptr(self_type *);
+    static uint32_t hash_of(sockaddr const *key);
+    static sockaddr const *key_of(self_type const *ssn);
+    static bool equal(sockaddr const *lhs, sockaddr const *rhs);
+    // Add a couple overloads for internal convenience.
+    static bool equal(sockaddr const *lhs, PoolableSession const *rhs);
+    static bool equal(PoolableSession const *lhs, sockaddr const *rhs);
+  } _ip_link;
+
+  /// Hash map descriptor class for FQDN map.
+  struct FQDNLinkage {
+    self_type *_next = nullptr;
+    self_type *_prev = nullptr;
+
+    static self_type *&next_ptr(self_type *);
+    static self_type *&prev_ptr(self_type *);
+    static uint64_t hash_of(CryptoHash const &key);
+    static CryptoHash const &key_of(self_type *ssn);
+    static bool equal(CryptoHash const &lhs, CryptoHash const &rhs);
+  } _fqdn_link;
+
+  CryptoHash hostname_hash;
+  PooledState state = INIT;
+
+  // Copy of the owning SM's server session sharing settings
+  TSServerSessionSharingMatchMask sharing_match = TS_SERVER_SESSION_SHARING_MATCH_MASK_NONE;
+  TSServerSessionSharingPoolType sharing_pool   = TS_SERVER_SESSION_SHARING_POOL_GLOBAL;
+
+  // Keep track of connection limiting and a pointer to the
+  // singleton that keeps track of the connection counts.
+  OutboundConnTrack::Group *conn_track_group = nullptr;
+
+  void set_active();
+  bool is_active();
+  void set_private(bool new_private = true);
+  bool is_private() const;
+
+  void set_netvc(NetVConnection *newvc);
+
+private:
+  // Sessions become if authentication headers
+  //  are sent over them
+  bool private_session = false;
+};
+
+inline void
+PoolableSession::set_active()
+{
+  state = SSN_IN_USE;
+}
+inline bool
+PoolableSession::is_active()
+{
+  return state == SSN_IN_USE;
+}
+inline void
+PoolableSession::set_private(bool new_private)
+{
+  private_session = new_private;
+}
+inline bool
+PoolableSession::is_private() const
+{
+  return private_session;
+}
+
+inline void
+PoolableSession::set_netvc(NetVConnection *newvc)
+{
+  ProxySession::_vc = newvc;
+}
+
+//
+// LINKAGE
+
+inline PoolableSession *&
+PoolableSession::IPLinkage::next_ptr(self_type *ssn)
+{
+  return ssn->_ip_link._next;
+}
+
+inline PoolableSession *&
+PoolableSession::IPLinkage::prev_ptr(self_type *ssn)
+{
+  return ssn->_ip_link._prev;
+}
+
+inline uint32_t
+PoolableSession::IPLinkage::hash_of(sockaddr const *key)
+{
+  return ats_ip_hash(key);
+}
+
+inline sockaddr const *
+PoolableSession::IPLinkage::key_of(self_type const *ssn)
+{
+  return ssn->get_remote_addr();
+}
+
+inline bool
+PoolableSession::IPLinkage::equal(sockaddr const *lhs, sockaddr const *rhs)
+{
+  return ats_ip_addr_port_eq(lhs, rhs);
+}
+
+inline bool
+PoolableSession::IPLinkage::equal(sockaddr const *lhs, PoolableSession const *rhs)
+{
+  return ats_ip_addr_port_eq(lhs, key_of(rhs));
+}
+
+inline bool
+PoolableSession::IPLinkage::equal(PoolableSession const *lhs, sockaddr const *rhs)
+{
+  return ats_ip_addr_port_eq(key_of(lhs), rhs);
+}
+
+inline PoolableSession *&
+PoolableSession::FQDNLinkage::next_ptr(self_type *ssn)
+{
+  return ssn->_fqdn_link._next;
+}
+
+inline PoolableSession *&
+PoolableSession::FQDNLinkage::prev_ptr(self_type *ssn)
+{
+  return ssn->_fqdn_link._prev;
+}
+
+inline uint64_t
+PoolableSession::FQDNLinkage::hash_of(CryptoHash const &key)
+{
+  return key.fold();
+}
+
+inline CryptoHash const &
+PoolableSession::FQDNLinkage::key_of(self_type *ssn)
+{
+  return ssn->hostname_hash;
+}
+
+inline bool
+PoolableSession::FQDNLinkage::equal(CryptoHash const &lhs, CryptoHash const &rhs)
+{
+  return lhs == rhs;
+}
diff --git a/proxy/ProxySession.cc b/proxy/ProxySession.cc
index 07af66a..a866507 100644
--- a/proxy/ProxySession.cc
+++ b/proxy/ProxySession.cc
@@ -35,7 +35,7 @@ ProxySession::set_session_active()
 {
   if (!m_active) {
     m_active = true;
-    this->increment_current_active_client_connections_stat();
+    this->increment_current_active_connections_stat();
   }
 }
 
@@ -44,7 +44,7 @@ ProxySession::clear_session_active()
 {
   if (m_active) {
     m_active = false;
-    this->decrement_current_active_client_connections_stat();
+    this->decrement_current_active_connections_stat();
   }
 }
 
@@ -201,12 +201,12 @@ ProxySession::connection_id() const
 }
 
 bool
-ProxySession::attach_server_session(Http1ServerSession *ssession, bool transaction_done)
+ProxySession::attach_server_session(PoolableSession *ssession, bool transaction_done)
 {
   return false;
 }
 
-Http1ServerSession *
+PoolableSession *
 ProxySession::get_server_session() const
 {
   return nullptr;
@@ -236,6 +236,14 @@ ProxySession::cancel_inactivity_timeout()
   }
 }
 
+void
+ProxySession::cancel_active_timeout()
+{
+  if (_vc) {
+    _vc->cancel_active_timeout();
+  }
+}
+
 int
 ProxySession::populate_protocol(std::string_view *result, int size) const
 {
@@ -249,7 +257,7 @@ ProxySession::protocol_contains(std::string_view tag_prefix) const
 }
 
 sockaddr const *
-ProxySession::get_client_addr()
+ProxySession::get_remote_addr() const
 {
   return _vc ? _vc->get_remote_addr() : nullptr;
 }
diff --git a/proxy/ProxySession.h b/proxy/ProxySession.h
index 8c6a071..d31888f 100644
--- a/proxy/ProxySession.h
+++ b/proxy/ProxySession.h
@@ -30,7 +30,6 @@
 #include <memory>
 #include "P_Net.h"
 #include "InkAPIInternal.h"
-#include "http/Http1ServerSession.h"
 #include "http/HttpSessionAccept.h"
 #include "IPAllow.h"
 #include "private/SSLProxySession.h"
@@ -41,6 +40,7 @@
 #define SsnDebug(ssn, tag, ...) SpecificDebug((ssn)->debug(), tag, __VA_ARGS__)
 
 class ProxyTransaction;
+class PoolableSession;
 
 enum class ProxyErrorClass {
   NONE,
@@ -89,18 +89,17 @@ public:
   // Virtual Methods
   virtual void new_connection(NetVConnection *new_vc, MIOBuffer *iobuf, IOBufferReader *reader) = 0;
   virtual void start()                                                                          = 0;
-  virtual bool attach_server_session(Http1ServerSession *ssession, bool transaction_done = true);
+  virtual bool attach_server_session(PoolableSession *ssession, bool transaction_done = true);
 
   virtual void release(ProxyTransaction *trans) = 0;
 
   virtual void destroy() = 0;
   virtual void free();
 
-  virtual void increment_current_active_client_connections_stat() = 0;
-  virtual void decrement_current_active_client_connections_stat() = 0;
+  virtual void increment_current_active_connections_stat() = 0;
+  virtual void decrement_current_active_connections_stat() = 0;
 
   // Virtual Accessors
-  NetVConnection *get_netvc() const;
   virtual int get_transact_count() const          = 0;
   virtual const char *get_protocol_string() const = 0;
 
@@ -111,20 +110,22 @@ public:
   virtual void set_half_close_flag(bool flag);
   virtual bool get_half_close_flag() const;
 
-  virtual Http1ServerSession *get_server_session() const;
+  virtual PoolableSession *get_server_session() const;
 
   // Replicate NetVConnection API
-  virtual sockaddr const *get_client_addr();
+  virtual sockaddr const *get_remote_addr() const;
   virtual sockaddr const *get_local_addr();
 
   virtual void set_active_timeout(ink_hrtime timeout_in);
   virtual void set_inactivity_timeout(ink_hrtime timeout_in);
   virtual void cancel_inactivity_timeout();
+  virtual void cancel_active_timeout();
 
   virtual int populate_protocol(std::string_view *result, int size) const;
   virtual const char *protocol_contains(std::string_view tag_prefix) const;
 
   // Non-Virtual Methods
+  NetVConnection *get_netvc() const;
   int do_api_callout(TSHttpHookID id);
 
   void set_debug(bool flag);
diff --git a/proxy/ProxyTransaction.cc b/proxy/ProxyTransaction.cc
index 2ef8ad1..3f80e77 100644
--- a/proxy/ProxyTransaction.cc
+++ b/proxy/ProxyTransaction.cc
@@ -22,7 +22,6 @@
  */
 
 #include "http/HttpSM.h"
-#include "http/Http1ServerSession.h"
 #include "Plugin.h"
 
 #define HttpTxnDebug(fmt, ...) SsnDebug(this, "http_txn", fmt, __VA_ARGS__)
@@ -57,7 +56,7 @@ ProxyTransaction::new_transaction(bool from_early_data)
 }
 
 bool
-ProxyTransaction::attach_server_session(Http1ServerSession *ssession, bool transaction_done)
+ProxyTransaction::attach_server_session(PoolableSession *ssession, bool transaction_done)
 {
   return _proxy_ssn->attach_server_session(ssession, transaction_done);
 }
@@ -185,3 +184,34 @@ ProxyTransaction::transaction_done()
   SCOPED_MUTEX_LOCK(lock, this->mutex, this_ethread());
   this->decrement_client_transactions_stat();
 }
+
+// Implement VConnection interface.
+VIO *
+ProxyTransaction::do_io_read(Continuation *c, int64_t nbytes, MIOBuffer *buf)
+{
+  return _proxy_ssn->do_io_read(c, nbytes, buf);
+}
+VIO *
+ProxyTransaction::do_io_write(Continuation *c, int64_t nbytes, IOBufferReader *buf, bool owner)
+{
+  return _proxy_ssn->do_io_write(c, nbytes, buf, owner);
+}
+
+void
+ProxyTransaction::do_io_close(int lerrno)
+{
+  _proxy_ssn->do_io_close(lerrno);
+  // this->destroy(); Parent owns this data structure.  No need for separate destroy.
+}
+
+void
+ProxyTransaction::do_io_shutdown(ShutdownHowTo_t howto)
+{
+  _proxy_ssn->do_io_shutdown(howto);
+}
+
+void
+ProxyTransaction::reenable(VIO *vio)
+{
+  _proxy_ssn->reenable(vio);
+}
diff --git a/proxy/ProxyTransaction.h b/proxy/ProxyTransaction.h
index 6ceb3c0..7c1e3de 100644
--- a/proxy/ProxyTransaction.h
+++ b/proxy/ProxyTransaction.h
@@ -27,7 +27,6 @@
 #include <string_view>
 
 class HttpSM;
-class Http1ServerSession;
 
 // Abstract Class for any transaction with-in the HttpSM
 class ProxyTransaction : public VConnection
@@ -38,18 +37,28 @@ public:
   /// Virtual Methods
   //
   virtual void new_transaction(bool from_early_data = false);
-  virtual bool attach_server_session(Http1ServerSession *ssession, bool transaction_done = true);
+  virtual bool attach_server_session(PoolableSession *ssession, bool transaction_done = true);
   Action *adjust_thread(Continuation *cont, int event, void *data);
   virtual void release(IOBufferReader *r) = 0;
   virtual void transaction_done();
   virtual void destroy();
 
+  virtual void set_active_timeout(ink_hrtime timeout_in);
+  virtual void set_inactivity_timeout(ink_hrtime timeout_in);
+  virtual void cancel_inactivity_timeout();
+  virtual void cancel_active_timeout();
+
+  // Implement VConnection interface.
+  VIO *do_io_read(Continuation *c, int64_t nbytes = INT64_MAX, MIOBuffer *buf = nullptr) override;
+  VIO *do_io_write(Continuation *c = nullptr, int64_t nbytes = INT64_MAX, IOBufferReader *buf = nullptr,
+                   bool owner = false) override;
+  void do_io_close(int lerrno = -1) override;
+  void do_io_shutdown(ShutdownHowTo_t howto) override;
+  void reenable(VIO *vio) override;
+
   /// Virtual Accessors
   //
-  virtual void set_active_timeout(ink_hrtime timeout_in)     = 0;
-  virtual void set_inactivity_timeout(ink_hrtime timeout_in) = 0;
-  virtual void cancel_inactivity_timeout()                   = 0;
-  virtual int get_transaction_id() const                     = 0;
+  virtual int get_transaction_id() const = 0;
   virtual int get_transaction_priority_weight() const;
   virtual int get_transaction_priority_dependence() const;
   virtual bool allow_half_open() const              = 0;
@@ -97,7 +106,7 @@ public:
   const IpAllow::ACL &get_acl() const;
 
   ProxySession *get_proxy_ssn();
-  Http1ServerSession *get_server_session() const;
+  PoolableSession *get_server_session() const;
   HttpSM *get_sm() const;
 
   // This function must return a non-negative number that is different for two in-progress transactions with the same proxy_ssn
@@ -185,7 +194,7 @@ ProxyTransaction::set_proxy_ssn(ProxySession *new_proxy_ssn)
   _proxy_ssn = new_proxy_ssn;
 }
 
-inline Http1ServerSession *
+inline PoolableSession *
 ProxyTransaction::get_server_session() const
 {
   return _proxy_ssn ? _proxy_ssn->get_server_session() : nullptr;
@@ -221,6 +230,38 @@ ProxyTransaction::support_sni() const
   return _proxy_ssn ? _proxy_ssn->support_sni() : false;
 }
 
+inline void
+ProxyTransaction::set_active_timeout(ink_hrtime timeout_in)
+{
+  if (_proxy_ssn) {
+    _proxy_ssn->set_active_timeout(timeout_in);
+  }
+}
+
+inline void
+ProxyTransaction::set_inactivity_timeout(ink_hrtime timeout_in)
+{
+  if (_proxy_ssn) {
+    _proxy_ssn->set_inactivity_timeout(timeout_in);
+  }
+}
+
+inline void
+ProxyTransaction::cancel_inactivity_timeout()
+{
+  if (_proxy_ssn) {
+    _proxy_ssn->cancel_inactivity_timeout();
+  }
+}
+
+inline void
+ProxyTransaction::cancel_active_timeout()
+{
+  if (_proxy_ssn) {
+    _proxy_ssn->cancel_active_timeout();
+  }
+}
+
 // See if we need to schedule on the primary thread for the transaction or change the thread that is associated with the VC.
 // If we reschedule, the scheduled action is returned.  Otherwise, NULL is returned
 inline Action *
diff --git a/proxy/http/Http1ClientSession.cc b/proxy/http/Http1ClientSession.cc
index 4ffc6b1..14291cb 100644
--- a/proxy/http/Http1ClientSession.cc
+++ b/proxy/http/Http1ClientSession.cc
@@ -35,8 +35,8 @@
 #include "Http1Transaction.h"
 #include "HttpSM.h"
 #include "HttpDebugNames.h"
-#include "Http1ServerSession.h"
 #include "Plugin.h"
+#include "PoolableSession.h"
 
 #define HttpSsnDebug(fmt, ...) SsnDebug(this, "http_cs", fmt, __VA_ARGS__)
 
@@ -46,11 +46,6 @@
     HttpSsnDebug("[%" PRId64 "] [%s, %s]", con_id, #state_name, HttpDebugNames::get_event_name(event)); \
   } while (0)
 
-enum {
-  HTTP_CS_MAGIC_ALIVE = 0x0123F00D,
-  HTTP_CS_MAGIC_DEAD  = 0xDEADF00D,
-};
-
 #ifdef USE_HTTP_DEBUG_LISTS
 
 // We have debugging list that we can use to find stuck
@@ -227,7 +222,7 @@ Http1ClientSession::do_io_close(int alerrno)
   // If we have an attached server session, release
   //   it back to our shared pool
   if (bound_ss) {
-    bound_ss->release();
+    bound_ss->release(nullptr);
     bound_ss     = nullptr;
     slave_ka_vio = nullptr;
   }
@@ -339,7 +334,7 @@ Http1ClientSession::state_slave_keep_alive(int event, void *data)
   case VC_EVENT_ACTIVE_TIMEOUT:
   case VC_EVENT_INACTIVITY_TIMEOUT:
     // Timeout - place the session on the shared pool
-    bound_ss->release();
+    bound_ss->release(nullptr);
     bound_ss     = nullptr;
     slave_ka_vio = nullptr;
     break;
@@ -461,14 +456,13 @@ Http1ClientSession::new_transaction()
 }
 
 bool
-Http1ClientSession::attach_server_session(Http1ServerSession *ssession, bool transaction_done)
+Http1ClientSession::attach_server_session(PoolableSession *ssession, bool transaction_done)
 {
   if (ssession) {
     ink_assert(bound_ss == nullptr);
-    ssession->state = HSS_KA_CLIENT_SLAVE;
+    ssession->state = PoolableSession::KA_RESERVED;
     bound_ss        = ssession;
-    HttpSsnDebug("[%" PRId64 "] attaching server session [%" PRId64 "] as slave", con_id, ssession->con_id);
-    ink_assert(ssession->get_reader()->read_avail() == 0);
+    HttpSsnDebug("[%" PRId64 "] attaching server session [%" PRId64 "] as slave", con_id, ssession->connection_id());
     ink_assert(ssession->get_netvc() != this->get_netvc());
 
     // handling potential keep-alive here
@@ -478,21 +472,19 @@ Http1ClientSession::attach_server_session(Http1ServerSession *ssession, bool tra
     //  have it call the client session back.  This IO also prevent
     //  the server net conneciton from calling back a dead sm
     SET_HANDLER(&Http1ClientSession::state_keep_alive);
-    slave_ka_vio = ssession->do_io_read(this, INT64_MAX, ssession->read_buffer);
-    this->do_io_write(this, 0, nullptr); // Capture the inactivity timeouts
+    slave_ka_vio = ssession->do_io_read(this, 0, nullptr);
     ink_assert(slave_ka_vio != ka_vio);
 
     // Transfer control of the write side as well
     ssession->do_io_write(this, 0, nullptr);
 
     if (transaction_done) {
-      ssession->get_netvc()->set_inactivity_timeout(
-        HRTIME_SECONDS(trans.get_sm()->t_state.txn_conf->keep_alive_no_activity_timeout_out));
-      ssession->get_netvc()->cancel_active_timeout();
+      ssession->set_inactivity_timeout(HRTIME_SECONDS(trans.get_sm()->t_state.txn_conf->keep_alive_no_activity_timeout_out));
+      ssession->cancel_active_timeout();
     } else {
       // we are serving from the cache - this could take a while.
-      ssession->get_netvc()->cancel_inactivity_timeout();
-      ssession->get_netvc()->cancel_active_timeout();
+      ssession->cancel_inactivity_timeout();
+      ssession->cancel_active_timeout();
     }
   } else {
     ink_assert(bound_ss != nullptr);
@@ -503,13 +495,12 @@ Http1ClientSession::attach_server_session(Http1ServerSession *ssession, bool tra
 }
 
 void
-Http1ClientSession::increment_current_active_client_connections_stat()
+Http1ClientSession::increment_current_active_connections_stat()
 {
   HTTP_INCREMENT_DYN_STAT(http_current_active_client_connections_stat);
 }
-
 void
-Http1ClientSession::decrement_current_active_client_connections_stat()
+Http1ClientSession::decrement_current_active_connections_stat()
 {
   HTTP_DECREMENT_DYN_STAT(http_current_active_client_connections_stat);
 }
@@ -558,7 +549,7 @@ Http1ClientSession::is_outbound_transparent() const
   return f_outbound_transparent;
 }
 
-Http1ServerSession *
+PoolableSession *
 Http1ClientSession::get_server_session() const
 {
   return bound_ss;
diff --git a/proxy/http/Http1ClientSession.h b/proxy/http/Http1ClientSession.h
index 686f5f4..0c6e2f5 100644
--- a/proxy/http/Http1ClientSession.h
+++ b/proxy/http/Http1ClientSession.h
@@ -43,9 +43,12 @@
 extern ink_mutex debug_cs_list_mutex;
 #endif
 
-class HttpSM;
-class Http1ServerSession;
+enum {
+  HTTP_CS_MAGIC_ALIVE = 0x0123FEED,
+  HTTP_CS_MAGIC_DEAD  = 0xDEADFEED,
+};
 
+class HttpSM;
 class Http1ClientSession : public ProxySession
 {
 public:
@@ -60,7 +63,7 @@ public:
   void destroy() override;
   void free() override;
 
-  bool attach_server_session(Http1ServerSession *ssession, bool transaction_done = true) override;
+  bool attach_server_session(PoolableSession *ssession, bool transaction_done = true) override;
 
   // Implement VConnection interface.
   void do_io_close(int lerrno = -1) override;
@@ -73,11 +76,11 @@ public:
   int get_transact_count() const override;
   virtual bool is_outbound_transparent() const;
 
-  Http1ServerSession *get_server_session() const override;
+  PoolableSession *get_server_session() const override;
   const char *get_protocol_string() const override;
 
-  void increment_current_active_client_connections_stat() override;
-  void decrement_current_active_client_connections_stat() override;
+  void increment_current_active_connections_stat() override;
+  void decrement_current_active_connections_stat() override;
 
 private:
   Http1ClientSession(Http1ClientSession &);
@@ -96,7 +99,7 @@ private:
     HCS_CLOSED,
   };
 
-  int magic          = HTTP_SS_MAGIC_DEAD;
+  int magic          = HTTP_CS_MAGIC_DEAD;
   int transact_count = 0;
   bool half_close    = false;
   bool conn_decrease = false;
@@ -109,7 +112,7 @@ private:
   VIO *ka_vio       = nullptr;
   VIO *slave_ka_vio = nullptr;
 
-  Http1ServerSession *bound_ss = nullptr;
+  PoolableSession *bound_ss = nullptr;
 
   int released_transactions = 0;
 
diff --git a/proxy/http/Http1ServerSession.cc b/proxy/http/Http1ServerSession.cc
index e794668..b1b94fb 100644
--- a/proxy/http/Http1ServerSession.cc
+++ b/proxy/http/Http1ServerSession.cc
@@ -36,15 +36,13 @@
 #include "HttpSessionManager.h"
 #include "HttpSM.h"
 
-static int64_t next_ss_id = static_cast<int64_t>(0);
 ClassAllocator<Http1ServerSession> httpServerSessionAllocator("httpServerSessionAllocator");
 
 void
 Http1ServerSession::destroy()
 {
-  ink_release_assert(server_vc == nullptr);
+  ink_release_assert(_vc == nullptr);
   ink_assert(read_buffer);
-  ink_assert(server_trans_stat == 0);
   magic = HTTP_SS_MAGIC_DEAD;
   if (read_buffer) {
     free_MIOBuffer(read_buffer);
@@ -60,26 +58,30 @@ Http1ServerSession::destroy()
 }
 
 void
-Http1ServerSession::new_connection(NetVConnection *new_vc)
+Http1ServerSession::new_connection(NetVConnection *new_vc, MIOBuffer *iobuf, IOBufferReader *reader)
 {
   ink_assert(new_vc != nullptr);
-  server_vc = new_vc;
+  _vc = new_vc;
 
   // Used to do e.g. mutex = new_vc->thread->mutex; when per-thread pools enabled
   mutex = new_vc->mutex;
 
-  // Unique client session identifier.
-  con_id = ink_atomic_increment((&next_ss_id), 1);
+  // Unique session identifier.
+  con_id = ProxySession::next_connection_id();
 
   magic = HTTP_SS_MAGIC_ALIVE;
   HTTP_SUM_GLOBAL_DYN_STAT(http_current_server_connections_stat, 1); // Update the true global stat
   HTTP_INCREMENT_DYN_STAT(http_total_server_connections_stat);
 
-  read_buffer = new_MIOBuffer(HTTP_SERVER_RESP_HDR_BUFFER_INDEX);
-
-  buf_reader = read_buffer->alloc_reader();
+  if (iobuf == nullptr) {
+    read_buffer = new_MIOBuffer(HTTP_SERVER_RESP_HDR_BUFFER_INDEX);
+    buf_reader  = read_buffer->alloc_reader();
+  } else {
+    read_buffer = iobuf;
+    buf_reader  = reader;
+  }
   Debug("http_ss", "[%" PRId64 "] session born, netvc %p", con_id, new_vc);
-  state = HSS_INIT;
+  state = INIT;
 
   new_vc->set_tcp_congestion_control(SERVER_SIDE);
 }
@@ -96,37 +98,18 @@ Http1ServerSession::enable_outbound_connection_tracking(OutboundConnTrack::Group
   }
 }
 
-VIO *
-Http1ServerSession::do_io_read(Continuation *c, int64_t nbytes, MIOBuffer *buf)
-{
-  return server_vc ? server_vc->do_io_read(c, nbytes, buf) : nullptr;
-}
-
-VIO *
-Http1ServerSession::do_io_write(Continuation *c, int64_t nbytes, IOBufferReader *buf, bool owner)
-{
-  return server_vc ? server_vc->do_io_write(c, nbytes, buf, owner) : nullptr;
-}
-
-void
-Http1ServerSession::do_io_shutdown(ShutdownHowTo_t howto)
-{
-  server_vc->do_io_shutdown(howto);
-}
-
 void
 Http1ServerSession::do_io_close(int alerrno)
 {
   ts::LocalBufferWriter<256> w;
   bool debug_p = is_debug_tag_set("http_ss");
 
-  if (state == HSS_ACTIVE) {
+  if (state == SSN_IN_USE) {
     HTTP_DECREMENT_DYN_STAT(http_current_server_transactions_stat);
-    this->server_trans_stat--;
   }
 
   if (debug_p) {
-    w.print("[{}] session close: nevtc {:x}", con_id, server_vc);
+    w.print("[{}] session close: nevtc {:x}", con_id, _vc);
   }
 
   HTTP_SUM_GLOBAL_DYN_STAT(http_current_server_connections_stat, -1); // Make sure to work on the global stat
@@ -149,10 +132,10 @@ Http1ServerSession::do_io_close(int alerrno)
     Debug("http_ss", "%.*s", static_cast<int>(w.size()), w.data());
   }
 
-  if (server_vc) {
-    server_vc->do_io_close(alerrno);
+  if (_vc) {
+    _vc->do_io_close(alerrno);
   }
-  server_vc = nullptr;
+  _vc = nullptr;
 
   if (to_parent_proxy) {
     HTTP_DECREMENT_DYN_STAT(http_current_parent_proxy_connections_stat);
@@ -160,27 +143,21 @@ Http1ServerSession::do_io_close(int alerrno)
   destroy();
 }
 
-void
-Http1ServerSession::reenable(VIO *vio)
-{
-  server_vc->reenable(vio);
-}
-
 // void Http1ServerSession::release()
 //
 //   Releases the session for K-A reuse
 //
 void
-Http1ServerSession::release()
+Http1ServerSession::release(ProxyTransaction *trans)
 {
-  Debug("http_ss", "Releasing session, private_session=%d, sharing_match=%d", private_session, sharing_match);
+  Debug("http_ss", "Releasing session, private_session=%d, sharing_match=%d", this->is_private(), sharing_match);
   // Set our state to KA for stat issues
-  state = HSS_KA_SHARED;
+  state = KA_POOLED;
 
-  server_vc->control_flags.set_flags(0);
+  _vc->control_flags.set_flags(0);
 
   // Private sessions are never released back to the shared pool
-  if (private_session || sharing_match == 0) {
+  if (this->is_private() || sharing_match == 0) {
     this->do_io_close();
     return;
   }
@@ -206,36 +183,37 @@ Http1ServerSession::release()
   }
 }
 
-NetVConnection *
-Http1ServerSession::get_netvc() const
-{
-  return server_vc;
-};
-
-void
-Http1ServerSession::set_netvc(NetVConnection *new_vc)
-{
-  server_vc = new_vc;
-}
-
 // Keys for matching hostnames
 IpEndpoint const &
 Http1ServerSession::get_server_ip() const
 {
-  ink_release_assert(server_vc != nullptr);
-  return server_vc->get_remote_endpoint();
+  ink_release_assert(_vc != nullptr);
+  return _vc->get_remote_endpoint();
 }
 
 int
-Http1ServerSession::populate_protocol(std::string_view *result, int size) const
+Http1ServerSession::get_transact_count() const
 {
-  auto vc = this->get_netvc();
-  return vc ? vc->populate_protocol(result, size) : 0;
+  return transact_count;
 }
 
 const char *
-Http1ServerSession::protocol_contains(std::string_view tag_prefix) const
+Http1ServerSession::get_protocol_string() const
+{
+  return "http";
+}
+void
+Http1ServerSession::increment_current_active_connections_stat()
+{
+  // TODO: Implement stats
+}
+void
+Http1ServerSession::decrement_current_active_connections_stat()
+{
+  // TODO: Implement stats
+}
+
+void
+Http1ServerSession::start()
 {
-  auto vc = this->get_netvc();
-  return vc ? vc->protocol_contains(tag_prefix) : nullptr;
 }
diff --git a/proxy/http/Http1ServerSession.h b/proxy/http/Http1ServerSession.h
index a46c6dd..9594006 100644
--- a/proxy/http/Http1ServerSession.h
+++ b/proxy/http/Http1ServerSession.h
@@ -36,64 +36,52 @@
 
 #include "HttpConnectionCount.h"
 #include "HttpProxyAPIEnums.h"
+#include "PoolableSession.h"
 
 class HttpSM;
 class MIOBuffer;
 class IOBufferReader;
 
-enum HSS_State {
-  HSS_INIT,
-  HSS_ACTIVE,
-  HSS_KA_CLIENT_SLAVE,
-  HSS_KA_SHARED,
-};
-
 enum {
   HTTP_SS_MAGIC_ALIVE = 0x0123FEED,
   HTTP_SS_MAGIC_DEAD  = 0xDEADFEED,
 };
 
-class Http1ServerSession : public VConnection
+class Http1ServerSession : public PoolableSession
 {
   using self_type  = Http1ServerSession;
-  using super_type = VConnection;
+  using super_type = PoolableSession;
 
 public:
-  Http1ServerSession() : super_type(nullptr) {}
+  Http1ServerSession() : super_type() {}
   Http1ServerSession(self_type const &) = delete;
   self_type &operator=(self_type const &) = delete;
 
   ////////////////////
   // Methods
-  void new_connection(NetVConnection *new_vc);
-  void release();
-  void destroy();
+  void release(ProxyTransaction *) override;
+  void destroy() override;
 
   // VConnection Methods
-  VIO *do_io_read(Continuation *c, int64_t nbytes = INT64_MAX, MIOBuffer *buf = nullptr) override;
-  VIO *do_io_write(Continuation *c = nullptr, int64_t nbytes = INT64_MAX, IOBufferReader *buf = nullptr,
-                   bool owner = false) override;
   void do_io_close(int lerrno = -1) override;
-  void do_io_shutdown(ShutdownHowTo_t howto) override;
 
-  void reenable(VIO *vio) override;
+  // ProxySession Methods
+  int get_transact_count() const override;
+  const char *get_protocol_string() const override;
+  void increment_current_active_connections_stat() override;
+  void decrement_current_active_connections_stat() override;
+  void new_connection(NetVConnection *new_vc, MIOBuffer *iobuf, IOBufferReader *reader) override;
+  void start() override;
 
   void enable_outbound_connection_tracking(OutboundConnTrack::Group *group);
   IOBufferReader *get_reader();
   void attach_hostname(const char *hostname);
-  NetVConnection *get_netvc() const;
-  void set_netvc(NetVConnection *new_vc);
   IpEndpoint const &get_server_ip() const;
-  int populate_protocol(std::string_view *result, int size) const;
-  const char *protocol_contains(std::string_view tag_prefix) const;
 
   ////////////////////
   // Variables
-  CryptoHash hostname_hash;
 
-  int64_t con_id     = 0;
   int transact_count = 0;
-  HSS_State state    = HSS_INIT;
 
   // Used to determine whether the session is for parent proxy
   // it is session to origin server
@@ -102,49 +90,6 @@ public:
   // proxy.process.http.current_parent_proxy_connections
   bool to_parent_proxy = false;
 
-  // Used to verify we are recording the server
-  //   transaction stat properly
-  int server_trans_stat = 0;
-
-  // Sessions become if authentication headers
-  //  are sent over them
-  bool private_session = false;
-
-  // Copy of the owning SM's server session sharing settings
-  TSServerSessionSharingMatchMask sharing_match = TS_SERVER_SESSION_SHARING_MATCH_MASK_NONE;
-  TSServerSessionSharingPoolType sharing_pool   = TS_SERVER_SESSION_SHARING_POOL_GLOBAL;
-
-  /// Hash map descriptor class for IP map.
-  struct IPLinkage {
-    self_type *_next = nullptr;
-    self_type *_prev = nullptr;
-
-    static self_type *&next_ptr(self_type *);
-    static self_type *&prev_ptr(self_type *);
-    static uint32_t hash_of(sockaddr const *key);
-    static sockaddr const *key_of(self_type const *ssn);
-    static bool equal(sockaddr const *lhs, sockaddr const *rhs);
-    // Add a couple overloads for internal convenience.
-    static bool equal(sockaddr const *lhs, Http1ServerSession const *rhs);
-    static bool equal(Http1ServerSession const *lhs, sockaddr const *rhs);
-  } _ip_link;
-
-  /// Hash map descriptor class for FQDN map.
-  struct FQDNLinkage {
-    self_type *_next = nullptr;
-    self_type *_prev = nullptr;
-
-    static self_type *&next_ptr(self_type *);
-    static self_type *&prev_ptr(self_type *);
-    static uint64_t hash_of(CryptoHash const &key);
-    static CryptoHash const &key_of(self_type *ssn);
-    static bool equal(CryptoHash const &lhs, CryptoHash const &rhs);
-  } _fqdn_link;
-
-  // Keep track of connection limiting and a pointer to the
-  // singleton that keeps track of the connection counts.
-  OutboundConnTrack::Group *conn_track_group = nullptr;
-
   // The ServerSession owns the following buffer which use
   //   for parsing the headers.  The server session needs to
   //   own the buffer so we can go from a keep-alive state
@@ -155,8 +100,7 @@ public:
   MIOBuffer *read_buffer = nullptr;
 
 private:
-  NetVConnection *server_vc = nullptr;
-  int magic                 = HTTP_SS_MAGIC_DEAD;
+  int magic = HTTP_SS_MAGIC_DEAD;
 
   IOBufferReader *buf_reader = nullptr;
 };
@@ -179,78 +123,3 @@ Http1ServerSession::get_reader()
 {
   return buf_reader;
 };
-
-//
-// LINKAGE
-
-inline Http1ServerSession *&
-Http1ServerSession::IPLinkage::next_ptr(self_type *ssn)
-{
-  return ssn->_ip_link._next;
-}
-
-inline Http1ServerSession *&
-Http1ServerSession::IPLinkage::prev_ptr(self_type *ssn)
-{
-  return ssn->_ip_link._prev;
-}
-
-inline uint32_t
-Http1ServerSession::IPLinkage::hash_of(sockaddr const *key)
-{
-  return ats_ip_hash(key);
-}
-
-inline sockaddr const *
-Http1ServerSession::IPLinkage::key_of(self_type const *ssn)
-{
-  return &ssn->get_server_ip().sa;
-}
-
-inline bool
-Http1ServerSession::IPLinkage::equal(sockaddr const *lhs, sockaddr const *rhs)
-{
-  return ats_ip_addr_port_eq(lhs, rhs);
-}
-
-inline bool
-Http1ServerSession::IPLinkage::equal(sockaddr const *lhs, Http1ServerSession const *rhs)
-{
-  return ats_ip_addr_port_eq(lhs, key_of(rhs));
-}
-
-inline bool
-Http1ServerSession::IPLinkage::equal(Http1ServerSession const *lhs, sockaddr const *rhs)
-{
-  return ats_ip_addr_port_eq(key_of(lhs), rhs);
-}
-
-inline Http1ServerSession *&
-Http1ServerSession::FQDNLinkage::next_ptr(self_type *ssn)
-{
-  return ssn->_fqdn_link._next;
-}
-
-inline Http1ServerSession *&
-Http1ServerSession::FQDNLinkage::prev_ptr(self_type *ssn)
-{
-  return ssn->_fqdn_link._prev;
-}
-
-inline uint64_t
-Http1ServerSession::FQDNLinkage::hash_of(CryptoHash const &key)
-{
-  return key.fold();
-}
-
-inline CryptoHash const &
-Http1ServerSession::FQDNLinkage::key_of(self_type *ssn)
-{
-  return ssn->hostname_hash;
-}
-
-inline bool
-Http1ServerSession::FQDNLinkage::equal(CryptoHash const &lhs, CryptoHash const &rhs)
-{
-  return lhs == rhs;
-}
diff --git a/proxy/http/Http1Transaction.cc b/proxy/http/Http1Transaction.cc
index 29ebec0..6a37e7c 100644
--- a/proxy/http/Http1Transaction.cc
+++ b/proxy/http/Http1Transaction.cc
@@ -46,12 +46,6 @@ Http1Transaction::transaction_done()
   }
 }
 
-void
-Http1Transaction::reenable(VIO *vio)
-{
-  _proxy_ssn->reenable(vio);
-}
-
 bool
 Http1Transaction::allow_half_open() const
 {
@@ -75,52 +69,6 @@ Http1Transaction::decrement_client_transactions_stat()
   HTTP_DECREMENT_DYN_STAT(http_current_client_transactions_stat);
 }
 
-// Implement VConnection interface.
-VIO *
-Http1Transaction::do_io_read(Continuation *c, int64_t nbytes, MIOBuffer *buf)
-{
-  return _proxy_ssn->do_io_read(c, nbytes, buf);
-}
-VIO *
-Http1Transaction::do_io_write(Continuation *c, int64_t nbytes, IOBufferReader *buf, bool owner)
-{
-  return _proxy_ssn->do_io_write(c, nbytes, buf, owner);
-}
-
-void
-Http1Transaction::do_io_close(int lerrno)
-{
-  _proxy_ssn->do_io_close(lerrno);
-  // this->destroy(); Parent owns this data structure.  No need for separate destroy.
-}
-
-void
-Http1Transaction::do_io_shutdown(ShutdownHowTo_t howto)
-{
-  _proxy_ssn->do_io_shutdown(howto);
-}
-
-void
-Http1Transaction::set_active_timeout(ink_hrtime timeout_in)
-{
-  if (_proxy_ssn) {
-    _proxy_ssn->set_active_timeout(timeout_in);
-  }
-}
-void
-Http1Transaction::set_inactivity_timeout(ink_hrtime timeout_in)
-{
-  if (_proxy_ssn) {
-    _proxy_ssn->set_inactivity_timeout(timeout_in);
-  }
-}
-void
-Http1Transaction::cancel_inactivity_timeout()
-{
-  if (_proxy_ssn) {
-    _proxy_ssn->cancel_inactivity_timeout();
-  }
-}
 //
 int
 Http1Transaction::get_transaction_id() const
diff --git a/proxy/http/Http1Transaction.h b/proxy/http/Http1Transaction.h
index 407d73e..d9c423d 100644
--- a/proxy/http/Http1Transaction.h
+++ b/proxy/http/Http1Transaction.h
@@ -39,18 +39,7 @@ public:
   void release(IOBufferReader *r) override;
   void destroy() override; // todo make ~Http1Transaction()
 
-  // Implement VConnection interface.
-  VIO *do_io_read(Continuation *c, int64_t nbytes = INT64_MAX, MIOBuffer *buf = nullptr) override;
-  VIO *do_io_write(Continuation *c = nullptr, int64_t nbytes = INT64_MAX, IOBufferReader *buf = nullptr,
-                   bool owner = false) override;
-  void do_io_close(int lerrno = -1) override;
-  void do_io_shutdown(ShutdownHowTo_t howto) override;
-  void reenable(VIO *vio) override;
-
   bool allow_half_open() const override;
-  void set_active_timeout(ink_hrtime timeout_in) override;
-  void set_inactivity_timeout(ink_hrtime timeout_in) override;
-  void cancel_inactivity_timeout() override;
   void transaction_done() override;
   int get_transaction_id() const override;
   void increment_client_transactions_stat() override;
diff --git a/proxy/http/HttpSM.cc b/proxy/http/HttpSM.cc
index dcde8fd..650107e 100644
--- a/proxy/http/HttpSM.cc
+++ b/proxy/http/HttpSM.cc
@@ -274,48 +274,48 @@ HttpVCTable::cleanup_all()
  * Helper functions to ensure that the parallel
  * API set timeouts are set consistenly with the records.config settings
  */
-void
-HttpSM::set_server_netvc_inactivity_timeout(NetVConnection *netvc)
+ink_hrtime
+HttpSM::get_server_inactivity_timeout()
 {
-  if (netvc) {
-    if (t_state.api_txn_no_activity_timeout_value != -1) {
-      netvc->set_inactivity_timeout(HRTIME_MSECONDS(t_state.api_txn_no_activity_timeout_value));
-    } else {
-      netvc->set_inactivity_timeout(HRTIME_SECONDS(t_state.txn_conf->transaction_no_activity_timeout_out));
-    }
+  ink_hrtime retval = 0;
+  if (t_state.api_txn_no_activity_timeout_value != -1) {
+    retval = HRTIME_MSECONDS(t_state.api_txn_no_activity_timeout_value);
+  } else {
+    retval = HRTIME_SECONDS(t_state.txn_conf->transaction_no_activity_timeout_out);
   }
+  return retval;
 }
 
-void
-HttpSM::set_server_netvc_active_timeout(NetVConnection *netvc)
+ink_hrtime
+HttpSM::get_server_active_timeout()
 {
-  if (netvc) {
-    if (t_state.api_txn_active_timeout_value != -1) {
-      netvc->set_active_timeout(HRTIME_MSECONDS(t_state.api_txn_active_timeout_value));
-    } else {
-      netvc->set_active_timeout(HRTIME_SECONDS(t_state.txn_conf->transaction_active_timeout_out));
-    }
+  ink_hrtime retval = 0;
+  if (t_state.api_txn_active_timeout_value != -1) {
+    retval = HRTIME_MSECONDS(t_state.api_txn_active_timeout_value);
+  } else {
+    retval = HRTIME_SECONDS(t_state.txn_conf->transaction_active_timeout_out);
   }
+  return retval;
 }
 
-void
-HttpSM::set_server_netvc_connect_timeout(NetVConnection *netvc)
+ink_hrtime
+HttpSM::get_server_connect_timeout()
 {
-  if (netvc) {
-    if (t_state.api_txn_connect_timeout_value != -1) {
-      netvc->set_inactivity_timeout(HRTIME_MSECONDS(t_state.api_txn_connect_timeout_value));
+  ink_hrtime retval = 0;
+  if (t_state.api_txn_connect_timeout_value != -1) {
+    retval = HRTIME_MSECONDS(t_state.api_txn_connect_timeout_value);
+  } else {
+    int connect_timeout;
+    if (t_state.method == HTTP_WKSIDX_POST || t_state.method == HTTP_WKSIDX_PUT) {
+      connect_timeout = t_state.txn_conf->post_connect_attempts_timeout;
+    } else if (t_state.current.server == &t_state.parent_info) {
+      connect_timeout = t_state.txn_conf->parent_connect_timeout;
     } else {
-      int connect_timeout;
-      if (t_state.method == HTTP_WKSIDX_POST || t_state.method == HTTP_WKSIDX_PUT) {
-        connect_timeout = t_state.txn_conf->post_connect_attempts_timeout;
-      } else if (t_state.current.server == &t_state.parent_info) {
-        connect_timeout = t_state.txn_conf->parent_connect_timeout;
-      } else {
-        connect_timeout = t_state.txn_conf->connect_attempts_timeout;
-      }
-      netvc->set_inactivity_timeout(HRTIME_SECONDS(connect_timeout));
+      connect_timeout = t_state.txn_conf->connect_attempts_timeout;
     }
+    retval = HRTIME_SECONDS(connect_timeout);
   }
+  return retval;
 }
 
 HttpSM::HttpSM() : Continuation(nullptr), vc_table(this) {}
@@ -1185,8 +1185,8 @@ HttpSM::state_raw_http_server_open(int event, void *data)
     t_state.current.state    = HttpTransact::CONNECTION_ALIVE;
     ats_ip_copy(&t_state.server_info.src_addr, netvc->get_local_addr());
 
-    set_server_netvc_inactivity_timeout(netvc);
-    set_server_netvc_active_timeout(netvc);
+    netvc->set_inactivity_timeout(get_server_inactivity_timeout());
+    netvc->set_active_timeout(get_server_active_timeout());
     break;
 
   case VC_EVENT_ERROR:
@@ -1708,8 +1708,8 @@ HttpSM::handle_api_return()
           SMDebug("http_websocket",
                   "(server session) Setting websocket active timeout=%" PRId64 "s and inactive timeout=%" PRId64 "s",
                   t_state.txn_conf->websocket_active_timeout, t_state.txn_conf->websocket_inactive_timeout);
-          server_session->get_netvc()->set_active_timeout(HRTIME_SECONDS(t_state.txn_conf->websocket_active_timeout));
-          server_session->get_netvc()->set_inactivity_timeout(HRTIME_SECONDS(t_state.txn_conf->websocket_inactive_timeout));
+          server_session->set_active_timeout(HRTIME_SECONDS(t_state.txn_conf->websocket_active_timeout));
+          server_session->set_inactivity_timeout(HRTIME_SECONDS(t_state.txn_conf->websocket_inactive_timeout));
         }
       }
 
@@ -1796,11 +1796,11 @@ HttpSM::state_http_server_open(int event, void *data)
     ink_release_assert(pending_action == nullptr || pending_action->continuation == vc->get_action()->continuation);
     pending_action = nullptr;
 
-    session->new_connection(vc);
+    session->new_connection(vc, nullptr, nullptr);
 
     ATS_PROBE1(new_origin_server_connection, t_state.current.server->name);
 
-    session->state = HSS_ACTIVE;
+    session->set_active();
     ats_ip_copy(&t_state.server_info.src_addr, netvc->get_local_addr());
 
     // If origin_max_connections or origin_min_keep_alive_connections is set then we are metering
@@ -1839,7 +1839,7 @@ HttpSM::state_http_server_open(int event, void *data)
     server_entry->vc_handler = &HttpSM::state_send_server_request_header;
 
     // Reset the timeout to the non-connect timeout
-    set_server_netvc_inactivity_timeout(server_session->get_netvc());
+    server_session->set_inactivity_timeout(get_server_inactivity_timeout());
     handle_http_server_open();
     return 0;
   case EVENT_INTERVAL: // Delayed call from another thread
@@ -1935,7 +1935,7 @@ HttpSM::state_read_server_response_header(int event, void *data)
   if (server_response_hdr_bytes == 0) {
     milestones[TS_MILESTONE_SERVER_FIRST_READ] = Thread::get_hrtime();
 
-    set_server_netvc_inactivity_timeout(server_session->get_netvc());
+    server_session->set_inactivity_timeout(get_server_inactivity_timeout());
 
     // For requests that contain a body, we can cancel the ua inactivity timeout.
     if (ua_txn && t_state.hdr_info.request_content_length) {
@@ -1953,7 +1953,7 @@ HttpSM::state_read_server_response_header(int event, void *data)
   // Don't allow HTTP 0.9 (unparsable headers) on resued connections.
   // And don't allow empty headers from closed connections
   if ((state == PARSE_RESULT_DONE && t_state.hdr_info.server_response.version_get() == HTTPVersion(0, 9) &&
-       server_session->transact_count > 1) ||
+       server_session->get_transact_count() > 1) ||
       (server_entry->eos && vio->ndone == 0)) {
     state = PARSE_RESULT_ERROR;
   }
@@ -3144,7 +3144,6 @@ HttpSM::tunnel_handler_server(int event, HttpTunnelProducer *p)
     }
   } else {
     server_session->attach_hostname(t_state.current.server->name);
-    server_session->server_trans_stat--;
     HTTP_DECREMENT_DYN_STAT(http_current_server_transactions_stat);
 
     // If the option to attach the server session to the client session is set
@@ -3161,8 +3160,8 @@ HttpSM::tunnel_handler_server(int event, HttpTunnelProducer *p)
     }
     if (release_origin_connection) {
       // Release the session back into the shared session pool
-      server_session->get_netvc()->set_inactivity_timeout(HRTIME_SECONDS(t_state.txn_conf->keep_alive_no_activity_timeout_out));
-      server_session->release();
+      server_session->set_inactivity_timeout(HRTIME_SECONDS(t_state.txn_conf->keep_alive_no_activity_timeout_out));
+      server_session->release(nullptr);
     }
   }
 
@@ -3291,7 +3290,7 @@ HttpSM::tunnel_handler_ua(int event, HttpTunnelConsumer *c)
         HTTP_INCREMENT_DYN_STAT(http_background_fill_current_count_stat);
         ink_assert(server_entry->vc == server_session);
         ink_assert(c->is_downstream_from(server_session));
-        server_session->get_netvc()->set_active_timeout(HRTIME_SECONDS(t_state.txn_conf->background_fill_active_timeout));
+        server_session->set_active_timeout(HRTIME_SECONDS(t_state.txn_conf->background_fill_active_timeout));
       }
 
       // Even with the background fill, the client side should go down
@@ -4988,7 +4987,7 @@ HttpSM::do_http_server_open(bool raw)
 
   // If there is already an attached server session mark it as private.
   if (server_session != nullptr && will_be_private_ss) {
-    set_server_session_private(true);
+    server_session->set_private();
   }
 
   if ((raw == false) && TS_SERVER_SESSION_SHARING_MATCH_NONE != t_state.txn_conf->server_session_sharing_match &&
@@ -5022,16 +5021,16 @@ HttpSM::do_http_server_open(bool raw)
   // session when we already have an attached server session.
   else if ((TS_SERVER_SESSION_SHARING_MATCH_NONE == t_state.txn_conf->server_session_sharing_match || is_private()) &&
            (ua_txn != nullptr)) {
-    Http1ServerSession *existing_ss = ua_txn->get_server_session();
+    PoolableSession *existing_ss = ua_txn->get_server_session();
 
     if (existing_ss) {
       // [amc] Not sure if this is the best option, but we don't get here unless session sharing is disabled
       // so there's no point in further checking on the match or pool values. But why check anything? The
       // client has already exchanged a request with this specific origin server and has sent another one
       // shouldn't we just automatically keep the association?
-      if (ats_ip_addr_port_eq(&existing_ss->get_server_ip().sa, &t_state.current.server->dst_addr.sa)) {
+      if (ats_ip_addr_port_eq(existing_ss->get_remote_addr(), &t_state.current.server->dst_addr.sa)) {
         ua_txn->attach_server_session(nullptr);
-        existing_ss->state = HSS_ACTIVE;
+        existing_ss->set_active();
         this->attach_server_session(existing_ss);
         hsm_release_assert(server_session != nullptr);
         handle_http_server_open();
@@ -5040,7 +5039,7 @@ HttpSM::do_http_server_open(bool raw)
         // As this is in the non-sharing configuration, we want to close
         // the existing connection and call connect_re to get a new one
         existing_ss->get_netvc()->set_inactivity_timeout(HRTIME_SECONDS(t_state.txn_conf->keep_alive_no_activity_timeout_out));
-        existing_ss->release();
+        existing_ss->release(nullptr);
         ua_txn->attach_server_session(nullptr);
       }
     }
@@ -5049,10 +5048,10 @@ HttpSM::do_http_server_open(bool raw)
   // to get a new one.
   // ua_txn is null when t_state.req_flavor == REQ_FLAVOR_SCHEDULED_UPDATE
   else if (ua_txn != nullptr) {
-    Http1ServerSession *existing_ss = ua_txn->get_server_session();
+    PoolableSession *existing_ss = ua_txn->get_server_session();
     if (existing_ss) {
       existing_ss->get_netvc()->set_inactivity_timeout(HRTIME_SECONDS(t_state.txn_conf->keep_alive_no_activity_timeout_out));
-      existing_ss->release();
+      existing_ss->release(nullptr);
       ua_txn->attach_server_session(nullptr);
     }
   }
@@ -5462,12 +5461,11 @@ HttpSM::release_server_session(bool serve_from_cache)
         t_state.www_auth_content != HttpTransact::CACHE_AUTH_NONE)) &&
       plugin_tunnel_type == HTTP_NO_PLUGIN_TUNNEL) {
     HTTP_DECREMENT_DYN_STAT(http_current_server_transactions_stat);
-    server_session->server_trans_stat--;
     server_session->attach_hostname(t_state.current.server->name);
     if (t_state.www_auth_content == HttpTransact::CACHE_AUTH_NONE || serve_from_cache == false) {
       // Must explicitly set the keep_alive_no_activity time before doing the release
-      server_session->get_netvc()->set_inactivity_timeout(HRTIME_SECONDS(t_state.txn_conf->keep_alive_no_activity_timeout_out));
-      server_session->release();
+      server_session->set_inactivity_timeout(HRTIME_SECONDS(t_state.txn_conf->keep_alive_no_activity_timeout_out));
+      server_session->release(nullptr);
     } else {
       // an authenticated server connection - attach to the local client
       // we are serving from cache for the current transaction
@@ -5887,7 +5885,7 @@ HttpSM::do_setup_post_tunnel(HttpVC_t to_vc_type)
   }
 
   ua_txn->set_inactivity_timeout(HRTIME_SECONDS(t_state.txn_conf->transaction_no_activity_timeout_in));
-  set_server_netvc_inactivity_timeout(server_session->get_netvc());
+  server_session->set_inactivity_timeout(get_server_inactivity_timeout());
 
   tunnel.tunnel_run(p);
 
@@ -6050,12 +6048,13 @@ HttpSM::write_header_into_buffer(HTTPHdr *h, MIOBuffer *b)
 }
 
 void
-HttpSM::attach_server_session(Http1ServerSession *s)
+HttpSM::attach_server_session(PoolableSession *s)
 {
   hsm_release_assert(server_session == nullptr);
   hsm_release_assert(server_entry == nullptr);
-  hsm_release_assert(s->state == HSS_ACTIVE);
-  server_session        = s;
+  hsm_release_assert(s != nullptr);
+  hsm_release_assert(s->is_active());
+  server_session        = static_cast<Http1ServerSession *>(s);
   server_transact_count = server_session->transact_count++;
 
   // update the dst_addr when using an existing session
@@ -6064,8 +6063,8 @@ HttpSM::attach_server_session(Http1ServerSession *s)
     ip_port_text_buffer ipb1, ipb2;
     Debug("http_ss", "updating ip when attaching server session from %s to %s",
           ats_ip_ntop(&t_state.current.server->dst_addr.sa, ipb1, sizeof(ipb1)),
-          ats_ip_ntop(&server_session->get_server_ip(), ipb2, sizeof(ipb2)));
-    ats_ip_copy(&t_state.current.server->dst_addr, &server_session->get_server_ip());
+          ats_ip_ntop(server_session->get_remote_addr(), ipb2, sizeof(ipb2)));
+    ats_ip_copy(&t_state.current.server->dst_addr, server_session->get_remote_addr());
   }
 
   // Propagate the per client IP debugging
@@ -6080,7 +6079,6 @@ HttpSM::attach_server_session(Http1ServerSession *s)
   server_session->mutex = this->mutex;
 
   HTTP_INCREMENT_DYN_STAT(http_current_server_transactions_stat);
-  ++s->server_trans_stat;
 
   // Record the VC in our table
   server_entry             = vc_table.new_entry();
@@ -6128,12 +6126,12 @@ HttpSM::attach_server_session(Http1ServerSession *s)
   // Set the inactivity timeout to the connect timeout so that we
   //   we fail this server if it doesn't start sending the response
   //   header
-  set_server_netvc_connect_timeout(server_session->get_netvc());
-  set_server_netvc_active_timeout(server_session->get_netvc());
+  server_session->set_inactivity_timeout(get_server_connect_timeout());
+  server_session->set_active_timeout(get_server_active_timeout());
 
   if (plugin_tunnel_type != HTTP_NO_PLUGIN_TUNNEL || will_be_private_ss) {
     SMDebug("http_ss", "Setting server session to private");
-    set_server_session_private(true);
+    server_session->set_private();
   }
 }
 
@@ -6141,7 +6139,7 @@ void
 HttpSM::setup_server_send_request_api()
 {
   // Make sure the VC is on the correct timeout
-  set_server_netvc_inactivity_timeout(server_session->get_netvc());
+  server_session->set_inactivity_timeout(get_server_inactivity_timeout());
   t_state.api_next_action = HttpTransact::SM_ACTION_API_SEND_REQUEST_HDR;
   do_api_callout();
 }
@@ -6183,11 +6181,7 @@ HttpSM::setup_server_send_request()
   server_entry->write_vio                     = server_entry->vc->do_io_write(this, hdr_length, buf_start);
 
   // Make sure the VC is using correct timeouts.  We may be reusing a previously used server session
-  if (t_state.api_txn_no_activity_timeout_value != -1) {
-    server_session->get_netvc()->set_inactivity_timeout(HRTIME_MSECONDS(t_state.api_txn_no_activity_timeout_value));
-  } else {
-    server_session->get_netvc()->set_inactivity_timeout(HRTIME_SECONDS(t_state.txn_conf->transaction_no_activity_timeout_out));
-  }
+  server_session->set_inactivity_timeout(get_server_inactivity_timeout());
 }
 
 void
@@ -8087,7 +8081,7 @@ bool
 HttpSM::set_server_session_private(bool private_session)
 {
   if (server_session != nullptr) {
-    server_session->private_session = private_session;
+    server_session->set_private(private_session);
     return true;
   }
   return false;
@@ -8098,11 +8092,11 @@ HttpSM::is_private()
 {
   bool res = false;
   if (server_session) {
-    res = server_session->private_session;
+    res = server_session->is_private();
   } else if (ua_txn) {
-    Http1ServerSession *ss = ua_txn->get_server_session();
+    Http1ServerSession *ss = dynamic_cast<Http1ServerSession *>(ua_txn->get_server_session());
     if (ss) {
-      res = ss->private_session;
+      res = ss->is_private();
     } else if (will_be_private_ss) {
       res = will_be_private_ss;
     }
@@ -8297,3 +8291,9 @@ PostDataBuffers::~PostDataBuffers()
 {
   this->clear();
 }
+
+PoolableSession *
+HttpSM::get_server_session() const
+{
+  return server_session;
+}
diff --git a/proxy/http/HttpSM.h b/proxy/http/HttpSM.h
index c343d76..c2d325c 100644
--- a/proxy/http/HttpSM.h
+++ b/proxy/http/HttpSM.h
@@ -221,15 +221,11 @@ public:
   // Called by httpSessionManager so that we can reset
   //  the session timeouts and initiate a read while
   //  holding the lock for the server session
-  void attach_server_session(Http1ServerSession *s);
+  void attach_server_session(PoolableSession *s);
 
   // Used to read attributes of
   // the current active server session
-  Http1ServerSession *
-  get_server_session()
-  {
-    return server_session;
-  }
+  PoolableSession *get_server_session() const;
 
   ProxyTransaction *
   get_ua_txn()
@@ -634,9 +630,9 @@ public:
     return _client_transaction_priority_dependence;
   }
 
-  void set_server_netvc_inactivity_timeout(NetVConnection *netvc);
-  void set_server_netvc_active_timeout(NetVConnection *netvc);
-  void set_server_netvc_connect_timeout(NetVConnection *netvc);
+  ink_hrtime get_server_inactivity_timeout();
+  ink_hrtime get_server_active_timeout();
+  ink_hrtime get_server_connect_timeout();
   void rewind_state_machine();
 
 private:
diff --git a/proxy/http/HttpSessionManager.cc b/proxy/http/HttpSessionManager.cc
index f0564cd..c4aa296 100644
--- a/proxy/http/HttpSessionManager.cc
+++ b/proxy/http/HttpSessionManager.cc
@@ -32,7 +32,6 @@
 
 #include "HttpSessionManager.h"
 #include "../ProxySession.h"
-#include "Http1ServerSession.h"
 #include "HttpSM.h"
 #include "HttpDebugNames.h"
 
@@ -57,21 +56,21 @@ ServerSessionPool::purge()
 {
   // @c do_io_close can free the instance which clears the intrusive links and breaks the iterator.
   // Therefore @c do_io_close is called on a post-incremented iterator.
-  m_ip_pool.apply([](Http1ServerSession *ssn) -> void { ssn->do_io_close(); });
+  m_ip_pool.apply([](PoolableSession *ssn) -> void { ssn->do_io_close(); });
   m_ip_pool.clear();
   m_fqdn_pool.clear();
 }
 
 bool
-ServerSessionPool::match(Http1ServerSession *ss, sockaddr const *addr, CryptoHash const &hostname_hash,
+ServerSessionPool::match(PoolableSession *ss, sockaddr const *addr, CryptoHash const &hostname_hash,
                          TSServerSessionSharingMatchMask match_style)
 {
   bool retval = match_style != 0;
   if (retval && (TS_SERVER_SESSION_SHARING_MATCH_MASK_IP & match_style)) {
-    retval = ats_ip_addr_port_eq(ss->get_server_ip(), addr);
+    retval = ats_ip_addr_port_eq(ss->get_remote_addr(), addr);
   }
   if (retval && (TS_SERVER_SESSION_SHARING_MATCH_MASK_HOSTONLY & match_style)) {
-    retval = (ats_ip_port_cast(addr) == ats_ip_port_cast(ss->get_server_ip()) && ss->hostname_hash == hostname_hash);
+    retval = (ats_ip_port_cast(addr) == ats_ip_port_cast(ss->get_remote_addr()) && ss->hostname_hash == hostname_hash);
   }
   return retval;
 }
@@ -142,7 +141,7 @@ ServerSessionPool::validate_cert(HttpSM *sm, NetVConnection *netvc)
 
 HSMresult_t
 ServerSessionPool::acquireSession(sockaddr const *addr, CryptoHash const &hostname_hash,
-                                  TSServerSessionSharingMatchMask match_style, HttpSM *sm, Http1ServerSession *&to_return)
+                                  TSServerSessionSharingMatchMask match_style, HttpSM *sm, PoolableSession *&to_return)
 {
   HSMresult_t zret = HSM_NOT_FOUND;
   to_return        = nullptr;
@@ -151,12 +150,16 @@ ServerSessionPool::acquireSession(sockaddr const *addr, CryptoHash const &hostna
     // This is broken out because only in this case do we check the host hash first. The range must be checked
     // to verify an upstream that matches port and SNI name is selected. Walk backwards to select oldest.
     in_port_t port = ats_ip_port_cast(addr);
-    auto first     = m_fqdn_pool.find(hostname_hash);
-    while (first != m_fqdn_pool.end() && first->hostname_hash == hostname_hash) {
-      if (port == ats_ip_port_cast(first->get_server_ip()) &&
-          (!(match_style & TS_SERVER_SESSION_SHARING_MATCH_MASK_SNI) || validate_sni(sm, first->get_netvc())) &&
-          (!(match_style & TS_SERVER_SESSION_SHARING_MATCH_MASK_HOSTSNISYNC) || validate_host_sni(sm, first->get_netvc())) &&
-          (!(match_style & TS_SERVER_SESSION_SHARING_MATCH_MASK_CERT) || validate_cert(sm, first->get_netvc()))) {
+    FQDNTable::iterator first, last;
+    // FreeBSD/clang++ bug workaround: explicit cast to super type to make overload work. Not needed on Fedora27 nor gcc.
+    // Not fixed on FreeBSD as of llvm 6.0.1.
+    std::tie(first, last) = static_cast<const decltype(m_fqdn_pool)::range::super_type &>(m_fqdn_pool.equal_range(hostname_hash));
+    while (last != first) {
+      --last;
+      if (port == ats_ip_port_cast(last->get_remote_addr()) &&
+          (!(match_style & TS_SERVER_SESSION_SHARING_MATCH_MASK_SNI) || validate_sni(sm, last->get_netvc())) &&
+          (!(match_style & TS_SERVER_SESSION_SHARING_MATCH_MASK_HOSTSNISYNC) || validate_host_sni(sm, last->get_netvc())) &&
+          (!(match_style & TS_SERVER_SESSION_SHARING_MATCH_MASK_CERT) || validate_cert(sm, last->get_netvc()))) {
         zret = HSM_DONE;
         break;
       }
@@ -173,7 +176,7 @@ ServerSessionPool::acquireSession(sockaddr const *addr, CryptoHash const &hostna
     // And matches the other constraints as well
     // Note the port is matched as part of the address key so it doesn't need to be checked again.
     if (match_style & (~TS_SERVER_SESSION_SHARING_MATCH_MASK_IP)) {
-      while (first != m_ip_pool.end() && ats_ip_addr_port_eq(first->get_server_ip(), addr)) {
+      while (first != m_ip_pool.end() && ats_ip_addr_port_eq(first->get_remote_addr(), addr)) {
         if ((!(match_style & TS_SERVER_SESSION_SHARING_MATCH_MASK_HOSTONLY) || first->hostname_hash == hostname_hash) &&
             (!(match_style & TS_SERVER_SESSION_SHARING_MATCH_MASK_SNI) || validate_sni(sm, first->get_netvc())) &&
             (!(match_style & TS_SERVER_SESSION_SHARING_MATCH_MASK_HOSTSNISYNC) || validate_host_sni(sm, first->get_netvc())) &&
@@ -196,21 +199,21 @@ ServerSessionPool::acquireSession(sockaddr const *addr, CryptoHash const &hostna
 }
 
 void
-ServerSessionPool::releaseSession(Http1ServerSession *ss)
+ServerSessionPool::releaseSession(PoolableSession *ss)
 {
-  ss->state = HSS_KA_SHARED;
+  ss->state = PoolableSession::KA_POOLED;
   // Now we need to issue a read on the connection to detect
   //  if it closes on us.  We will get called back in the
   //  continuation for this bucket, ensuring we have the lock
   //  to remove the connection from our lists
-  ss->do_io_read(this, INT64_MAX, ss->read_buffer);
+  ss->do_io_read(this, 0, nullptr);
 
   // Transfer control of the write side as well
   ss->do_io_write(this, 0, nullptr);
 
   // we probably don't need the active timeout set, but will leave it for now
-  ss->get_netvc()->set_inactivity_timeout(ss->get_netvc()->get_inactivity_timeout());
-  ss->get_netvc()->set_active_timeout(ss->get_netvc()->get_active_timeout());
+  ss->set_inactivity_timeout(ss->get_netvc()->get_inactivity_timeout());
+  ss->set_active_timeout(ss->get_netvc()->get_active_timeout());
   // put it in the pools.
   m_ip_pool.insert(ss);
   m_fqdn_pool.insert(ss);
@@ -218,7 +221,7 @@ ServerSessionPool::releaseSession(Http1ServerSession *ss)
   Debug("http_ss",
         "[%" PRId64 "] [release session] "
         "session placed into shared pool",
-        ss->con_id);
+        ss->connection_id());
 }
 
 //   Called from the NetProcessor to let us know that a
@@ -228,7 +231,7 @@ int
 ServerSessionPool::eventHandler(int event, void *data)
 {
   NetVConnection *net_vc = nullptr;
-  Http1ServerSession *s  = nullptr;
+  PoolableSession *s     = nullptr;
 
   switch (event) {
   case VC_EVENT_READ_READY:
@@ -257,7 +260,7 @@ ServerSessionPool::eventHandler(int event, void *data)
       // keeping the connection alive will not keep us above the # of max connections
       // to the origin and we are below the min number of keep alive connections to this
       // origin, then reset the timeouts on our end and do not close the connection
-      if ((event == VC_EVENT_INACTIVITY_TIMEOUT || event == VC_EVENT_ACTIVE_TIMEOUT) && s->state == HSS_KA_SHARED &&
+      if ((event == VC_EVENT_INACTIVITY_TIMEOUT || event == VC_EVENT_ACTIVE_TIMEOUT) && s->state == PoolableSession::KA_POOLED &&
           s->conn_track_group) {
         Debug("http_ss", "s->conn_track_group->min_keep_alive_conns : %d", s->conn_track_group->min_keep_alive_conns);
         bool connection_count_below_min = s->conn_track_group->_count <= s->conn_track_group->min_keep_alive_conns;
@@ -266,7 +269,7 @@ ServerSessionPool::eventHandler(int event, void *data)
           Debug("http_ss",
                 "[%" PRId64 "] [session_bucket] session received io notice [%s], "
                 "resetting timeout to maintain minimum number of connections",
-                s->con_id, HttpDebugNames::get_event_name(event));
+                s->connection_id(), HttpDebugNames::get_event_name(event));
           s->get_netvc()->set_inactivity_timeout(s->get_netvc()->get_inactivity_timeout());
           s->get_netvc()->set_active_timeout(s->get_netvc()->get_active_timeout());
           found = true;
@@ -276,9 +279,9 @@ ServerSessionPool::eventHandler(int event, void *data)
 
       // We've found our server session. Remove it from
       //   our lists and close it down
-      Debug("http_ss", "[%" PRId64 "] [session_pool] session %p received io notice [%s]", s->con_id, s,
+      Debug("http_ss", "[%" PRId64 "] [session_pool] session %p received io notice [%s]", s->connection_id(), s,
             HttpDebugNames::get_event_name(event));
-      ink_assert(s->state == HSS_KA_SHARED);
+      ink_assert(s->state == PoolableSession::KA_POOLED);
       // Out of the pool! Now!
       m_ip_pool.erase(spot);
       m_fqdn_pool.erase(s);
@@ -330,8 +333,7 @@ HSMresult_t
 HttpSessionManager::acquire_session(Continuation * /* cont ATS_UNUSED */, sockaddr const *ip, const char *hostname,
                                     ProxyTransaction *ua_txn, HttpSM *sm)
 {
-  // First test for any session bound to the ua_txn
-  Http1ServerSession *to_return = nullptr;
+  PoolableSession *to_return = nullptr;
   TSServerSessionSharingMatchMask match_style =
     static_cast<TSServerSessionSharingMatchMask>(sm->t_state.txn_conf->server_session_sharing_match);
   CryptoHash hostname_hash;
@@ -356,8 +358,8 @@ HttpSessionManager::acquire_session(Continuation * /* cont ATS_UNUSED */, sockad
          ServerSessionPool::validate_host_sni(sm, to_return->get_netvc())) &&
         (!(match_style & TS_SERVER_SESSION_SHARING_MATCH_MASK_CERT) ||
          ServerSessionPool::validate_cert(sm, to_return->get_netvc()))) {
-      Debug("http_ss", "[%" PRId64 "] [acquire session] returning attached session ", to_return->con_id);
-      to_return->state = HSS_ACTIVE;
+      Debug("http_ss", "[%" PRId64 "] [acquire session] returning attached session ", to_return->connection_id());
+      to_return->state = PoolableSession::SSN_IN_USE;
       sm->attach_server_session(to_return);
       return HSM_DONE;
     }
@@ -366,8 +368,8 @@ HttpSessionManager::acquire_session(Continuation * /* cont ATS_UNUSED */, sockad
     Debug("http_ss",
           "[%" PRId64 "] [acquire session] "
           "session not a match, returning to shared pool",
-          to_return->con_id);
-    to_return->release();
+          to_return->connection_id());
+    to_return->release(nullptr);
     to_return = nullptr;
   }
 
@@ -389,8 +391,8 @@ HSMresult_t
 HttpSessionManager::_acquire_session(sockaddr const *ip, CryptoHash const &hostname_hash, HttpSM *sm,
                                      TSServerSessionSharingMatchMask match_style, TSServerSessionSharingPoolType pool_type)
 {
-  Http1ServerSession *to_return = nullptr;
-  HSMresult_t retval            = HSM_NOT_FOUND;
+  PoolableSession *to_return = nullptr;
+  HSMresult_t retval         = HSM_NOT_FOUND;
 
   // Extend the mutex window until the acquired Server session is attached
   // to the SM. Releasing the mutex before that results in race conditions
@@ -444,8 +446,8 @@ HttpSessionManager::_acquire_session(sockaddr const *ip, CryptoHash const &hostn
     }
 
     if (to_return) {
-      Debug("http_ss", "[%" PRId64 "] [acquire session] return session from shared pool", to_return->con_id);
-      to_return->state = HSS_ACTIVE;
+      Debug("http_ss", "[%" PRId64 "] [acquire session] return session from shared pool", to_return->connection_id());
+      to_return->state = PoolableSession::SSN_IN_USE;
       // the attach_server_session will issue the do_io_read under the sm lock
       sm->attach_server_session(to_return);
       retval = HSM_DONE;
@@ -455,7 +457,7 @@ HttpSessionManager::_acquire_session(sockaddr const *ip, CryptoHash const &hostn
 }
 
 HSMresult_t
-HttpSessionManager::release_session(Http1ServerSession *to_release)
+HttpSessionManager::release_session(PoolableSession *to_release)
 {
   EThread *ethread = this_ethread();
   ServerSessionPool *pool =
@@ -471,7 +473,8 @@ HttpSessionManager::release_session(Http1ServerSession *to_release)
     to_release->sharing_pool = TS_SERVER_SESSION_SHARING_POOL_THREAD;
     return release_session(to_release);
   } else {
-    Debug("http_ss", "[%" PRId64 "] [release session] could not release session due to lock contention", to_release->con_id);
+    Debug("http_ss", "[%" PRId64 "] [release session] could not release session due to lock contention",
+          to_release->connection_id());
     released_p = false;
   }
 
diff --git a/proxy/http/HttpSessionManager.h b/proxy/http/HttpSessionManager.h
index 66a98bd..45344582 100644
--- a/proxy/http/HttpSessionManager.h
+++ b/proxy/http/HttpSessionManager.h
@@ -33,7 +33,7 @@
 #pragma once
 
 #include "P_EventSystem.h"
-#include "Http1ServerSession.h"
+#include "PoolableSession.h"
 #include "tscore/IntrusiveHashMap.h"
 
 class ProxyTransaction;
@@ -74,13 +74,13 @@ public:
   }
 
 protected:
-  using IPTable   = IntrusiveHashMap<Http1ServerSession::IPLinkage>;
-  using FQDNTable = IntrusiveHashMap<Http1ServerSession::FQDNLinkage>;
+  using IPTable   = IntrusiveHashMap<PoolableSession::IPLinkage>;
+  using FQDNTable = IntrusiveHashMap<PoolableSession::FQDNLinkage>;
 
 public:
   /** Check if a session matches address and host name.
    */
-  static bool match(Http1ServerSession *ss, sockaddr const *addr, CryptoHash const &host_hash,
+  static bool match(PoolableSession *ss, sockaddr const *addr, CryptoHash const &host_hash,
                     TSServerSessionSharingMatchMask match_style);
 
   /** Get a session from the pool.
@@ -91,10 +91,10 @@ public:
       @return A pointer to the session or @c NULL if not matching session was found.
   */
   HSMresult_t acquireSession(sockaddr const *addr, CryptoHash const &host_hash, TSServerSessionSharingMatchMask match_style,
-                             HttpSM *sm, Http1ServerSession *&server_session);
+                             HttpSM *sm, PoolableSession *&server_session);
   /** Release a session to to pool.
    */
-  void releaseSession(Http1ServerSession *ss);
+  void releaseSession(PoolableSession *ss);
 
   /// Close all sessions and then clear the table.
   void purge();
@@ -111,7 +111,7 @@ public:
   HttpSessionManager() {}
   ~HttpSessionManager() {}
   HSMresult_t acquire_session(Continuation *cont, sockaddr const *addr, const char *hostname, ProxyTransaction *ua_txn, HttpSM *sm);
-  HSMresult_t release_session(Http1ServerSession *to_release);
+  HSMresult_t release_session(PoolableSession *to_release);
   void purge_keepalives();
   void init();
   int main_handler(int event, void *data);
diff --git a/proxy/http/HttpTransactHeaders.cc b/proxy/http/HttpTransactHeaders.cc
index 1a54fe2..4ce0037 100644
--- a/proxy/http/HttpTransactHeaders.cc
+++ b/proxy/http/HttpTransactHeaders.cc
@@ -35,6 +35,7 @@
 #include "HdrUtils.h"
 #include "HttpCompat.h"
 #include "HttpSM.h"
+#include "PoolableSession.h"
 
 #include "I_Machine.h"
 
diff --git a/proxy/http2/Http2ClientSession.cc b/proxy/http2/Http2ClientSession.cc
index 4ec6d3d..d28d0b8 100644
--- a/proxy/http2/Http2ClientSession.cc
+++ b/proxy/http2/Http2ClientSession.cc
@@ -362,7 +362,7 @@ Http2ClientSession::main_event_handler(int event, void *edata)
     } else if (this->connection_state.get_stream_error_rate() >
                Http2::stream_error_rate_threshold) { // For a case many stream errors happened
       ip_port_text_buffer ipb;
-      const char *client_ip = ats_ip_ntop(get_client_addr(), ipb, sizeof(ipb));
+      const char *client_ip = ats_ip_ntop(get_remote_addr(), ipb, sizeof(ipb));
       Warning("HTTP/2 session error client_ip=%s session_id=%" PRId64
               " closing a connection, because its stream error rate (%f) exceeded the threshold (%f)",
               client_ip, connection_id(), this->connection_state.get_stream_error_rate(), Http2::stream_error_rate_threshold);
@@ -559,7 +559,7 @@ Http2ClientSession::state_process_frame_read(int event, VIO *vio, bool inside_fr
     Http2ErrorCode err = Http2ErrorCode::HTTP2_ERROR_NO_ERROR;
     if (this->connection_state.get_stream_error_rate() > std::min(1.0, Http2::stream_error_rate_threshold * 2.0)) {
       ip_port_text_buffer ipb;
-      const char *client_ip = ats_ip_ntop(get_client_addr(), ipb, sizeof(ipb));
+      const char *client_ip = ats_ip_ntop(get_remote_addr(), ipb, sizeof(ipb));
       Warning("HTTP/2 session error client_ip=%s session_id=%" PRId64
               " closing a connection, because its stream error rate (%f) exceeded the threshold (%f)",
               client_ip, connection_id(), this->connection_state.get_stream_error_rate(), Http2::stream_error_rate_threshold);
@@ -603,13 +603,13 @@ Http2ClientSession::state_process_frame_read(int event, VIO *vio, bool inside_fr
 }
 
 void
-Http2ClientSession::increment_current_active_client_connections_stat()
+Http2ClientSession::increment_current_active_connections_stat()
 {
   HTTP2_INCREMENT_THREAD_DYN_STAT(HTTP2_STAT_CURRENT_ACTIVE_CLIENT_CONNECTION_COUNT, this_ethread());
 }
 
 void
-Http2ClientSession::decrement_current_active_client_connections_stat()
+Http2ClientSession::decrement_current_active_connections_stat()
 {
   HTTP2_DECREMENT_THREAD_DYN_STAT(HTTP2_STAT_CURRENT_ACTIVE_CLIENT_CONNECTION_COUNT, this_ethread());
 }
@@ -628,7 +628,7 @@ Http2ClientSession::_should_do_something_else()
 }
 
 sockaddr const *
-Http2ClientSession::get_client_addr()
+Http2ClientSession::get_remote_addr() const
 {
   return _vc ? _vc->get_remote_addr() : &cached_client_addr.sa;
 }
diff --git a/proxy/http2/Http2ClientSession.h b/proxy/http2/Http2ClientSession.h
index 26ce15f..5e2b00d 100644
--- a/proxy/http2/Http2ClientSession.h
+++ b/proxy/http2/Http2ClientSession.h
@@ -88,14 +88,14 @@ public:
 
   ////////////////////
   // Accessors
-  sockaddr const *get_client_addr() override;
+  sockaddr const *get_remote_addr() const override;
   sockaddr const *get_local_addr() override;
   int get_transact_count() const override;
   const char *get_protocol_string() const override;
   int populate_protocol(std::string_view *result, int size) const override;
   const char *protocol_contains(std::string_view prefix) const override;
-  void increment_current_active_client_connections_stat() override;
-  void decrement_current_active_client_connections_stat() override;
+  void increment_current_active_connections_stat() override;
+  void decrement_current_active_connections_stat() override;
 
   void set_upgrade_context(HTTPHdr *h);
   void set_dying_event(int event);
diff --git a/proxy/http2/Http2ConnectionState.cc b/proxy/http2/Http2ConnectionState.cc
index b2597e8..d1256cd 100644
--- a/proxy/http2/Http2ConnectionState.cc
+++ b/proxy/http2/Http2ConnectionState.cc
@@ -1068,7 +1068,7 @@ Http2ConnectionState::main_event_handler(int event, void *edata)
 
     if (error.cls != Http2ErrorClass::HTTP2_ERROR_CLASS_NONE) {
       ip_port_text_buffer ipb;
-      const char *client_ip = ats_ip_ntop(ua_session->get_client_addr(), ipb, sizeof(ipb));
+      const char *client_ip = ats_ip_ntop(ua_session->get_remote_addr(), ipb, sizeof(ipb));
       if (error.cls == Http2ErrorClass::HTTP2_ERROR_CLASS_CONNECTION) {
         if (error.msg) {
           Error("HTTP/2 connection error code=0x%02x client_ip=%s session_id=%" PRId64 " stream_id=%u %s",
diff --git a/proxy/http2/Http2Stream.h b/proxy/http2/Http2Stream.h
index 3e3467b..cb48229 100644
--- a/proxy/http2/Http2Stream.h
+++ b/proxy/http2/Http2Stream.h
@@ -96,7 +96,7 @@ public:
   // Accessors
   void set_active_timeout(ink_hrtime timeout_in) override;
   void set_inactivity_timeout(ink_hrtime timeout_in) override;
-  void cancel_active_timeout();
+  void cancel_active_timeout() override;
   void cancel_inactivity_timeout() override;
   bool is_active_timeout_expired(ink_hrtime now);
   bool is_inactive_timeout_expired(ink_hrtime now);
diff --git a/proxy/http3/Http3Session.cc b/proxy/http3/Http3Session.cc
index aaea1dfd..8e1168b 100644
--- a/proxy/http3/Http3Session.cc
+++ b/proxy/http3/Http3Session.cc
@@ -170,13 +170,13 @@ Http3Session::~Http3Session()
 }
 
 void
-Http3Session::increment_current_active_client_connections_stat()
+Http3Session::increment_current_active_connections_stat()
 {
   // TODO Implement stats
 }
 
 void
-Http3Session::decrement_current_active_client_connections_stat()
+Http3Session::decrement_current_active_connections_stat()
 {
   // TODO Implement stats
 }
@@ -202,13 +202,13 @@ Http09Session::~Http09Session()
 }
 
 void
-Http09Session::increment_current_active_client_connections_stat()
+Http09Session::increment_current_active_connections_stat()
 {
   // TODO Implement stats
 }
 
 void
-Http09Session::decrement_current_active_client_connections_stat()
+Http09Session::decrement_current_active_connections_stat()
 {
   // TODO Implement stats
 }
diff --git a/proxy/http3/Http3Session.h b/proxy/http3/Http3Session.h
index a6aec41..0d912ce 100644
--- a/proxy/http3/Http3Session.h
+++ b/proxy/http3/Http3Session.h
@@ -71,8 +71,8 @@ public:
   ~Http3Session();
 
   // ProxySession interface
-  void increment_current_active_client_connections_stat() override;
-  void decrement_current_active_client_connections_stat() override;
+  void increment_current_active_connections_stat() override;
+  void decrement_current_active_connections_stat() override;
 
   QPACK *local_qpack();
   QPACK *remote_qpack();
@@ -94,8 +94,8 @@ public:
   ~Http09Session();
 
   // ProxySession interface
-  void increment_current_active_client_connections_stat() override;
-  void decrement_current_active_client_connections_stat() override;
+  void increment_current_active_connections_stat() override;
+  void decrement_current_active_connections_stat() override;
 
 private:
 };
diff --git a/src/traffic_server/InkAPI.cc b/src/traffic_server/InkAPI.cc
index eee68ed..18ebfca 100644
--- a/src/traffic_server/InkAPI.cc
+++ b/src/traffic_server/InkAPI.cc
@@ -4920,8 +4920,8 @@ TSHttpSsnClientVConnGet(TSHttpSsn ssnp)
 TSVConn
 TSHttpSsnServerVConnGet(TSHttpSsn ssnp)
 {
-  TSVConn vconn          = nullptr;
-  Http1ServerSession *ss = reinterpret_cast<Http1ServerSession *>(ssnp);
+  TSVConn vconn       = nullptr;
+  PoolableSession *ss = reinterpret_cast<PoolableSession *>(ssnp);
   if (ss != nullptr) {
     vconn = reinterpret_cast<TSVConn>(ss->get_netvc());
   }
@@ -4935,7 +4935,7 @@ TSHttpTxnServerVConnGet(TSHttpTxn txnp)
   sdk_assert(sdk_sanity_check_txn(txnp) == TS_SUCCESS);
   HttpSM *sm = reinterpret_cast<HttpSM *>(txnp);
   if (sm != nullptr) {
-    Http1ServerSession *ss = sm->get_server_session();
+    PoolableSession *ss = sm->get_server_session();
     if (ss != nullptr) {
       vconn = reinterpret_cast<TSVConn>(ss->get_netvc());
     }
@@ -5745,7 +5745,7 @@ TSHttpSsnClientAddrGet(TSHttpSsn ssnp)
   if (cs == nullptr) {
     return nullptr;
   }
-  return cs->get_client_addr();
+  return cs->get_remote_addr();
 }
 sockaddr const *
 TSHttpTxnClientAddrGet(TSHttpTxn txnp)
@@ -5782,7 +5782,7 @@ TSHttpTxnOutgoingAddrGet(TSHttpTxn txnp)
 
   HttpSM *sm = reinterpret_cast<HttpSM *>(txnp);
 
-  Http1ServerSession *ssn = sm->get_server_session();
+  PoolableSession *ssn = sm->get_server_session();
   if (ssn == nullptr) {
     return nullptr;
   }
@@ -5916,12 +5916,14 @@ TSHttpTxnServerPacketMarkSet(TSHttpTxn txnp, int mark)
   HttpSM *sm = (HttpSM *)txnp;
 
   // change the mark on an active server session
-  Http1ServerSession *ssn = sm->get_server_session();
-  if (nullptr != ssn) {
-    NetVConnection *vc = ssn->get_netvc();
-    if (vc != nullptr) {
-      vc->options.packet_mark = (uint32_t)mark;
-      vc->apply_options();
+  if (nullptr != sm->ua_txn) {
+    PoolableSession *ssn = sm->ua_txn->get_server_session();
+    if (nullptr != ssn) {
+      NetVConnection *vc = ssn->get_netvc();
+      if (vc != nullptr) {
+        vc->options.packet_mark = (uint32_t)mark;
+        vc->apply_options();
+      }
     }
   }
 
@@ -5956,12 +5958,14 @@ TSHttpTxnServerPacketTosSet(TSHttpTxn txnp, int tos)
   HttpSM *sm = (HttpSM *)txnp;
 
   // change the tos on an active server session
-  Http1ServerSession *ssn = sm->get_server_session();
-  if (nullptr != ssn) {
-    NetVConnection *vc = ssn->get_netvc();
-    if (vc != nullptr) {
-      vc->options.packet_tos = (uint32_t)tos;
-      vc->apply_options();
+  if (nullptr != sm->ua_txn) {
+    PoolableSession *ssn = sm->ua_txn->get_server_session();
+    if (nullptr != ssn) {
+      NetVConnection *vc = ssn->get_netvc();
+      if (vc != nullptr) {
+        vc->options.packet_tos = (uint32_t)tos;
+        vc->apply_options();
+      }
     }
   }
 
@@ -5996,12 +6000,14 @@ TSHttpTxnServerPacketDscpSet(TSHttpTxn txnp, int dscp)
   HttpSM *sm = (HttpSM *)txnp;
 
   // change the tos on an active server session
-  Http1ServerSession *ssn = sm->get_server_session();
-  if (nullptr != ssn) {
-    NetVConnection *vc = ssn->get_netvc();
-    if (vc != nullptr) {
-      vc->options.packet_tos = (uint32_t)dscp << 2;
-      vc->apply_options();
+  if (nullptr != sm->ua_txn) {
+    PoolableSession *ssn = sm->ua_txn->get_server_session();
+    if (nullptr != ssn) {
+      NetVConnection *vc = ssn->get_netvc();
+      if (vc != nullptr) {
+        vc->options.packet_tos = (uint32_t)dscp << 2;
+        vc->apply_options();
+      }
     }
   }
 
@@ -7782,7 +7788,7 @@ TSHttpTxnServerFdGet(TSHttpTxn txnp, int *fdp)
   HttpSM *sm = reinterpret_cast<HttpSM *>(txnp);
   *fdp       = -1;
 
-  Http1ServerSession *ss = sm->get_server_session();
+  PoolableSession *ss = sm->get_server_session();
   if (ss == nullptr) {
     return TS_ERROR;
   }
diff --git a/tests/gold_tests/continuations/session_id.test.py b/tests/gold_tests/continuations/session_id.test.py
index a4e0293..3580a1c 100644
--- a/tests/gold_tests/continuations/session_id.test.py
+++ b/tests/gold_tests/continuations/session_id.test.py
@@ -96,6 +96,15 @@ tr.Processes.Default.ReturnCode = Any(0, 2)
 # AuTest already searches for errors in diags.log and fails if it encounters
 # them. The test plugin prints an error to this log if it sees duplicate ids.
 # The following is to verify that we encountered the expected ids.
-ts.Streams.stderr += Testers.ContainsExpression(
-    "session id: 199",
-    "Verify the various session ids were found.")
+
+
+def verify_session_count(output):
+    global numberOfRequests
+    nReq = numberOfRequests * 2
+    session_ids = [line[0:line.find("\n")] for line in str(output).split("session id: ")[1:]]
+    if len(session_ids) != nReq:
+        return "Found {} session_id's, expected {}".format(len(session_ids), nReq)
+    return ""
+
+
+ts.Streams.All += Testers.FileContentCallback(verify_session_count, 'verify_session_count')