fd/intf: Add sendto / recvfrom operations

Change-Id: I2f3f20cb79e806aa665cc3b7e5823cbf3d71034a
Signed-off-by: William A. Kennington III <wak@google.com>
diff --git a/include-fd/stdplus/fd/gmock.hpp b/include-fd/stdplus/fd/gmock.hpp
index 2349e44..29f8150 100644
--- a/include-fd/stdplus/fd/gmock.hpp
+++ b/include-fd/stdplus/fd/gmock.hpp
@@ -15,10 +15,19 @@
                 (override));
     MOCK_METHOD(std::span<std::byte>, recv,
                 (std::span<std::byte> buf, RecvFlags flags), (override));
+    MOCK_METHOD((std::tuple<std::span<std::byte>, std::span<std::byte>>),
+                recvfrom,
+                (std::span<std::byte> buf, RecvFlags flags,
+                 std::span<std::byte> sockaddr),
+                (override));
     MOCK_METHOD(std::span<const std::byte>, write,
                 (std::span<const std::byte> data), (override));
     MOCK_METHOD(std::span<const std::byte>, send,
                 (std::span<const std::byte> data, SendFlags flags), (override));
+    MOCK_METHOD(std::span<const std::byte>, sendto,
+                (std::span<const std::byte> data, SendFlags flags,
+                 std::span<const std::byte> sockaddr),
+                (override));
     MOCK_METHOD(size_t, lseek, (off_t offset, Whence whence), (override));
     MOCK_METHOD(void, truncate, (off_t size), (override));
     MOCK_METHOD(void, bind, (std::span<const std::byte> sockaddr), (override));
diff --git a/include-fd/stdplus/fd/impl.hpp b/include-fd/stdplus/fd/impl.hpp
index bd8c4dc..1393340 100644
--- a/include-fd/stdplus/fd/impl.hpp
+++ b/include-fd/stdplus/fd/impl.hpp
@@ -14,9 +14,15 @@
     std::span<std::byte> read(std::span<std::byte> buf) override;
     std::span<std::byte> recv(std::span<std::byte> buf,
                               RecvFlags flags) override;
+    std::tuple<std::span<std::byte>, std::span<std::byte>>
+        recvfrom(std::span<std::byte> buf, RecvFlags flags,
+                 std::span<std::byte> sockaddr) override;
     std::span<const std::byte> write(std::span<const std::byte> data) override;
     std::span<const std::byte> send(std::span<const std::byte> data,
                                     SendFlags flags) override;
+    std::span<const std::byte>
+        sendto(std::span<const std::byte> data, SendFlags flags,
+               std::span<const std::byte> sockaddr) override;
     size_t lseek(off_t offset, Whence whence) override;
     void truncate(off_t size) override;
     void bind(std::span<const std::byte> sockaddr) override;
diff --git a/include-fd/stdplus/fd/intf.hpp b/include-fd/stdplus/fd/intf.hpp
index 9faff66..0b33744 100644
--- a/include-fd/stdplus/fd/intf.hpp
+++ b/include-fd/stdplus/fd/intf.hpp
@@ -121,10 +121,16 @@
     virtual std::span<std::byte> read(std::span<std::byte> buf) = 0;
     virtual std::span<std::byte> recv(std::span<std::byte> buf,
                                       RecvFlags flags) = 0;
+    virtual std::tuple<std::span<std::byte>, std::span<std::byte>>
+        recvfrom(std::span<std::byte> buf, RecvFlags flags,
+                 std::span<std::byte> sockaddr) = 0;
     virtual std::span<const std::byte>
         write(std::span<const std::byte> data) = 0;
     virtual std::span<const std::byte> send(std::span<const std::byte> data,
                                             SendFlags flags) = 0;
+    virtual std::span<const std::byte>
+        sendto(std::span<const std::byte> data, SendFlags flags,
+               std::span<const std::byte> sockaddr) = 0;
     virtual size_t lseek(off_t offset, Whence whence) = 0;
     virtual void truncate(off_t size) = 0;
     virtual void bind(std::span<const std::byte> sockaddr) = 0;
diff --git a/src/fd/impl.cpp b/src/fd/impl.cpp
index 1ac9938..22a1b3b 100644
--- a/src/fd/impl.cpp
+++ b/src/fd/impl.cpp
@@ -46,6 +46,19 @@
                 ::recv(get(), buf.data(), buf.size(), static_cast<int>(flags)));
 }
 
+std::tuple<std::span<std::byte>, std::span<std::byte>>
+    FdImpl::recvfrom(std::span<std::byte> buf, RecvFlags flags,
+                     std::span<std::byte> sockaddr)
+{
+    socklen_t sockaddrsize = sockaddr.size();
+    auto ret =
+        fret(buf, "recvfrom",
+             ::recvfrom(get(), buf.data(), buf.size(), static_cast<int>(flags),
+                        reinterpret_cast<struct sockaddr*>(sockaddr.data()),
+                        &sockaddrsize));
+    return std::make_tuple(ret, sockaddr.subspan(0, sockaddrsize));
+}
+
 std::span<const std::byte> FdImpl::write(std::span<const std::byte> data)
 {
     return fret(data, "write", ::write(get(), data.data(), data.size()));
@@ -59,6 +72,17 @@
         ::send(get(), data.data(), data.size(), static_cast<int>(flags)));
 }
 
+std::span<const std::byte> FdImpl::sendto(std::span<const std::byte> data,
+                                          SendFlags flags,
+                                          std::span<const std::byte> sockaddr)
+{
+    return fret(
+        data, "sendto",
+        ::sendto(get(), data.data(), data.size(), static_cast<int>(flags),
+                 reinterpret_cast<const struct sockaddr*>(sockaddr.data()),
+                 sockaddr.size()));
+}
+
 static std::string_view whenceStr(Whence whence)
 {
     switch (whence)