You are viewing a plain text version of this content. The canonical link for it is here.
Posted to github@trafficserver.apache.org by GitBox <gi...@apache.org> on 2022/11/21 16:42:55 UTC

[GitHub] [trafficserver] bneradt commented on a diff in pull request #9209: libswoc: Add ATS IP address utitilies on top of libswoc.

bneradt commented on code in PR #9209:
URL: https://github.com/apache/trafficserver/pull/9209#discussion_r1028272521


##########
include/tscpp/util/ts_ip.h:
##########
@@ -0,0 +1,440 @@
+/** @file
+
+  IP address handling support.
+
+  Built on top of libswoc IP networking support to provide utilities specialized for ATS.
+
+  @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 <optional>
+
+#include "swoc/swoc_ip.h"
+
+namespace ts
+{
+/// Pair of addresses, each optional.
+/// Used in situations where both an IPv4 and IPv6 may be needed.
+class IPAddrPair
+{
+public:
+  using self_type = IPAddrPair;
+
+  IPAddrPair() = default; ///< Default construct empty pair.
+
+  /// @return @c true if either address is present.
+  bool has_value() const;
+
+  /// @return @c true if an IPv4 address is present.
+  bool has_ip4() const;
+
+  /// @return @c true if an IPv6 address is present.
+  bool has_ip6() const;
+
+  /// @return The IPv4 address
+  /// @note Does not check if the address is present.
+  swoc::IP4Addr const &ip4() const;
+
+  /// @return The IPv6 address
+  /// @note Does not check if the address is present.
+  swoc::IP6Addr const &ip6() const;
+
+  /** Assign the IPv4 address.
+   *
+   * @param addr Address to assign.
+   * @return @a this
+   */
+  self_type &operator=(swoc::IP4Addr const &addr);
+
+  /** Assign the IPv6 address.
+   *
+   * @param addr Address to assign.
+   * @return @a this
+   */
+  self_type &operator=(swoc::IP6Addr const &addr);
+
+  /** Assign an address.
+   *
+   * @param addr Address to assign.
+   * @return @a this
+   *
+   * The appropriate internal address is assigned based on the address in @a addr.
+   */
+  self_type &operator=(swoc::IPAddr const &addr);
+
+protected:
+  std::optional<swoc::IP4Addr> _ip4;
+  std::optional<swoc::IP6Addr> _ip6;
+};
+
+inline bool
+IPAddrPair::has_value() const
+{
+  return _ip4.has_value() || _ip6.has_value();
+}
+
+inline bool
+IPAddrPair::has_ip4() const
+{
+  return _ip4.has_value();
+}
+
+inline bool
+IPAddrPair::has_ip6() const
+{
+  return _ip6.has_value();
+}
+
+inline swoc::IP4Addr const &
+IPAddrPair::ip4() const
+{
+  return _ip4.value();
+}
+
+inline swoc::IP6Addr const &
+IPAddrPair::ip6() const
+{
+  return _ip6.value();
+}
+
+inline auto
+IPAddrPair::operator=(swoc::IP4Addr const &addr) -> self_type &
+{
+  _ip4 = addr;
+  return *this;
+}
+
+inline auto
+IPAddrPair::operator=(swoc::IP6Addr const &addr) -> self_type &
+{
+  _ip6 = addr;
+  return *this;
+}
+
+inline auto
+IPAddrPair::operator=(swoc::IPAddr const &addr) -> self_type &
+{
+  if (addr.is_ip4()) {
+    _ip4 = addr.ip4();
+  } else if (addr.is_ip6()) {
+    _ip6 = addr.ip6();
+  }
+  return *this;
+}
+
+/// Pair of services, each optional.
+/// Used in situations where both IPv4 and IPv6 may be needed.
+class IPSrvPair
+{
+  using self_type = IPSrvPair;
+
+public:
+  IPSrvPair() = default; ///< Default construct empty pair.
+
+  /** Construct from address(es) and port.
+   *
+   * @param a4 IPv4 address.
+   * @param a6 IPv6 address.
+   * @param port Port
+   *
+   * @a port is used for both service instances.
+   */
+  IPSrvPair(swoc::IP4Addr const &a4, swoc::IP6Addr const &a6, in_port_t port = 0);
+
+  /** Construct from IPv4 address and optional port.
+   *
+   * @param a4 IPv4 address
+   * @param port Port.
+   */
+  explicit IPSrvPair(swoc::IP4Addr const &a4, in_port_t port = 0);
+
+  /** Construct from IPv6 address and optional port.
+   *
+   * @param a6 IPv6 address
+   * @param port Port.
+   */
+  explicit IPSrvPair(swoc::IP6Addr const &a6, in_port_t port = 0);
+
+  /** Construct from an address pair and optional port.
+   *
+   * @param a Address pair.
+   * @param port port.
+   *
+   * For each family the service is instantatied only if the address is present in @a a.
+   * @a port is used for all service instances.
+   */
+  explicit IPSrvPair(IPAddrPair const &a, in_port_t port = 0);
+
+  /// @return @c true if any service is present.
+  bool has_value() const;
+
+  /// @return @c true if the IPv4 service is present.
+  bool has_ip4() const;
+
+  /// @return @c true if the the IPv6 service is present.
+  bool has_ip6() const;
+
+  /// @return The IPv4 service.
+  /// @note Does not check if the service is present.
+  swoc::IP4Srv const &ip4() const;
+
+  /// @return The IPv6 service.
+  /// @note Does not check if the service is present.
+  swoc::IP6Srv const &ip6() const;
+
+  /** Assign the IPv4 service.
+   *
+   * @param srv Service to assign.
+   * @return @a this
+   */
+  self_type &operator=(swoc::IP4Srv const &srv);
+
+  /** Assign the IPv6 service.
+   *
+   * @param srv Service to assign.
+   * @return @a this
+   */
+  self_type &operator=(swoc::IP6Srv const &srv);
+
+  /** Assign a service.
+   *
+   * @param srv Service to assign.
+   * @return @a this
+   *
+   * The assigned service is the same family as @a srv.
+   */
+  self_type &operator=(swoc::IPSrv const &srv);
+
+protected:
+  std::optional<swoc::IP4Srv> _ip4;
+  std::optional<swoc::IP6Srv> _ip6;
+};
+
+inline IPSrvPair::IPSrvPair(swoc::IP4Addr const &a4, swoc::IP6Addr const &a6, in_port_t port)
+  : _ip4(swoc::IP4Srv(a4, port)), _ip6(swoc::IP6Srv(a6, port))
+{
+}
+
+inline IPSrvPair::IPSrvPair(swoc::IP4Addr const &a4, in_port_t port) : _ip4(swoc::IP4Srv(a4, port)) {}
+
+inline IPSrvPair::IPSrvPair(swoc::IP6Addr const &a6, in_port_t port) : _ip6(swoc::IP6Srv(a6, port)) {}
+
+inline IPSrvPair::IPSrvPair(IPAddrPair const &a, in_port_t port)
+{
+  if (a.has_ip4()) {
+    _ip4 = swoc::IP4Srv(a.ip4(), port);
+  } else if (a.has_ip6()) {
+    _ip6 = swoc::IP6Srv(a.ip6(), port);
+  }

Review Comment:
   Isn't it possible you'd want to set both? An IPAddrPair may have both v4 and v6 configured, right?



##########
src/tscpp/util/ts_ip.cc:
##########
@@ -0,0 +1,121 @@
+/** @file
+
+    IP address handling support.
+
+    @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.
+*/
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netdb.h>
+
+#include <tscore/ink_memory.h>
+
+#include "tscpp/util/ts_ip.h"
+
+namespace ts
+{
+IPAddrPair
+getbestaddrinfo(swoc::TextView name)
+{
+  if (swoc::IP4Addr addr; addr.load(name)) {
+    return {};
+  }
+
+  if (swoc::IP6Addr addr; addr.load(name)) {
+    return {};
+  }

Review Comment:
   Why does this return empty if it is a valid v4 or v6 address? load returns true if the parse is successful, right?
   http://docs.solidwallofcode.com/libswoc/reference/classswoc_1_1IP4Addr.html#abe02426da0f5f003cc45d81869eb3f3b



##########
include/tscpp/util/ts_ip.h:
##########
@@ -0,0 +1,440 @@
+/** @file
+
+  IP address handling support.
+
+  Built on top of libswoc IP networking support to provide utilities specialized for ATS.
+
+  @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 <optional>
+
+#include "swoc/swoc_ip.h"
+
+namespace ts
+{
+/// Pair of addresses, each optional.
+/// Used in situations where both an IPv4 and IPv6 may be needed.
+class IPAddrPair
+{
+public:
+  using self_type = IPAddrPair;
+
+  IPAddrPair() = default; ///< Default construct empty pair.
+
+  /// @return @c true if either address is present.
+  bool has_value() const;
+
+  /// @return @c true if an IPv4 address is present.
+  bool has_ip4() const;
+
+  /// @return @c true if an IPv6 address is present.
+  bool has_ip6() const;
+
+  /// @return The IPv4 address
+  /// @note Does not check if the address is present.
+  swoc::IP4Addr const &ip4() const;
+
+  /// @return The IPv6 address
+  /// @note Does not check if the address is present.
+  swoc::IP6Addr const &ip6() const;
+
+  /** Assign the IPv4 address.
+   *
+   * @param addr Address to assign.
+   * @return @a this
+   */
+  self_type &operator=(swoc::IP4Addr const &addr);
+
+  /** Assign the IPv6 address.
+   *
+   * @param addr Address to assign.
+   * @return @a this
+   */
+  self_type &operator=(swoc::IP6Addr const &addr);
+
+  /** Assign an address.
+   *
+   * @param addr Address to assign.
+   * @return @a this
+   *
+   * The appropriate internal address is assigned based on the address in @a addr.
+   */
+  self_type &operator=(swoc::IPAddr const &addr);
+
+protected:
+  std::optional<swoc::IP4Addr> _ip4;
+  std::optional<swoc::IP6Addr> _ip6;
+};
+
+inline bool
+IPAddrPair::has_value() const
+{
+  return _ip4.has_value() || _ip6.has_value();
+}
+
+inline bool
+IPAddrPair::has_ip4() const
+{
+  return _ip4.has_value();
+}
+
+inline bool
+IPAddrPair::has_ip6() const
+{
+  return _ip6.has_value();
+}
+
+inline swoc::IP4Addr const &
+IPAddrPair::ip4() const
+{
+  return _ip4.value();
+}
+
+inline swoc::IP6Addr const &
+IPAddrPair::ip6() const
+{
+  return _ip6.value();
+}
+
+inline auto
+IPAddrPair::operator=(swoc::IP4Addr const &addr) -> self_type &
+{
+  _ip4 = addr;
+  return *this;
+}
+
+inline auto
+IPAddrPair::operator=(swoc::IP6Addr const &addr) -> self_type &
+{
+  _ip6 = addr;
+  return *this;
+}
+
+inline auto
+IPAddrPair::operator=(swoc::IPAddr const &addr) -> self_type &
+{
+  if (addr.is_ip4()) {
+    _ip4 = addr.ip4();
+  } else if (addr.is_ip6()) {
+    _ip6 = addr.ip6();
+  }
+  return *this;
+}
+
+/// Pair of services, each optional.
+/// Used in situations where both IPv4 and IPv6 may be needed.
+class IPSrvPair
+{
+  using self_type = IPSrvPair;
+
+public:
+  IPSrvPair() = default; ///< Default construct empty pair.
+
+  /** Construct from address(es) and port.
+   *
+   * @param a4 IPv4 address.
+   * @param a6 IPv6 address.
+   * @param port Port
+   *
+   * @a port is used for both service instances.
+   */
+  IPSrvPair(swoc::IP4Addr const &a4, swoc::IP6Addr const &a6, in_port_t port = 0);
+
+  /** Construct from IPv4 address and optional port.
+   *
+   * @param a4 IPv4 address
+   * @param port Port.
+   */
+  explicit IPSrvPair(swoc::IP4Addr const &a4, in_port_t port = 0);
+
+  /** Construct from IPv6 address and optional port.
+   *
+   * @param a6 IPv6 address
+   * @param port Port.
+   */
+  explicit IPSrvPair(swoc::IP6Addr const &a6, in_port_t port = 0);
+
+  /** Construct from an address pair and optional port.
+   *
+   * @param a Address pair.
+   * @param port port.
+   *
+   * For each family the service is instantatied only if the address is present in @a a.
+   * @a port is used for all service instances.
+   */
+  explicit IPSrvPair(IPAddrPair const &a, in_port_t port = 0);
+
+  /// @return @c true if any service is present.
+  bool has_value() const;
+
+  /// @return @c true if the IPv4 service is present.
+  bool has_ip4() const;
+
+  /// @return @c true if the the IPv6 service is present.
+  bool has_ip6() const;
+
+  /// @return The IPv4 service.
+  /// @note Does not check if the service is present.
+  swoc::IP4Srv const &ip4() const;
+
+  /// @return The IPv6 service.
+  /// @note Does not check if the service is present.
+  swoc::IP6Srv const &ip6() const;
+
+  /** Assign the IPv4 service.
+   *
+   * @param srv Service to assign.
+   * @return @a this
+   */
+  self_type &operator=(swoc::IP4Srv const &srv);
+
+  /** Assign the IPv6 service.
+   *
+   * @param srv Service to assign.
+   * @return @a this
+   */
+  self_type &operator=(swoc::IP6Srv const &srv);
+
+  /** Assign a service.
+   *
+   * @param srv Service to assign.
+   * @return @a this
+   *
+   * The assigned service is the same family as @a srv.
+   */
+  self_type &operator=(swoc::IPSrv const &srv);
+
+protected:
+  std::optional<swoc::IP4Srv> _ip4;
+  std::optional<swoc::IP6Srv> _ip6;
+};
+
+inline IPSrvPair::IPSrvPair(swoc::IP4Addr const &a4, swoc::IP6Addr const &a6, in_port_t port)
+  : _ip4(swoc::IP4Srv(a4, port)), _ip6(swoc::IP6Srv(a6, port))
+{
+}
+
+inline IPSrvPair::IPSrvPair(swoc::IP4Addr const &a4, in_port_t port) : _ip4(swoc::IP4Srv(a4, port)) {}
+
+inline IPSrvPair::IPSrvPair(swoc::IP6Addr const &a6, in_port_t port) : _ip6(swoc::IP6Srv(a6, port)) {}
+
+inline IPSrvPair::IPSrvPair(IPAddrPair const &a, in_port_t port)
+{
+  if (a.has_ip4()) {
+    _ip4 = swoc::IP4Srv(a.ip4(), port);
+  } else if (a.has_ip6()) {
+    _ip6 = swoc::IP6Srv(a.ip6(), port);
+  }
+}
+
+inline bool
+IPSrvPair::has_value() const
+{
+  return _ip4.has_value() || _ip6.has_value();
+}
+
+inline bool
+IPSrvPair::has_ip4() const
+{
+  return _ip4.has_value();
+}
+
+inline bool
+IPSrvPair::has_ip6() const
+{
+  return _ip6.has_value();
+}
+
+inline swoc::IP4Srv const &
+IPSrvPair::ip4() const
+{
+  return _ip4.value();
+}
+
+inline swoc::IP6Srv const &
+IPSrvPair::ip6() const
+{
+  return _ip6.value();
+}
+
+inline auto
+IPSrvPair::operator=(swoc::IP4Srv const &srv) -> self_type &
+{
+  _ip4 = srv;
+  return *this;
+}
+
+inline auto
+IPSrvPair::operator=(swoc::IP6Srv const &srv) -> self_type &
+{
+  _ip6 = srv;
+  return *this;
+}
+
+inline auto
+IPSrvPair::operator=(swoc::IPSrv const &srv) -> self_type &
+{
+  if (srv.is_ip4()) {
+    _ip4 = srv.ip4();
+  } else if (srv.is_ip6()) {
+    _ip6 = srv.ip6();
+  }
+  return *this;
+}
+
+/** Get the best address info for @a name.
+
+ * @param name Address / host.
+ * @param ip4 [out] Best IPv4 result, if any.
+ * @param ip6 [out] Best IPv6 result, if any.
+ * @return @c true if an address was found, @c false if not.
+ *
+ * If @a name is a valid IP address it is interpreted as such. Otherwise it is presumed
+ * to be a host name suitable for resolution using @c getaddrinfo. The "best" address is
+ * selected by ranking the types of addresss in the order
+ *
+ * - Global, multi-cast, non-routable (private), link local, loopback
+ *
+ * For a host name, both IPv4 and IPv6 addresses may be returned. Each is judged
+ * independently.
+ *
+ * Either @a ip4 or @ip6 can be @c nullptr in which that result is discarded.
+ *
+ * @note If @name is known or required to be an IP address, use a standard address conversion
+ * instead, e.g. @c IPAddr::load .
+ *
+ * @see getaddrinfo
+ */
+IPAddrPair getbestaddrinfo(swoc::TextView name);
+
+/** Get the best address info for @a name.
+
+ * @param name Address / host.
+ * @param ip4 [out] Best IPv4 result, if any.
+ * @param ip6 [out] Best IPv6 result, if any.
+ * @return @c true if an address was found, @c false if not.

Review Comment:
   These don't seem to apply.



##########
include/tscpp/util/ts_ip.h:
##########
@@ -0,0 +1,440 @@
+/** @file
+
+  IP address handling support.
+
+  Built on top of libswoc IP networking support to provide utilities specialized for ATS.
+
+  @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 <optional>
+
+#include "swoc/swoc_ip.h"
+
+namespace ts
+{
+/// Pair of addresses, each optional.
+/// Used in situations where both an IPv4 and IPv6 may be needed.
+class IPAddrPair
+{
+public:
+  using self_type = IPAddrPair;
+
+  IPAddrPair() = default; ///< Default construct empty pair.
+
+  /// @return @c true if either address is present.
+  bool has_value() const;
+
+  /// @return @c true if an IPv4 address is present.
+  bool has_ip4() const;
+
+  /// @return @c true if an IPv6 address is present.
+  bool has_ip6() const;
+
+  /// @return The IPv4 address
+  /// @note Does not check if the address is present.
+  swoc::IP4Addr const &ip4() const;
+
+  /// @return The IPv6 address
+  /// @note Does not check if the address is present.
+  swoc::IP6Addr const &ip6() const;
+
+  /** Assign the IPv4 address.
+   *
+   * @param addr Address to assign.
+   * @return @a this
+   */
+  self_type &operator=(swoc::IP4Addr const &addr);
+
+  /** Assign the IPv6 address.
+   *
+   * @param addr Address to assign.
+   * @return @a this
+   */
+  self_type &operator=(swoc::IP6Addr const &addr);
+
+  /** Assign an address.
+   *
+   * @param addr Address to assign.
+   * @return @a this
+   *
+   * The appropriate internal address is assigned based on the address in @a addr.
+   */
+  self_type &operator=(swoc::IPAddr const &addr);
+
+protected:
+  std::optional<swoc::IP4Addr> _ip4;
+  std::optional<swoc::IP6Addr> _ip6;
+};
+
+inline bool
+IPAddrPair::has_value() const
+{
+  return _ip4.has_value() || _ip6.has_value();
+}
+
+inline bool
+IPAddrPair::has_ip4() const
+{
+  return _ip4.has_value();
+}
+
+inline bool
+IPAddrPair::has_ip6() const
+{
+  return _ip6.has_value();
+}
+
+inline swoc::IP4Addr const &
+IPAddrPair::ip4() const
+{
+  return _ip4.value();
+}
+
+inline swoc::IP6Addr const &
+IPAddrPair::ip6() const
+{
+  return _ip6.value();
+}
+
+inline auto
+IPAddrPair::operator=(swoc::IP4Addr const &addr) -> self_type &
+{
+  _ip4 = addr;
+  return *this;
+}
+
+inline auto
+IPAddrPair::operator=(swoc::IP6Addr const &addr) -> self_type &
+{
+  _ip6 = addr;
+  return *this;
+}
+
+inline auto
+IPAddrPair::operator=(swoc::IPAddr const &addr) -> self_type &
+{
+  if (addr.is_ip4()) {
+    _ip4 = addr.ip4();
+  } else if (addr.is_ip6()) {
+    _ip6 = addr.ip6();
+  }
+  return *this;
+}
+
+/// Pair of services, each optional.
+/// Used in situations where both IPv4 and IPv6 may be needed.
+class IPSrvPair
+{
+  using self_type = IPSrvPair;
+
+public:
+  IPSrvPair() = default; ///< Default construct empty pair.
+
+  /** Construct from address(es) and port.
+   *
+   * @param a4 IPv4 address.
+   * @param a6 IPv6 address.
+   * @param port Port
+   *
+   * @a port is used for both service instances.
+   */
+  IPSrvPair(swoc::IP4Addr const &a4, swoc::IP6Addr const &a6, in_port_t port = 0);
+
+  /** Construct from IPv4 address and optional port.
+   *
+   * @param a4 IPv4 address
+   * @param port Port.
+   */
+  explicit IPSrvPair(swoc::IP4Addr const &a4, in_port_t port = 0);
+
+  /** Construct from IPv6 address and optional port.
+   *
+   * @param a6 IPv6 address
+   * @param port Port.
+   */
+  explicit IPSrvPair(swoc::IP6Addr const &a6, in_port_t port = 0);
+
+  /** Construct from an address pair and optional port.
+   *
+   * @param a Address pair.
+   * @param port port.
+   *
+   * For each family the service is instantatied only if the address is present in @a a.
+   * @a port is used for all service instances.
+   */
+  explicit IPSrvPair(IPAddrPair const &a, in_port_t port = 0);
+
+  /// @return @c true if any service is present.
+  bool has_value() const;
+
+  /// @return @c true if the IPv4 service is present.
+  bool has_ip4() const;
+
+  /// @return @c true if the the IPv6 service is present.
+  bool has_ip6() const;
+
+  /// @return The IPv4 service.
+  /// @note Does not check if the service is present.
+  swoc::IP4Srv const &ip4() const;
+
+  /// @return The IPv6 service.
+  /// @note Does not check if the service is present.
+  swoc::IP6Srv const &ip6() const;
+
+  /** Assign the IPv4 service.
+   *
+   * @param srv Service to assign.
+   * @return @a this
+   */
+  self_type &operator=(swoc::IP4Srv const &srv);
+
+  /** Assign the IPv6 service.
+   *
+   * @param srv Service to assign.
+   * @return @a this
+   */
+  self_type &operator=(swoc::IP6Srv const &srv);
+
+  /** Assign a service.
+   *
+   * @param srv Service to assign.
+   * @return @a this
+   *
+   * The assigned service is the same family as @a srv.
+   */
+  self_type &operator=(swoc::IPSrv const &srv);
+
+protected:
+  std::optional<swoc::IP4Srv> _ip4;
+  std::optional<swoc::IP6Srv> _ip6;
+};
+
+inline IPSrvPair::IPSrvPair(swoc::IP4Addr const &a4, swoc::IP6Addr const &a6, in_port_t port)
+  : _ip4(swoc::IP4Srv(a4, port)), _ip6(swoc::IP6Srv(a6, port))
+{
+}
+
+inline IPSrvPair::IPSrvPair(swoc::IP4Addr const &a4, in_port_t port) : _ip4(swoc::IP4Srv(a4, port)) {}
+
+inline IPSrvPair::IPSrvPair(swoc::IP6Addr const &a6, in_port_t port) : _ip6(swoc::IP6Srv(a6, port)) {}
+
+inline IPSrvPair::IPSrvPair(IPAddrPair const &a, in_port_t port)
+{
+  if (a.has_ip4()) {
+    _ip4 = swoc::IP4Srv(a.ip4(), port);
+  } else if (a.has_ip6()) {
+    _ip6 = swoc::IP6Srv(a.ip6(), port);
+  }
+}
+
+inline bool
+IPSrvPair::has_value() const
+{
+  return _ip4.has_value() || _ip6.has_value();
+}
+
+inline bool
+IPSrvPair::has_ip4() const
+{
+  return _ip4.has_value();
+}
+
+inline bool
+IPSrvPair::has_ip6() const
+{
+  return _ip6.has_value();
+}
+
+inline swoc::IP4Srv const &
+IPSrvPair::ip4() const
+{
+  return _ip4.value();
+}
+
+inline swoc::IP6Srv const &
+IPSrvPair::ip6() const
+{
+  return _ip6.value();
+}
+
+inline auto
+IPSrvPair::operator=(swoc::IP4Srv const &srv) -> self_type &
+{
+  _ip4 = srv;
+  return *this;
+}
+
+inline auto
+IPSrvPair::operator=(swoc::IP6Srv const &srv) -> self_type &
+{
+  _ip6 = srv;
+  return *this;
+}
+
+inline auto
+IPSrvPair::operator=(swoc::IPSrv const &srv) -> self_type &
+{
+  if (srv.is_ip4()) {
+    _ip4 = srv.ip4();
+  } else if (srv.is_ip6()) {
+    _ip6 = srv.ip6();
+  }
+  return *this;
+}
+
+/** Get the best address info for @a name.
+
+ * @param name Address / host.
+ * @param ip4 [out] Best IPv4 result, if any.
+ * @param ip6 [out] Best IPv6 result, if any.
+ * @return @c true if an address was found, @c false if not.

Review Comment:
   These don't seem to apply.



##########
include/tscpp/util/ts_ip.h:
##########
@@ -0,0 +1,440 @@
+/** @file
+
+  IP address handling support.
+
+  Built on top of libswoc IP networking support to provide utilities specialized for ATS.
+
+  @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 <optional>
+
+#include "swoc/swoc_ip.h"
+
+namespace ts
+{
+/// Pair of addresses, each optional.
+/// Used in situations where both an IPv4 and IPv6 may be needed.
+class IPAddrPair
+{
+public:
+  using self_type = IPAddrPair;
+
+  IPAddrPair() = default; ///< Default construct empty pair.
+
+  /// @return @c true if either address is present.
+  bool has_value() const;
+
+  /// @return @c true if an IPv4 address is present.
+  bool has_ip4() const;
+
+  /// @return @c true if an IPv6 address is present.
+  bool has_ip6() const;
+
+  /// @return The IPv4 address
+  /// @note Does not check if the address is present.
+  swoc::IP4Addr const &ip4() const;
+
+  /// @return The IPv6 address
+  /// @note Does not check if the address is present.
+  swoc::IP6Addr const &ip6() const;
+
+  /** Assign the IPv4 address.
+   *
+   * @param addr Address to assign.
+   * @return @a this
+   */
+  self_type &operator=(swoc::IP4Addr const &addr);
+
+  /** Assign the IPv6 address.
+   *
+   * @param addr Address to assign.
+   * @return @a this
+   */
+  self_type &operator=(swoc::IP6Addr const &addr);
+
+  /** Assign an address.
+   *
+   * @param addr Address to assign.
+   * @return @a this
+   *
+   * The appropriate internal address is assigned based on the address in @a addr.
+   */
+  self_type &operator=(swoc::IPAddr const &addr);
+
+protected:
+  std::optional<swoc::IP4Addr> _ip4;
+  std::optional<swoc::IP6Addr> _ip6;
+};
+
+inline bool
+IPAddrPair::has_value() const
+{
+  return _ip4.has_value() || _ip6.has_value();
+}
+
+inline bool
+IPAddrPair::has_ip4() const
+{
+  return _ip4.has_value();
+}
+
+inline bool
+IPAddrPair::has_ip6() const
+{
+  return _ip6.has_value();
+}
+
+inline swoc::IP4Addr const &
+IPAddrPair::ip4() const
+{
+  return _ip4.value();
+}
+
+inline swoc::IP6Addr const &
+IPAddrPair::ip6() const
+{
+  return _ip6.value();
+}
+
+inline auto
+IPAddrPair::operator=(swoc::IP4Addr const &addr) -> self_type &
+{
+  _ip4 = addr;
+  return *this;
+}
+
+inline auto
+IPAddrPair::operator=(swoc::IP6Addr const &addr) -> self_type &
+{
+  _ip6 = addr;
+  return *this;
+}
+
+inline auto
+IPAddrPair::operator=(swoc::IPAddr const &addr) -> self_type &
+{
+  if (addr.is_ip4()) {
+    _ip4 = addr.ip4();
+  } else if (addr.is_ip6()) {
+    _ip6 = addr.ip6();
+  }
+  return *this;
+}
+
+/// Pair of services, each optional.
+/// Used in situations where both IPv4 and IPv6 may be needed.
+class IPSrvPair
+{
+  using self_type = IPSrvPair;
+
+public:
+  IPSrvPair() = default; ///< Default construct empty pair.
+
+  /** Construct from address(es) and port.
+   *
+   * @param a4 IPv4 address.
+   * @param a6 IPv6 address.
+   * @param port Port
+   *
+   * @a port is used for both service instances.
+   */
+  IPSrvPair(swoc::IP4Addr const &a4, swoc::IP6Addr const &a6, in_port_t port = 0);
+
+  /** Construct from IPv4 address and optional port.
+   *
+   * @param a4 IPv4 address
+   * @param port Port.
+   */
+  explicit IPSrvPair(swoc::IP4Addr const &a4, in_port_t port = 0);
+
+  /** Construct from IPv6 address and optional port.
+   *
+   * @param a6 IPv6 address
+   * @param port Port.
+   */
+  explicit IPSrvPair(swoc::IP6Addr const &a6, in_port_t port = 0);
+
+  /** Construct from an address pair and optional port.
+   *
+   * @param a Address pair.
+   * @param port port.
+   *
+   * For each family the service is instantatied only if the address is present in @a a.
+   * @a port is used for all service instances.
+   */
+  explicit IPSrvPair(IPAddrPair const &a, in_port_t port = 0);
+
+  /// @return @c true if any service is present.
+  bool has_value() const;
+
+  /// @return @c true if the IPv4 service is present.
+  bool has_ip4() const;
+
+  /// @return @c true if the the IPv6 service is present.
+  bool has_ip6() const;
+
+  /// @return The IPv4 service.
+  /// @note Does not check if the service is present.
+  swoc::IP4Srv const &ip4() const;
+
+  /// @return The IPv6 service.
+  /// @note Does not check if the service is present.
+  swoc::IP6Srv const &ip6() const;
+
+  /** Assign the IPv4 service.
+   *
+   * @param srv Service to assign.
+   * @return @a this
+   */
+  self_type &operator=(swoc::IP4Srv const &srv);
+
+  /** Assign the IPv6 service.
+   *
+   * @param srv Service to assign.
+   * @return @a this
+   */
+  self_type &operator=(swoc::IP6Srv const &srv);
+
+  /** Assign a service.
+   *
+   * @param srv Service to assign.
+   * @return @a this
+   *
+   * The assigned service is the same family as @a srv.
+   */
+  self_type &operator=(swoc::IPSrv const &srv);
+
+protected:
+  std::optional<swoc::IP4Srv> _ip4;
+  std::optional<swoc::IP6Srv> _ip6;
+};
+
+inline IPSrvPair::IPSrvPair(swoc::IP4Addr const &a4, swoc::IP6Addr const &a6, in_port_t port)
+  : _ip4(swoc::IP4Srv(a4, port)), _ip6(swoc::IP6Srv(a6, port))
+{
+}
+
+inline IPSrvPair::IPSrvPair(swoc::IP4Addr const &a4, in_port_t port) : _ip4(swoc::IP4Srv(a4, port)) {}
+
+inline IPSrvPair::IPSrvPair(swoc::IP6Addr const &a6, in_port_t port) : _ip6(swoc::IP6Srv(a6, port)) {}
+
+inline IPSrvPair::IPSrvPair(IPAddrPair const &a, in_port_t port)
+{
+  if (a.has_ip4()) {
+    _ip4 = swoc::IP4Srv(a.ip4(), port);
+  } else if (a.has_ip6()) {
+    _ip6 = swoc::IP6Srv(a.ip6(), port);
+  }
+}
+
+inline bool
+IPSrvPair::has_value() const
+{
+  return _ip4.has_value() || _ip6.has_value();
+}
+
+inline bool
+IPSrvPair::has_ip4() const
+{
+  return _ip4.has_value();
+}
+
+inline bool
+IPSrvPair::has_ip6() const
+{
+  return _ip6.has_value();
+}
+
+inline swoc::IP4Srv const &
+IPSrvPair::ip4() const
+{
+  return _ip4.value();
+}
+
+inline swoc::IP6Srv const &
+IPSrvPair::ip6() const
+{
+  return _ip6.value();
+}
+
+inline auto
+IPSrvPair::operator=(swoc::IP4Srv const &srv) -> self_type &
+{
+  _ip4 = srv;
+  return *this;
+}
+
+inline auto
+IPSrvPair::operator=(swoc::IP6Srv const &srv) -> self_type &
+{
+  _ip6 = srv;
+  return *this;
+}
+
+inline auto
+IPSrvPair::operator=(swoc::IPSrv const &srv) -> self_type &
+{
+  if (srv.is_ip4()) {
+    _ip4 = srv.ip4();
+  } else if (srv.is_ip6()) {
+    _ip6 = srv.ip6();
+  }
+  return *this;
+}
+
+/** Get the best address info for @a name.
+
+ * @param name Address / host.
+ * @param ip4 [out] Best IPv4 result, if any.
+ * @param ip6 [out] Best IPv6 result, if any.
+ * @return @c true if an address was found, @c false if not.
+ *
+ * If @a name is a valid IP address it is interpreted as such. Otherwise it is presumed
+ * to be a host name suitable for resolution using @c getaddrinfo. The "best" address is
+ * selected by ranking the types of addresss in the order
+ *
+ * - Global, multi-cast, non-routable (private), link local, loopback
+ *
+ * For a host name, both IPv4 and IPv6 addresses may be returned. Each is judged
+ * independently.
+ *
+ * Either @a ip4 or @ip6 can be @c nullptr in which that result is discarded.
+ *
+ * @note If @name is known or required to be an IP address, use a standard address conversion
+ * instead, e.g. @c IPAddr::load .
+ *
+ * @see getaddrinfo
+ */
+IPAddrPair getbestaddrinfo(swoc::TextView name);
+
+/** Get the best address info for @a name.
+
+ * @param name Address / host.
+ * @param ip4 [out] Best IPv4 result, if any.
+ * @param ip6 [out] Best IPv6 result, if any.
+ * @return @c true if an address was found, @c false if not.
+ *
+ * If @a name is a valid IP address it is interpreted as such. Otherwise it is presumed
+ * to be a host name suitable for resolution using @c getaddrinfo. The "best" address is
+ * selected by ranking the types of addresss in the order
+ *
+ * - Global, multi-cast, non-routable (private), link local, loopback
+ *
+ * For a host name, both IPv4 and IPv6 addresses may be returned. Each is judged
+ * independently.
+ *
+ * Either @a ip4 or @ip6 can be @c nullptr in which that result is discarded.
+ *
+ * @note If @name is known or required to be an IP address, use a standard address conversion
+ * instead, e.g. @c IPAddr::load .
+ *
+ * @see getaddrinfo
+ */
+IPSrvPair getbestsrvinfo(swoc::TextView name);
+
+/** An IPSpace that only tracks the presence of IP addresses.
+ *
+ * @note Because there is only one value stored, there is no difference between @c mark and @c fill.

Review Comment:
   Aren't there a range of values?



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: github-unsubscribe@trafficserver.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org