Files
utun2/src/ntp_time.h
T

69 lines
5.8 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/* ntp_time — асинхронные UDP NTP-запросы с DNS и периодическим повтором в uasync-потоке ядра.
* Не меняет часы ОС: хранит local_time - ntp_time в instance->ntp.offset_us.
* get_us/get_seconds возвращают скорректированное wall-clock время; до синхронизации — локальное.
* В uasync-потоке вызвать init после создания config/ua, destroy — до освобождения ua, вне callbacks модуля.
* Один цикл обходит серверы до первого успеха; на сервер — до трёх UDP-запросов с таймаутом 2 с.
* Между завершением цикла и следующим запуском — resync_interval_sec. DNS выполняется асинхронно (IPv4).
* enabled управляет только интернет-опросом; synced учитывает также коррекцию от ntp_node_time.
* destroy отменяет DNS/сокет/таймеры, сохраняя synced, offset_us и last_sync_tb. Часы ОС не меняются. */
#ifndef NTP_TIME_H
#define NTP_TIME_H
#include <stdint.h>
#include <time.h>
#include "../lib/platform_compat.h"
#ifdef __cplusplus
extern "C" {
#endif
struct UTUN_INSTANCE;
#define NTP_DEFAULT_INTERVAL_SEC 3600
#define NTP_FIRST_SYNC_DELAY_SEC 0
struct NTP_TIME {
int enabled; // интернет-опрос разрешён конфигом; 0 не запрещает коррекцию от пиров
int synced; // есть поправка от NTP или пира; не означает её свежесть/доступность интернета
int reachable; // успех последнего завершённого NTP-цикла; до первого результата = 1 (оптимистично)
int64_t offset_us; // local_time - reference_time, мкс; положительное = локальные часы спешат
uint64_t last_sync_tb; // монотонное время последней коррекции от NTP/пира, единицы 0,1 мс; 0 до синхронизации
void* timer; // таймер следующего цикла, NULL во время опроса/после остановки/при ошибке таймера
char **servers; // принадлежащие модулю копии IPv4-адресов/имён серверов, освобождаются destroy
int server_count; // число элементов servers; после destroy = 0
int server_current; // начальный индекс следующего цикла; после успеха — следующий за ответившим
int resync_interval_sec;// пауза после цикла, секунды; при активном опросе 1..INT_MAX/10000
struct sockaddr_in test_addr; // sin_port != 0: единственный сервер цикла, без DNS/перехода к servers
struct sockaddr_in test_dns; // sin_port != 0: IPv4 DNS-сервер для тестов
uint16_t test_port; // порт запросов к servers в тестах: 0 = 123; не влияет на test_addr
void* sync; // активный контекст синхронизации (struct ntp_sync*, opaque)
};
// Читает instance->config, копирует серверы, ставит таймер 0 (запуск при обработке uasync, не внутри init).
// instance/config/ua обязательны, состояние исходно нулевое либо после destroy; повторный активный init запрещён.
// 0 — успех (включая отключённый опрос/пустой список), -1 — ошибка с освобождением новых ресурсов.
// Ошибка повторного init сохраняет прежнее состояние. Повторная инициализация сбрасывает поправку и test_*.
int ntp_time_init(struct UTUN_INSTANCE* instance);
// Отменяет опрос и освобождает серверы; поправку/reachable сохраняет, enabled сбрасывает. NULL допустим.
void ntp_time_destroy(struct UTUN_INSTANCE* instance);
// После init, до первого poll задать IPv4-литерал ip и порт сервера; port=0 отключает подмену.
// Неверный ip сбрасывает test_addr; NULL ntp/ip игнорируется. Требуется непустой список серверов в конфиге.
void ntp_time_set_test_addr(struct NTP_TIME* ntp, const char* ip, uint16_t port);
// После init, до poll задать IPv4-литерал ip, dns_port (0 отключает подмену DNS) и ntp_port (0 = 123).
// Неверный ip сбрасывает test_dns и test_port; NULL ntp/ip игнорируется. test_addr имеет приоритет.
void ntp_time_set_test_dns(struct NTP_TIME* ntp, const char* ip, uint16_t dns_port, uint16_t ntp_port);
// Unix wall-clock в мкс: local - offset_us при synced, иначе локальное время; NULL возвращает локальное.
int64_t ntp_time_get_us(struct UTUN_INSTANCE* instance);
// То же время в целых секундах: get_us()/1000000 с приведением к time_t; NULL допустим.
time_t ntp_time_get_seconds(struct UTUN_INSTANCE* instance);
// Ненулевое значение, если есть поправка от NTP/пира (включая после destroy); для NULL — 0.
int ntp_time_is_synced(struct UTUN_INSTANCE* instance);
#ifdef __cplusplus
}
#endif
#endif // NTP_TIME_H