]> git.ipfire.org Git - thirdparty/chrony.git/commitdiff
ntp: use async name resolving for NTP sources
authorMiroslav Lichvar <mlichvar@redhat.com>
Fri, 25 Apr 2014 14:58:21 +0000 (16:58 +0200)
committerMiroslav Lichvar <mlichvar@redhat.com>
Tue, 29 Apr 2014 10:43:03 +0000 (12:43 +0200)
Use the new asynchronous call to resolve addresses of NTP servers
configured by the server/peer directives. Introduce a callback to be
notified when the first resolving attempt ends to correctly finish
chronyd initialization (dumpfile reload and reference mode end).

conf.c
main.c
ntp_sources.c
ntp_sources.h

diff --git a/conf.c b/conf.c
index 3a176e11afa7a286b6acb66f7b5c0bff59be4c90..e19c5d95bfe19d58f82cf90431ba1a58faca3f62 100644 (file)
--- a/conf.c
+++ b/conf.c
@@ -1186,8 +1186,6 @@ CNF_AddSources(void) {
     NSR_AddUnresolvedSource(ntp_sources[i].params.name, ntp_sources[i].params.port,
         ntp_sources[i].type, &ntp_sources[i].params.params);
   }
-
-  NSR_ResolveSources();
 }
 
 /* ================================================== */
diff --git a/main.c b/main.c
index 4de366972afa93e45fbeb5a42b94ff0269d9917a..acaaf0d15ff972e7e89927cfc8e1b23c9dc4c0eb 100644 (file)
--- a/main.c
+++ b/main.c
@@ -123,20 +123,10 @@ signal_cleanup(int x)
 /* ================================================== */
 
 static void
-post_init_ntp_hook(void *anything)
+ntp_source_resolving_end(void)
 {
-  if (ref_mode == REF_ModeInitStepSlew) {
-    /* Remove the initstepslew sources and set normal mode */
-    NSR_RemoveAllSources();
-    ref_mode = REF_ModeNormal;
-    REF_SetMode(ref_mode);
-  }
-
-  /* Close the pipe to the foreground process so it can exit */
-  LOG_CloseParentFd();
+  NSR_SetSourceResolvingEndHandler(NULL);
 
-  CNF_AddSources();
-  CNF_AddBroadcasts();
   if (reload) {
     /* Note, we want reload to come well after the initialisation from
        the real time clock - this gives us a fighting chance that the
@@ -159,6 +149,28 @@ post_init_ntp_hook(void *anything)
 
 /* ================================================== */
 
+static void
+post_init_ntp_hook(void *anything)
+{
+  if (ref_mode == REF_ModeInitStepSlew) {
+    /* Remove the initstepslew sources and set normal mode */
+    NSR_RemoveAllSources();
+    ref_mode = REF_ModeNormal;
+    REF_SetMode(ref_mode);
+  }
+
+  /* Close the pipe to the foreground process so it can exit */
+  LOG_CloseParentFd();
+
+  CNF_AddSources();
+  CNF_AddBroadcasts();
+
+  NSR_SetSourceResolvingEndHandler(ntp_source_resolving_end);
+  NSR_ResolveSources();
+}
+
+/* ================================================== */
+
 static void
 reference_mode_end(int result)
 {
index 7836bfa53a2d9218e9874159d3ae94df07059520..1dc575438e7b2f7f002d72dcfc0b5065584b749d 100644 (file)
@@ -37,7 +37,7 @@
 #include "logging.h"
 #include "local.h"
 #include "memory.h"
-#include "nameserv.h"
+#include "nameserv_async.h"
 #include "sched.h"
 
 /* ================================================== */
@@ -77,9 +77,14 @@ struct UnresolvedSource {
 static struct UnresolvedSource *unresolved_sources = NULL;
 static int resolving_interval = 0;
 static SCH_TimeoutID resolving_id;
+static struct UnresolvedSource *resolving_source = NULL;
+static NSR_SourceResolvingEndHandler resolving_end_handler = NULL;
 
 /* ================================================== */
 /* Forward prototypes */
+
+static void resolve_sources(void *arg);
+
 static void
 slew_sources(struct timeval *raw,
              struct timeval *cooked,
@@ -219,45 +224,90 @@ NSR_AddSource(NTP_Remote_Address *remote_addr, NTP_Source_Type type, SourceParam
 /* ================================================== */
 
 static void
-resolve_sources(void *arg)
+name_resolve_handler(DNS_Status status, IPAddr *ip_addr, void *anything)
 {
+  struct UnresolvedSource *us, **i, *next;
   NTP_Remote_Address address;
-  struct UnresolvedSource *us, **i;
-  DNS_Status s;
 
-  DNS_Reload();
+  us = (struct UnresolvedSource *)anything;
 
-  for (i = &unresolved_sources; *i; ) {
-    us = *i;
-    s = DNS_Name2IPAddress(us->name, &address.ip_addr);
-    if (s == DNS_TryAgain) {
-      i = &(*i)->next;
-      continue;
-    } else if (s == DNS_Success) {
+  assert(us == resolving_source);
+
+  switch (status) {
+    case DNS_TryAgain:
+      break;
+    case DNS_Success:
+      DEBUG_LOG(LOGF_NtpSources, "%s resolved to %s", us->name, UTI_IPToString(ip_addr));
+      address.ip_addr = *ip_addr;
       address.port = us->port;
       NSR_AddSource(&address, us->type, &us->params);
-    } else {
+      break;
+    case DNS_Failure:
       LOG(LOGS_WARN, LOGF_NtpSources, "Invalid host %s", us->name);
-    }
-    
-    *i = us->next;
+      break;
+    default:
+      assert(0);
+  }
+
+  next = us->next;
 
-    Free(us->name);
-    Free(us);
+  if (status != DNS_TryAgain) {
+    /* Remove the source from the list */
+    for (i = &unresolved_sources; *i; i = &(*i)->next) {
+      if (*i == us) {
+        *i = us->next;
+        Free(us->name);
+        Free(us);
+        break;
+      }
+    }
   }
 
-  if (unresolved_sources) {
-    /* Try again later */
-    if (resolving_interval < 9)
-      resolving_interval++;
-    resolving_id = SCH_AddTimeoutByDelay(7 * (1 << resolving_interval), resolve_sources, NULL);
+  resolving_source = next;
+
+  if (next) {
+    /* Continue with the next source in the list */
+    DEBUG_LOG(LOGF_NtpSources, "resolving %s", next->name);
+    DNS_Name2IPAddressAsync(next->name, name_resolve_handler, next);
   } else {
-    resolving_interval = 0;
+    /* This was the last source in the list. If some sources couldn't
+       be resolved, try again in exponentially increasing interval. */
+    if (unresolved_sources) {
+      if (resolving_interval < 9)
+        resolving_interval++;
+      resolving_id = SCH_AddTimeoutByDelay(7 * (1 << resolving_interval), resolve_sources, NULL);
+    } else {
+      resolving_interval = 0;
+    }
+
+    /* This round of resolving is done */
+    if (resolving_end_handler)
+      (resolving_end_handler)();
   }
 }
 
 /* ================================================== */
 
+static void
+resolve_sources(void *arg)
+{
+  struct UnresolvedSource *us;
+
+  assert(!resolving_source);
+
+  DNS_Reload();
+
+  /* Start with the first source in the list, name_resolve_handler
+     will iterate over the rest */
+  us = unresolved_sources;
+
+  resolving_source = us;
+  DEBUG_LOG(LOGF_NtpSources, "resolving %s", us->name);
+  DNS_Name2IPAddressAsync(us->name, name_resolve_handler, us);
+}
+
+/* ================================================== */
+
 /* Procedure to add a new server or peer source, but instead of an IP address
    only a name is provided */
 void
@@ -285,14 +335,31 @@ NSR_AddUnresolvedSource(char *name, int port, NTP_Source_Type type, SourceParame
 
 /* ================================================== */
 
+void
+NSR_SetSourceResolvingEndHandler(NSR_SourceResolvingEndHandler handler)
+{
+  resolving_end_handler = handler;
+}
+
+/* ================================================== */
+
 void
 NSR_ResolveSources(void)
 {
   /* Try to resolve unresolved sources now */
-  if (resolving_interval) {
-    SCH_RemoveTimeout(resolving_id);
-    resolving_interval--;
-    resolve_sources(NULL);
+  if (unresolved_sources) {
+    /* Make sure no resolving is currently running */
+    if (!resolving_source) {
+      if (resolving_interval) {
+        SCH_RemoveTimeout(resolving_id);
+        resolving_interval--;
+      }
+      resolve_sources(NULL);
+    }
+  } else {
+    /* No unresolved sources, we are done */
+    if (resolving_end_handler)
+      (resolving_end_handler)();
   }
 }
 
index cb25e5f4408d51e2f4ff0f79ba5eed1ff6fb1913..e6cb39f5fa1162e66e13b20641b4ef8d83a49d6b 100644 (file)
@@ -54,7 +54,14 @@ extern NSR_Status NSR_AddSource(NTP_Remote_Address *remote_addr, NTP_Source_Type
    until it succeeds or fails with a non-temporary error. */
 extern void NSR_AddUnresolvedSource(char *name, int port, NTP_Source_Type type, SourceParameters *params);
 
-/* Procedure to try resolve unresolved sources immediately. */
+/* Function type for handlers to be called back when an attempt
+ * (possibly unsuccessful) to resolve unresolved sources ends */
+typedef void (*NSR_SourceResolvingEndHandler)(void);
+
+/* Set the handler, or NULL to disable the notification */
+extern void NSR_SetSourceResolvingEndHandler(NSR_SourceResolvingEndHandler handler);
+
+/* Procedure to start resolving unresolved sources immediately */
 extern void NSR_ResolveSources(void);
 
 /* Procedure to start all sources */