pending to transmit to the source */
SCH_TimeoutID timeout_id; /* Scheduler's timeout ID, if we are
running on a timer. */
+ int tx_suspended; /* Boolean indicating we can't transmit yet */
int auto_offline; /* If 1, automatically go offline if server/peer
isn't responding */
/* Maximum poll interval set by KoD RATE */
#define MAX_KOD_RATE_POLL SRC_DEFAULT_MAXPOLL
+#define INVALID_SOCK_FD -1
+
/* ================================================== */
static ADF_AuthTable access_auth_table;
static void
start_initial_timeout(NCR_Instance inst)
{
+ /* Check if we can transmit */
+ if (inst->tx_suspended) {
+ assert(!inst->timer_running);
+ return;
+ }
+
+ /* Stop old timer if running */
+ if (inst->timer_running)
+ SCH_RemoveTimeout(inst->timeout_id);
- /* Start timer for first transmission */
+ /* Start new timer for transmission */
inst->timeout_id = SCH_AddTimeoutInClass(INITIAL_DELAY, SAMPLING_SEPARATION,
SAMPLING_RANDOMNESS,
SCH_NtpSamplingClass,
transmit_timeout, (void *)inst);
- inst->timer_running = 1;
- /* Mark source active */
- SRC_SetActive(inst->source);
+ if (!inst->timer_running) {
+ /* This will be the first transmission after mode change */
+
+ inst->timer_running = 1;
+
+ /* Mark source active */
+ SRC_SetActive(inst->source);
- /* Open client socket */
- if (inst->mode == MODE_CLIENT)
- inst->local_addr.sock_fd = NIO_GetClientSocket(&inst->remote_addr);
+ /* Open client socket */
+ if (inst->mode == MODE_CLIENT) {
+ assert(inst->local_addr.sock_fd == INVALID_SOCK_FD);
+ inst->local_addr.sock_fd = NIO_GetClientSocket(&inst->remote_addr);
+ }
+ }
}
/* ================================================== */
SRC_UnsetActive(inst->source);
/* Close client socket */
- if (inst->mode == MODE_CLIENT)
+ if (inst->mode == MODE_CLIENT && inst->local_addr.sock_fd != INVALID_SOCK_FD) {
NIO_CloseClientSocket(inst->local_addr.sock_fd);
+ inst->local_addr.sock_fd = INVALID_SOCK_FD;
+ }
}
/* ================================================== */
switch (type) {
case NTP_SERVER:
/* Client socket will be obtained when timer is started */
+ result->local_addr.sock_fd = INVALID_SOCK_FD;
result->mode = MODE_CLIENT;
break;
case NTP_PEER:
/* Create a source instance for this NTP source */
result->source = SRC_CreateNewInstance(UTI_IPToRefid(&remote_addr->ip_addr), SRC_NTP, params->sel_option, &result->remote_addr.ip_addr);
- if (params->online) {
- start_initial_timeout(result);
- result->opmode = MD_ONLINE;
- } else {
- result->timer_running = 0;
- result->timeout_id = 0;
- result->opmode = MD_OFFLINE;
- }
+ result->timer_running = 0;
+ result->timeout_id = 0;
+ result->tx_suspended = 1;
+ result->opmode = params->online ? MD_ONLINE : MD_OFFLINE;
if (params->iburst) {
NCR_InitiateSampleBurst(result, IBURST_GOOD_SAMPLES, IBURST_TOTAL_SAMPLES);
/* ================================================== */
+void
+NCR_StartInstance(NCR_Instance instance)
+{
+ instance->tx_suspended = 0;
+ if (instance->opmode != MD_OFFLINE)
+ start_initial_timeout(instance);
+}
+
+/* ================================================== */
+
static int
check_packet_auth(NTP_Packet *pkt, unsigned long keyid, int auth_len)
{
}
/* Ignore packets from offline sources */
- if (inst->opmode == MD_OFFLINE) {
+ if (inst->opmode == MD_OFFLINE || inst->tx_suspended) {
return;
}
/* Nothing to do */
break;
case MD_OFFLINE:
- if (!inst->timer_running) {
- /* We are not already actively polling it */
- LOG(LOGS_INFO, LOGF_NtpCore, "Source %s online", UTI_IPToString(&inst->remote_addr.ip_addr));
- inst->tx_count = 0;
- inst->local_poll = inst->minpoll;
- inst->poll_score = 0.5;
- inst->opmode = MD_ONLINE;
- start_initial_timeout(inst);
- }
+ LOG(LOGS_INFO, LOGF_NtpCore, "Source %s online", UTI_IPToString(&inst->remote_addr.ip_addr));
+ inst->tx_count = 0;
+ inst->local_poll = inst->minpoll;
+ inst->poll_score = 0.5;
+ inst->opmode = MD_ONLINE;
+ start_initial_timeout(inst);
break;
case MD_BURST_WAS_ONLINE:
/* Will revert */
{
switch (inst->opmode) {
case MD_ONLINE:
- if (inst->timer_running) {
- LOG(LOGS_INFO, LOGF_NtpCore, "Source %s offline", UTI_IPToString(&inst->remote_addr.ip_addr));
- take_offline(inst);
- }
+ LOG(LOGS_INFO, LOGF_NtpCore, "Source %s offline", UTI_IPToString(&inst->remote_addr.ip_addr));
+ take_offline(inst);
break;
case MD_OFFLINE:
break;
break;
case MD_ONLINE:
- inst->opmode = MD_BURST_WAS_ONLINE;
- inst->burst_good_samples_to_go = n_good_samples;
- inst->burst_total_samples_to_go = n_total_samples;
- assert(inst->timer_running);
- SCH_RemoveTimeout(inst->timeout_id);
- inst->timeout_id = SCH_AddTimeoutInClass(INITIAL_DELAY, SAMPLING_SEPARATION,
- SAMPLING_RANDOMNESS,
- SCH_NtpSamplingClass,
- transmit_timeout, (void *) inst);
- break;
case MD_OFFLINE:
- inst->opmode = MD_BURST_WAS_OFFLINE;
+ inst->opmode = inst->opmode == MD_ONLINE ?
+ MD_BURST_WAS_ONLINE : MD_BURST_WAS_OFFLINE;
inst->burst_good_samples_to_go = n_good_samples;
inst->burst_total_samples_to_go = n_total_samples;
start_initial_timeout(inst);
/* The largest number of sources we want to have stored in the hash table */
#define MAX_SOURCES 64
+/* Flag indicating new sources will be started automatically when added */
+static int auto_start_sources = 0;
+
/* Source with unknown address (which may be resolved later) */
struct UnresolvedSource {
char *name;
n_sources++;
records[slot].data = NCR_GetInstance(remote_addr, type, params); /* Will need params passing through */
records[slot].remote_addr = NCR_GetRemoteAddress(records[slot].data);
+ if (auto_start_sources)
+ NCR_StartInstance(records[slot].data);
return NSR_Success;
}
}
/* ================================================== */
+void NSR_StartSources(void)
+{
+ int i;
+
+ for (i = 0; i < N_RECORDS; i++) {
+ if (!records[i].remote_addr)
+ continue;
+ NCR_StartInstance(records[i].data);
+ }
+}
+
+/* ================================================== */
+
+void NSR_AutoStartSources(void)
+{
+ auto_start_sources = 1;
+}
+
+/* ================================================== */
+
/* Procedure to remove a source. We don't bother whether the port
address is matched - we're only interested in removing a record for
the right IP address. Thus the caller can specify the port number