client: Wait for a reply when removing service
[platform/upstream/connman.git] / client / data_manager.c
1 /*
2  *
3  *  Connection Manager
4  *
5  *  Copyright (C) 2012  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 as published by
9  *  the Free Software Foundation; either version 2 of the License, or
10  *  (at your option) any later version.
11  *
12  *  This program is distributed in the hope that it will be useful,
13  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
14  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  *  GNU General Public License for more details.
16  *
17  *  You should have received a copy of the GNU General Public License
18  *  along with this program; if not, write to the Free Software
19  *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
20  *
21  */
22
23 #ifdef HAVE_CONFIG_H
24 #include <config.h>
25 #endif
26
27 #include <stdio.h>
28 #include <stdlib.h>
29 #include <stdint.h>
30 #include <unistd.h>
31 #include <string.h>
32 #include <errno.h>
33
34 #include <glib.h>
35 #include <gdbus.h>
36
37 #include "services.h"
38 #include "technology.h"
39 #include "data_manager.h"
40 #include "dbus.h"
41
42 static void extract_manager_properties(DBusMessage *message)
43 {
44         DBusMessageIter iter, array;
45
46         dbus_message_iter_init(message, &iter);
47         dbus_message_iter_recurse(&iter, &array);
48         extract_properties(&array);
49 }
50
51 int store_proxy_input(DBusConnection *connection, DBusMessage *message,
52                                 char *name, int num_args, char *argv[])
53 {
54         int i, j, k;
55         int error = 0;
56         gchar **servers = NULL;
57         gchar **excludes = NULL;
58
59         for (i = 0; argv[i] != NULL && strcmp(argv[i], "excludes") != 0 &&
60                      strncmp(argv[i], "--", 2) != 0; i++) {
61                 servers = g_try_realloc(servers, (i + 1) * sizeof(char *));
62                 if (servers == NULL) {
63                         fprintf(stderr, "Could not allocate memory for list\n");
64                         return -ENOMEM;
65                 }
66                 servers[i] = g_strdup(argv[i]);
67                 /* In case the user doesn't enter "excludes" */
68                 if (i + 1 == num_args) {
69                         i++;
70                         j = 0;
71                         goto free_servers;
72                 }
73         }
74         for (j = 0; j + (i + 1) != num_args && argv[j + (i + 1)] != NULL &&
75                      strncmp(argv[j + i + 1], "--", 2) != 0; j++) {
76                 excludes = g_try_realloc(excludes, (j + 1) * sizeof(char *));
77                 if (excludes == NULL) {
78                         fprintf(stderr, "Could not allocate memory for list\n");
79                         return -ENOMEM;
80                 }
81                 excludes[j] = g_strdup(argv[j + (i + 1)]);
82         }
83
84 free_servers:
85         error = set_proxy_manual(connection, message, name, servers, excludes,
86                                                                         i, j);
87
88         for (k = 0; k < j - 1; k++)
89                 g_free(excludes[k]);
90         g_free(excludes);
91
92         for (k = 0; k < i - 1; k++)
93                 g_free(servers[k]);
94         g_free(servers);
95
96         if (error < 0)
97                 return error;
98
99         if (i > 0)
100                 i++;
101         if (j > 0)
102                 j++;
103         return i + j;
104 }
105
106 int connect_service(DBusConnection *connection, char *name)
107 {
108         DBusMessage *message, *message_connect = NULL;
109         struct service_data service;
110         char *path = NULL;
111         const char *path_name;
112         DBusError err;
113         int err_ret = 0;
114
115         message = get_message(connection, "GetServices");
116         if (message == NULL)
117                 return -ENOMEM;
118
119         path_name = find_service(connection, message, name, &service);
120         if (path_name == NULL) {
121                 err_ret = -ENXIO;
122                 goto error;
123         }
124
125         path = g_strdup_printf("/net/connman/service/%s", path_name);
126         message_connect = dbus_message_new_method_call("net.connman", path,
127                                                 "net.connman.Service",
128                                                 "Connect");
129         if (message_connect == NULL) {
130                 err_ret = -ENOMEM;
131                 goto error;
132         }
133
134         dbus_error_init(&err);
135         dbus_connection_send_with_reply_and_block(connection, message_connect,
136                                                                 -1, &err);
137
138         if (dbus_error_is_set(&err)) {
139                 printf("Connection failed; error: '%s'\n", err.message);
140                 err_ret = -EINVAL;
141                 goto error;
142         }
143
144         dbus_connection_send(connection, message_connect, NULL);
145         dbus_connection_flush(connection);
146
147 error:
148         if (message != NULL)
149                 dbus_message_unref(message);
150         if (message_connect != NULL)
151                 dbus_message_unref(message_connect);
152         g_free(path);
153
154         return err_ret;
155 }
156
157 int disconnect_service(DBusConnection *connection, char *name)
158 {
159         DBusMessage *message, *message_disconnect = NULL;
160         struct service_data service;
161         char *path = NULL;
162         const char *path_name;
163         DBusError err;
164         int err_ret = 0;
165
166         message = get_message(connection, "GetServices");
167         if (message == NULL)
168                 return -ENOMEM;
169
170         path_name = find_service(connection, message, name, &service);
171         if (path_name == NULL) {
172                 err_ret = -ENXIO;
173                 goto error;
174         }
175
176         path = g_strdup_printf("/net/connman/service/%s", path_name);
177         printf("%s\n", path);
178         message_disconnect = dbus_message_new_method_call("net.connman", path,
179                                                           "net.connman.Service",
180                                                           "Disconnect");
181         if (message_disconnect == NULL) {
182                 err_ret = -ENOMEM;
183                 goto error;
184         }
185
186         dbus_error_init(&err);
187         dbus_connection_send_with_reply_and_block(connection,
188                                                   message_disconnect,
189                                                   -1, &err);
190
191         if (dbus_error_is_set(&err)) {
192                 printf("Connection failed; error: '%s'\n", err.message);
193                 err_ret = -EINVAL;
194                 goto error;
195         }
196
197         dbus_connection_send(connection, message_disconnect, NULL);
198         dbus_connection_flush(connection);
199
200 error:
201         if (message != NULL)
202                 dbus_message_unref(message);
203         if (message_disconnect != NULL)
204                 dbus_message_unref(message_disconnect);
205         g_free(path);
206
207         return err_ret;
208 }
209
210 int set_manager(DBusConnection *connection, char *key, dbus_bool_t value)
211 {
212         DBusMessage *message;
213         DBusMessageIter iter;
214
215         message = dbus_message_new_method_call("net.connman", "/",
216                                                 "net.connman.Manager",
217                                                 "SetProperty");
218         if (message == NULL)
219                 return -ENOMEM;
220
221         dbus_message_iter_init_append(message, &iter);
222         dbus_property_append_basic(&iter, (const char *) key,
223                                                 DBUS_TYPE_BOOLEAN, &value);
224         dbus_connection_send(connection, message, NULL);
225         dbus_connection_flush(connection);
226         dbus_message_unref(message);
227
228         return 0;
229 }
230
231 /* Call with any given function we want connman to respond to */
232 DBusMessage *get_message(DBusConnection *connection, char *function)
233 {
234         DBusMessage *message, *reply;
235         DBusError error;
236
237         message = dbus_message_new_method_call(CONNMAN_SERVICE,
238                                                 CONNMAN_MANAGER_PATH,
239                                                 CONNMAN_MANAGER_INTERFACE,
240                                                 function);
241         if (message == NULL)
242                 return NULL;
243
244         dbus_error_init(&error);
245
246         reply = dbus_connection_send_with_reply_and_block(connection,
247                                                            message, -1, &error);
248         if (dbus_error_is_set(&error) == TRUE) {
249                 fprintf(stderr, "%s\n", error.message);
250                 dbus_error_free(&error);
251         } else if (reply == NULL)
252                 fprintf(stderr, "Failed to receive message\n");
253
254         dbus_message_unref(message);
255
256         return reply;
257 }
258
259 int list_properties(DBusConnection *connection, char *function,
260                         char *service_name)
261 {
262         DBusMessage *message;
263
264         message = get_message(connection, function);
265         if (message == NULL)
266                 return -ENOMEM;
267
268         if (strcmp(function, "GetProperties") == 0)
269                 extract_manager_properties(message);
270
271         else if (strcmp(function, "GetServices") == 0 && service_name != NULL)
272                 extract_services(message, service_name);
273
274         else if (strcmp(function, "GetServices") == 0 && service_name == NULL)
275                 get_services(message);
276
277         else if (strcmp(function, "GetTechnologies") == 0)
278                 extract_tech(message);
279
280         dbus_message_unref(message);
281
282         return 0;
283 }