fd/ops: Add sendto / recvfrom helpers
Change-Id: I19311c43b2b310831d9a57c699e4461552911393
Signed-off-by: William A. Kennington III <wak@google.com>
diff --git a/include-fd/stdplus/fd/ops.hpp b/include-fd/stdplus/fd/ops.hpp
index c2def78..7dc47ef 100644
--- a/include-fd/stdplus/fd/ops.hpp
+++ b/include-fd/stdplus/fd/ops.hpp
@@ -18,6 +18,8 @@
void recvExact(Fd& fd, std::span<std::byte> data, RecvFlags flags);
void writeExact(Fd& fd, std::span<const std::byte> data);
void sendExact(Fd& fd, std::span<const std::byte> data, SendFlags flags);
+void sendtoExact(Fd& fd, std::span<const std::byte> data, SendFlags flags,
+ std::span<const std::byte> addr);
std::span<std::byte> readAligned(Fd& fd, size_t align,
std::span<std::byte> buf);
@@ -55,6 +57,18 @@
}
template <typename Container>
+auto recvfrom(Fd& fd, Container&& c, SockAddrBuf& addr, RecvFlags flags = {})
+{
+ using Data = raw::detail::dataType<Container>;
+ auto ret = fd.recvfrom(
+ raw::asSpan<std::byte>(c), flags,
+ std::span(reinterpret_cast<std::byte*>(&addr), addr.maxLen));
+ addr.len = std::get<1>(ret).size();
+ return std::span<Data>(std::begin(c),
+ std::get<0>(ret).size() / sizeof(Data));
+}
+
+template <typename Container>
inline auto write(Fd& fd, Container&& c)
{
return detail::alignedOp(detail::writeAligned, fd,
@@ -68,6 +82,17 @@
std::forward<Container>(c), flags);
}
+template <typename Container>
+auto sendto(Fd& fd, Container&& c, const SockAddrBuf& addr,
+ SendFlags flags = {})
+{
+ using Data = raw::detail::dataType<Container>;
+ auto ret = fd.sendto(
+ raw::asSpan<std::byte>(c), flags,
+ std::span(reinterpret_cast<const std::byte*>(&addr), addr.len));
+ return std::span<Data>(std::begin(c), ret.size() / sizeof(Data));
+}
+
template <typename T>
inline void readExact(Fd& fd, T&& t)
{
@@ -92,6 +117,15 @@
detail::sendExact(fd, raw::asSpan<std::byte>(t), flags);
}
+template <typename Container>
+inline void sendtoExact(Fd& fd, Container&& c, const SockAddrBuf& addr,
+ SendFlags flags = {})
+{
+ detail::sendtoExact(
+ fd, raw::asSpan<std::byte>(c), flags,
+ std::span(reinterpret_cast<const std::byte*>(&addr), addr.len));
+}
+
inline size_t lseek(Fd& fd, off_t offset, Whence whence)
{
return fd.lseek(offset, whence);
diff --git a/src/fd/ops.cpp b/src/fd/ops.cpp
index d18e855..c299ed0 100644
--- a/src/fd/ops.cpp
+++ b/src/fd/ops.cpp
@@ -61,6 +61,20 @@
opExact("sendExact", &Fd::send, fd, data, flags);
}
+void sendtoExact(Fd& fd, std::span<const std::byte> data, SendFlags flags,
+ std::span<const std::byte> addr)
+{
+ auto r = fd.sendto(data, flags, addr);
+ if (r.size() == 0)
+ {
+ throw exception::WouldBlock("sendto");
+ }
+ if (r.size() < data.size())
+ {
+ throw exception::Incomplete("sendto");
+ }
+}
+
template <typename Fun, typename Byte, typename... Args>
static std::span<Byte> opAligned(const char* name, Fun&& fun, Fd& fd,
size_t align, std::span<Byte> data,