| 58 | static int64_t g_TimeOffset = 0; // in seconds |
| 59 | |
| 60 | static void SyncTimeWithNTP (const std::string& address) |
| 61 | { |
| 62 | LogPrint (eLogInfo, "Timestamp: NTP request to ", address); |
| 63 | boost::asio::io_context service; |
| 64 | boost::system::error_code ec; |
| 65 | auto endpoints = boost::asio::ip::udp::resolver (service).resolve (address, "ntp", ec); |
| 66 | if (!ec) |
| 67 | { |
| 68 | bool found = false; |
| 69 | boost::asio::ip::udp::endpoint ep; |
| 70 | for (const auto& it: endpoints) |
| 71 | { |
| 72 | ep = it; |
| 73 | if (!ep.address ().is_unspecified ()) |
| 74 | { |
| 75 | if (ep.address ().is_v4 ()) |
| 76 | { |
| 77 | if (i2p::context.SupportsV4 ()) found = true; |
| 78 | } |
| 79 | else if (ep.address ().is_v6 ()) |
| 80 | { |
| 81 | if (i2p::util::net::IsYggdrasilAddress (ep.address ())) |
| 82 | { |
| 83 | if (i2p::context.SupportsMesh ()) found = true; |
| 84 | } |
| 85 | else if (i2p::context.SupportsV6 ()) found = true; |
| 86 | } |
| 87 | } |
| 88 | if (found) break; |
| 89 | } |
| 90 | if (!found) |
| 91 | { |
| 92 | LogPrint (eLogError, "Timestamp: can't find compatible address for ", address); |
| 93 | return; |
| 94 | } |
| 95 | |
| 96 | boost::asio::ip::udp::socket socket (service); |
| 97 | socket.open (ep.protocol (), ec); |
| 98 | if (!ec) |
| 99 | { |
| 100 | uint8_t buf[48];// 48 bytes NTP request/response |
| 101 | memset (buf, 0, 48); |
| 102 | htobe32buf (buf, (3 << 27) | (3 << 24)); // RFC 4330 |
| 103 | size_t len = 0; |
| 104 | try |
| 105 | { |
| 106 | socket.send_to (boost::asio::buffer (buf, 48), ep); |
| 107 | int i = 0; |
| 108 | while (!socket.available() && i < 10) // 10 seconds max |
| 109 | { |
| 110 | std::this_thread::sleep_for (std::chrono::seconds(1)); |
| 111 | i++; |
| 112 | } |
| 113 | if (socket.available ()) |
| 114 | len = socket.receive_from (boost::asio::buffer (buf, 48), ep); |
| 115 | } |
| 116 | catch (std::exception& e) |
| 117 | { |
no test coverage detected