ntptun/src/UdpSocket.cpp
2026-07-24 17:15:46 +02:00

115 lines
2.9 KiB
C++

#include "ntptun/UdpSocket.hpp"
#include <cstring>
#include "ntptun/Platform.hpp"
namespace ntptun {
UdpSocket::~UdpSocket() { close_fd(); }
UdpSocket::UdpSocket(UdpSocket&& other) noexcept : fd_(other.fd_) {
other.fd_ = kInvalidSocket;
}
UdpSocket& UdpSocket::operator=(UdpSocket&& other) noexcept {
if (this != &other) {
close_fd();
fd_ = other.fd_;
other.fd_ = kInvalidSocket;
}
return *this;
}
void UdpSocket::close_fd() noexcept {
if (fd_ != kInvalidSocket) {
socket_close(fd_);
fd_ = kInvalidSocket;
}
}
UdpSocket UdpSocket::create(int family) {
net_startup();
const socket_t fd = ::socket(family, SOCK_DGRAM, IPPROTO_UDP);
if (fd == kInvalidSocket) {
socket_throw("socket");
}
return UdpSocket(fd);
}
UdpSocket UdpSocket::bind(const Endpoint& local) {
UdpSocket sock = create(local.family());
const int one = 1;
::setsockopt(sock.fd_, SOL_SOCKET, SO_REUSEADDR,
reinterpret_cast<const char*>(&one), sizeof(one));
if (::bind(sock.fd_, local.sockaddr_ptr(), local.length()) != 0) {
socket_throw("bind");
}
return sock;
}
void UdpSocket::connect(const Endpoint& remote) {
if (::connect(fd_, remote.sockaddr_ptr(), remote.length()) != 0) {
socket_throw("connect");
}
}
void UdpSocket::set_nonblocking(bool enabled) {
socket_set_nonblocking(fd_, enabled);
}
ssize_t UdpSocket::recv_from(Byte* buf, std::size_t len, Endpoint& from) {
sockaddr_storage src{};
socklen_t src_len = sizeof(src);
const ssize_t n =
::recvfrom(fd_, reinterpret_cast<char*>(buf), static_cast<int>(len), 0,
reinterpret_cast<sockaddr*>(&src), &src_len);
if (n < 0) {
if (socket_would_block()) {
return -1;
}
socket_throw("recvfrom");
}
std::memcpy(from.sockaddr_ptr(), &src, src_len);
from.set_length(src_len);
return n;
}
ssize_t UdpSocket::send_to(const Byte* buf, std::size_t len, const Endpoint& to) {
const ssize_t n =
::sendto(fd_, reinterpret_cast<const char*>(buf), static_cast<int>(len), 0,
to.sockaddr_ptr(), to.length());
if (n < 0) {
if (socket_would_block()) {
return -1;
}
socket_throw("sendto");
}
return n;
}
ssize_t UdpSocket::recv(Byte* buf, std::size_t len) {
const ssize_t n =
::recv(fd_, reinterpret_cast<char*>(buf), static_cast<int>(len), 0);
if (n < 0) {
if (socket_would_block()) {
return -1;
}
socket_throw("recv");
}
return n;
}
ssize_t UdpSocket::send(const Byte* buf, std::size_t len) {
const ssize_t n =
::send(fd_, reinterpret_cast<const char*>(buf), static_cast<int>(len), 0);
if (n < 0) {
if (socket_would_block()) {
return -1;
}
socket_throw("send");
}
return n;
}
} // namespace ntptun