Tizen 2.0 release
[framework/connectivity/obexd.git] / client / map.c
1 /*
2  *
3  *  OBEX Client
4  *
5  *  Copyright (C) 2011  Bartosz Szatkowski <bulislaw@linux.com> for Comarch
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 <errno.h>
28 #include <string.h>
29 #include <glib.h>
30 #include <gdbus.h>
31
32 #include "log.h"
33
34 #include "map.h"
35 #include "transfer.h"
36 #include "session.h"
37 #include "driver.h"
38
39 #define OBEX_MAS_UUID \
40         "\xBB\x58\x2B\x40\x42\x0C\x11\xDB\xB0\xDE\x08\x00\x20\x0C\x9A\x66"
41 #define OBEX_MAS_UUID_LEN 16
42
43 #define MAP_INTERFACE  "org.openobex.MessageAccess"
44 #define MAS_UUID "00001132-0000-1000-8000-00805f9b34fb"
45
46 struct map_data {
47         struct obc_session *session;
48         DBusMessage *msg;
49 };
50
51 static DBusConnection *conn = NULL;
52
53 static void simple_cb(struct obc_session *session,
54                                                 struct obc_transfer *transfer,
55                                                 GError *err, void *user_data)
56 {
57         DBusMessage *reply;
58         struct map_data *map = user_data;
59
60         if (err != NULL)
61                 reply = g_dbus_create_error(map->msg,
62                                                 "org.openobex.Error.Failed",
63                                                 "%s", err->message);
64         else
65                 reply = dbus_message_new_method_return(map->msg);
66
67         g_dbus_send_message(conn, reply);
68         dbus_message_unref(map->msg);
69 }
70
71 static DBusMessage *map_setpath(DBusConnection *connection,
72                                         DBusMessage *message, void *user_data)
73 {
74         struct map_data *map = user_data;
75         const char *folder;
76         GError *err = NULL;
77
78         if (dbus_message_get_args(message, NULL, DBUS_TYPE_STRING, &folder,
79                                                 DBUS_TYPE_INVALID) == FALSE)
80                 return g_dbus_create_error(message,
81                                         "org.openobex.Error.InvalidArguments",
82                                         NULL);
83
84         obc_session_setpath(map->session, folder, simple_cb, map, &err);
85         if (err != NULL) {
86                 DBusMessage *reply;
87                 reply =  g_dbus_create_error(message,
88                                                 "org.openobex.Error.Failed",
89                                                 "%s", err->message);
90                 g_error_free(err);
91                 return reply;
92         }
93
94         map->msg = dbus_message_ref(message);
95
96         return NULL;
97 }
98
99 static void buffer_cb(struct obc_session *session,
100                                                 struct obc_transfer *transfer,
101                                                 GError *err, void *user_data)
102 {
103         struct map_data *map = user_data;
104         DBusMessage *reply;
105         char *contents;
106         size_t size;
107         int perr;
108
109         if (err != NULL) {
110                 reply = g_dbus_create_error(map->msg,
111                                                 "org.openobex.Error.Failed",
112                                                 "%s", err->message);
113                 goto done;
114         }
115
116         perr = obc_transfer_get_contents(transfer, &contents, &size);
117         if (perr < 0) {
118                 reply = g_dbus_create_error(map->msg,
119                                                 "org.openobex.Error.Failed",
120                                                 "Error reading contents: %s",
121                                                 strerror(-perr));
122                 goto done;
123         }
124
125         reply = g_dbus_create_reply(map->msg, DBUS_TYPE_STRING, &contents,
126                                                         DBUS_TYPE_INVALID);
127
128         g_free(contents);
129 done:
130         g_dbus_send_message(conn, reply);
131         dbus_message_unref(map->msg);
132 }
133
134 static DBusMessage *map_get_folder_listing(DBusConnection *connection,
135                                         DBusMessage *message, void *user_data)
136 {
137         struct map_data *map = user_data;
138         struct obc_transfer *transfer;
139         GError *err = NULL;
140         DBusMessage *reply;
141
142         transfer = obc_transfer_get("x-obex/folder-listing", NULL, NULL, &err);
143         if (transfer == NULL)
144                 goto fail;
145
146         if (obc_session_queue(map->session, transfer, buffer_cb, map, &err)) {
147                 map->msg = dbus_message_ref(message);
148                 return NULL;
149         }
150
151 fail:
152         reply = g_dbus_create_error(message, "org.openobex.Error.Failed", "%s",
153                                                                 err->message);
154         g_error_free(err);
155         return reply;
156 }
157
158 static DBusMessage *map_get_message_listing(DBusConnection *connection,
159                                         DBusMessage *message, void *user_data)
160 {
161         struct map_data *map = user_data;
162         struct obc_transfer *transfer;
163         const char *folder;
164         DBusMessageIter msg_iter;
165         GError *err = NULL;
166         DBusMessage *reply;
167
168         dbus_message_iter_init(message, &msg_iter);
169
170         if (dbus_message_iter_get_arg_type(&msg_iter) != DBUS_TYPE_STRING)
171                 return g_dbus_create_error(message,
172                                 "org.openobex.Error.InvalidArguments", NULL);
173
174         dbus_message_iter_get_basic(&msg_iter, &folder);
175
176         transfer = obc_transfer_get("x-bt/MAP-msg-listing", folder, NULL, &err);
177         if (transfer == NULL)
178                 goto fail;
179
180         if (obc_session_queue(map->session, transfer, buffer_cb, map, &err)) {
181                 map->msg = dbus_message_ref(message);
182                 return NULL;
183         }
184
185 fail:
186         reply = g_dbus_create_error(message, "org.openobex.Error.Failed", "%s",
187                                                                 err->message);
188         g_error_free(err);
189         return reply;
190 }
191
192 static GDBusMethodTable map_methods[] = {
193         { "SetFolder",          "s", "",        map_setpath,
194                                                 G_DBUS_METHOD_FLAG_ASYNC },
195         { "GetFolderListing",   "a{ss}", "s",   map_get_folder_listing,
196                                                 G_DBUS_METHOD_FLAG_ASYNC },
197         { "GetMessageListing",  "sa{ss}", "s",  map_get_message_listing,
198                                                 G_DBUS_METHOD_FLAG_ASYNC },
199         { }
200 };
201
202 static void map_free(void *data)
203 {
204         struct map_data *map = data;
205
206         obc_session_unref(map->session);
207         g_free(map);
208 }
209
210 static int map_probe(struct obc_session *session)
211 {
212         struct map_data *map;
213         const char *path;
214
215         path = obc_session_get_path(session);
216
217         DBG("%s", path);
218
219         map = g_try_new0(struct map_data, 1);
220         if (!map)
221                 return -ENOMEM;
222
223         map->session = obc_session_ref(session);
224
225         if (!g_dbus_register_interface(conn, path, MAP_INTERFACE, map_methods,
226                                         NULL, NULL, map, map_free)) {
227                 map_free(map);
228
229                 return -ENOMEM;
230         }
231
232         return 0;
233 }
234
235 static void map_remove(struct obc_session *session)
236 {
237         const char *path = obc_session_get_path(session);
238
239         DBG("%s", path);
240
241         g_dbus_unregister_interface(conn, path, MAP_INTERFACE);
242 }
243
244 static struct obc_driver map = {
245         .service = "MAP",
246         .uuid = MAS_UUID,
247         .target = OBEX_MAS_UUID,
248         .target_len = OBEX_MAS_UUID_LEN,
249         .probe = map_probe,
250         .remove = map_remove
251 };
252
253 int map_init(void)
254 {
255         int err;
256
257         DBG("");
258
259         conn = dbus_bus_get(DBUS_BUS_SESSION, NULL);
260         if (!conn)
261                 return -EIO;
262
263         err = obc_driver_register(&map);
264         if (err < 0) {
265                 dbus_connection_unref(conn);
266                 conn = NULL;
267                 return err;
268         }
269
270         return 0;
271 }
272
273 void map_exit(void)
274 {
275         DBG("");
276
277         dbus_connection_unref(conn);
278         conn = NULL;
279
280         obc_driver_unregister(&map);
281 }