2 * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
24 #include "bluetooth-api.h"
25 #include "bt-internal-types.h"
27 #include "bt-service-common.h"
28 #include "bt-service-event.h"
29 #include "bt-service-util.h"
30 #include "bt-service-map-client.h"
31 #include "bt-service-obex-agent.h"
32 #include "bt-service-adapter.h"
34 #define DBUS_TIMEOUT 20 * 1000 /* 20 Seconds */
36 enum bt_map_transfer_type {
37 BT_MAP_TRANSFER_GET_MESSAGE = 0,
38 BT_MAP_TRANSFER_PUSH_MESSAGE
42 enum bt_map_transfer_type transfer_type;
45 } bt_map_callback_data_t;
47 static GSList *transfer_list = NULL;
49 bt_session_info_t *session_info;
51 static void __bt_free_session_info(bt_session_info_t *info)
54 g_free(info->address);
58 void _bt_map_disconnected(const char *session_path)
61 GVariant *param = NULL;
62 ret_if(session_info == NULL);
64 if (g_strcmp0(session_info->session_path,
66 BT_INFO("Path mismatch, previous transfer failed! Returning");
70 param = g_variant_new("(isi)", session_info->result,
71 session_info->address,
72 session_info->request_id);
73 _bt_send_event(BT_MAP_CLIENT_EVENT,
74 BLUETOOTH_EVENT_MAP_DISCONNECTED,
77 __bt_free_session_info(session_info);
83 int _bt_create_session_sync(const char* address, char** session_id)
85 BT_DBG("Entered SERVICE create session");
86 GDBusConnection *g_conn;
87 GDBusProxy *session_proxy;
90 retv_if(address == NULL, BLUETOOTH_ERROR_INVALID_PARAM);
92 g_conn = _bt_gdbus_get_session_gconn();
93 retv_if(g_conn == NULL, BLUETOOTH_ERROR_INTERNAL);
95 session_proxy = g_dbus_proxy_new_sync(g_conn, G_DBUS_PROXY_FLAGS_NONE,
96 NULL, BT_OBEX_SERVICE_NAME,
98 BT_OBEX_CLIENT_INTERFACE,
100 if (session_proxy == NULL && err) {
101 BT_ERR("Unable to create session_proxy: %s", err->message);
103 return BLUETOOTH_ERROR_INTERNAL;
106 GVariantBuilder* builder = g_variant_builder_new(G_VARIANT_TYPE_ARRAY);
107 g_variant_builder_add(builder, "{sv}", "Target",
108 g_variant_new("s", "map"));
109 GVariant *args = g_variant_builder_end(builder);
110 g_variant_builder_unref(builder);
111 GVariant *param = g_variant_new("(s@a{sv})", address, args);
113 GVariant *value = g_dbus_proxy_call_sync(session_proxy, "CreateSession", param,
114 G_DBUS_CALL_FLAGS_NONE, -1, NULL, &err);
116 g_object_unref(session_proxy);
119 BT_ERR("Could not create session: %s\n", err->message);
121 return BLUETOOTH_ERROR_INTERNAL;
124 BT_ERR("create session returned value is null\n");
125 return BLUETOOTH_ERROR_INTERNAL;
127 BT_DBG("create session succeed\n");
131 g_variant_get(value, "(&o)", session_id);
132 BT_DBG("session_id = \"%s\"\n", *session_id);
134 return BLUETOOTH_ERROR_NONE;
137 int _bt_destroy_session_sync(const char* session_id)
139 BT_DBG("Entered SERVICE destroy session with id: \"%s\"", session_id);
140 GDBusConnection *g_conn;
141 GDBusProxy *session_proxy;
144 retv_if(session_id == NULL, BLUETOOTH_ERROR_INVALID_PARAM);
146 g_conn = _bt_gdbus_get_session_gconn();
147 retv_if(g_conn == NULL, BLUETOOTH_ERROR_INTERNAL);
149 session_proxy = g_dbus_proxy_new_sync(g_conn, G_DBUS_PROXY_FLAGS_NONE,
150 NULL, BT_OBEX_SERVICE_NAME,
152 BT_OBEX_CLIENT_INTERFACE,
154 if (session_proxy == NULL && err) {
155 BT_ERR("Unable to create session_proxy: %s", err->message);
157 return BLUETOOTH_ERROR_INTERNAL;
160 GVariant *param = g_variant_new("(o)", session_id);
162 g_dbus_proxy_call_sync(session_proxy, "RemoveSession", param,
163 G_DBUS_CALL_FLAGS_NONE, -1, NULL, &err);
165 g_object_unref(session_proxy);
168 BT_ERR("Could not remove session: %s\n", err->message);
170 return BLUETOOTH_ERROR_INTERNAL;
172 BT_DBG("remove session succeed\n");
175 return BLUETOOTH_ERROR_NONE;
178 int _bt_map_client_set_folder(const char* session_id, const char* name)
183 GDBusConnection *g_conn;
184 GDBusProxy *message_proxy;
185 GVariant *ret = NULL;
187 g_conn = _bt_gdbus_get_session_gconn();
188 retv_if(g_conn == NULL, BLUETOOTH_ERROR_INTERNAL);
190 message_proxy = g_dbus_proxy_new_sync(g_conn,
191 G_DBUS_PROXY_FLAGS_NONE, NULL,
192 BT_OBEX_SERVICE_NAME, session_id,
193 BT_OBEX_MESSAGE_INTERFACE, NULL, &err);
195 retv_if(message_proxy == NULL, BLUETOOTH_ERROR_INTERNAL);
197 ret = g_dbus_proxy_call_sync(message_proxy,
198 "SetFolder", g_variant_new("(s)", name),
199 G_DBUS_CALL_FLAGS_NONE, DBUS_TIMEOUT,
204 BT_ERR("SetFolder Error: %s\n", err->message);
208 g_variant_unref(ret);
211 g_object_unref(message_proxy);
215 return BLUETOOTH_ERROR_NONE;
218 static void __bt_list_folders_cb(GDBusProxy *proxy,
219 GAsyncResult *res, gpointer user_data)
223 GError *error = NULL;
224 GVariant *value, *in_param, *param;
226 int result = BLUETOOTH_ERROR_NONE;
229 in_param = (GVariant*) user_data;
230 g_variant_get(in_param, "(i)", &request_id);
232 value = g_dbus_proxy_call_finish(proxy, res, &error);
235 BT_ERR("%s", error->message);
236 g_clear_error(&error);
237 result = BLUETOOTH_ERROR_INTERNAL;
240 param = g_variant_new("(iiv)", result, request_id, value);
241 BT_DBG("RequestID[%d]", request_id);
242 result = _bt_send_event(BT_MAP_CLIENT_EVENT,
243 BLUETOOTH_EVENT_MAP_LIST_FOLDERS_COMPLETE, param);
245 g_variant_unref(value);
246 g_variant_unref(in_param);
251 int _bt_map_client_list_folders(
253 GDBusMethodInvocation *context,
254 const char* session_id,
255 const char* filter_serialized)
257 BT_DBG("Entered _bt_map_list_folders with session id: \"%s\"", session_id);
258 GDBusConnection *g_conn;
259 GDBusProxy *message_access_proxy;
260 GError *error = NULL;
261 int result = BLUETOOTH_ERROR_NONE;
263 retv_if(session_id == NULL, BLUETOOTH_ERROR_INVALID_PARAM);
265 g_conn = _bt_gdbus_get_session_gconn();
266 retv_if(g_conn == NULL, BLUETOOTH_ERROR_INTERNAL);
268 GVariant *out_param1 = g_variant_new_from_data((const GVariantType *)"ay",
269 &request_id, sizeof(int),
271 g_dbus_method_invocation_return_value(context,
272 g_variant_new("(iv)", result, out_param1));
274 // create message access proxy
275 g_clear_error(&error);
276 message_access_proxy = g_dbus_proxy_new_sync(g_conn, G_DBUS_PROXY_FLAGS_NONE, NULL,
277 BT_OBEX_SERVICE_NAME, session_id, "org.bluez.obex.MessageAccess1",
280 BT_ERR("Could not create message access proxy: %s\n", error->message);
281 result = BLUETOOTH_ERROR_INTERNAL;
283 if (!message_access_proxy) {
284 BT_ERR("message proxy handle is null\n");
285 result = BLUETOOTH_ERROR_INTERNAL;
287 BT_DBG("message proxy set");
289 GVariant *filter_variant = g_variant_parse(NULL, filter_serialized, NULL, NULL, NULL);
291 GVariant *params = g_variant_new("(@a{sv})", filter_variant);
292 GVariant *param = g_variant_new("(i)", request_id);
294 g_dbus_proxy_call(message_access_proxy,
295 "ListFolders", params,
296 G_DBUS_CALL_FLAGS_NONE, -1,
298 (GAsyncReadyCallback)__bt_list_folders_cb,
303 g_object_unref(message_access_proxy);
309 static void __bt_list_filter_fields_cb(GDBusProxy *proxy,
310 GAsyncResult *res, gpointer user_data)
314 GError *error = NULL;
315 GVariant *value, *in_param, *param;
317 int result = BLUETOOTH_ERROR_NONE;
320 in_param = (GVariant*) user_data;
321 g_variant_get(in_param, "(i)", &request_id);
323 value = g_dbus_proxy_call_finish(proxy, res, &error);
326 BT_ERR("%s", error->message);
327 g_clear_error(&error);
328 result = BLUETOOTH_ERROR_INTERNAL;
331 param = g_variant_new("(ivi)", result, value, request_id);
333 _bt_send_event(BT_MAP_CLIENT_EVENT, BLUETOOTH_EVENT_MAP_LIST_FILTER_FIELD_COMPLETE,
336 g_variant_unref(value);
337 g_variant_unref(in_param);
342 int _bt_map_client_list_filter_fields(int request_id, GDBusMethodInvocation *context, const char* session_id)
347 GDBusConnection *g_conn;
348 GDBusProxy *message_proxy;
349 int result = BLUETOOTH_ERROR_NONE;
351 retv_if(session_id == NULL, BLUETOOTH_ERROR_INVALID_PARAM);
353 g_conn = _bt_gdbus_get_session_gconn();
354 retv_if(g_conn == NULL, BLUETOOTH_ERROR_INTERNAL);
356 GVariant *out_param = g_variant_new_from_data((const GVariantType *)"ay",
357 &request_id, sizeof(int),
360 g_dbus_method_invocation_return_value(context,
361 g_variant_new("(iv)", result, out_param));
364 message_proxy = g_dbus_proxy_new_sync(g_conn,
365 G_DBUS_PROXY_FLAGS_NONE, NULL,
366 BT_OBEX_SERVICE_NAME, session_id,
367 BT_OBEX_MESSAGE_INTERFACE, NULL, &err);
369 retv_if(message_proxy == NULL, BLUETOOTH_ERROR_INTERNAL);
371 GVariant *param = g_variant_new("(i)", request_id);
373 g_dbus_proxy_call(message_proxy,
374 "ListFilterFields", g_variant_new("()"),
375 G_DBUS_CALL_FLAGS_NONE, -1,
377 (GAsyncReadyCallback)__bt_list_filter_fields_cb,
380 g_object_unref(message_proxy);
384 return BLUETOOTH_ERROR_NONE;
387 static void __bt_list_messages_cb(
388 GDBusProxy *proxy, GAsyncResult *res, gpointer user_data)
392 GError *error = NULL;
393 GVariant *value, *in_param, *param;
395 int result = BLUETOOTH_ERROR_NONE;
398 in_param = (GVariant*) user_data;
399 g_variant_get(in_param, "(i)", &request_id);
401 value = g_dbus_proxy_call_finish(proxy, res, &error);
404 BT_ERR("%s", error->message);
405 g_clear_error(&error);
406 result = BLUETOOTH_ERROR_INTERNAL;
409 param = g_variant_new("(iiv)", result, request_id, value);
410 BT_DBG("RequestID[%d]", request_id);
411 result = _bt_send_event(BT_MAP_CLIENT_EVENT,
412 BLUETOOTH_EVENT_MAP_LIST_MESSAGES_COMPLETE, param);
414 g_variant_unref(value);
415 g_variant_unref(in_param);
420 int _bt_map_client_list_messages(
422 GDBusMethodInvocation *context,
423 const char* session_id,
425 const char* filter_serialized)
427 BT_DBG("Entered _bt_map_client_list_messages with session id: \"%s\"", session_id);
428 BT_DBG("Entered folder: %s", folder);
429 GDBusConnection *g_conn;
430 GDBusProxy *message_access_proxy;
431 GError *error = NULL;
432 int result = BLUETOOTH_ERROR_NONE;
434 retv_if(session_id == NULL, BLUETOOTH_ERROR_INVALID_PARAM);
436 g_conn = _bt_gdbus_get_session_gconn();
437 retv_if(g_conn == NULL, BLUETOOTH_ERROR_INTERNAL);
439 GVariant *out_param1 = g_variant_new_from_data((const GVariantType *)"ay",
440 &request_id, sizeof(int),
442 g_dbus_method_invocation_return_value(context,
443 g_variant_new("(iv)", result, out_param1));
445 // create message access proxy
446 g_clear_error(&error);
447 message_access_proxy = g_dbus_proxy_new_sync(g_conn, G_DBUS_PROXY_FLAGS_NONE, NULL,
448 BT_OBEX_SERVICE_NAME, session_id, "org.bluez.obex.MessageAccess1",
451 BT_ERR("Could not create message access proxy: %s\n", error->message);
452 result = BLUETOOTH_ERROR_INTERNAL;
454 if (!message_access_proxy) {
455 BT_ERR("message proxy handle is null\n");
456 result = BLUETOOTH_ERROR_INTERNAL;
458 BT_DBG("message proxy set");
460 GVariant *filter_variant = g_variant_parse(NULL, filter_serialized, NULL, NULL, NULL);
462 GVariant *params = g_variant_new("(s@a{sv})", folder, filter_variant);
463 GVariant *param = g_variant_new("(i)", request_id);
465 g_dbus_proxy_call(message_access_proxy,
466 "ListMessages", params,
467 G_DBUS_CALL_FLAGS_NONE, -1,
469 (GAsyncReadyCallback)__bt_list_messages_cb,
474 g_object_unref(message_access_proxy);
480 int _bt_map_client_update_inbox(const char* session_id)
485 GDBusConnection *g_conn;
486 GDBusProxy *message_proxy;
487 GVariant *ret = NULL;
489 g_conn = _bt_gdbus_get_session_gconn();
490 retv_if(g_conn == NULL, BLUETOOTH_ERROR_INTERNAL);
492 message_proxy = g_dbus_proxy_new_sync(g_conn,
493 G_DBUS_PROXY_FLAGS_NONE, NULL,
494 BT_OBEX_SERVICE_NAME, session_id,
495 BT_OBEX_MESSAGE_INTERFACE, NULL, &err);
497 retv_if(message_proxy == NULL, BLUETOOTH_ERROR_INTERNAL);
499 ret = g_dbus_proxy_call_sync(message_proxy,
500 "UpdateInbox", g_variant_new("()"),
501 G_DBUS_CALL_FLAGS_NONE, -1,
506 BT_ERR("UpdateInbox Error: %s\n", err->message);
510 g_variant_unref(ret);
513 g_object_unref(message_proxy);
517 return BLUETOOTH_ERROR_NONE;
520 void _bt_map_on_transfer_finished(const char *transfer_object_path, const int error)
522 BT_DBG("Entered _bt_map_on_transfer_finished");
523 BT_DBG("Looking for transfer %s id", transfer_object_path);
525 bt_map_callback_data_t *callback_data = NULL;
526 GSList* transfer = NULL;
527 for (transfer = transfer_list; transfer != NULL; transfer = g_slist_next(transfer)) {
528 callback_data = transfer->data;
529 if (NULL == callback_data)
532 if (0 == strcmp(transfer_object_path, callback_data->transfer_path)) {
533 BT_DBG("request id FOUND - triggering event");
535 GVariant *param = g_variant_new("(ii)", error, callback_data->request_id);
538 switch (callback_data->transfer_type) {
539 case BT_MAP_TRANSFER_GET_MESSAGE:
540 event = BLUETOOTH_EVENT_MAP_GET_MESSAGE_COMPLETE;
542 case BT_MAP_TRANSFER_PUSH_MESSAGE:
543 event = BLUETOOTH_EVENT_MAP_PUSH_MESSAGE_COMPLETE;
547 _bt_send_event(BT_MAP_CLIENT_EVENT, event, param);
549 // remove callback data from list
550 transfer_list = g_slist_remove(transfer_list, transfer);
552 //free memory and break loop
553 free(callback_data->transfer_path);
554 callback_data->transfer_path = NULL;
562 static void __bt_push_message_cb(GDBusProxy *proxy,
563 GAsyncResult *res, gpointer user_data)
567 GError *error = NULL;
568 GVariant *value, *in_param;
570 char *transfer_object_path = NULL;
571 GVariantIter *iter = NULL;
575 in_param = (GVariant*) user_data;
576 g_variant_get(in_param, "(i)", &request_id);
578 value = g_dbus_proxy_call_finish(proxy, res, &error);
580 BT_ERR("%s", error->message);
581 g_clear_error(&error);
585 g_variant_get(value, "(oa{sv})", &transfer_object_path, &iter);
587 BT_DBG("transfer object path: [%s]", transfer_object_path);
589 BT_DBG("Adding request id %d - transfer [%s]", request_id, transfer_object_path);
590 bt_map_callback_data_t* callback_data = malloc(sizeof(*callback_data));
591 callback_data->transfer_type = BT_MAP_TRANSFER_PUSH_MESSAGE;
592 callback_data->request_id = request_id;
593 callback_data->transfer_path = transfer_object_path;
595 transfer_list = g_slist_append(transfer_list, callback_data);
597 g_variant_unref(value);
598 g_variant_unref(in_param);
603 int _bt_map_client_push_message(
605 GDBusMethodInvocation *context,
606 const char* session_id,
607 const char* source_file,
609 const char* args_serialized)
611 BT_DBG("Entered _bt_map_client_push_message with session id: \"%s\"", session_id);
612 BT_DBG("Entered source_file: %s", source_file);
613 BT_DBG("Entered folder: %s", folder);
615 GDBusConnection *g_conn;
616 GDBusProxy *message_access_proxy;
617 GError *error = NULL;
618 int result = BLUETOOTH_ERROR_NONE;
620 retv_if(session_id == NULL, BLUETOOTH_ERROR_INVALID_PARAM);
622 // TODO event listeners registration on first call, where should it be unregistered??
623 _bt_map_client_event_init();
625 g_conn = _bt_gdbus_get_session_gconn();
626 retv_if(g_conn == NULL, BLUETOOTH_ERROR_INTERNAL);
628 GVariant *out_param1 = g_variant_new_from_data((const GVariantType *)"ay",
629 &request_id, sizeof(int),
631 g_dbus_method_invocation_return_value(context, g_variant_new("(iv)", result, out_param1));
633 // create message access proxy
634 g_clear_error(&error);
635 message_access_proxy = g_dbus_proxy_new_sync(g_conn, G_DBUS_PROXY_FLAGS_NONE, NULL,
636 BT_OBEX_SERVICE_NAME, session_id, BT_OBEX_MESSAGE_INTERFACE,
639 BT_ERR("Could not create message access proxy: %s\n", error->message);
640 result = BLUETOOTH_ERROR_INTERNAL;
642 if (!message_access_proxy) {
643 BT_ERR("message proxy handle is null\n");
644 result = BLUETOOTH_ERROR_INTERNAL;
646 BT_DBG("message proxy set");
648 GVariant *args_variant = g_variant_parse(NULL, args_serialized, NULL, NULL, NULL);
650 GVariant *params = g_variant_new("(ss@a{sv})", source_file, folder, args_variant);
651 GVariant *req_id = g_variant_new("(i)", request_id);
653 g_dbus_proxy_call(message_access_proxy,
654 "PushMessage", params,
655 G_DBUS_CALL_FLAGS_NONE, -1,
656 NULL, (GAsyncReadyCallback)__bt_push_message_cb,
661 g_object_unref(message_access_proxy);
667 static void __bt_get_message_cb(GDBusProxy *proxy,
668 GAsyncResult *res, gpointer user_data)
672 GError *error = NULL;
673 GVariant *value, *in_param;
675 char *transfer_object_path = NULL;
676 GVariantIter *iter = NULL;
680 in_param = (GVariant*) user_data;
681 g_variant_get(in_param, "(i)", &request_id);
683 value = g_dbus_proxy_call_finish(proxy, res, &error);
685 BT_ERR("%s", error->message);
686 g_clear_error(&error);
690 g_variant_get(value, "(oa{sv})", &transfer_object_path, &iter);
692 BT_DBG("transfer object path: [%s]", transfer_object_path);
694 BT_DBG("Adding request id %d - transfer [%s]", request_id, transfer_object_path);
695 bt_map_callback_data_t* callback_data = malloc(sizeof(*callback_data));
696 callback_data->transfer_type = BT_MAP_TRANSFER_GET_MESSAGE;
697 callback_data->request_id = request_id;
698 callback_data->transfer_path = transfer_object_path;
700 transfer_list = g_slist_append(transfer_list, callback_data);
702 g_variant_unref(value);
703 g_variant_unref(in_param);
708 int _bt_map_client_get_message(
710 GDBusMethodInvocation *context,
711 const char* message_object,
712 const char* target_file,
715 BT_DBG("Entered _bt_map_client_get_message");
717 GDBusConnection *g_conn;
718 GDBusProxy *message_proxy;
719 GError *error = NULL;
720 int result = BLUETOOTH_ERROR_NONE;
722 retv_if(message_object == NULL, BLUETOOTH_ERROR_INVALID_PARAM);
724 // TODO event listeners registration on first call, where should it be unregistered??
725 _bt_map_client_event_init();
727 g_conn = _bt_gdbus_get_session_gconn();
728 retv_if(g_conn == NULL, BLUETOOTH_ERROR_INTERNAL);
730 GVariant *out_param1 = g_variant_new_from_data((const GVariantType *)"ay",
731 &request_id, sizeof(int),
733 g_dbus_method_invocation_return_value(context, g_variant_new("(iv)", result, out_param1));
735 // create message proxy
736 g_clear_error(&error);
737 message_proxy = g_dbus_proxy_new_sync(g_conn, G_DBUS_PROXY_FLAGS_NONE, NULL,
738 BT_OBEX_SERVICE_NAME, message_object, "org.bluez.obex.Message1",
741 BT_ERR("Could not create message proxy: %s\n", error->message);
742 result = BLUETOOTH_ERROR_INTERNAL;
744 if (!message_proxy) {
745 BT_ERR("message proxy handle is null\n");
746 result = BLUETOOTH_ERROR_INTERNAL;
748 BT_DBG("message proxy set");
749 GVariant *params = g_variant_new("(sb)", target_file, attachment);
750 GVariant *req_id = g_variant_new("(i)", request_id);
752 g_dbus_proxy_call(message_proxy, "Get", params, G_DBUS_CALL_FLAGS_NONE, -1,
753 NULL, (GAsyncReadyCallback)__bt_get_message_cb, (void*)req_id);
757 g_object_unref(message_proxy);