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,
101 BT_ERR("Unable to create session_proxy: %s", err->message);
103 return BLUETOOTH_ERROR_INTERNAL;
105 retv_if(session_proxy == NULL, BLUETOOTH_ERROR_INTERNAL);
107 GVariantBuilder* builder = g_variant_builder_new(G_VARIANT_TYPE_ARRAY);
108 g_variant_builder_add(builder, "{sv}", "Target",
109 g_variant_new("s", "map"));
110 GVariant *args = g_variant_builder_end(builder);
111 g_variant_builder_unref(builder);
112 GVariant *param = g_variant_new("(s@a{sv})", address, args);
114 GVariant *value = g_dbus_proxy_call_sync(session_proxy, "CreateSession", param,
115 G_DBUS_CALL_FLAGS_NONE, -1, NULL, &err);
117 BT_ERR("Could not create session: %s\n", err->message);
119 return BLUETOOTH_ERROR_INTERNAL;
122 BT_ERR("create session returned value is null\n");
123 return BLUETOOTH_ERROR_INTERNAL;
125 BT_DBG("create session succeed\n");
129 g_variant_get(value, "(&o)", session_id);
130 BT_DBG("session_id = \"%s\"\n", *session_id);
132 return BLUETOOTH_ERROR_NONE;
135 int _bt_destroy_session_sync(const char* session_id)
137 BT_DBG("Entered SERVICE destroy session with id: \"%s\"", session_id);
138 GDBusConnection *g_conn;
139 GDBusProxy *session_proxy;
142 retv_if(session_id == NULL, BLUETOOTH_ERROR_INVALID_PARAM);
144 g_conn = _bt_gdbus_get_session_gconn();
145 retv_if(g_conn == NULL, BLUETOOTH_ERROR_INTERNAL);
147 session_proxy = g_dbus_proxy_new_sync(g_conn, G_DBUS_PROXY_FLAGS_NONE,
148 NULL, BT_OBEX_SERVICE_NAME,
150 BT_OBEX_CLIENT_INTERFACE,
153 BT_ERR("Unable to create session_proxy: %s", err->message);
155 return BLUETOOTH_ERROR_INTERNAL;
157 retv_if(session_proxy == NULL, BLUETOOTH_ERROR_INTERNAL);
159 GVariant *param = g_variant_new("(o)", session_id);
161 g_dbus_proxy_call_sync(session_proxy, "RemoveSession", param,
162 G_DBUS_CALL_FLAGS_NONE, -1, NULL, &err);
164 BT_ERR("Could not remove session: %s\n", err->message);
166 return BLUETOOTH_ERROR_INTERNAL;
168 BT_DBG("remove session succeed\n");
171 return BLUETOOTH_ERROR_NONE;
174 int _bt_map_client_set_folder(const char* session_id, const char* name)
179 GDBusConnection *g_conn;
180 GDBusProxy *message_proxy;
181 GVariant *ret = NULL;
183 g_conn = _bt_gdbus_get_session_gconn();
184 retv_if(g_conn == NULL, BLUETOOTH_ERROR_INTERNAL);
186 message_proxy = g_dbus_proxy_new_sync(g_conn,
187 G_DBUS_PROXY_FLAGS_NONE, NULL,
188 BT_OBEX_SERVICE_NAME, session_id,
189 BT_OBEX_MESSAGE_INTERFACE, NULL, &err);
191 retv_if(message_proxy == NULL, BLUETOOTH_ERROR_INTERNAL);
193 ret = g_dbus_proxy_call_sync(message_proxy,
194 "SetFolder", g_variant_new("(s)", name),
195 G_DBUS_CALL_FLAGS_NONE, DBUS_TIMEOUT,
200 BT_ERR("SetFolder Error: %s\n", err->message);
204 g_variant_unref(ret);
207 g_object_unref(message_proxy);
211 return BLUETOOTH_ERROR_NONE;
214 static void __bt_list_folders_cb(GDBusProxy *proxy,
215 GAsyncResult *res, gpointer user_data)
219 GError *error = NULL;
220 GVariant *value, *in_param, *param;
222 int result = BLUETOOTH_ERROR_NONE;
225 in_param = (GVariant*) user_data;
226 g_variant_get(in_param, "(i)", &request_id);
228 value = g_dbus_proxy_call_finish(proxy, res, &error);
231 BT_ERR("%s", error->message);
232 g_clear_error(&error);
233 result = BLUETOOTH_ERROR_INTERNAL;
236 param = g_variant_new("(iiv)", result, request_id, value);
237 BT_DBG("RequestID[%d]", request_id);
238 result = _bt_send_event(BT_MAP_CLIENT_EVENT,
239 BLUETOOTH_EVENT_MAP_LIST_FOLDERS_COMPLETE, param);
241 g_variant_unref(value);
242 g_variant_unref(in_param);
247 int _bt_map_client_list_folders(
249 GDBusMethodInvocation *context,
250 const char* session_id,
251 const char* filter_serialized)
253 BT_DBG("Entered _bt_map_list_folders with session id: \"%s\"", session_id);
254 GDBusConnection *g_conn;
255 GDBusProxy *message_access_proxy;
256 GError *error = NULL;
257 int result = BLUETOOTH_ERROR_NONE;
259 retv_if(session_id == NULL, BLUETOOTH_ERROR_INVALID_PARAM);
261 g_conn = _bt_gdbus_get_session_gconn();
262 retv_if(g_conn == NULL, BLUETOOTH_ERROR_INTERNAL);
264 GVariant *out_param1 = g_variant_new_from_data((const GVariantType *)"ay",
265 &request_id, sizeof(int),
267 g_dbus_method_invocation_return_value(context,
268 g_variant_new("(iv)", result, out_param1));
270 // create message access proxy
271 g_clear_error(&error);
272 message_access_proxy = g_dbus_proxy_new_sync(g_conn, G_DBUS_PROXY_FLAGS_NONE, NULL,
273 BT_OBEX_SERVICE_NAME, session_id, "org.bluez.obex.MessageAccess1",
276 BT_ERR("Could not create message access proxy: %s\n", error->message);
277 result = BLUETOOTH_ERROR_INTERNAL;
279 if (!message_access_proxy) {
280 BT_ERR("message proxy handle is null\n");
281 result = BLUETOOTH_ERROR_INTERNAL;
283 BT_DBG("message proxy set");
285 GVariant *filter_variant = g_variant_parse(NULL, filter_serialized, NULL, NULL, NULL);
287 GVariant *params = g_variant_new("(@a{sv})", filter_variant);
288 GVariant *param = g_variant_new("(i)", request_id);
290 g_dbus_proxy_call(message_access_proxy,
291 "ListFolders", params,
292 G_DBUS_CALL_FLAGS_NONE, -1,
294 (GAsyncReadyCallback)__bt_list_folders_cb,
299 g_object_unref(message_access_proxy);
305 static void __bt_list_filter_fields_cb(GDBusProxy *proxy,
306 GAsyncResult *res, gpointer user_data)
310 GError *error = NULL;
311 GVariant *value, *in_param, *param;
313 int result = BLUETOOTH_ERROR_NONE;
316 in_param = (GVariant*) user_data;
317 g_variant_get(in_param, "(i)", &request_id);
319 value = g_dbus_proxy_call_finish(proxy, res, &error);
322 BT_ERR("%s", error->message);
323 g_clear_error(&error);
324 result = BLUETOOTH_ERROR_INTERNAL;
327 param = g_variant_new("(ivi)", result, value, request_id);
329 _bt_send_event(BT_MAP_CLIENT_EVENT, BLUETOOTH_EVENT_MAP_LIST_FILTER_FIELD_COMPLETE,
332 g_variant_unref(value);
333 g_variant_unref(in_param);
338 int _bt_map_client_list_filter_fields(int request_id, GDBusMethodInvocation *context, const char* session_id)
343 GDBusConnection *g_conn;
344 GDBusProxy *message_proxy;
345 int result = BLUETOOTH_ERROR_NONE;
347 retv_if(session_id == NULL, BLUETOOTH_ERROR_INVALID_PARAM);
349 g_conn = _bt_gdbus_get_session_gconn();
350 retv_if(g_conn == NULL, BLUETOOTH_ERROR_INTERNAL);
352 GVariant *out_param = g_variant_new_from_data((const GVariantType *)"ay",
353 &request_id, sizeof(int),
356 g_dbus_method_invocation_return_value(context,
357 g_variant_new("(iv)", result, out_param));
360 message_proxy = g_dbus_proxy_new_sync(g_conn,
361 G_DBUS_PROXY_FLAGS_NONE, NULL,
362 BT_OBEX_SERVICE_NAME, session_id,
363 BT_OBEX_MESSAGE_INTERFACE, NULL, &err);
365 retv_if(message_proxy == NULL, BLUETOOTH_ERROR_INTERNAL);
367 GVariant *param = g_variant_new("(i)", request_id);
369 g_dbus_proxy_call(message_proxy,
370 "ListFilterFields", g_variant_new("()"),
371 G_DBUS_CALL_FLAGS_NONE, -1,
373 (GAsyncReadyCallback)__bt_list_filter_fields_cb,
376 g_object_unref(message_proxy);
380 return BLUETOOTH_ERROR_NONE;
383 static void __bt_list_messages_cb(
384 GDBusProxy *proxy, GAsyncResult *res, gpointer user_data)
388 GError *error = NULL;
389 GVariant *value, *in_param, *param;
391 int result = BLUETOOTH_ERROR_NONE;
394 in_param = (GVariant*) user_data;
395 g_variant_get(in_param, "(i)", &request_id);
397 value = g_dbus_proxy_call_finish(proxy, res, &error);
400 BT_ERR("%s", error->message);
401 g_clear_error(&error);
402 result = BLUETOOTH_ERROR_INTERNAL;
405 param = g_variant_new("(iiv)", result, request_id, value);
406 BT_DBG("RequestID[%d]", request_id);
407 result = _bt_send_event(BT_MAP_CLIENT_EVENT,
408 BLUETOOTH_EVENT_MAP_LIST_MESSAGES_COMPLETE, param);
410 g_variant_unref(value);
411 g_variant_unref(in_param);
416 int _bt_map_client_list_messages(
418 GDBusMethodInvocation *context,
419 const char* session_id,
421 const char* filter_serialized)
423 BT_DBG("Entered _bt_map_client_list_messages with session id: \"%s\"", session_id);
424 BT_DBG("Entered folder: %s", folder);
425 GDBusConnection *g_conn;
426 GDBusProxy *message_access_proxy;
427 GError *error = NULL;
428 int result = BLUETOOTH_ERROR_NONE;
430 retv_if(session_id == NULL, BLUETOOTH_ERROR_INVALID_PARAM);
432 g_conn = _bt_gdbus_get_session_gconn();
433 retv_if(g_conn == NULL, BLUETOOTH_ERROR_INTERNAL);
435 GVariant *out_param1 = g_variant_new_from_data((const GVariantType *)"ay",
436 &request_id, sizeof(int),
438 g_dbus_method_invocation_return_value(context,
439 g_variant_new("(iv)", result, out_param1));
441 // create message access proxy
442 g_clear_error(&error);
443 message_access_proxy = g_dbus_proxy_new_sync(g_conn, G_DBUS_PROXY_FLAGS_NONE, NULL,
444 BT_OBEX_SERVICE_NAME, session_id, "org.bluez.obex.MessageAccess1",
447 BT_ERR("Could not create message access proxy: %s\n", error->message);
448 result = BLUETOOTH_ERROR_INTERNAL;
450 if (!message_access_proxy) {
451 BT_ERR("message proxy handle is null\n");
452 result = BLUETOOTH_ERROR_INTERNAL;
454 BT_DBG("message proxy set");
456 GVariant *filter_variant = g_variant_parse(NULL, filter_serialized, NULL, NULL, NULL);
458 GVariant *params = g_variant_new("(s@a{sv})", folder, filter_variant);
459 GVariant *param = g_variant_new("(i)", request_id);
461 g_dbus_proxy_call(message_access_proxy,
462 "ListMessages", params,
463 G_DBUS_CALL_FLAGS_NONE, -1,
465 (GAsyncReadyCallback)__bt_list_messages_cb,
470 g_object_unref(message_access_proxy);
476 int _bt_map_client_update_inbox(const char* session_id)
481 GDBusConnection *g_conn;
482 GDBusProxy *message_proxy;
483 GVariant *ret = NULL;
485 g_conn = _bt_gdbus_get_session_gconn();
486 retv_if(g_conn == NULL, BLUETOOTH_ERROR_INTERNAL);
488 message_proxy = g_dbus_proxy_new_sync(g_conn,
489 G_DBUS_PROXY_FLAGS_NONE, NULL,
490 BT_OBEX_SERVICE_NAME, session_id,
491 BT_OBEX_MESSAGE_INTERFACE, NULL, &err);
493 retv_if(message_proxy == NULL, BLUETOOTH_ERROR_INTERNAL);
495 ret = g_dbus_proxy_call_sync(message_proxy,
496 "UpdateInbox", g_variant_new("()"),
497 G_DBUS_CALL_FLAGS_NONE, -1,
502 BT_ERR("UpdateInbox Error: %s\n", err->message);
506 g_variant_unref(ret);
509 g_object_unref(message_proxy);
513 return BLUETOOTH_ERROR_NONE;
516 void _bt_map_on_transfer_finished(const char *transfer_object_path, const int error)
518 BT_DBG("Entered _bt_map_on_transfer_finished");
519 BT_DBG("Looking for transfer %s id", transfer_object_path);
521 bt_map_callback_data_t *callback_data = NULL;
522 GSList* transfer = NULL;
523 for (transfer = transfer_list; transfer != NULL; transfer = g_slist_next(transfer)) {
524 callback_data = transfer->data;
525 if (NULL == callback_data)
528 if (0 == strcmp(transfer_object_path, callback_data->transfer_path)) {
529 BT_DBG("request id FOUND - triggering event");
531 GVariant *param = g_variant_new("(ii)", error, callback_data->request_id);
534 switch (callback_data->transfer_type) {
535 case BT_MAP_TRANSFER_GET_MESSAGE:
536 event = BLUETOOTH_EVENT_MAP_GET_MESSAGE_COMPLETE;
538 case BT_MAP_TRANSFER_PUSH_MESSAGE:
539 event = BLUETOOTH_EVENT_MAP_PUSH_MESSAGE_COMPLETE;
543 _bt_send_event(BT_MAP_CLIENT_EVENT, event, param);
545 // remove callback data from list
546 transfer_list = g_slist_remove(transfer_list, transfer);
548 //free memory and break loop
549 free(callback_data->transfer_path);
550 callback_data->transfer_path = NULL;
558 static void __bt_push_message_cb(GDBusProxy *proxy,
559 GAsyncResult *res, gpointer user_data)
563 GError *error = NULL;
564 GVariant *value, *in_param;
566 char *transfer_object_path = NULL;
567 GVariantIter *iter = NULL;
571 in_param = (GVariant*) user_data;
572 g_variant_get(in_param, "(i)", &request_id);
574 value = g_dbus_proxy_call_finish(proxy, res, &error);
576 BT_ERR("%s", error->message);
577 g_clear_error(&error);
581 g_variant_get(value, "(oa{sv})", &transfer_object_path, &iter);
582 g_variant_unref(value);
585 BT_DBG("transfer object path: [%s]", transfer_object_path);
587 BT_DBG("Adding request id %d - transfer [%s]", request_id, transfer_object_path);
588 bt_map_callback_data_t* callback_data = malloc(sizeof(*callback_data));
589 callback_data->transfer_type = BT_MAP_TRANSFER_PUSH_MESSAGE;
590 callback_data->request_id = request_id;
591 callback_data->transfer_path = transfer_object_path;
593 transfer_list = g_slist_append(transfer_list, callback_data);
595 g_variant_unref(value);
596 g_variant_unref(in_param);
601 int _bt_map_client_push_message(
603 GDBusMethodInvocation *context,
604 const char* session_id,
605 const char* source_file,
607 const char* args_serialized)
609 BT_DBG("Entered _bt_map_client_push_message with session id: \"%s\"", session_id);
610 BT_DBG("Entered source_file: %s", source_file);
611 BT_DBG("Entered folder: %s", folder);
613 GDBusConnection *g_conn;
614 GDBusProxy *message_access_proxy;
615 GError *error = NULL;
616 int result = BLUETOOTH_ERROR_NONE;
618 retv_if(session_id == NULL, BLUETOOTH_ERROR_INVALID_PARAM);
620 // TODO event listeners registration on first call, where should it be unregistered??
621 _bt_map_client_event_init();
623 g_conn = _bt_gdbus_get_session_gconn();
624 retv_if(g_conn == NULL, BLUETOOTH_ERROR_INTERNAL);
626 GVariant *out_param1 = g_variant_new_from_data((const GVariantType *)"ay",
627 &request_id, sizeof(int),
629 g_dbus_method_invocation_return_value(context, g_variant_new("(iv)", result, out_param1));
631 // create message access proxy
632 g_clear_error(&error);
633 message_access_proxy = g_dbus_proxy_new_sync(g_conn, G_DBUS_PROXY_FLAGS_NONE, NULL,
634 BT_OBEX_SERVICE_NAME, session_id, BT_OBEX_MESSAGE_INTERFACE,
637 BT_ERR("Could not create message access proxy: %s\n", error->message);
638 result = BLUETOOTH_ERROR_INTERNAL;
640 if (!message_access_proxy) {
641 BT_ERR("message proxy handle is null\n");
642 result = BLUETOOTH_ERROR_INTERNAL;
644 BT_DBG("message proxy set");
646 GVariant *args_variant = g_variant_parse(NULL, args_serialized, NULL, NULL, NULL);
648 GVariant *params = g_variant_new("(ss@a{sv})", source_file, folder, args_variant);
649 GVariant *req_id = g_variant_new("(i)", request_id);
651 g_dbus_proxy_call(message_access_proxy,
652 "PushMessage", params,
653 G_DBUS_CALL_FLAGS_NONE, -1,
654 NULL, (GAsyncReadyCallback)__bt_push_message_cb,
659 g_object_unref(message_access_proxy);
665 static void __bt_get_message_cb(GDBusProxy *proxy,
666 GAsyncResult *res, gpointer user_data)
670 GError *error = NULL;
671 GVariant *value, *in_param;
673 char *transfer_object_path = NULL;
674 GVariantIter *iter = NULL;
678 in_param = (GVariant*) user_data;
679 g_variant_get(in_param, "(i)", &request_id);
681 value = g_dbus_proxy_call_finish(proxy, res, &error);
683 BT_ERR("%s", error->message);
684 g_clear_error(&error);
688 g_variant_get(value, "(oa{sv})", &transfer_object_path, &iter);
689 g_variant_unref(value);
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);