Table of Contents
- CLOCK_SYNC: client/server clock offset estimation
- Structures
- Functions
- Defines
- Functions Documentation
- function n_clock_sync_should_send
- function n_clock_sync_server_time
- function n_clock_sync_seed
- function n_clock_sync_process_response
- function n_clock_sync_new
- function n_clock_sync_mark_sent
- function n_clock_sync_delete
- function median_of
- function cmp_double
- function clock_sync_store_sample
- function clock_sync_effective_offset
- Macros Documentation
CLOCK_SYNC: client/server clock offset estimation
Structures
| Name | |
|---|---|
| struct | N_CLOCK_SYNC clock synchronization estimator |
Functions
| Name | |
|---|---|
| int | n_clock_sync_should_send(const N_CLOCK_SYNC * cs, double local_now) check if it's time to send a new sync request (returns TRUE/FALSE). |
| double | n_clock_sync_server_time(const N_CLOCK_SYNC * cs, double local_now) get estimated server time given a local time value. |
| void | n_clock_sync_seed(N_CLOCK_SYNC * cs, double offset, double rtt) Inject a synthetic (offset, rtt) sample, e.g. |
| int | n_clock_sync_process_response(N_CLOCK_SYNC * cs, double client_send_time, double server_time, double local_now) record a sync response: client_send_time is the local time the request was sent, server_time is the server's timestamp from the response, local_now is the current local time when the response was received. |
| N_CLOCK_SYNC * | n_clock_sync_new(void ) allocate and initialize a new clock sync estimator |
| void | n_clock_sync_mark_sent(N_CLOCK_SYNC * cs, double local_now) mark that a sync request was just sent |
| void | n_clock_sync_delete(N_CLOCK_SYNC ** cs) free a clock sync estimator |
| double | median_of(const double * samples, int count) compute the median of an array of doubles |
| int | cmp_double(const void * a, const void * b) comparison function for qsort on doubles |
| void | clock_sync_store_sample(N_CLOCK_SYNC * cs, double offset, double rtt, double local_now) store one (offset, rtt) sample and recompute the estimates. |
| double | clock_sync_effective_offset(const N_CLOCK_SYNC * cs, double local_now) effective (slewed) offset at local_now, pure function of the stored state so the const getter needs no mutation. |
Defines
| Name | |
|---|---|
| N_CLOCK_SYNC_SLEW_SECONDS seconds over which n_clock_sync_server_time slews from the previous offset estimate to a new one (smoothstep). |
|
| N_CLOCK_SYNC_SAMPLE_COUNT number of samples for the median filter |
|
| N_CLOCK_SYNC_MAX_RTT responses with an RTT above this are rejected outright (retransmit storms / suspend-resume artefacts, not usable timing data) |
|
| N_CLOCK_SYNC_INTERVAL default interval between sync requests in seconds |
|
| N_CLOCK_SYNC_BURST_SAMPLES number of REAL samples below which the burst interval applies |
|
| N_CLOCK_SYNC_BURST_INTERVAL accelerated interval used until N_CLOCK_SYNC_BURST_SAMPLES real responses have been collected, a fresh estimator converges in a couple of seconds instead of minutes |
Functions Documentation
function n_clock_sync_should_send
int n_clock_sync_should_send(
const N_CLOCK_SYNC * cs,
double local_now
)
check if it's time to send a new sync request (returns TRUE/FALSE).
Uses N_CLOCK_SYNC_BURST_INTERVAL until N_CLOCK_SYNC_BURST_SAMPLES real responses have been collected, then N_CLOCK_SYNC_INTERVAL.
function n_clock_sync_server_time
double n_clock_sync_server_time(
const N_CLOCK_SYNC * cs,
double local_now
)
get estimated server time given a local time value.
When the underlying offset estimate changes, the returned time SLEWS from the previous estimate to the new one over N_CLOCK_SYNC_SLEW_SECONDS (smoothstep) instead of stepping, pure function of the stored state, safe to call at any rate.
function n_clock_sync_seed
void n_clock_sync_seed(
N_CLOCK_SYNC * cs,
double offset,
double rtt
)
Inject a synthetic (offset, rtt) sample, e.g.
a server-supplied clock value at login, so the estimator is usable BEFORE the first request/response round-trip completes. Pass the believed offset (server_time - local_now) and a conservative synthetic rtt. RESETS the estimator to this single sample and adopts the offset immediately (no slew, at login there is nothing to slew from). The FIRST real response flushes the seed wholesale, so a seed with a synthetic rtt lower than the link's real RTT can never pin the estimate (offset selection is best-rtt, NTP-style).
function n_clock_sync_process_response
int n_clock_sync_process_response(
N_CLOCK_SYNC * cs,
double client_send_time,
double server_time,
double local_now
)
record a sync response: client_send_time is the local time the request was sent, server_time is the server's timestamp from the response, local_now is the current local time when the response was received.
Updates estimated_offset and estimated_rtt. Returns TRUE on success, FALSE on error.
function n_clock_sync_new
N_CLOCK_SYNC * n_clock_sync_new(
void
)
allocate and initialize a new clock sync estimator
function n_clock_sync_mark_sent
void n_clock_sync_mark_sent(
N_CLOCK_SYNC * cs,
double local_now
)
mark that a sync request was just sent
function n_clock_sync_delete
void n_clock_sync_delete(
N_CLOCK_SYNC ** cs
)
free a clock sync estimator
function median_of
static double median_of(
const double * samples,
int count
)
compute the median of an array of doubles
function cmp_double
static int cmp_double(
const void * a,
const void * b
)
comparison function for qsort on doubles
function clock_sync_store_sample
static void clock_sync_store_sample(
N_CLOCK_SYNC * cs,
double offset,
double rtt,
double local_now
)
store one (offset, rtt) sample and recompute the estimates.
Offset selection is NTP-style: the sample with the LOWEST rtt wins, because its one-way uncertainty (+/-rtt/2) is the smallest. A plain median is poisoned for minutes when the link is congested at startup (e.g. an MMO client receiving its login chunk burst: every early sample carries seconds of queueing delay, and the median needs a majority of clean samples to recover). estimated_rtt stays a median, it feeds timeout heuristics, where typical beats best.
local_now anchors the slew when the adopted offset changes: n_clock_sync_server_time blends from the previous effective offset instead of stepping.
function clock_sync_effective_offset
static double clock_sync_effective_offset(
const N_CLOCK_SYNC * cs,
double local_now
)
effective (slewed) offset at local_now, pure function of the stored state so the const getter needs no mutation.
Blends offset_prev -> estimated_offset with a smoothstep over N_CLOCK_SYNC_SLEW_SECONDS from the moment the estimate last changed.
Macros Documentation
define N_CLOCK_SYNC_SLEW_SECONDS
#define N_CLOCK_SYNC_SLEW_SECONDS 1.0
seconds over which n_clock_sync_server_time slews from the previous offset estimate to a new one (smoothstep).
A consumer that anchors motion on this clock sees a bounded rate change instead of a step.
define N_CLOCK_SYNC_SAMPLE_COUNT
#define N_CLOCK_SYNC_SAMPLE_COUNT 11
number of samples for the median filter
define N_CLOCK_SYNC_MAX_RTT
#define N_CLOCK_SYNC_MAX_RTT 10.0
responses with an RTT above this are rejected outright (retransmit storms / suspend-resume artefacts, not usable timing data)
define N_CLOCK_SYNC_INTERVAL
#define N_CLOCK_SYNC_INTERVAL 3.0
default interval between sync requests in seconds
define N_CLOCK_SYNC_BURST_SAMPLES
#define N_CLOCK_SYNC_BURST_SAMPLES 5
number of REAL samples below which the burst interval applies
define N_CLOCK_SYNC_BURST_INTERVAL
#define N_CLOCK_SYNC_BURST_INTERVAL 0.5
accelerated interval used until N_CLOCK_SYNC_BURST_SAMPLES real responses have been collected, a fresh estimator converges in a couple of seconds instead of minutes
Modules
- AABB3D
- ACCEPT_POOL
- ALLEGRO4
- ALLEGRO5
- ANIM_LIB
- ASTAR
- ATLAS_LIB
- AVRO
- CLOCK_SYNC
- COMMONS
- CONFIGFILE
- CYPHER_BASE64
- CYPHER_VIGENERE
- DEAD_RECKONING
- ENUMS
- EXCEPTIONS
- GAME_ENV
- GIT
- GUI
- HASH_TABLE
- ISOMETRIC_ENGINE
- LIST
- LOG
- LOGNODUP
- LZ4
- NETWORKING
- NETWORK_MSG
- N_COOKIES
- N_DIFF
- N_DIGEST
- N_DISK_CACHE
- N_DNS
- N_ECC
- N_ENTROPY
- N_FILES
- N_FLUIDS
- N_GUI_COLOR
- N_GUI_COLORWHEEL
- N_GUI_CURVE
- N_GUI_GRID
- N_GUI_POPUP
- N_HEX
- N_HTTP3
- N_HTTP_COOKIE
- N_HTTP_FORM
- N_HTTP_MIME
- N_HTTP_REQ
- N_HTTP_RESP
- N_HTTP_ROUTER
- N_HTTP_SERVER
- N_ICC
- N_JSON
- N_KAFKA
- N_LINALG
- N_MODULE
- N_OPENSSL_COMPAT
- N_PRETTY
- N_PTH
- N_QUERY
- N_RANDOM
- N_SHA256
- N_STR
- N_TIFF
- N_TIME
- N_USER
- N_X509
- N_ZIP
- PARTICLES
- PCRE
- PHYSICS
- SIGNALS
- STACK
- THREADS
- TRAJECTORY
- TREE
- ZLIB