Add __connman_timerserver_sync() to resolve a list of timeservers
authorAlok Barsode <alok.barsode@linux.intel.com>
Fri, 3 Feb 2012 18:26:00 +0000 (20:26 +0200)
committerSamuel Ortiz <sameo@linux.intel.com>
Sat, 4 Feb 2012 00:15:36 +0000 (01:15 +0100)
__connman_timerserver_sync() resolves system timeservers one at a time
and queries the resolved server or the 1st of the resolved servers for
time correction. If the resolution fails it resolves the next one.
__connman_timerserver_sync_next() resolves the next system timeserver.
__connman_timerserver_stop() stops this query.If the user modifies the
system timeserver list, we restart the ntp process.

include/timeserver.h
src/connman.h
src/ntp.c
src/service.c
src/timeserver.c

index 3749482..e37fada 100644 (file)
@@ -38,7 +38,6 @@ extern "C" {
 
 int connman_timeserver_append(const char *server);
 int connman_timeserver_remove(const char *server);
-void connman_timeserver_sync(void);
 
 int __connman_timeserver_system_append(const char *server);
 int __connman_timeserver_system_remove(const char *server);
index 5c63503..dcde0f3 100644 (file)
@@ -321,6 +321,10 @@ void __connman_timeserver_cleanup(void);
 
 char **__connman_timeserver_system_get();
 
+int __connman_timeserver_sync(struct connman_service *service);
+void __connman_timeserver_sync_next();
+void __connman_timeserver_stop();
+
 typedef void (* dhcp_cb) (struct connman_network *network,
                                connman_bool_t success);
 int __connman_dhcp_start(struct connman_network *network, dhcp_cb callback);
index f70dfc7..4d3cd88 100644 (file)
--- a/src/ntp.c
+++ b/src/ntp.c
@@ -329,7 +329,7 @@ send:
 
 int __connman_ntp_start(char *server)
 {
-       DBG("");
+       DBG("%s", server);
 
        if (server == NULL)
                return -EINVAL;
index 42117a3..2fe93fc 100644 (file)
@@ -3992,9 +3992,8 @@ static int service_indicate_state(struct connman_service *service)
                }
        }
 
-       if (new_state == CONNMAN_SERVICE_STATE_ONLINE) {
-               connman_timeserver_sync();
-       }
+       if (new_state == CONNMAN_SERVICE_STATE_ONLINE)
+               __connman_timeserver_sync(service);
 
        if (new_state == CONNMAN_SERVICE_STATE_IDLE) {
                connman_bool_t reconnect;
@@ -4065,6 +4064,8 @@ static int service_indicate_state(struct connman_service *service)
                dns_changed(service);
                domain_changed(service);
 
+               __connman_timeserver_stop();
+
                __connman_notifier_disconnect(service->type);
 
                /*
index 3bdc74f..2af173d 100644 (file)
 #include <errno.h>
 
 #include <glib.h>
+#include <stdlib.h>
+#include <gweb/gresolv.h>
 
 #include "connman.h"
 
 static GSList *driver_list = NULL;
 static GHashTable *server_hash = NULL;
 
+static char **system_timeservers = NULL;
+
+static GResolv *resolv = NULL;
+static int resolv_id = 0;
+static volatile int count;
+
+static void resolv_debug(const char *str, void *data)
+{
+       connman_info("%s: %s\n", (const char *) data, str);
+}
 static void save_timeservers(char **servers)
 {
        GKeyFile *keyfile;
@@ -182,20 +194,128 @@ int connman_timeserver_remove(const char *server)
        return driver->remove(server);
 }
 
-void connman_timeserver_sync(void)
+/* Restart NTP procedure */
+static void connman_timeserver_restart()
 {
-       GSList *list;
+       if (resolv == NULL) {
+               DBG("No online service.");
+               return;
+       }
 
-       DBG("");
+       /* Cancel current lookup */
+       if(resolv_id > 0)
+               g_resolv_cancel_lookup(resolv, resolv_id);
 
-       for (list = driver_list; list; list = list->next) {
-               struct connman_timeserver_driver *driver = list->data;
+       /* Reload system timeserver list */
+       if (system_timeservers != NULL) {
+               g_strfreev(system_timeservers);
+               system_timeservers = NULL;
+       }
 
-               if (driver->sync == NULL)
-                       continue;
+       system_timeservers = load_timeservers();
+
+       if (system_timeservers == NULL)
+               return;
+
+       __connman_ntp_stop();
+
+       count = 0;
+
+       __connman_timeserver_sync_next();
+}
+
+static void resolv_result(GResolvResultStatus status, char **results, gpointer user_data)
+{
+       int i;
+
+       DBG("status %d", status);
+
+       if (status == G_RESOLV_RESULT_STATUS_SUCCESS) {
+               if (results != NULL) {
+                       for (i = 0; results[i]; i++)
+                               DBG("result: %s", results[i]);
+
+                       __connman_ntp_start(results[0]);
+
+                       return;
+               }
+       }
+       __sync_fetch_and_add(&count, 1);
+       __connman_timeserver_sync_next();
+}
+
+void __connman_timeserver_sync_next()
+{
+       if (system_timeservers == NULL ||
+       system_timeservers[count] == NULL)
+               return;
+
+       DBG("Trying timeserver %s", system_timeservers[count]);
+
+       if (resolv)
+               resolv_id = g_resolv_lookup_hostname(resolv,
+                       system_timeservers[count], resolv_result,
+                                               NULL);
+}
+
+int __connman_timeserver_sync(struct connman_service *service)
+{
+       char **nameservers = NULL;
+       int i;
+
+       DBG("service %p", service);
+
+       i = __connman_service_get_index(service);
+       if (i < 0)
+               return -EINVAL;
+
+       nameservers = connman_service_get_nameservers(service);
+       if (nameservers == NULL)
+               return -EINVAL;
 
-               driver->sync();
+       resolv = g_resolv_new(i);
+       if (resolv == NULL)
+               return -ENOMEM;
+
+       if (getenv("CONNMAN_RESOLV_DEBUG"))
+               g_resolv_set_debug(resolv, resolv_debug, "RESOLV");
+
+       for (i = 0; nameservers[i] != NULL; i++)
+               g_resolv_add_nameserver(resolv, nameservers[i], 53, 0);
+
+       count = 0;
+
+       system_timeservers = load_timeservers();
+
+       if (system_timeservers == NULL || system_timeservers[count] == NULL) {
+               DBG("No timeservers set.");
+               return 0;
        }
+
+       DBG("Trying server %s", system_timeservers[count]);
+
+       resolv_id = g_resolv_lookup_hostname(resolv, system_timeservers[count],
+                                               resolv_result, NULL);
+       return 0;
+}
+
+void __connman_timeserver_stop()
+{
+       DBG(" ");
+
+       if (resolv != NULL) {
+               g_resolv_unref(resolv);
+               resolv = NULL;
+       }
+
+       if (system_timeservers != NULL) {
+               g_strfreev(system_timeservers);
+               system_timeservers = NULL;
+       }
+
+       count = 0;
+
+       __connman_ntp_stop();
 }
 
 int __connman_timeserver_system_append(const char *server)
@@ -205,7 +325,7 @@ int __connman_timeserver_system_append(const char *server)
 
        if (server == NULL) {
                save_timeservers(servers);
-               return 0;
+               goto restart;
        }
 
        DBG("server %s", server);
@@ -237,6 +357,8 @@ int __connman_timeserver_system_append(const char *server)
        save_timeservers(servers);
 
        g_strfreev(servers);
+restart:
+       connman_timeserver_restart();
 
        return 0;
 }
@@ -291,6 +413,8 @@ int __connman_timeserver_system_remove(const char *server)
        save_timeservers(servers);
        g_strfreev(servers);
 
+       connman_timeserver_restart();
+
        return 0;
 }