timeserver: Fix memory leak
[framework/connectivity/connman.git] / src / timeserver.c
1 /*
2  *
3  *  Connection Manager
4  *
5  *  Copyright (C) 2007-2010  Intel Corporation. All rights reserved.
6  *
7  *  This program is free software; you can redistribute it and/or modify
8  *  it under the terms of the GNU General Public License version 2 as
9  *  published by the Free Software Foundation.
10  *
11  *  This program is distributed in the hope that it will be useful,
12  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  *  GNU General Public License for more details.
15  *
16  *  You should have received a copy of the GNU General Public License
17  *  along with this program; if not, write to the Free Software
18  *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
19  *
20  */
21
22 #ifdef HAVE_CONFIG_H
23 #include <config.h>
24 #endif
25
26 #include <glib.h>
27
28 #include "connman.h"
29
30 static GSList *driver_list = NULL;
31 static GHashTable *server_hash = NULL;
32
33 static gint compare_priority(gconstpointer a, gconstpointer b)
34 {
35         const struct connman_timeserver_driver *driver1 = a;
36         const struct connman_timeserver_driver *driver2 = b;
37
38         return driver2->priority - driver1->priority;
39 }
40
41 /**
42  * connman_timeserver_driver_register:
43  * @driver: timeserver driver definition
44  *
45  * Register a new timeserver driver
46  *
47  * Returns: %0 on success
48  */
49 int connman_timeserver_driver_register(struct connman_timeserver_driver *driver)
50 {
51         DBG("driver %p name %s", driver, driver->name);
52
53         driver_list = g_slist_insert_sorted(driver_list, driver,
54                                                         compare_priority);
55
56         return 0;
57 }
58
59 /**
60  * connman_timeserver_driver_unregister:
61  * @driver: timeserver driver definition
62  *
63  * Remove a previously registered timeserver driver
64  */
65 void connman_timeserver_driver_unregister(struct connman_timeserver_driver *driver)
66 {
67         DBG("driver %p name %s", driver, driver->name);
68
69         driver_list = g_slist_remove(driver_list, driver);
70 }
71
72 /**
73  * connman_timeserver_append:
74  * @server: server address
75  *
76  * Append time server server address to current list
77  */
78 int connman_timeserver_append(const char *server)
79 {
80         GSList *list;
81
82         DBG("server %s", server);
83
84         if (server == NULL)
85                 return -EINVAL;
86
87         /* This server is already handled by a driver */
88         if (g_hash_table_lookup(server_hash, server))
89                 return 0;
90
91         for (list = driver_list; list; list = list->next) {
92                 struct connman_timeserver_driver *driver = list->data;
93                 char *new_server;
94
95                 if (driver->append == NULL)
96                         continue;
97
98                 new_server = g_strdup(server);
99                 if (new_server == NULL)
100                         return -ENOMEM;
101
102                 if (driver->append(server) == 0) {
103                         g_hash_table_insert(server_hash, new_server, driver);
104                         return 0;
105                 } else {
106                         g_free(new_server);
107                 }
108         }
109
110         return -ENOENT;
111 }
112
113 /**
114  * connman_timeserver_remove:
115  * @server: server address
116  *
117  * Remover time server server address from current list
118  */
119 int connman_timeserver_remove(const char *server)
120 {
121         struct connman_timeserver_driver *driver;
122
123         DBG("server %s", server);
124
125         if (server == NULL)
126                 return -EINVAL;
127
128         driver = g_hash_table_lookup(server_hash, server);
129         if (driver == NULL)
130                 return -EINVAL;
131
132         g_hash_table_remove(server_hash, server);
133
134         if (driver->remove == NULL)
135                 return -ENOENT;
136
137         return driver->remove(server);
138 }
139
140 void connman_timeserver_sync(void)
141 {
142         GSList *list;
143
144         DBG("");
145
146         for (list = driver_list; list; list = list->next) {
147                 struct connman_timeserver_driver *driver = list->data;
148
149                 if (driver->sync == NULL)
150                         continue;
151
152                 driver->sync();
153         }
154 }
155
156 int __connman_timeserver_init(void)
157 {
158         DBG("");
159
160         server_hash = g_hash_table_new_full(g_str_hash, g_str_equal,
161                                                 g_free, NULL);
162
163         return 0;
164 }
165
166 void __connman_timeserver_cleanup(void)
167 {
168         DBG("");
169
170         g_hash_table_destroy(server_hash);
171 }