mirror of
https://gitlab.com/shadow_contributor/ntptun.git
synced 2026-10-03 03:46:50 +00:00
115 lines
2.9 KiB
C++
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
|