-static bool manager_sample_spike_detection(Manager *m, double offset, double delay) {
- unsigned int i, idx_cur, idx_new, idx_min;
- double jitter;
- double j;
-
- assert(m);
-
- m->packet_count++;
-
- /* ignore initial sample */
- if (m->packet_count == 1)
- return false;
-
- /* store the current data in our samples array */
- idx_cur = m->samples_idx;
- idx_new = (idx_cur + 1) % ELEMENTSOF(m->samples);
- m->samples_idx = idx_new;
- m->samples[idx_new].offset = offset;
- m->samples[idx_new].delay = delay;
-
- /* calculate new jitter value from the RMS differences relative to the lowest delay sample */
- jitter = m->samples_jitter;
- for (idx_min = idx_cur, i = 0; i < ELEMENTSOF(m->samples); i++)
- if (m->samples[i].delay > 0 && m->samples[i].delay < m->samples[idx_min].delay)
- idx_min = i;
-
- j = 0;
- for (i = 0; i < ELEMENTSOF(m->samples); i++)
- j += square(m->samples[i].offset - m->samples[idx_min].offset);
- m->samples_jitter = sqrt(j / (ELEMENTSOF(m->samples) - 1));
-
- /* ignore samples when resyncing */
- if (m->poll_resync)
- return false;
-
- /* always accept offset if we are farther off than the round-trip delay */
- if (fabs(offset) > delay)
- return false;
-
- /* we need a few samples before looking at them */
- if (m->packet_count < 4)
- return false;
-
- /* do not accept anything worse than the maximum possible error of the best sample */
- if (fabs(offset) > m->samples[idx_min].delay)
- return true;
-
- /* compare the difference between the current offset to the previous offset and jitter */
- return fabs(offset - m->samples[idx_cur].offset) > 3 * jitter;
-}
-
-static void manager_adjust_poll(Manager *m, double offset, bool spike) {
- assert(m);
-
- if (m->poll_resync) {
- m->poll_interval_usec = NTP_POLL_INTERVAL_MIN_SEC * USEC_PER_SEC;
- m->poll_resync = false;
- return;
- }
-
- /* set to minimal poll interval */
- if (!spike && fabs(offset) > NTP_ACCURACY_SEC) {
- m->poll_interval_usec = NTP_POLL_INTERVAL_MIN_SEC * USEC_PER_SEC;
- return;
- }
-
- /* increase polling interval */
- if (fabs(offset) < NTP_ACCURACY_SEC * 0.25) {
- if (m->poll_interval_usec < NTP_POLL_INTERVAL_MAX_SEC * USEC_PER_SEC)
- m->poll_interval_usec *= 2;
- return;
- }
-
- /* decrease polling interval */
- if (spike || fabs(offset) > NTP_ACCURACY_SEC * 0.75) {
- if (m->poll_interval_usec > NTP_POLL_INTERVAL_MIN_SEC * USEC_PER_SEC)
- m->poll_interval_usec /= 2;
- return;
- }
-}
-
-static bool sockaddr_equal(union sockaddr_union *a, union sockaddr_union *b) {
- assert(a);
- assert(b);
-
- if (a->sa.sa_family != b->sa.sa_family)
- return false;
-
- if (a->sa.sa_family == AF_INET)
- return a->in.sin_addr.s_addr == b->in.sin_addr.s_addr;
-
- if (a->sa.sa_family == AF_INET6)
- return memcmp(&a->in6.sin6_addr, &b->in6.sin6_addr, sizeof(a->in6.sin6_addr)) == 0;
-
- return false;
-}
-
-static int manager_receive_response(sd_event_source *source, int fd, uint32_t revents, void *userdata) {
- _cleanup_free_ char *pretty = NULL;
- Manager *m = userdata;
- struct ntp_msg ntpmsg;
-
- struct iovec iov = {
- .iov_base = &ntpmsg,
- .iov_len = sizeof(ntpmsg),
- };
- union {
- struct cmsghdr cmsghdr;
- uint8_t buf[CMSG_SPACE(sizeof(struct timeval))];
- } control;
- union sockaddr_union server_addr;
- struct msghdr msghdr = {
- .msg_iov = &iov,
- .msg_iovlen = 1,
- .msg_control = &control,
- .msg_controllen = sizeof(control),
- .msg_name = &server_addr,
- .msg_namelen = sizeof(server_addr),
- };
- struct cmsghdr *cmsg;
- struct timespec now_ts;
- struct timeval *recv_time;
- ssize_t len;
- double origin, receive, trans, dest;
- double delay, offset;
- bool spike;
- int leap_sec;