| #pragma once |
| #include <stdplus/fd/dupable.hpp> |
| #include <stdplus/fd/intf.hpp> |
| #include <stdplus/net/addr/sock.hpp> |
| #include <stdplus/raw.hpp> |
| |
| #include <span> |
| #include <utility> |
| |
| namespace stdplus |
| { |
| namespace fd |
| { |
| namespace detail |
| { |
| |
| void readExact(Fd& fd, std::span<std::byte> data); |
| 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); |
| std::span<std::byte> recvAligned(Fd& fd, size_t align, std::span<std::byte> buf, |
| RecvFlags flags); |
| std::span<const std::byte> writeAligned(Fd& fd, size_t align, |
| std::span<const std::byte> data); |
| std::span<const std::byte> sendAligned(Fd& fd, size_t align, |
| std::span<const std::byte> data, |
| SendFlags flags); |
| |
| template <typename Fun, typename Container, typename... Args> |
| auto alignedOp(Fun&& fun, Fd& fd, Container&& c, Args&&... args) |
| { |
| using Data = raw::detail::dataType<Container>; |
| auto ret = fun(fd, sizeof(Data), raw::asSpan<std::byte>(c), |
| std::forward<Args>(args)...); |
| return std::span<Data>(std::begin(c), ret.size() / sizeof(Data)); |
| } |
| |
| } // namespace detail |
| |
| template <typename Container> |
| inline auto read(Fd& fd, Container&& c) |
| { |
| return detail::alignedOp(detail::readAligned, fd, |
| std::forward<Container>(c)); |
| } |
| |
| template <typename Container> |
| inline auto recv(Fd& fd, Container&& c, RecvFlags flags = {}) |
| { |
| return detail::alignedOp(detail::recvAligned, fd, |
| std::forward<Container>(c), flags); |
| } |
| |
| 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, |
| std::forward<Container>(c)); |
| } |
| |
| template <typename Container> |
| inline auto send(Fd& fd, Container&& c, SendFlags flags = {}) |
| { |
| return detail::alignedOp(detail::sendAligned, fd, |
| 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) |
| { |
| detail::readExact(fd, raw::asSpan<std::byte>(t)); |
| } |
| |
| template <typename T> |
| inline void recvExact(Fd& fd, T&& t, RecvFlags flags = {}) |
| { |
| detail::recvExact(fd, raw::asSpan<std::byte>(t), flags); |
| } |
| |
| template <typename T> |
| inline void writeExact(Fd& fd, T&& t) |
| { |
| detail::writeExact(fd, raw::asSpan<std::byte>(t)); |
| } |
| |
| template <typename T> |
| inline void sendExact(Fd& fd, T&& t, SendFlags flags = {}) |
| { |
| 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); |
| } |
| |
| inline void truncate(Fd& fd, off_t size) |
| { |
| return fd.truncate(size); |
| } |
| |
| inline void bind(Fd& fd, const SockAddrBuf& addr) |
| { |
| return fd.bind({reinterpret_cast<const std::byte*>(&addr), addr.len}); |
| } |
| |
| inline void bind(Fd& fd, const SockAddr auto& addr) |
| { |
| return bind(fd, addr.buf()); |
| } |
| |
| inline void bind(Fd& fd, const auto& sockaddr) |
| { |
| return fd.bind(raw::asSpan<std::byte>(sockaddr)); |
| } |
| |
| inline void connect(Fd& fd, const SockAddrBuf& addr) |
| { |
| return fd.connect({reinterpret_cast<const std::byte*>(&addr), addr.len}); |
| } |
| |
| inline void connect(Fd& fd, const SockAddr auto& addr) |
| { |
| return connect(fd, addr.buf()); |
| } |
| |
| inline void connect(Fd& fd, const auto& sockaddr) |
| { |
| return fd.connect(raw::asSpan<std::byte>(sockaddr)); |
| } |
| |
| inline void listen(Fd& fd, int backlog) |
| { |
| return fd.listen(backlog); |
| } |
| |
| inline std::optional<DupableFd> accept(Fd& fd) |
| { |
| auto ret = fd.accept(std::span<std::byte>{}); |
| if (!ret) |
| { |
| return std::nullopt; |
| } |
| return DupableFd(std::move(std::get<0>(*ret))); |
| } |
| |
| template <typename Opt> |
| inline void setsockopt(Fd& fd, SockLevel level, SockOpt optname, Opt&& opt) |
| { |
| return fd.setsockopt(level, optname, raw::asSpan<std::byte>(opt)); |
| } |
| |
| template <typename Data> |
| inline int constIoctl(const Fd& fd, unsigned long id, Data&& data) |
| { |
| return fd.constIoctl(id, raw::asSpan<std::byte>(data).data()); |
| } |
| |
| template <typename Data> |
| inline int ioctl(Fd& fd, unsigned long id, Data&& data) |
| { |
| return fd.ioctl(id, raw::asSpan<std::byte>(data).data()); |
| } |
| |
| inline FdFlags getFdFlags(const Fd& fd) |
| { |
| return fd.fcntlGetfd(); |
| } |
| |
| inline void setFdFlags(Fd& fd, FdFlags flags) |
| { |
| return fd.fcntlSetfd(flags); |
| } |
| |
| inline FileFlags getFileFlags(const Fd& fd) |
| { |
| return fd.fcntlGetfl(); |
| } |
| |
| inline void setFileFlags(Fd& fd, FileFlags flags) |
| { |
| return fd.fcntlSetfl(flags); |
| } |
| |
| } // namespace fd |
| } // namespace stdplus |