Change pointers to absl::optional where possible

This changelist adds a targeted pull of the absl::optional type,
replacing raw pointers where feasible, using the rules suggested
in the abseil documentation:

https://abseil.io/tips/123

There are remaining raw pointers, however I believe that these
should be changed to std::unique_ptr or simple references,
due to their scope and complexity. These cases include the following:

api/impl
* internal_services (Singleton)

api/impl/quic
* quic_connection
* quic_connection_factory
* quic_service_common
* fake_quic_connection_factory
* fake_quic_connection

api/public
* network_service_manager
* presentation_controller
* presentation_receiver

discovery/mdns
* mdns_responder*platform

tools/cddl
* codegen
* parse
* sema

Bug: openscreen:4
Change-Id: Id330a1b6529531b52e9d77f3a6f1b375f5a048d3
Reviewed-on: https://chromium-review.googlesource.com/c/1412262
Commit-Queue: Jordan Bayles <jophba@chromium.org>
Reviewed-by: Brandon Tolsch <btolsch@chromium.org>
Reviewed-by: mark a. foltz <mfoltz@chromium.org>
diff --git a/.gitmodules b/.gitmodules
index 5df9ce2..984ed1f 100644
--- a/.gitmodules
+++ b/.gitmodules
@@ -15,3 +15,6 @@
 [submodule "third_party/tinycbor/src"]
 	path = third_party/tinycbor/src
 	url = https://github.com/intel/tinycbor.git
+[submodule "third_party/abseil/src"]
+	path = third_party/abseil/src
+	url = https://github.com/abseil/abseil-cpp.git
diff --git a/BUILD.gn b/BUILD.gn
index 14c270a..ec221f7 100644
--- a/BUILD.gn
+++ b/BUILD.gn
@@ -11,6 +11,7 @@
     "//discovery/mdns:embedder_demo",
     "//platform",
     "//sample:hello",
+    "//third_party/abseil",
     "//third_party/chromium_quic",
     "//third_party/chromium_quic:demo_client",
     "//third_party/chromium_quic:demo_server",
@@ -52,6 +53,7 @@
     "//discovery/mdns:mdns_unittests",
     "//msgs:unittests",
     "//sample:hello_unittests",
+    "//third_party/abseil",
     "//third_party/googletest:gtest_main",
   ]
 }
diff --git a/api/BUILD.gn b/api/BUILD.gn
index c6ca314..d53a4df 100644
--- a/api/BUILD.gn
+++ b/api/BUILD.gn
@@ -40,6 +40,7 @@
     "impl/quic:test_support",
     "impl/testing",
     "impl/testing:fakes_unittests",
+    "//third_party/abseil",
     "//third_party/googletest:gmock",
     "//third_party/googletest:gtest",
   ]
diff --git a/api/impl/quic/quic_connection_impl.cc b/api/impl/quic/quic_connection_impl.cc
index 884c9c2..1ca2e63 100644
--- a/api/impl/quic/quic_connection_impl.cc
+++ b/api/impl/quic/quic_connection_impl.cc
@@ -6,6 +6,7 @@
 
 #include "api/impl/quic/quic_connection_factory_impl.h"
 #include "base/make_unique.h"
+#include "third_party/abseil/src/absl/types/optional.h"
 #include "third_party/chromium_quic/src/net/third_party/quic/platform/impl/quic_chromium_clock.h"
 
 namespace openscreen {
@@ -21,7 +22,8 @@
 int UdpTransport::Write(const char* buffer,
                         size_t buffer_length,
                         const PacketInfo& info) {
-  return platform::SendUdp(socket_, buffer, buffer_length, destination_);
+  return platform::SendUdp(socket_, buffer, buffer_length, destination_)
+      .value_or(-1);
 }
 
 QuicStreamImpl::QuicStreamImpl(QuicStream::Delegate* delegate,
diff --git a/api/impl/testing/BUILD.gn b/api/impl/testing/BUILD.gn
index a6aaeea..db6084e 100644
--- a/api/impl/testing/BUILD.gn
+++ b/api/impl/testing/BUILD.gn
@@ -28,6 +28,7 @@
 
   deps = [
     ":testing",
+    "//third_party/abseil",
     "//third_party/googletest:gtest",
   ]
 }
diff --git a/base/BUILD.gn b/base/BUILD.gn
index 55db4f5..90ed46f 100644
--- a/base/BUILD.gn
+++ b/base/BUILD.gn
@@ -17,6 +17,10 @@
     "with_destruction_callback.cc",
     "with_destruction_callback.h",
   ]
+
+  deps = [
+    "//third_party/abseil",
+  ]
 }
 
 source_set("base_unittests") {
diff --git a/base/ip_address.cc b/base/ip_address.cc
index 5fde169..4ae688c 100644
--- a/base/ip_address.cc
+++ b/base/ip_address.cc
@@ -8,6 +8,7 @@
 #include <iomanip>
 
 #include "platform/api/logging.h"
+#include "third_party/abseil/src/absl/types/optional.h"
 
 namespace openscreen {
 
@@ -146,12 +147,12 @@
   uint8_t values[16];
   int i = 0;
   int num_previous_colons = 0;
-  int double_colon_index = -1;
+  absl::optional<int> double_colon_index = absl::nullopt;
   for (auto c : s) {
     if (c == ':') {
       ++num_previous_colons;
       if (num_previous_colons == 2) {
-        if (double_colon_index != -1) {
+        if (double_colon_index) {
           return false;
         }
         double_colon_index = i;
@@ -189,12 +190,11 @@
 
   values[i++] = static_cast<uint8_t>(next_value >> 8);
   values[i] = static_cast<uint8_t>(next_value & 0xff);
-  if (!((i == 15 && double_colon_index == -1) ||
-        (i < 14 && double_colon_index != -1))) {
+  if (!((i == 15 && !double_colon_index) || (i < 14 && double_colon_index))) {
     return false;
   }
   for (int j = 15; j >= 0;) {
-    if (i == double_colon_index) {
+    if (double_colon_index && (i == double_colon_index)) {
       address->bytes_[j--] = values[i--];
       while (j > i)
         address->bytes_[j--] = 0;
diff --git a/platform/BUILD.gn b/platform/BUILD.gn
index fbfc310..08a93d3 100644
--- a/platform/BUILD.gn
+++ b/platform/BUILD.gn
@@ -12,4 +12,8 @@
   } else if (is_mac) {
     deps += [ "mac" ]
   }
+
+  public_deps = [
+    "//third_party/abseil",
+  ]
 }
diff --git a/platform/api/BUILD.gn b/platform/api/BUILD.gn
index 65fb04d..8900278 100644
--- a/platform/api/BUILD.gn
+++ b/platform/api/BUILD.gn
@@ -17,5 +17,6 @@
 
   public_deps = [
     "//base",
+    "//third_party/abseil",
   ]
 }
diff --git a/platform/api/socket.h b/platform/api/socket.h
index a97d1d6..caa57e9 100644
--- a/platform/api/socket.h
+++ b/platform/api/socket.h
@@ -7,6 +7,7 @@
 
 #include "base/ip_address.h"
 #include "platform/api/network_interface.h"
+#include "third_party/abseil/src/absl/types/optional.h"
 
 namespace openscreen {
 namespace platform {
@@ -35,15 +36,15 @@
                            const IPAddress& address,
                            InterfaceIndex ifindex);
 
-int64_t ReceiveUdp(UdpSocketPtr socket,
-                   void* data,
-                   int64_t length,
-                   IPEndpoint* src,
-                   IPEndpoint* original_destination);
-int64_t SendUdp(UdpSocketPtr socket,
-                const void* data,
-                int64_t length,
-                const IPEndpoint& dest);
+absl::optional<int64_t> ReceiveUdp(UdpSocketPtr socket,
+                                   void* data,
+                                   int64_t length,
+                                   IPEndpoint* src,
+                                   IPEndpoint* original_destination);
+absl::optional<int64_t> SendUdp(UdpSocketPtr socket,
+                                const void* data,
+                                int64_t length,
+                                const IPEndpoint& dest);
 
 }  // namespace platform
 }  // namespace openscreen
diff --git a/platform/base/event_loop.cc b/platform/base/event_loop.cc
index 2abd089..d4b7c84 100644
--- a/platform/base/event_loop.cc
+++ b/platform/base/event_loop.cc
@@ -17,18 +17,18 @@
 bool ReceiveDataFromEvent(const UdpSocketReadableEvent& read_event,
                           ReceivedData* data) {
   OSP_DCHECK(data);
-  ssize_t len =
+  absl::optional<int> len =
       ReceiveUdp(read_event.socket, &data->bytes[0], data->bytes.size(),
                  &data->source, &data->original_destination);
-  if (len == -1) {
+  if (!len) {
     OSP_LOG_ERROR << "recv() failed: " << GetLastErrorString();
     return false;
   } else if (len == 0) {
     OSP_LOG_WARN << "recv() = 0, closed?";
     return false;
   }
-  OSP_DCHECK_LE(len, kUdpMaxPacketSize);
-  data->length = len;
+  OSP_DCHECK_LE(*len, kUdpMaxPacketSize);
+  data->length = *len;
   data->socket = read_event.socket;
   return true;
 }
diff --git a/platform/linux/network_interface.cc b/platform/linux/network_interface.cc
index c4a8c05..81d4f08 100644
--- a/platform/linux/network_interface.cc
+++ b/platform/linux/network_interface.cc
@@ -99,7 +99,7 @@
   info->type = GetInterfaceType(info->name);
 }
 
-InterfaceAddresses* GetAddressesForIndex(
+InterfaceAddresses* FindOrAddAddressesForIndex(
     std::vector<InterfaceAddresses>* address_list,
     const std::vector<InterfaceInfo>& info_list,
     InterfaceIndex index) {
@@ -360,7 +360,7 @@
 
         struct ifaddrmsg* interface_address =
             static_cast<struct ifaddrmsg*>(NLMSG_DATA(netlink_header));
-        InterfaceAddresses* addresses = GetAddressesForIndex(
+        InterfaceAddresses* addresses = FindOrAddAddressesForIndex(
             &address_list, info_list, interface_address->ifa_index);
         if (!addresses) {
           OSP_DVLOG(1) << "skipping address for interface "
diff --git a/platform/mac/network_interface.cc b/platform/mac/network_interface.cc
index 07c8251..c36cc8d 100644
--- a/platform/mac/network_interface.cc
+++ b/platform/mac/network_interface.cc
@@ -21,6 +21,7 @@
 
 #include "base/ip_address.h"
 #include "base/scoped_pipe.h"
+#include "platform/api/logging.h"
 
 namespace openscreen {
 namespace platform {
@@ -35,27 +36,32 @@
 uint8_t ToPrefixLength(const uint8_t (&netmask)[N]) {
   uint8_t result = 0;
   size_t i = 0;
+
+  // Ensure all of the leftmost bits are set.
   while (i < N && netmask[i] == UINT8_C(0xff)) {
     result += 8;
     ++i;
   }
-  if (i < N) {
+
+  // Check the intermediate byte, the first that is not 0xFF,
+  // e.g. 0b11100000 or 0x00
+  if (i < N && netmask[i] != UINT8_C(0x00)) {
     uint8_t last_byte = netmask[i];
+    // Check the left most bit, bitshifting as we go.
     while (last_byte & UINT8_C(0x80)) {
       ++result;
       last_byte <<= 1;
     }
-    if (last_byte != UINT8_C(0x00)) {
-      return -1;
-    }
+    OSP_CHECK(last_byte == UINT8_C(0x00));
     ++i;
   }
+
+  // Ensure the rest of the bytes are zeroed out.
   while (i < N) {
-    if (netmask[i] != 0) {
-      return -1;
-    }
+    OSP_CHECK(netmask[i] == UINT8_C(0x00));
     ++i;
   }
+
   return result;
 }
 
diff --git a/platform/posix/socket.cc b/platform/posix/socket.cc
index 7be9679..9243eae 100644
--- a/platform/posix/socket.cc
+++ b/platform/posix/socket.cc
@@ -17,6 +17,8 @@
 #include "platform/api/logging.h"
 #include "platform/posix/socket.h"
 
+#include "third_party/abseil/src/absl/types/optional.h"
+
 namespace openscreen {
 namespace platform {
 namespace {
@@ -31,16 +33,16 @@
 using IPv4InterfaceIndex = decltype(ip_mreqn().imr_ifindex);
 using IPv6InterfaceIndex = decltype(ipv6_mreq().ipv6mr_interface);
 
-int CreateNonBlockingUdpSocket(int domain) {
+absl::optional<int> CreateNonBlockingUdpSocket(int domain) {
   const int fd = socket(domain, SOCK_DGRAM, 0);
   if (fd == -1) {
-    return -1;
+    return absl::nullopt;
   }
   // On non-Linux, the SOCK_NONBLOCK option is not available, so use the
   // more-portable method of calling fcntl() to set this behavior.
   if (fcntl(fd, F_SETFL, fcntl(fd, F_GETFL, 0) | O_NONBLOCK) == -1) {
     close(fd);
-    return -1;
+    return absl::nullopt;
   }
   return fd;
 }
@@ -48,15 +50,15 @@
 }  // namespace
 
 UdpSocketPtr CreateUdpSocketIPv4() {
-  const int fd = CreateNonBlockingUdpSocket(AF_INET);
-  return fd == -1 ? nullptr
-                  : new UdpSocketPrivate{fd, UdpSocketPrivate::Version::kV4};
+  const absl::optional<int> fd = CreateNonBlockingUdpSocket(AF_INET);
+  return fd ? new UdpSocketPrivate{fd.value(), UdpSocketPrivate::Version::kV4}
+            : nullptr;
 }
 
 UdpSocketPtr CreateUdpSocketIPv6() {
-  const int fd = CreateNonBlockingUdpSocket(AF_INET6);
-  return fd == -1 ? nullptr
-                  : new UdpSocketPrivate{fd, UdpSocketPrivate::Version::kV6};
+  const absl::optional<int> fd = CreateNonBlockingUdpSocket(AF_INET6);
+  return fd ? new UdpSocketPrivate{fd.value(), UdpSocketPrivate::Version::kV6}
+            : nullptr;
 }
 
 bool IsIPv4Socket(UdpSocketPtr socket) {
@@ -183,11 +185,11 @@
   }
 }
 
-int64_t ReceiveUdp(UdpSocketPtr socket,
-                   void* data,
-                   int64_t length,
-                   IPEndpoint* src,
-                   IPEndpoint* original_destination) {
+absl::optional<int64_t> ReceiveUdp(UdpSocketPtr socket,
+                                   void* data,
+                                   int64_t length,
+                                   IPEndpoint* src,
+                                   IPEndpoint* original_destination) {
   OSP_DCHECK_GE(socket->fd, 0);
   struct iovec iov = {data, static_cast<size_t>(length)};
   char control_buf[1024];
@@ -207,7 +209,7 @@
 
     int64_t len = recvmsg(socket->fd, &msg, 0);
     if (len < 0)
-      return len;
+      return absl::nullopt;
 
     src->address =
         IPAddress(IPAddress::Version::kV4,
@@ -245,7 +247,7 @@
       }
     }
 
-    return len;
+    return absl::optional<int>(len);
   } else {
     struct sockaddr_in6 sa;
     struct msghdr msg;
@@ -302,44 +304,45 @@
   }
 }
 
-int64_t SendUdp(UdpSocketPtr socket,
-                const void* data,
-                int64_t length,
-                const IPEndpoint& dest) {
+absl::optional<int64_t> SendUdp(UdpSocketPtr socket,
+                                const void* data,
+                                int64_t length,
+                                const IPEndpoint& dest) {
   OSP_DCHECK_GE(socket->fd, 0);
+
+  struct msghdr msg;
+  msg.msg_iovlen = 1;
+  msg.msg_control = nullptr;
+  msg.msg_controllen = 0;
+  msg.msg_flags = 0;
+
   if (socket->version == UdpSocketPrivate::Version::kV4) {
     struct sockaddr_in sa = {
         .sin_family = AF_INET,
         .sin_port = htons(dest.port),
     };
-    dest.address.CopyToV4(reinterpret_cast<uint8_t*>(&sa.sin_addr.s_addr));
-    struct iovec iov = {const_cast<void*>(data), static_cast<size_t>(length)};
-    struct msghdr msg;
     msg.msg_name = &sa;
     msg.msg_namelen = sizeof(sa);
+
+    dest.address.CopyToV4(reinterpret_cast<uint8_t*>(&sa.sin_addr.s_addr));
+    struct iovec iov = {const_cast<void*>(data), static_cast<size_t>(length)};
     msg.msg_iov = &iov;
-    msg.msg_iovlen = 1;
-    msg.msg_control = nullptr;
-    msg.msg_controllen = 0;
-    msg.msg_flags = 0;
-    return sendmsg(socket->fd, &msg, 0);
   } else {
     struct sockaddr_in6 sa = {
         .sin6_family = AF_INET6,
         .sin6_port = htons(dest.port),
     };
-    dest.address.CopyToV6(reinterpret_cast<uint8_t*>(&sa.sin6_addr.s6_addr));
-    struct iovec iov = {const_cast<void*>(data), static_cast<size_t>(length)};
-    struct msghdr msg;
     msg.msg_name = &sa;
     msg.msg_namelen = sizeof(sa);
+
+    dest.address.CopyToV6(reinterpret_cast<uint8_t*>(&sa.sin6_addr.s6_addr));
+    struct iovec iov = {const_cast<void*>(data), static_cast<size_t>(length)};
     msg.msg_iov = &iov;
-    msg.msg_iovlen = 1;
-    msg.msg_control = nullptr;
-    msg.msg_controllen = 0;
-    msg.msg_flags = 0;
-    return sendmsg(socket->fd, &msg, 0);
   }
+
+  const int64_t return_value = sendmsg(socket->fd, &msg, 0);
+  return (return_value >= 0) ? absl::optional<int>(return_value)
+                             : absl::optional<int>();
 }
 
 }  // namespace platform
diff --git a/third_party/abseil/BUILD.gn b/third_party/abseil/BUILD.gn
new file mode 100644
index 0000000..d6e61b1
--- /dev/null
+++ b/third_party/abseil/BUILD.gn
@@ -0,0 +1,39 @@
+# Copyright 2018 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+config("abseil_config") {
+  include_dirs = [
+    "//third_party/abseil/src",
+  ]
+}
+
+source_set("abseil") {
+  sources = [
+    "src/absl/base/attributes.h",
+    "src/absl/base/config.h",
+    "src/absl/base/internal/atomic_hook.h",
+    "src/absl/base/internal/identity.h",
+    "src/absl/base/internal/inline_variable.h",
+    "src/absl/base/internal/invoke.h",
+    "src/absl/base/internal/raw_logging.cc",
+    "src/absl/base/internal/raw_logging.h",
+    "src/absl/base/log_severity.h",
+    "src/absl/base/macros.h",
+    "src/absl/base/optimization.h",
+    "src/absl/base/policy_checks.h",
+    "src/absl/base/port.h",
+    "src/absl/memory/memory.h",
+    "src/absl/meta/type_traits.h",
+    "src/absl/types/bad_optional_access.cc",
+    "src/absl/types/bad_optional_access.h",
+    "src/absl/types/optional.cc",
+    "src/absl/types/optional.h",
+  ]
+
+  configs -= [ "//build/config:symbol_visibility_hidden" ]
+  configs += [ "//build/config:symbol_visibility_default" ]
+  configs -= [ "//build:default_include_dirs" ]
+
+  public_configs = [":abseil_config"]
+}
diff --git a/third_party/abseil/src b/third_party/abseil/src
new file mode 160000
index 0000000..5eea0f7
--- /dev/null
+++ b/third_party/abseil/src
@@ -0,0 +1 @@
+Subproject commit 5eea0f713c14ac17788b83e496f11903f8e2bbb0