27 const int sock = ::socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
29 out_error_code = errno;
33 addrinfo hints{}, *res =
nullptr;
34 hints.ai_family = AF_INET;
35 hints.ai_socktype = SOCK_DGRAM;
36 hints.ai_protocol = IPPROTO_UDP;
38 const int resolve_code = getaddrinfo(req.host.c_str(),
nullptr, &hints, &res);
39 if (resolve_code != 0 || !res) {
40 out_error_code = (resolve_code != 0) ? resolve_code : errno;
46 addr.sin_family = AF_INET;
47 addr.sin_port = htons(
static_cast<uint16_t
>(req.port));
48 addr.sin_addr =
reinterpret_cast<sockaddr_in*
>(res->ai_addr)->sin_addr;
52 const int timeout_ms = req.timeout_ms > 0 ? req.timeout_ms : 5000;
54 tv.tv_sec = timeout_ms / 1000;
55 tv.tv_usec = (timeout_ms % 1000) * 1000;
56 ::setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, &tv,
sizeof(tv));
58 const ssize_t sent = ::sendto(sock,
62 reinterpret_cast<sockaddr*
>(&addr),
64 if (sent < 0 ||
static_cast<std::size_t
>(sent) != req.send_size) {
65 out_error_code = errno;
71 socklen_t from_len =
sizeof(from);
72 const ssize_t received = ::recvfrom(sock,
76 reinterpret_cast<sockaddr*
>(&from),
79 if (received < 0 ||
static_cast<std::size_t
>(received) != req.recv_size) {
80 out_error_code = errno;