timeserver: Do not use element driver API
[framework/connectivity/connman.git] / plugins / ntpd.c
index ce14027..d437ecb 100644 (file)
 #include <string.h>
 #include <arpa/inet.h>
 
+#include <gdbus.h>
+
 #define CONNMAN_API_SUBJECT_TO_CHANGE
+#include <connman/types.h>
 #include <connman/plugin.h>
 #include <connman/task.h>
 #include <connman/timeserver.h>
-#include <connman/driver.h>
 #include <connman/log.h>
 
 /*
@@ -45,7 +47,11 @@ static GList *peers = NULL;
 static GList *pending_peers = NULL;
 
 #define NTPD_PORT 123
-#define DEFAULT_NTP_PEER "ntp.meego.com"
+
+struct ntpd_peer {
+       char *server;
+       gint refcount;
+};
 
 struct ntpdate_task {
        struct connman_task *task;
@@ -53,6 +59,31 @@ struct ntpdate_task {
        char *conf_path;
 };
 
+static struct ntpd_peer *find_peer(GList *peer_list, const char* server)
+{
+       GList *list;
+       struct ntpd_peer *peer;
+
+       for (list = peer_list; list; list = list->next) {
+               peer = list->data;
+
+               if (g_str_equal(peer->server, server))
+                       return peer;
+       }
+
+       return NULL;
+}
+
+static void remove_peer(GList *peer_list, struct ntpd_peer *peer)
+{
+       if (!g_atomic_int_dec_and_test(&peer->refcount))
+               return;
+
+       g_free(peer->server);
+       g_free(peer);
+       peer_list = g_list_remove(peer_list, peer);
+}
+
 static connman_bool_t ntpd_running(void)
 {
        int sock;
@@ -73,14 +104,16 @@ static connman_bool_t ntpd_running(void)
                        ret = TRUE;
                else
                        ret = FALSE;
-        }
+        } else
+               ret = FALSE;
 
        close(sock);
 
        return ret;
 }
 
-static void ntpdate_died(struct connman_task *task, void *user_data)
+static void ntpdate_died(struct connman_task *task,
+                               int exit_code, void *user_data)
 {
        struct ntpdate_task *ntpdate = user_data;
 
@@ -113,6 +146,7 @@ static int ntpdate(void)
        int err;
        GError *g_err;
        GList *list;
+       struct ntpd_peer *peer;
        struct ntpdate_task *ntpdate;
 
        DBG("");
@@ -128,6 +162,7 @@ static int ntpdate(void)
                goto error_task;
        }
 
+       connman_task_add_argument(ntpdate->task, "-g", NULL);
        connman_task_add_argument(ntpdate->task, "-q", NULL);
 
        /* The servers are added through a temp configuration file */
@@ -143,14 +178,17 @@ static int ntpdate(void)
 
        DBG("conf path %s", ntpdate->conf_path);
 
-       if (pending_peers == NULL && peers == NULL)
-               ntpdate_add_peer(ntpdate, DEFAULT_NTP_PEER);
+       for (list = pending_peers; list; list = list->next) {
+               peer = list->data;
+
+               ntpdate_add_peer(ntpdate, peer->server);
+       }
 
-       for (list = pending_peers; list; list = list->next)
-               ntpdate_add_peer(ntpdate, list->data);
+       for (list = peers; list; list = list->next) {
+               peer = list->data;
 
-       for (list = peers; list; list = list->next)
-               ntpdate_add_peer(ntpdate, list->data);
+               ntpdate_add_peer(ntpdate, peer->server);
+       }
 
        close(ntpdate->conf_fd);
 
@@ -179,6 +217,10 @@ static void ntpd_sync(void)
 
        DBG("");
 
+       if (g_list_length(pending_peers) == 0 &&
+                       g_list_length(peers) == 0)
+               return;
+
        if (!ntpd_running()) {
                ntpdate();
                return;
@@ -188,9 +230,9 @@ static void ntpd_sync(void)
 
        list = g_list_first(pending_peers);
        while(list) {
-               char *peer = list->data;
+               struct ntpd_peer *peer = list->data;
 
-               err = ntpd_add_peer(peer);
+               err = ntpd_add_peer(peer->server);
                if (err)
                        continue;
 
@@ -202,30 +244,68 @@ static void ntpd_sync(void)
        };
 }
 
-static int ntpd_append(char *server)
+static int ntpd_append(const char *server)
 {
+       struct ntpd_peer *peer;
+
        DBG("");
 
-       pending_peers = g_list_prepend(pending_peers, server);
+       if (server == NULL)
+               return 0;
+
+       if ((peer = find_peer(pending_peers, server)) ||
+                       (peer = find_peer(peers, server))) {
+               g_atomic_int_inc(&peer->refcount);
+               return 0;
+       }
+
+       peer = g_try_new0(struct ntpd_peer, 1);
+       if (peer == NULL)
+               return -ENOMEM;
+
+       peer->server = g_strdup(server);
+       if (peer->server == NULL) {
+               g_free(peer);
+               return -ENOMEM;
+       }
+
+       peer->refcount = 1;
+
+       pending_peers = g_list_prepend(pending_peers, peer);
 
        return 0;
 }
 
-static int ntpd_remove(char *server)
+static int ntpd_remove(const char *server)
 {
+       struct ntpd_peer *peer;
+
        DBG("");
 
-       peers = g_list_remove(peers, server);
+       if (server == NULL)
+               return 0;
+
+       peer = find_peer(peers, server);
+       if (peer == NULL)
+               goto remove;
+
+       remove_peer(peers, peer);
+
+remove:
        /* TODO: send ntpd remove command */
 
-       pending_peers = g_list_remove(pending_peers, server);
+       peer = find_peer(pending_peers, server);
+       if (peer == NULL)
+               return 0;
+
+       remove_peer(pending_peers, peer);
 
        return 0;
 }
 
 static struct connman_timeserver_driver ntpd_driver = {
        .name           = "ntpd",
-       .priority       = CONNMAN_DRIVER_PRIORITY_DEFAULT,
+       .priority       = CONNMAN_TIMESERVER_PRIORITY_DEFAULT,
        .append         = ntpd_append,
        .remove         = ntpd_remove,
        .sync           = ntpd_sync,