Time Shield Library
C++ library for working with time
Toggle main menu visibility
Loading...
Searching...
No Matches
udp_transport_posix.hpp
Go to the documentation of this file.
1
// SPDX-License-Identifier: MIT
2
#pragma once
3
#ifndef TIME_SHIELD_HEADER_TIME_SHIELD_NTP_CLIENT_UDP_TRANSPORT_POSIX_HPP_INCLUDED
4
#define TIME_SHIELD_HEADER_TIME_SHIELD_NTP_CLIENT_UDP_TRANSPORT_POSIX_HPP_INCLUDED
5
6
#if TIME_SHIELD_PLATFORM_UNIX
7
8
#include "
udp_transport.hpp
"
9
10
#include <arpa/inet.h>
11
#include <netdb.h>
12
#include <netinet/in.h>
13
#include <sys/socket.h>
14
#include <unistd.h>
15
#include <cerrno>
16
#include <cstring>
17
18
namespace
time_shield
{
19
namespace
detail
{
20
22
class
UdpTransportPosix
:
public
IUdpTransport
{
23
public
:
25
bool
transact
(
const
UdpRequest
& req,
int
& out_error_code)
noexcept
override
{
26
out_error_code = 0;
27
const
int
sock = ::socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
28
if
(sock < 0) {
29
out_error_code = errno;
30
return
false
;
31
}
32
33
addrinfo hints{}, *res =
nullptr
;
34
hints.ai_family = AF_INET;
35
hints.ai_socktype = SOCK_DGRAM;
36
hints.ai_protocol = IPPROTO_UDP;
37
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;
41
::close(sock);
42
return
false
;
43
}
44
45
sockaddr_in addr{};
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;
49
freeaddrinfo(res);
50
res =
nullptr
;
51
52
const
int
timeout_ms = req.timeout_ms > 0 ? req.timeout_ms : 5000;
53
timeval tv;
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));
57
58
const
ssize_t sent = ::sendto(sock,
59
req.send_data,
60
req.send_size,
61
0,
62
reinterpret_cast<
sockaddr*
>
(&addr),
63
sizeof
(addr));
64
if
(sent < 0 ||
static_cast<
std::size_t
>
(sent) != req.send_size) {
65
out_error_code = errno;
66
::close(sock);
67
return
false
;
68
}
69
70
sockaddr_in from{};
71
socklen_t from_len =
sizeof
(from);
72
const
ssize_t received = ::recvfrom(sock,
73
req.recv_data,
74
req.recv_size,
75
0,
76
reinterpret_cast<
sockaddr*
>
(&from),
77
&from_len);
78
79
if
(received < 0 ||
static_cast<
std::size_t
>
(received) != req.recv_size) {
80
out_error_code = errno;
81
::close(sock);
82
return
false
;
83
}
84
85
::close(sock);
86
return
true
;
87
}
88
};
89
90
}
// namespace detail
91
}
// namespace time_shield
92
93
#endif
// _TIME_SHIELD_PLATFORM_UNIX
94
95
#endif
// TIME_SHIELD_HEADER_TIME_SHIELD_NTP_CLIENT_UDP_TRANSPORT_POSIX_HPP_INCLUDED
time_shield::detail::IUdpTransport
Abstract UDP transport interface for NTP queries.
Definition
udp_transport.hpp:24
time_shield::detail::UdpTransportPosix
POSIX UDP transport for NTP queries.
Definition
udp_transport_posix.hpp:22
time_shield::detail::UdpTransportPosix::transact
bool transact(const UdpRequest &req, int &out_error_code) noexcept override
Send request and receive response over UDP.
Definition
udp_transport_posix.hpp:25
time_shield::detail
Definition
fast_date.hpp:14
time_shield
Main namespace for the Time Shield library.
time_shield::detail::UdpRequest
UDP request parameters for NTP transactions.
Definition
udp_transport.hpp:13
udp_transport.hpp
include
time_shield
ntp_client
udp_transport_posix.hpp
Generated by
1.17.0