You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@trafficserver.apache.org by am...@apache.org on 2017/03/11 03:21:06 UTC

[trafficserver] branch master updated: Change protocol stack reporting to use StringView to avoid strlen calls. See #1520, #1534

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

amc 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  a9a354a   Change protocol stack reporting to use StringView to avoid strlen calls. See #1520, #1534
a9a354a is described below

commit a9a354abf74c544feee9208ff9ee3487e259db49
Author: Alan M. Carroll <am...@apache.org>
AuthorDate: Tue Feb 28 23:27:37 2017 -0800

    Change protocol stack reporting to use StringView to avoid strlen calls.
    See #1520, #1534
---
 iocore/net/I_NetVConnection.h     |  9 +++--
 iocore/net/NetVConnection.cc      | 21 +++++-----
 iocore/net/P_SSLNetVConnection.h  | 23 +++++------
 iocore/net/P_UnixNetVConnection.h | 82 +++++++++++++++++++--------------------
 iocore/net/SSLNetVConnection.cc   | 57 ++++++++++++++-------------
 lib/records/RecHttp.cc            | 28 ++++++-------
 lib/ts/ink_inet.cc                | 18 ++++++++-
 lib/ts/ink_inet.h                 | 17 +++++++-
 mgmt/LocalManager.cc              |  4 +-
 proxy/InkAPI.cc                   | 21 ++++++----
 proxy/ProxyClientSession.h        | 22 +++--------
 proxy/ProxyClientTransaction.h    | 18 +++------
 proxy/http/HttpSM.cc              | 32 +++++++--------
 proxy/http/HttpSM.h               | 10 +++--
 proxy/http/HttpTransactHeaders.cc | 48 ++++++++++-------------
 proxy/http2/Http2ClientSession.h  | 73 +++++++++++++++++-----------------
 16 files changed, 253 insertions(+), 230 deletions(-)

diff --git a/iocore/net/I_NetVConnection.h b/iocore/net/I_NetVConnection.h
index 4725580..a815cf3 100644
--- a/iocore/net/I_NetVConnection.h
+++ b/iocore/net/I_NetVConnection.h
@@ -33,6 +33,7 @@
 #include "I_IOBuffer.h"
 #include "I_Socks.h"
 #include <ts/apidefs.h>
+#include <ts/MemView.h>
 
 #define CONNECT_SUCCESS 1
 #define CONNECT_FAILURE 0
@@ -233,9 +234,9 @@ struct NetVCOptions {
     return *this;
   }
 
-  const char *get_family_string() const;
+  ts::StringView get_family_string() const;
 
-  const char *get_proto_string() const;
+  ts::StringView get_proto_string() const;
 
   /// @name Debugging
   //@{
@@ -626,13 +627,13 @@ public:
   }
 
   virtual int
-  populate_protocol(const char **results, int n) const
+  populate_protocol(ts::StringView *results, int n) const
   {
     return 0;
   }
 
   virtual const char *
-  protocol_contains(const char *tag) const
+  protocol_contains(ts::StringView prefix) const
   {
     return nullptr;
   }
diff --git a/iocore/net/NetVConnection.cc b/iocore/net/NetVConnection.cc
index b73ea29..68a9507 100644
--- a/iocore/net/NetVConnection.cc
+++ b/iocore/net/NetVConnection.cc
@@ -45,33 +45,30 @@ NetVConnection::cancel_OOB()
   return;
 }
 
-const char *
+ts::StringView
 NetVCOptions::get_proto_string() const
 {
   switch (ip_proto) {
   case USE_TCP:
-    return TS_PROTO_TAG_TCP;
+    return IP_PROTO_TAG_TCP;
   case USE_UDP:
-    return TS_PROTO_TAG_UDP;
+    return IP_PROTO_TAG_UDP;
   default:
-    return nullptr;
+    break;
   }
+  return nullptr;
 }
 
-const char *
+ts::StringView
 NetVCOptions::get_family_string() const
 {
-  const char *retval;
   switch (ip_family) {
   case AF_INET:
-    retval = TS_PROTO_TAG_IPV4;
-    break;
+    return IP_PROTO_TAG_IPV4;
   case AF_INET6:
-    retval = TS_PROTO_TAG_IPV6;
-    break;
+    return IP_PROTO_TAG_IPV6;
   default:
-    retval = nullptr;
     break;
   }
-  return retval;
+  return nullptr;
 }
diff --git a/iocore/net/P_SSLNetVConnection.h b/iocore/net/P_SSLNetVConnection.h
index ae09bd8..e4a11d0 100644
--- a/iocore/net/P_SSLNetVConnection.h
+++ b/iocore/net/P_SSLNetVConnection.h
@@ -37,6 +37,7 @@
 #include "P_UnixNetVConnection.h"
 #include "P_UnixNet.h"
 #include "ts/apidefs.h"
+#include <ts/MemView.h>
 
 #include <openssl/ssl.h>
 #include <openssl/err.h>
@@ -87,8 +88,8 @@ class SSLNetVConnection : public UnixNetVConnection
   typedef UnixNetVConnection super; ///< Parent type.
 
 public:
-  virtual int sslStartHandShake(int event, int &err);
-  virtual void free(EThread *t);
+  int sslStartHandShake(int event, int &err) override;
+  void free(EThread *t) override;
 
   virtual void
   enableRead()
@@ -97,8 +98,8 @@ public:
     write.enabled = 1;
   }
 
-  virtual bool
-  getSSLHandShakeComplete() const
+  bool
+  getSSLHandShakeComplete() const override
   {
     return sslHandShakeComplete;
   }
@@ -123,10 +124,10 @@ public:
 
   int sslServerHandShakeEvent(int &err);
   int sslClientHandShakeEvent(int &err);
-  virtual void net_read_io(NetHandler *nh, EThread *lthread);
-  virtual int64_t load_buffer_and_write(int64_t towrite, MIOBufferAccessor &buf, int64_t &total_written, int &needs);
+  void net_read_io(NetHandler *nh, EThread *lthread) override;
+  int64_t load_buffer_and_write(int64_t towrite, MIOBufferAccessor &buf, int64_t &total_written, int &needs) override;
   void registerNextProtocolSet(const SSLNextProtocolSet *);
-  virtual void do_io_close(int lerrno = -1);
+  void do_io_close(int lerrno = -1) override;
 
   ////////////////////////////////////////////////////////////
   // Instances of NetVConnection should be allocated        //
@@ -240,15 +241,15 @@ public:
     return ssl ? SSL_get_cipher_name(ssl) : nullptr;
   }
 
-  int populate_protocol(const char **results, int n) const;
-  const char *protocol_contains(const char *tag) const;
+  int populate_protocol(ts::StringView *results, int n) const override;
+  const char *protocol_contains(ts::StringView tag) const override;
 
   /**
    * Populate the current object based on the socket information in in the
    * con parameter and the ssl object in the arg parameter
    * This is logic is invoked when the NetVC object is created in a new thread context
    */
-  virtual int populate(Connection &con, Continuation *c, void *arg);
+  int populate(Connection &con, Continuation *c, void *arg) override;
 
   SSL *ssl;
   ink_hrtime sslHandshakeBeginTime;
@@ -262,7 +263,7 @@ private:
   SSLNetVConnection(const SSLNetVConnection &);
   SSLNetVConnection &operator=(const SSLNetVConnection &);
 
-  const char *map_tls_protocol_to_tag(const char *proto_string) const;
+  ts::StringView map_tls_protocol_to_tag(const char *proto_string) const;
 
   bool sslHandShakeComplete;
   bool sslClientRenegotiationAbort;
diff --git a/iocore/net/P_UnixNetVConnection.h b/iocore/net/P_UnixNetVConnection.h
index e5b5d25..e2bf94f 100644
--- a/iocore/net/P_UnixNetVConnection.h
+++ b/iocore/net/P_UnixNetVConnection.h
@@ -103,14 +103,14 @@ enum tcp_congestion_control_t { CLIENT_SIDE, SERVER_SIDE };
 class UnixNetVConnection : public NetVConnection
 {
 public:
-  virtual int64_t outstanding();
-  virtual VIO *do_io_read(Continuation *c, int64_t nbytes, MIOBuffer *buf);
-  virtual VIO *do_io_write(Continuation *c, int64_t nbytes, IOBufferReader *buf, bool owner = false);
+  int64_t outstanding() override;
+  VIO *do_io_read(Continuation *c, int64_t nbytes, MIOBuffer *buf) override;
+  VIO *do_io_write(Continuation *c, int64_t nbytes, IOBufferReader *buf, bool owner = false) override;
 
-  virtual bool get_data(int id, void *data);
+  bool get_data(int id, void *data) override;
 
-  virtual Action *send_OOB(Continuation *cont, char *buf, int len);
-  virtual void cancel_OOB();
+  Action *send_OOB(Continuation *cont, char *buf, int len) override;
+  void cancel_OOB() override;
 
   virtual void
   setSSLHandshakeWantsRead(bool /* flag */)
@@ -134,8 +134,8 @@ public:
     return false;
   }
 
-  virtual void do_io_close(int lerrno = -1);
-  virtual void do_io_shutdown(ShutdownHowTo_t howto);
+  void do_io_close(int lerrno = -1) override;
+  void do_io_shutdown(ShutdownHowTo_t howto) override;
 
   ////////////////////////////////////////////////////////////
   // Set the timeouts associated with this connection.      //
@@ -149,21 +149,21 @@ public:
   // called when handing an  event from this NetVConnection,//
   // or the NetVConnection creation callback.               //
   ////////////////////////////////////////////////////////////
-  virtual void set_active_timeout(ink_hrtime timeout_in);
-  virtual void set_inactivity_timeout(ink_hrtime timeout_in);
-  virtual void cancel_active_timeout();
-  virtual void cancel_inactivity_timeout();
-  virtual void set_action(Continuation *c);
-  virtual void add_to_keep_alive_queue();
-  virtual void remove_from_keep_alive_queue();
-  virtual bool add_to_active_queue();
+  void set_active_timeout(ink_hrtime timeout_in) override;
+  void set_inactivity_timeout(ink_hrtime timeout_in) override;
+  void cancel_active_timeout() override;
+  void cancel_inactivity_timeout() override;
+  void set_action(Continuation *c) override;
+  void add_to_keep_alive_queue() override;
+  void remove_from_keep_alive_queue() override;
+  bool add_to_active_queue() override;
   virtual void remove_from_active_queue();
 
   // The public interface is VIO::reenable()
-  virtual void reenable(VIO *vio);
-  virtual void reenable_re(VIO *vio);
+  void reenable(VIO *vio) override;
+  void reenable_re(VIO *vio) override;
 
-  virtual SOCKET get_socket();
+  SOCKET get_socket() override;
 
   virtual ~UnixNetVConnection();
 
@@ -175,33 +175,31 @@ public:
   UnixNetVConnection();
 
   int
-  populate_protocol(const char **results, int n) const
+  populate_protocol(ts::StringView *results, int n) const override
   {
     int retval = 0;
-    if (n > 0) {
-      results[retval++] = options.get_proto_string();
-      if (n > 1) {
-        results[retval++] = options.get_family_string();
+    if (n > retval) {
+      if (!(results[retval] = options.get_proto_string()).isEmpty())
+        ++retval;
+      if (n > retval) {
+        if (!(results[retval] = options.get_family_string()).isEmpty())
+          ++retval;
       }
     }
     return retval;
   }
 
   const char *
-  protocol_contains(const char *tag) const
+  protocol_contains(ts::StringView tag) const override
   {
-    const char *retval   = nullptr;
-    unsigned int tag_len = strlen(tag);
-    const char *test_tag = options.get_proto_string();
-    if (strncmp(tag, test_tag, tag_len) == 0) {
-      retval = test_tag;
-    } else {
-      test_tag = options.get_family_string();
-      if (strncmp(tag, test_tag, tag_len) == 0) {
-        retval = test_tag;
+    ts::StringView retval = options.get_proto_string();
+    if (strncmp(tag.ptr(), retval.ptr(), tag.size()) != 0) {
+      retval = options.get_family_string();
+      if (strncmp(tag.ptr(), retval.ptr(), tag.size()) != 0) {
+        retval.clear();
       }
     }
-    return retval;
+    return retval.ptr();
   }
 
 private:
@@ -310,14 +308,14 @@ public:
   virtual int populate(Connection &con, Continuation *c, void *arg);
   virtual void free(EThread *t);
 
-  virtual ink_hrtime get_inactivity_timeout();
-  virtual ink_hrtime get_active_timeout();
+  ink_hrtime get_inactivity_timeout() override;
+  ink_hrtime get_active_timeout() override;
 
-  virtual void set_local_addr();
-  virtual void set_remote_addr();
-  virtual int set_tcp_init_cwnd(int init_cwnd);
-  virtual int set_tcp_congestion_control(int side);
-  virtual void apply_options();
+  void set_local_addr() override;
+  void set_remote_addr() override;
+  int set_tcp_init_cwnd(int init_cwnd) override;
+  int set_tcp_congestion_control(int side) override;
+  void apply_options() override;
 
   friend void write_to_net_io(NetHandler *, UnixNetVConnection *, EThread *);
 
diff --git a/iocore/net/SSLNetVConnection.cc b/iocore/net/SSLNetVConnection.cc
index 6f2784c..36429ac 100644
--- a/iocore/net/SSLNetVConnection.cc
+++ b/iocore/net/SSLNetVConnection.cc
@@ -1542,21 +1542,28 @@ SSLNetVConnection::populate(Connection &con, Continuation *c, void *arg)
   return EVENT_DONE;
 }
 
-const char *
+ts::StringView
 SSLNetVConnection::map_tls_protocol_to_tag(const char *proto_string) const
 {
-  const char *retval    = nullptr;
-  const char *ssl_proto = getSSLProtocol();
-  if (ssl_proto && strncmp(ssl_proto, "TLSv1", 5) == 0) {
-    if (ssl_proto[5] == '\0') {
-      retval = TS_PROTO_TAG_TLS_1_0;
-    } else if (ssl_proto[5] == '.') {
-      if (ssl_proto[6] == '1' && ssl_proto[7] == '\0') {
-        retval = TS_PROTO_TAG_TLS_1_1;
-      } else if (ssl_proto[6] == '2' && ssl_proto[7] == '\0') {
-        retval = TS_PROTO_TAG_TLS_1_2;
-      } else if (ssl_proto[6] == '3' && ssl_proto[7] == '\0') {
-        retval = TS_PROTO_TAG_TLS_1_3;
+  // Prefix for the string the SSL library hands back.
+  static const ts::StringView PREFIX("TLSv1");
+
+  ts::StringView retval;
+  ts::StringView proto(proto_string);
+
+  if (proto.size() >= PREFIX.size() && strncmp(proto.ptr(), PREFIX.ptr(), PREFIX.size()) == 0) {
+    proto += PREFIX.size();
+    if (proto.size() <= 0) {
+      retval = IP_PROTO_TAG_TLS_1_0;
+    } else if (*proto == '.') {
+      ++proto; // skip .
+      if (proto.size() == 1) {
+        if (*proto == '1')
+          retval = IP_PROTO_TAG_TLS_1_1;
+        else if (*proto == '2')
+          retval = IP_PROTO_TAG_TLS_1_2;
+        else if (*proto == '3')
+          retval = IP_PROTO_TAG_TLS_1_3;
       }
     }
   }
@@ -1564,14 +1571,13 @@ SSLNetVConnection::map_tls_protocol_to_tag(const char *proto_string) const
 }
 
 int
-SSLNetVConnection::populate_protocol(const char **results, int n) const
+SSLNetVConnection::populate_protocol(ts::StringView *results, int n) const
 {
   int retval = 0;
-  if (n > 0) {
-    results[0] = map_tls_protocol_to_tag(getSSLProtocol());
-    if (results[0] != nullptr) {
-      retval++;
-    }
+  if (n > retval) {
+    results[retval] = map_tls_protocol_to_tag(getSSLProtocol());
+    if (results[retval])
+      ++retval;
     if (n > retval) {
       retval += super::populate_protocol(results + retval, n - retval);
     }
@@ -1580,15 +1586,14 @@ SSLNetVConnection::populate_protocol(const char **results, int n) const
 }
 
 const char *
-SSLNetVConnection::protocol_contains(const char *tag) const
+SSLNetVConnection::protocol_contains(ts::StringView prefix) const
 {
-  const char *retval   = nullptr;
-  const char *tls_tag  = map_tls_protocol_to_tag(getSSLProtocol());
-  unsigned int tag_len = strlen(tag);
-  if (tag_len <= strlen(tls_tag) && strncmp(tag, tls_tag, tag_len) == 0) {
-    retval = tls_tag;
+  const char *retval = nullptr;
+  ts::StringView tag = map_tls_protocol_to_tag(getSSLProtocol());
+  if (prefix.size() <= tag.size() && strncmp(tag.ptr(), prefix.ptr(), prefix.size()) == 0) {
+    retval = tag.ptr();
   } else {
-    retval = super::protocol_contains(tag);
+    retval = super::protocol_contains(prefix);
   }
   return retval;
 }
diff --git a/lib/records/RecHttp.cc b/lib/records/RecHttp.cc
index 2076f5a..29ea1fa 100644
--- a/lib/records/RecHttp.cc
+++ b/lib/records/RecHttp.cc
@@ -26,7 +26,9 @@
 #include <ts/ink_defs.h>
 #include <ts/ink_hash_table.h>
 #include <ts/Tokenizer.h>
+#include <ts/MemView.h>
 #include <strings.h>
+#include <ts/ink_inet.h>
 
 SessionProtocolNameRegistry globalSessionProtocolNameRegistry;
 
@@ -34,10 +36,10 @@ SessionProtocolNameRegistry globalSessionProtocolNameRegistry;
    These are also used for NPN setup.
 */
 
-const char *const TS_ALPN_PROTOCOL_HTTP_0_9 = "http/0.9";
-const char *const TS_ALPN_PROTOCOL_HTTP_1_0 = "http/1.0";
-const char *const TS_ALPN_PROTOCOL_HTTP_1_1 = "http/1.1";
-const char *const TS_ALPN_PROTOCOL_HTTP_2_0 = "h2"; // HTTP/2 over TLS
+const char *const TS_ALPN_PROTOCOL_HTTP_0_9 = IP_PROTO_TAG_HTTP_0_9.ptr();
+const char *const TS_ALPN_PROTOCOL_HTTP_1_0 = IP_PROTO_TAG_HTTP_1_0.ptr();
+const char *const TS_ALPN_PROTOCOL_HTTP_1_1 = IP_PROTO_TAG_HTTP_1_1.ptr();
+const char *const TS_ALPN_PROTOCOL_HTTP_2_0 = IP_PROTO_TAG_HTTP_2_0.ptr();
 
 const char *const TS_ALPN_PROTOCOL_GROUP_HTTP  = "http";
 const char *const TS_ALPN_PROTOCOL_GROUP_HTTP2 = "http2";
@@ -45,14 +47,14 @@ const char *const TS_ALPN_PROTOCOL_GROUP_HTTP2 = "http2";
 const char *const TS_PROTO_TAG_HTTP_1_0 = TS_ALPN_PROTOCOL_HTTP_1_0;
 const char *const TS_PROTO_TAG_HTTP_1_1 = TS_ALPN_PROTOCOL_HTTP_1_1;
 const char *const TS_PROTO_TAG_HTTP_2_0 = TS_ALPN_PROTOCOL_HTTP_2_0;
-const char *const TS_PROTO_TAG_TLS_1_3  = "tls/1.3";
-const char *const TS_PROTO_TAG_TLS_1_2  = "tls/1.2";
-const char *const TS_PROTO_TAG_TLS_1_1  = "tls/1.1";
-const char *const TS_PROTO_TAG_TLS_1_0  = "tls/1.0";
-const char *const TS_PROTO_TAG_TCP      = "tcp";
-const char *const TS_PROTO_TAG_UDP      = "udp";
-const char *const TS_PROTO_TAG_IPV4     = "ipv4";
-const char *const TS_PROTO_TAG_IPV6     = "ipv6";
+const char *const TS_PROTO_TAG_TLS_1_3  = IP_PROTO_TAG_TLS_1_3.ptr();
+const char *const TS_PROTO_TAG_TLS_1_2  = IP_PROTO_TAG_TLS_1_2.ptr();
+const char *const TS_PROTO_TAG_TLS_1_1  = IP_PROTO_TAG_TLS_1_1.ptr();
+const char *const TS_PROTO_TAG_TLS_1_0  = IP_PROTO_TAG_TLS_1_0.ptr();
+const char *const TS_PROTO_TAG_TCP      = IP_PROTO_TAG_TCP.ptr();
+const char *const TS_PROTO_TAG_UDP      = IP_PROTO_TAG_UDP.ptr();
+const char *const TS_PROTO_TAG_IPV4     = IP_PROTO_TAG_IPV4.ptr();
+const char *const TS_PROTO_TAG_IPV6     = IP_PROTO_TAG_IPV6.ptr();
 
 InkHashTable *TSProtoTags;
 
@@ -386,7 +388,7 @@ HttpProxyPort::processOptions(const char *opts)
     if (in_ip_set_p && m_family != m_inbound_ip.family()) {
       Warning(
         "Invalid port descriptor '%s' - the inbound adddress family [%s] is not the same type as the explicit family value [%s]",
-        opts, ats_ip_family_name(m_inbound_ip.family()), ats_ip_family_name(m_family));
+        opts, ats_ip_family_name(m_inbound_ip.family()).ptr(), ats_ip_family_name(m_family).ptr());
       zret = false;
     }
   } else if (in_ip_set_p) {
diff --git a/lib/ts/ink_inet.cc b/lib/ts/ink_inet.cc
index 16f67dd..c6907f8 100644
--- a/lib/ts/ink_inet.cc
+++ b/lib/ts/ink_inet.cc
@@ -32,6 +32,19 @@
 
 IpAddr const IpAddr::INVALID;
 
+const ts::StringView IP_PROTO_TAG_IPV4("ipv4", ts::StringView::literal);
+const ts::StringView IP_PROTO_TAG_IPV6("ipv6", ts::StringView::literal);
+const ts::StringView IP_PROTO_TAG_UDP("udp", ts::StringView::literal);
+const ts::StringView IP_PROTO_TAG_TCP("tcp", ts::StringView::literal);
+const ts::StringView IP_PROTO_TAG_TLS_1_0("tls/1.0", ts::StringView::literal);
+const ts::StringView IP_PROTO_TAG_TLS_1_1("tls/1.1", ts::StringView::literal);
+const ts::StringView IP_PROTO_TAG_TLS_1_2("tls/1.2", ts::StringView::literal);
+const ts::StringView IP_PROTO_TAG_TLS_1_3("tls/1.3", ts::StringView::literal);
+const ts::StringView IP_PROTO_TAG_HTTP_0_9("http/0.9", ts::StringView::literal);
+const ts::StringView IP_PROTO_TAG_HTTP_1_0("http/1.0", ts::StringView::literal);
+const ts::StringView IP_PROTO_TAG_HTTP_1_1("http/1.1", ts::StringView::literal);
+const ts::StringView IP_PROTO_TAG_HTTP_2_0("h2", ts::StringView::literal); // HTTP/2 over TLS
+
 uint32_t
 ink_inet_addr(const char *s)
 {
@@ -119,10 +132,11 @@ ats_ip_ntop(const struct sockaddr *addr, char *dst, size_t size)
   return zret;
 }
 
-const char *
+ts::StringView
 ats_ip_family_name(int family)
 {
-  return AF_INET == family ? "IPv4" : AF_INET6 == family ? "IPv6" : "Unspec";
+  static const ts::StringView UNSPEC("Unspec", ts::StringView::literal);
+  return AF_INET == family ? IP_PROTO_TAG_IPV4 : AF_INET6 == family ? IP_PROTO_TAG_IPV6 : UNSPEC;
 }
 
 const char *
diff --git a/lib/ts/ink_inet.h b/lib/ts/ink_inet.h
index ce1b132..2f0c757 100644
--- a/lib/ts/ink_inet.h
+++ b/lib/ts/ink_inet.h
@@ -31,6 +31,7 @@
 #include "ts/ink_memory.h"
 #include "ts/ink_apidefs.h"
 #include "ts/TsBuffer.h"
+#include <ts/MemView.h>
 
 #if !TS_HAS_IN6_IS_ADDR_UNSPECIFIED
 #if defined(IN6_IS_ADDR_UNSPECIFIED)
@@ -44,6 +45,20 @@ IN6_IS_ADDR_UNSPECIFIED(in6_addr const *addr)
 }
 #endif
 
+// IP protocol stack tags.
+extern const ts::StringView IP_PROTO_TAG_IPV4;
+extern const ts::StringView IP_PROTO_TAG_IPV6;
+extern const ts::StringView IP_PROTO_TAG_UDP;
+extern const ts::StringView IP_PROTO_TAG_TCP;
+extern const ts::StringView IP_PROTO_TAG_TLS_1_0;
+extern const ts::StringView IP_PROTO_TAG_TLS_1_1;
+extern const ts::StringView IP_PROTO_TAG_TLS_1_2;
+extern const ts::StringView IP_PROTO_TAG_TLS_1_3;
+extern const ts::StringView IP_PROTO_TAG_HTTP_0_9;
+extern const ts::StringView IP_PROTO_TAG_HTTP_1_0;
+extern const ts::StringView IP_PROTO_TAG_HTTP_1_1;
+extern const ts::StringView IP_PROTO_TAG_HTTP_2_0;
+
 struct IpAddr; // forward declare.
 
 /** A union to hold the standard IP address structures.
@@ -174,7 +189,7 @@ ats_ip_invalidate(IpEndpoint *ip)
 /** Get a string name for an IP address family.
     @return The string name (never @c nullptr).
 */
-const char *ats_ip_family_name(int family);
+ts::StringView ats_ip_family_name(int family);
 
 /// Test for IP protocol.
 /// @return @c true if the address is IP, @c false otherwise.
diff --git a/mgmt/LocalManager.cc b/mgmt/LocalManager.cc
index 835c0f4..f274dee 100644
--- a/mgmt/LocalManager.cc
+++ b/mgmt/LocalManager.cc
@@ -1035,9 +1035,9 @@ LocalManager::listenForProxy()
 
     if ((listen(p.m_fd, backlog)) < 0) {
       mgmt_fatal(errno, "[LocalManager::listenForProxy] Unable to listen on port: %d (%s)\n", p.m_port,
-                 ats_ip_family_name(p.m_family));
+                 ats_ip_family_name(p.m_family).ptr());
     }
-    mgmt_log("[LocalManager::listenForProxy] Listening on port: %d (%s)\n", p.m_port, ats_ip_family_name(p.m_family));
+    mgmt_log("[LocalManager::listenForProxy] Listening on port: %d (%s)\n", p.m_port, ats_ip_family_name(p.m_family).ptr());
   }
   return;
 }
diff --git a/proxy/InkAPI.cc b/proxy/InkAPI.cc
index e8f63e2..40a3d7d 100644
--- a/proxy/InkAPI.cc
+++ b/proxy/InkAPI.cc
@@ -59,6 +59,7 @@
 #include "I_RecCore.h"
 #include "I_Machine.h"
 #include "HttpProxyServerMain.h"
+#include <ts/MemView.h>
 
 #include "api/ts/ts.h"
 
@@ -9329,10 +9330,13 @@ TSHttpTxnClientProtocolStackGet(TSHttpTxn txnp, int n, const char **result, int
 {
   sdk_assert(sdk_sanity_check_txn(txnp) == TS_SUCCESS);
   sdk_assert(n == 0 || result != nullptr);
-  HttpSM *sm = (HttpSM *)txnp;
+  HttpSM *sm = reinterpret_cast<HttpSM *>(txnp);
   int count  = 0;
-  if (sm) {
-    count = sm->populate_client_protocol(result, n);
+  if (sm && n > 0) {
+    auto mem = static_cast<ts::StringView *>(alloca(sizeof(ts::StringView) * n));
+    count    = sm->populate_client_protocol(mem, n);
+    for (int i  = 0; i < count; ++i)
+      result[i] = mem[i].ptr();
   }
   if (actual) {
     *actual = count;
@@ -9347,8 +9351,11 @@ TSHttpSsnClientProtocolStackGet(TSHttpSsn ssnp, int n, const char **result, int
   sdk_assert(n == 0 || result != nullptr);
   ProxyClientSession *cs = reinterpret_cast<ProxyClientSession *>(ssnp);
   int count              = 0;
-  if (cs) {
-    count = cs->populate_protocol(result, n);
+  if (cs && n > 0) {
+    auto mem = static_cast<ts::StringView *>(alloca(sizeof(ts::StringView) * n));
+    count    = cs->populate_protocol(mem, n);
+    for (int i  = 0; i < count; ++i)
+      result[i] = mem[i].ptr();
   }
   if (actual) {
     *actual = count;
@@ -9367,7 +9374,7 @@ TSHttpTxnClientProtocolStackContains(TSHttpTxn txnp, const char *tag)
 {
   sdk_assert(sdk_sanity_check_txn(txnp) == TS_SUCCESS);
   HttpSM *sm = (HttpSM *)txnp;
-  return sm->client_protocol_contains(tag);
+  return sm->client_protocol_contains(ts::StringView(tag));
 }
 
 const char *
@@ -9375,7 +9382,7 @@ TSHttpSsnClientProtocolStackContains(TSHttpSsn ssnp, const char *tag)
 {
   sdk_assert(sdk_sanity_check_http_ssn(ssnp) == TS_SUCCESS);
   ProxyClientSession *cs = reinterpret_cast<ProxyClientSession *>(ssnp);
-  return cs->protocol_contains(tag);
+  return cs->protocol_contains(ts::StringView(tag));
 }
 
 const char *
diff --git a/proxy/ProxyClientSession.h b/proxy/ProxyClientSession.h
index 831a654..9cfa1ab 100644
--- a/proxy/ProxyClientSession.h
+++ b/proxy/ProxyClientSession.h
@@ -189,27 +189,17 @@ public:
   }
 
   virtual int
-  populate_protocol(const char **result, int size) const
+  populate_protocol(ts::StringView *result, int size) const
   {
-    int retval = 0;
-
-    if (get_netvc()) {
-      retval += this->get_netvc()->populate_protocol(result, size);
-    }
-
-    return retval;
+    auto vc = this->get_netvc();
+    return vc ? vc->populate_protocol(result, size) : 0;
   }
 
   virtual const char *
-  protocol_contains(const char *tag_prefix) const
+  protocol_contains(ts::StringView tag_prefix) const
   {
-    const char *retval = NULL;
-
-    if (get_netvc()) {
-      retval = this->get_netvc()->protocol_contains(tag_prefix);
-    }
-
-    return retval;
+    auto vc = this->get_netvc();
+    return vc ? vc->protocol_contains(tag_prefix) : nullptr;
   }
 
   void set_session_active();
diff --git a/proxy/ProxyClientTransaction.h b/proxy/ProxyClientTransaction.h
index d0c67f0..b5735f8 100644
--- a/proxy/ProxyClientTransaction.h
+++ b/proxy/ProxyClientTransaction.h
@@ -25,6 +25,7 @@
 #define __PROXY_CLIENT_TRANSACTION_H__
 
 #include "ProxyClientSession.h"
+#include <ts/MemView.h>
 
 class HttpSM;
 class HttpServerSession;
@@ -243,22 +244,15 @@ public:
   }
 
   virtual int
-  populate_protocol(const char **result, int size) const
+  populate_protocol(ts::StringView *result, int size) const
   {
-    int retval = 0;
-    if (parent) {
-      retval = parent->populate_protocol(result, size);
-    }
-    return retval;
+    return parent ? parent->populate_protocol(result, size) : 0;
   }
+
   virtual const char *
-  protocol_contains(const char *tag_prefix) const
+  protocol_contains(ts::StringView tag_prefix) const
   {
-    const char *retval = NULL;
-    if (parent) {
-      retval = parent->protocol_contains(tag_prefix);
-    }
-    return retval;
+    return parent ? parent->protocol_contains(tag_prefix) : nullptr;
   }
 
 protected:
diff --git a/proxy/http/HttpSM.cc b/proxy/http/HttpSM.cc
index e0efc8d..09d7fed 100644
--- a/proxy/http/HttpSM.cc
+++ b/proxy/http/HttpSM.cc
@@ -50,6 +50,8 @@
 #include "congest/Congestion.h"
 #include "ts/I_Layout.h"
 
+using ts::StringView;
+
 #define DEFAULT_RESPONSE_BUFFER_SIZE_INDEX 6 // 8K
 #define DEFAULT_REQUEST_BUFFER_SIZE_INDEX 6  // 8K
 #define MIN_CONFIG_BUFFER_SIZE_INDEX 5       // 4K
@@ -4729,7 +4731,7 @@ void
 HttpSM::do_http_server_open(bool raw)
 {
   int ip_family = t_state.current.server->dst_addr.sa.sa_family;
-  DebugSM("http_track", "entered inside do_http_server_open ][%s]", ats_ip_family_name(ip_family));
+  DebugSM("http_track", "entered inside do_http_server_open ][%s]", ats_ip_family_name(ip_family).ptr());
 
   // Make sure we are on the "right" thread
   if (ua_session) {
@@ -8057,14 +8059,13 @@ HttpSM::is_redirect_required()
 
 // Fill in the client protocols used.  Return the number of entries returned
 int
-HttpSM::populate_client_protocol(const char **result, int n) const
+HttpSM::populate_client_protocol(ts::StringView *result, int n) const
 {
   int retval = 0;
   if (n > 0) {
-    const char *proto = HttpSM::find_proto_string(t_state.hdr_info.client_request.version_get());
+    StringView proto = HttpSM::find_proto_string(t_state.hdr_info.client_request.version_get());
     if (proto) {
-      result[0] = proto;
-      retval    = 1;
+      result[retval++] = proto;
       if (n > retval && ua_session) {
         retval += ua_session->populate_protocol(result + retval, n - retval);
       }
@@ -8075,29 +8076,28 @@ HttpSM::populate_client_protocol(const char **result, int n) const
 
 // Look for a specific protocol
 const char *
-HttpSM::client_protocol_contains(const char *tag_prefix) const
+HttpSM::client_protocol_contains(StringView tag_prefix) const
 {
   const char *retval = nullptr;
-  const char *proto  = HttpSM::find_proto_string(t_state.hdr_info.client_request.version_get());
+  StringView proto   = HttpSM::find_proto_string(t_state.hdr_info.client_request.version_get());
   if (proto) {
-    unsigned int tag_prefix_len = strlen(tag_prefix);
-    if (tag_prefix_len <= strlen(proto) && strncmp(tag_prefix, proto, tag_prefix_len) == 0) {
-      retval = proto;
+    StringView prefix(tag_prefix);
+    if (prefix.size() <= proto.size() && 0 == strncmp(proto.ptr(), prefix.ptr(), prefix.size())) {
+      retval = proto.ptr();
     } else if (ua_session) {
-      retval = ua_session->protocol_contains(tag_prefix);
+      retval = ua_session->protocol_contains(prefix);
     }
   }
   return retval;
 }
 
-const char *
+StringView
 HttpSM::find_proto_string(HTTPVersion version) const
 {
   if (version == HTTPVersion(1, 1)) {
-    return TS_PROTO_TAG_HTTP_1_1;
+    return IP_PROTO_TAG_HTTP_1_1;
   } else if (version == HTTPVersion(1, 0)) {
-    return TS_PROTO_TAG_HTTP_1_0;
-  } else {
-    return nullptr;
+    return IP_PROTO_TAG_HTTP_1_0;
   }
+  return nullptr;
 }
diff --git a/proxy/http/HttpSM.h b/proxy/http/HttpSM.h
index 7d7e1b8..e9bd219 100644
--- a/proxy/http/HttpSM.h
+++ b/proxy/http/HttpSM.h
@@ -41,6 +41,7 @@
 #include "InkAPIInternal.h"
 #include "../ProxyClientTransaction.h"
 #include "HdrUtils.h"
+#include <ts/MemView.h>
 //#include "AuthHttpAdapter.h"
 
 /* Enable LAZY_BUF_ALLOC to delay allocation of buffers until they
@@ -263,9 +264,12 @@ public:
   bool is_private();
   bool is_redirect_required();
 
-  int populate_client_protocol(const char **result, int n) const;
-  const char *client_protocol_contains(const char *tag_prefix) const;
-  const char *find_proto_string(HTTPVersion version) const;
+  /// Get the protocol stack for the inbound (client, user agent) connection.
+  /// @arg result [out] Array to store the results
+  /// @arg n [in] Size of the array @a result.
+  int populate_client_protocol(ts::StringView *result, int n) const;
+  const char *client_protocol_contains(ts::StringView tag_prefix) const;
+  ts::StringView find_proto_string(HTTPVersion version) const;
 
   int64_t sm_id;
   unsigned int magic;
diff --git a/proxy/http/HttpTransactHeaders.cc b/proxy/http/HttpTransactHeaders.cc
index d16516f..4809c75 100644
--- a/proxy/http/HttpTransactHeaders.cc
+++ b/proxy/http/HttpTransactHeaders.cc
@@ -31,6 +31,8 @@
 
 #include "I_Machine.h"
 
+#include <array>
+
 bool
 HttpTransactHeaders::is_method_cacheable(const HttpConfigParams *http_config_param, const int method)
 {
@@ -685,6 +687,23 @@ HttpTransactHeaders::insert_server_header_in_response(const char *server_tag, in
   }
 }
 
+/// Look up the protocol stack and write it to the @a via_string.
+size_t
+write_client_protocol_stack(HttpTransact::State *s, char *via_string, size_t len)
+{
+  std::array<ts::StringView, 10> proto_buf; // 10 seems like a reasonable number of protos to print
+  int retval        = s->state_machine->populate_client_protocol(proto_buf.data(), proto_buf.size());
+  char *via         = via_string;
+  char *limit       = via_string + len;
+  ts::StringView *v = proto_buf.data();
+  for (int i = 0; i < retval && (via + v->size() + 1) < limit; ++i, ++v) {
+    memcpy(via, v->ptr(), v->size());
+    via += v->size();
+    *via++ = ' ';
+  }
+  return via - via_string;
+}
+
 ///////////////////////////////////////////////////////////////////////////////
 // Name       : insert_via_header_in_request
 // Description: takes in existing via_string and inserts it in header
@@ -741,26 +760,8 @@ HttpTransactHeaders::insert_via_header_in_request(HttpTransact::State *s, HTTPHd
   }
 
   char *incoming_via = s->via_string;
-  int scheme         = s->orig_scheme;
-  ink_assert(scheme >= 0);
-
-  int scheme_len   = hdrtoken_index_to_length(scheme);
-  int32_t hversion = header->version_get().m_version;
-
-  memcpy(via_string, hdrtoken_index_to_wks(scheme), scheme_len);
-  via_string += scheme_len;
 
-  // Common case (I hope?)
-  if ((HTTP_MAJOR(hversion) == 1) && HTTP_MINOR(hversion) == 1) {
-    memcpy(via_string, "/1.1 ", 5);
-    via_string += 5;
-  } else {
-    *via_string++ = '/';
-    *via_string++ = '0' + HTTP_MAJOR(hversion);
-    *via_string++ = '.';
-    *via_string++ = '0' + HTTP_MINOR(hversion);
-    *via_string++ = ' ';
-  }
+  via_string += write_client_protocol_stack(s, via_string, sizeof(new_via_string) - (via_string - new_via_string));
   via_string += nstrcpy(via_string, s->http_config_param->proxy_hostname);
 
   *via_string++ = '[';
@@ -827,14 +828,7 @@ HttpTransactHeaders::insert_via_header_in_response(HttpTransact::State *s, HTTPH
 
   char *incoming_via = s->via_string;
 
-  const char *proto_buf[10]; // 10 seems like a reasonable number of protos to print
-  int retval = s->state_machine->populate_client_protocol(proto_buf, countof(proto_buf));
-  for (int i = 0; i < retval; i++) {
-    memcpy(via_string, proto_buf[i], strlen(proto_buf[i]));
-    via_string += strlen(proto_buf[i]);
-    *via_string++ = ' ';
-  }
-
+  via_string += write_client_protocol_stack(s, via_string, sizeof(new_via_string) - (via_string - new_via_string));
   via_string += nstrcpy(via_string, s->http_config_param->proxy_hostname);
   *via_string++ = ' ';
   *via_string++ = '(';
diff --git a/proxy/http2/Http2ClientSession.h b/proxy/http2/Http2ClientSession.h
index dc4b7e7..2e9442e 100644
--- a/proxy/http2/Http2ClientSession.h
+++ b/proxy/http2/Http2ClientSession.h
@@ -28,6 +28,8 @@
 #include "Plugin.h"
 #include "ProxyClientSession.h"
 #include "Http2ConnectionState.h"
+#include <ts/MemView.h>
+#include <ts/ink_inet.h>
 
 // Name                       Edata                 Description
 // HTTP2_SESSION_EVENT_INIT   Http2ClientSession *  HTTP/2 session is born
@@ -152,15 +154,15 @@ class Http2ClientSession : public ProxyClientSession
 {
 public:
   typedef ProxyClientSession super; ///< Parent type.
-  Http2ClientSession();
-
   typedef int (Http2ClientSession::*SessionHandler)(int, void *);
 
+  Http2ClientSession();
+
   // Implement ProxyClientSession interface.
-  void start();
-  virtual void destroy();
-  virtual void free();
-  virtual void new_connection(NetVConnection *new_vc, MIOBuffer *iobuf, IOBufferReader *reader, bool backdoor);
+  void start() override;
+  void destroy() override;
+  void free() override;
+  void new_connection(NetVConnection *new_vc, MIOBuffer *iobuf, IOBufferReader *reader, bool backdoor) override;
 
   bool
   ready_to_free() const
@@ -169,20 +171,20 @@ public:
   }
 
   // Implement VConnection interface.
-  VIO *do_io_read(Continuation *c, int64_t nbytes = INT64_MAX, MIOBuffer *buf = 0);
-  VIO *do_io_write(Continuation *c = NULL, int64_t nbytes = INT64_MAX, IOBufferReader *buf = 0, bool owner = false);
-  void do_io_close(int lerrno = -1);
-  void do_io_shutdown(ShutdownHowTo_t howto);
-  void reenable(VIO *vio);
-
-  virtual NetVConnection *
-  get_netvc() const
+  VIO *do_io_read(Continuation *c, int64_t nbytes = INT64_MAX, MIOBuffer *buf = 0) override;
+  VIO *do_io_write(Continuation *c = NULL, int64_t nbytes = INT64_MAX, IOBufferReader *buf = 0, 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;
+
+  NetVConnection *
+  get_netvc() const override
   {
     return client_vc;
   }
 
-  virtual void
-  release_netvc()
+  void
+  release_netvc() override
   {
     // Make sure the vio's are also released to avoid later surprises in inactivity timeout
     if (client_vc) {
@@ -193,13 +195,13 @@ public:
   }
 
   sockaddr const *
-  get_client_addr()
+  get_client_addr() override
   {
     return client_vc ? client_vc->get_remote_addr() : &cached_client_addr.sa;
   }
 
   sockaddr const *
-  get_local_addr()
+  get_local_addr() override
   {
     return client_vc ? client_vc->get_local_addr() : &cached_local_addr.sa;
   }
@@ -218,14 +220,14 @@ public:
     return upgrade_context;
   }
 
-  virtual int
-  get_transact_count() const
+  int
+  get_transact_count() const override
   {
     return connection_state.get_stream_requests();
   }
 
-  virtual void
-  release(ProxyClientTransaction *trans)
+  void
+  release(ProxyClientTransaction *trans) override
   {
   }
 
@@ -248,35 +250,34 @@ public:
     return recursion > 0;
   }
 
-  virtual const char *
-  get_protocol_string() const
+  const char *
+  get_protocol_string() const override
   {
     return "http/2";
   }
 
   virtual int
-  populate_protocol(const char **result, int size) const
+  populate_protocol(ts::StringView *result, int size) const override
   {
     int retval = 0;
-    if (size > 0) {
-      result[0] = TS_PROTO_TAG_HTTP_2_0;
-      retval    = 1;
-      if (size > 1) {
-        retval += super::populate_protocol(result + 1, size - 1);
+    if (size > retval) {
+      result[retval++] = IP_PROTO_TAG_HTTP_2_0;
+      if (size > retval) {
+        retval += super::populate_protocol(result + retval, size - retval);
       }
     }
     return retval;
   }
 
   virtual const char *
-  protocol_contains(const char *tag_prefix) const
+  protocol_contains(ts::StringView prefix) const override
   {
-    const char *retval   = NULL;
-    unsigned int tag_len = strlen(tag_prefix);
-    if (tag_len <= strlen(TS_PROTO_TAG_HTTP_2_0) && strncmp(tag_prefix, TS_PROTO_TAG_HTTP_2_0, tag_len) == 0) {
-      retval = TS_PROTO_TAG_HTTP_2_0;
+    const char *retval = nullptr;
+
+    if (prefix.size() <= IP_PROTO_TAG_HTTP_2_0.size() && strncmp(IP_PROTO_TAG_HTTP_2_0.ptr(), prefix.ptr(), prefix.size()) == 0) {
+      retval = IP_PROTO_TAG_HTTP_2_0.ptr();
     } else {
-      retval = super::protocol_contains(tag_prefix);
+      retval = super::protocol_contains(prefix);
     }
     return retval;
   }

-- 
To stop receiving notification emails like this one, please contact
['"commits@trafficserver.apache.org" <co...@trafficserver.apache.org>'].