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.
21 #include <mime_type.h>
26 #include "bluetooth-api.h"
27 #include "bt-internal-types.h"
29 #include "bt-service-common.h"
30 #include "bt-service-event.h"
31 #include "bt-service-util.h"
32 #include "bt-service-map-client.h"
33 #include "bt-service-obex-agent.h"
34 #include "bt-service-adapter.h"
36 #define DBUS_TIMEOUT 20 * 1000 /* 20 Seconds */
38 enum bt_map_transfer_type {
39 BT_MAP_TRANSFER_GET_MESSAGE = 0,
40 BT_MAP_TRANSFER_PUSH_MESSAGE
44 enum bt_map_transfer_type transfer_type;
47 } bt_map_callback_data_t;
49 static GSList *transfer_list = NULL;
51 bt_session_info_t *session_info;
53 static void __bt_free_session_info(bt_session_info_t *info)
56 g_free(info->address);
60 void _bt_map_disconnected(const char *session_path)
63 GVariant *param = NULL;
64 ret_if(session_info == NULL);
66 if (g_strcmp0(session_info->session_path,
68 BT_INFO("Path mismatch, previous transfer failed! Returning");
72 param = g_variant_new("(isi)", session_info->result,
73 session_info->address,
74 session_info->request_id);
75 _bt_send_event(BT_MAP_CLIENT_EVENT,
76 BLUETOOTH_EVENT_MAP_DISCONNECTED,
79 __bt_free_session_info(session_info);
85 int _bt_create_session_sync(const char* address, char** session_id)
87 BT_DBG("Entered SERVICE create session");
88 GDBusConnection *g_conn;
89 GDBusProxy *session_proxy;
92 retv_if(address == NULL, BLUETOOTH_ERROR_INVALID_PARAM);
94 g_conn = _bt_gdbus_get_session_gconn();
95 retv_if(g_conn == NULL, BLUETOOTH_ERROR_INTERNAL);
97 session_proxy = g_dbus_proxy_new_sync(g_conn, G_DBUS_PROXY_FLAGS_NONE,
98 NULL, BT_OBEX_SERVICE_NAME,
100 BT_OBEX_CLIENT_INTERFACE,
103 BT_ERR("Unable to create session_proxy: %s", err->message);
105 return BLUETOOTH_ERROR_INTERNAL;
107 retv_if(session_proxy == NULL, BLUETOOTH_ERROR_INTERNAL);
109 GVariantBuilder* builder = g_variant_builder_new(G_VARIANT_TYPE_ARRAY);
110 g_variant_builder_add(builder, "{sv}", "Target",
111 g_variant_new("s", "map"));
112 GVariant *args = g_variant_builder_end(builder);
113 g_variant_builder_unref(builder);
114 GVariant *param = g_variant_new("(s@a{sv})", address, args);
116 GVariant *value = g_dbus_proxy_call_sync(session_proxy, "CreateSession", param,
117 G_DBUS_CALL_FLAGS_NONE, -1, NULL, &err);
119 g_object_unref(session_proxy);
122 BT_ERR("Could not create session: %s\n", err->message);
124 return BLUETOOTH_ERROR_INTERNAL;
127 BT_ERR("create session returned value is null\n");
128 return BLUETOOTH_ERROR_INTERNAL;
130 BT_DBG("create session succeed\n");
134 g_variant_get(value, "(&o)", session_id);
135 BT_DBG("session_id = \"%s\"\n", *session_id);
137 return BLUETOOTH_ERROR_NONE;
140 int _bt_destroy_session_sync(const char* session_id)
142 BT_DBG("Entered SERVICE destroy session with id: \"%s\"", session_id);
143 GDBusConnection *g_conn;
144 GDBusProxy *session_proxy;
147 retv_if(session_id == NULL, BLUETOOTH_ERROR_INVALID_PARAM);
149 g_conn = _bt_gdbus_get_session_gconn();
150 retv_if(g_conn == NULL, BLUETOOTH_ERROR_INTERNAL);
152 session_proxy = g_dbus_proxy_new_sync(g_conn, G_DBUS_PROXY_FLAGS_NONE,
153 NULL, BT_OBEX_SERVICE_NAME,
155 BT_OBEX_CLIENT_INTERFACE,
158 BT_ERR("Unable to create session_proxy: %s", err->message);
160 return BLUETOOTH_ERROR_INTERNAL;
162 retv_if(session_proxy == NULL, BLUETOOTH_ERROR_INTERNAL);
164 GVariant *param = g_variant_new("(o)", session_id);
166 g_dbus_proxy_call_sync(session_proxy, "RemoveSession", param,
167 G_DBUS_CALL_FLAGS_NONE, -1, NULL, &err);
169 g_object_unref(session_proxy);
172 BT_ERR("Could not remove session: %s\n", err->message);
174 return BLUETOOTH_ERROR_INTERNAL;
176 BT_DBG("remove session succeed\n");
179 return BLUETOOTH_ERROR_NONE;
182 int _bt_map_client_set_folder(const char* session_id, const char* name)
187 GDBusConnection *g_conn;
188 GDBusProxy *message_proxy;
189 GVariant *ret = NULL;
191 g_conn = _bt_gdbus_get_session_gconn();
192 retv_if(g_conn == NULL, BLUETOOTH_ERROR_INTERNAL);
194 message_proxy = g_dbus_proxy_new_sync(g_conn,
195 G_DBUS_PROXY_FLAGS_NONE, NULL,
196 BT_OBEX_SERVICE_NAME, session_id,
197 BT_OBEX_MESSAGE_INTERFACE, NULL, &err);
199 retv_if(message_proxy == NULL, BLUETOOTH_ERROR_INTERNAL);
201 ret = g_dbus_proxy_call_sync(message_proxy,
202 "SetFolder", g_variant_new("(s)", name),
203 G_DBUS_CALL_FLAGS_NONE, DBUS_TIMEOUT,
208 BT_ERR("SetFolder Error: %s\n", err->message);
212 g_variant_unref(ret);
215 g_object_unref(message_proxy);
219 return BLUETOOTH_ERROR_NONE;
222 static void __bt_list_folders_cb(GDBusProxy *proxy,
223 GAsyncResult *res, gpointer user_data)
227 GError *error = NULL;
228 GVariant *value, *in_param, *param;
230 int result = BLUETOOTH_ERROR_NONE;
233 in_param = (GVariant*) user_data;
234 g_variant_get(in_param, "(i)", &request_id);
236 value = g_dbus_proxy_call_finish(proxy, res, &error);
239 BT_ERR("%s", error->message);
240 g_clear_error(&error);
241 result = BLUETOOTH_ERROR_INTERNAL;
244 param = g_variant_new("(iiv)", result, request_id, value);
245 BT_DBG("RequestID[%d]", request_id);
246 result = _bt_send_event(BT_MAP_CLIENT_EVENT,
247 BLUETOOTH_EVENT_MAP_LIST_FOLDERS_COMPLETE, param);
249 g_variant_unref(value);
250 g_variant_unref(in_param);
255 int _bt_map_client_list_folders(
257 GDBusMethodInvocation *context,
258 const char* session_id,
259 const char* filter_serialized)
261 BT_DBG("Entered _bt_map_list_folders with session id: \"%s\"", session_id);
262 GDBusConnection *g_conn;
263 GDBusProxy *message_access_proxy;
264 GError *error = NULL;
265 int result = BLUETOOTH_ERROR_NONE;
267 retv_if(session_id == NULL, BLUETOOTH_ERROR_INVALID_PARAM);
269 g_conn = _bt_gdbus_get_session_gconn();
270 retv_if(g_conn == NULL, BLUETOOTH_ERROR_INTERNAL);
272 GVariant *out_param1 = g_variant_new_from_data((const GVariantType *)"ay",
273 &request_id, sizeof(int),
275 g_dbus_method_invocation_return_value(context,
276 g_variant_new("(iv)", result, out_param1));
278 // create message access proxy
279 g_clear_error(&error);
280 message_access_proxy = g_dbus_proxy_new_sync(g_conn, G_DBUS_PROXY_FLAGS_NONE, NULL,
281 BT_OBEX_SERVICE_NAME, session_id, "org.bluez.obex.MessageAccess1",
284 BT_ERR("Could not create message access proxy: %s\n", error->message);
285 result = BLUETOOTH_ERROR_INTERNAL;
287 if (!message_access_proxy) {
288 BT_ERR("message proxy handle is null\n");
289 result = BLUETOOTH_ERROR_INTERNAL;
291 BT_DBG("message proxy set");
293 GVariant *filter_variant = g_variant_parse(NULL, filter_serialized, NULL, NULL, NULL);
295 GVariant *params = g_variant_new("(@a{sv})", filter_variant);
296 GVariant *param = g_variant_new("(i)", request_id);
298 g_dbus_proxy_call(message_access_proxy,
299 "ListFolders", params,
300 G_DBUS_CALL_FLAGS_NONE, -1,
302 (GAsyncReadyCallback)__bt_list_folders_cb,
307 g_object_unref(message_access_proxy);
313 static void __bt_list_filter_fields_cb(GDBusProxy *proxy,
314 GAsyncResult *res, gpointer user_data)
318 GError *error = NULL;
319 GVariant *value, *in_param, *param;
321 int result = BLUETOOTH_ERROR_NONE;
324 in_param = (GVariant*) user_data;
325 g_variant_get(in_param, "(i)", &request_id);
327 value = g_dbus_proxy_call_finish(proxy, res, &error);
330 BT_ERR("%s", error->message);
331 g_clear_error(&error);
332 result = BLUETOOTH_ERROR_INTERNAL;
335 param = g_variant_new("(ivi)", result, value, request_id);
337 _bt_send_event(BT_MAP_CLIENT_EVENT, BLUETOOTH_EVENT_MAP_LIST_FILTER_FIELD_COMPLETE,
340 g_variant_unref(value);
341 g_variant_unref(in_param);
346 int _bt_map_client_list_filter_fields(int request_id, GDBusMethodInvocation *context, const char* session_id)
351 GDBusConnection *g_conn;
352 GDBusProxy *message_proxy;
353 int result = BLUETOOTH_ERROR_NONE;
355 retv_if(session_id == NULL, BLUETOOTH_ERROR_INVALID_PARAM);
357 g_conn = _bt_gdbus_get_session_gconn();
358 retv_if(g_conn == NULL, BLUETOOTH_ERROR_INTERNAL);
360 GVariant *out_param = g_variant_new_from_data((const GVariantType *)"ay",
361 &request_id, sizeof(int),
364 g_dbus_method_invocation_return_value(context,
365 g_variant_new("(iv)", result, out_param));
368 message_proxy = g_dbus_proxy_new_sync(g_conn,
369 G_DBUS_PROXY_FLAGS_NONE, NULL,
370 BT_OBEX_SERVICE_NAME, session_id,
371 BT_OBEX_MESSAGE_INTERFACE, NULL, &err);
373 retv_if(message_proxy == NULL, BLUETOOTH_ERROR_INTERNAL);
375 GVariant *param = g_variant_new("(i)", request_id);
377 g_dbus_proxy_call(message_proxy,
378 "ListFilterFields", g_variant_new("()"),
379 G_DBUS_CALL_FLAGS_NONE, -1,
381 (GAsyncReadyCallback)__bt_list_filter_fields_cb,
384 g_object_unref(message_proxy);
388 return BLUETOOTH_ERROR_NONE;
391 static void __bt_list_messages_cb(
392 GDBusProxy *proxy, GAsyncResult *res, gpointer user_data)
396 GError *error = NULL;
397 GVariant *value, *in_param, *param;
399 int result = BLUETOOTH_ERROR_NONE;
402 in_param = (GVariant*) user_data;
403 g_variant_get(in_param, "(i)", &request_id);
405 value = g_dbus_proxy_call_finish(proxy, res, &error);
408 BT_ERR("%s", error->message);
409 g_clear_error(&error);
410 result = BLUETOOTH_ERROR_INTERNAL;
413 param = g_variant_new("(iiv)", result, request_id, value);
414 BT_DBG("RequestID[%d]", request_id);
415 result = _bt_send_event(BT_MAP_CLIENT_EVENT,
416 BLUETOOTH_EVENT_MAP_LIST_MESSAGES_COMPLETE, param);
418 g_variant_unref(value);
419 g_variant_unref(in_param);
424 int _bt_map_client_list_messages(
426 GDBusMethodInvocation *context,
427 const char* session_id,
429 const char* filter_serialized)
431 BT_DBG("Entered _bt_map_client_list_messages with session id: \"%s\"", session_id);
432 BT_DBG("Entered folder: %s", folder);
433 GDBusConnection *g_conn;
434 GDBusProxy *message_access_proxy;
435 GError *error = NULL;
436 int result = BLUETOOTH_ERROR_NONE;
438 retv_if(session_id == NULL, BLUETOOTH_ERROR_INVALID_PARAM);
440 g_conn = _bt_gdbus_get_session_gconn();
441 retv_if(g_conn == NULL, BLUETOOTH_ERROR_INTERNAL);
443 GVariant *out_param1 = g_variant_new_from_data((const GVariantType *)"ay",
444 &request_id, sizeof(int),
446 g_dbus_method_invocation_return_value(context,
447 g_variant_new("(iv)", result, out_param1));
449 // create message access proxy
450 g_clear_error(&error);
451 message_access_proxy = g_dbus_proxy_new_sync(g_conn, G_DBUS_PROXY_FLAGS_NONE, NULL,
452 BT_OBEX_SERVICE_NAME, session_id, "org.bluez.obex.MessageAccess1",
455 BT_ERR("Could not create message access proxy: %s\n", error->message);
456 result = BLUETOOTH_ERROR_INTERNAL;
458 if (!message_access_proxy) {
459 BT_ERR("message proxy handle is null\n");
460 result = BLUETOOTH_ERROR_INTERNAL;
462 BT_DBG("message proxy set");
464 GVariant *filter_variant = g_variant_parse(NULL, filter_serialized, NULL, NULL, NULL);
466 GVariant *params = g_variant_new("(s@a{sv})", folder, filter_variant);
467 GVariant *param = g_variant_new("(i)", request_id);
469 g_dbus_proxy_call(message_access_proxy,
470 "ListMessages", params,
471 G_DBUS_CALL_FLAGS_NONE, -1,
473 (GAsyncReadyCallback)__bt_list_messages_cb,
478 g_object_unref(message_access_proxy);
484 int _bt_map_client_update_inbox(const char* session_id)
489 GDBusConnection *g_conn;
490 GDBusProxy *message_proxy;
491 GVariant *ret = NULL;
493 g_conn = _bt_gdbus_get_session_gconn();
494 retv_if(g_conn == NULL, BLUETOOTH_ERROR_INTERNAL);
496 message_proxy = g_dbus_proxy_new_sync(g_conn,
497 G_DBUS_PROXY_FLAGS_NONE, NULL,
498 BT_OBEX_SERVICE_NAME, session_id,
499 BT_OBEX_MESSAGE_INTERFACE, NULL, &err);
501 retv_if(message_proxy == NULL, BLUETOOTH_ERROR_INTERNAL);
503 ret = g_dbus_proxy_call_sync(message_proxy,
504 "UpdateInbox", g_variant_new("()"),
505 G_DBUS_CALL_FLAGS_NONE, -1,
510 BT_ERR("UpdateInbox Error: %s\n", err->message);
514 g_variant_unref(ret);
517 g_object_unref(message_proxy);
521 return BLUETOOTH_ERROR_NONE;
524 void _bt_map_on_transfer_finished(const char *transfer_object_path, const int error)
526 BT_DBG("Entered _bt_map_on_transfer_finished");
527 BT_DBG("Looking for transfer %s id", transfer_object_path);
529 bt_map_callback_data_t *callback_data = NULL;
530 GSList* transfer = NULL;
531 for (transfer = transfer_list; transfer != NULL; transfer = g_slist_next(transfer)) {
532 callback_data = transfer->data;
533 if (NULL == callback_data)
536 if (0 == strcmp(transfer_object_path, callback_data->transfer_path)) {
537 BT_DBG("request id FOUND - triggering event");
539 GVariant *param = g_variant_new("(ii)", error, callback_data->request_id);
542 switch (callback_data->transfer_type) {
543 case BT_MAP_TRANSFER_GET_MESSAGE:
544 event = BLUETOOTH_EVENT_MAP_GET_MESSAGE_COMPLETE;
546 case BT_MAP_TRANSFER_PUSH_MESSAGE:
547 event = BLUETOOTH_EVENT_MAP_PUSH_MESSAGE_COMPLETE;
551 _bt_send_event(BT_MAP_CLIENT_EVENT, event, param);
553 // remove callback data from list
554 transfer_list = g_slist_remove(transfer_list, transfer);
556 //free memory and break loop
557 free(callback_data->transfer_path);
558 callback_data->transfer_path = NULL;
566 static void __bt_push_message_cb(GDBusProxy *proxy,
567 GAsyncResult *res, gpointer user_data)
571 GError *error = NULL;
572 GVariant *value, *in_param;
574 char *transfer_object_path = NULL;
575 GVariantIter *iter = NULL;
579 in_param = (GVariant*) user_data;
580 g_variant_get(in_param, "(i)", &request_id);
582 value = g_dbus_proxy_call_finish(proxy, res, &error);
584 BT_ERR("%s", error->message);
585 g_clear_error(&error);
589 g_variant_get(value, "(oa{sv})", &transfer_object_path, &iter);
591 BT_DBG("transfer object path: [%s]", transfer_object_path);
593 BT_DBG("Adding request id %d - transfer [%s]", request_id, transfer_object_path);
594 bt_map_callback_data_t* callback_data = malloc(sizeof(*callback_data));
595 callback_data->transfer_type = BT_MAP_TRANSFER_PUSH_MESSAGE;
596 callback_data->request_id = request_id;
597 callback_data->transfer_path = transfer_object_path;
599 transfer_list = g_slist_append(transfer_list, callback_data);
601 g_variant_unref(value);
602 g_variant_unref(in_param);
607 int _bt_map_client_push_message(
609 GDBusMethodInvocation *context,
610 const char* session_id,
611 const char* source_file,
613 const char* args_serialized)
615 BT_DBG("Entered _bt_map_client_push_message with session id: \"%s\"", session_id);
616 BT_DBG("Entered source_file: %s", source_file);
617 BT_DBG("Entered folder: %s", folder);
619 GDBusConnection *g_conn;
620 GDBusProxy *message_access_proxy;
621 GError *error = NULL;
622 int result = BLUETOOTH_ERROR_NONE;
624 retv_if(session_id == NULL, BLUETOOTH_ERROR_INVALID_PARAM);
626 // TODO event listeners registration on first call, where should it be unregistered??
627 _bt_map_client_event_init();
629 g_conn = _bt_gdbus_get_session_gconn();
630 retv_if(g_conn == NULL, BLUETOOTH_ERROR_INTERNAL);
632 GVariant *out_param1 = g_variant_new_from_data((const GVariantType *)"ay",
633 &request_id, sizeof(int),
635 g_dbus_method_invocation_return_value(context, g_variant_new("(iv)", result, out_param1));
637 // create message access proxy
638 g_clear_error(&error);
639 message_access_proxy = g_dbus_proxy_new_sync(g_conn, G_DBUS_PROXY_FLAGS_NONE, NULL,
640 BT_OBEX_SERVICE_NAME, session_id, BT_OBEX_MESSAGE_INTERFACE,
643 BT_ERR("Could not create message access proxy: %s\n", error->message);
644 result = BLUETOOTH_ERROR_INTERNAL;
646 if (!message_access_proxy) {
647 BT_ERR("message proxy handle is null\n");
648 result = BLUETOOTH_ERROR_INTERNAL;
650 BT_DBG("message proxy set");
652 GVariant *args_variant = g_variant_parse(NULL, args_serialized, NULL, NULL, NULL);
654 GVariant *params = g_variant_new("(ss@a{sv})", source_file, folder, args_variant);
655 GVariant *req_id = g_variant_new("(i)", request_id);
657 g_dbus_proxy_call(message_access_proxy,
658 "PushMessage", params,
659 G_DBUS_CALL_FLAGS_NONE, -1,
660 NULL, (GAsyncReadyCallback)__bt_push_message_cb,
665 g_object_unref(message_access_proxy);
671 static void __bt_get_message_cb(GDBusProxy *proxy,
672 GAsyncResult *res, gpointer user_data)
676 GError *error = NULL;
677 GVariant *value, *in_param;
679 char *transfer_object_path = NULL;
680 GVariantIter *iter = NULL;
684 in_param = (GVariant*) user_data;
685 g_variant_get(in_param, "(i)", &request_id);
687 value = g_dbus_proxy_call_finish(proxy, res, &error);
689 BT_ERR("%s", error->message);
690 g_clear_error(&error);
694 g_variant_get(value, "(oa{sv})", &transfer_object_path, &iter);
696 BT_DBG("transfer object path: [%s]", transfer_object_path);
698 BT_DBG("Adding request id %d - transfer [%s]", request_id, transfer_object_path);
699 bt_map_callback_data_t* callback_data = malloc(sizeof(*callback_data));
700 callback_data->transfer_type = BT_MAP_TRANSFER_GET_MESSAGE;
701 callback_data->request_id = request_id;
702 callback_data->transfer_path = transfer_object_path;
704 transfer_list = g_slist_append(transfer_list, callback_data);
706 g_variant_unref(value);
707 g_variant_unref(in_param);
712 int _bt_map_client_get_message(
714 GDBusMethodInvocation *context,
715 const char* message_object,
716 const char* target_file,
719 BT_DBG("Entered _bt_map_client_get_message");
721 GDBusConnection *g_conn;
722 GDBusProxy *message_proxy;
723 GError *error = NULL;
724 int result = BLUETOOTH_ERROR_NONE;
726 retv_if(message_object == NULL, BLUETOOTH_ERROR_INVALID_PARAM);
728 // TODO event listeners registration on first call, where should it be unregistered??
729 _bt_map_client_event_init();
731 g_conn = _bt_gdbus_get_session_gconn();
732 retv_if(g_conn == NULL, BLUETOOTH_ERROR_INTERNAL);
734 GVariant *out_param1 = g_variant_new_from_data((const GVariantType *)"ay",
735 &request_id, sizeof(int),
737 g_dbus_method_invocation_return_value(context, g_variant_new("(iv)", result, out_param1));
739 // create message proxy
740 g_clear_error(&error);
741 message_proxy = g_dbus_proxy_new_sync(g_conn, G_DBUS_PROXY_FLAGS_NONE, NULL,
742 BT_OBEX_SERVICE_NAME, message_object, "org.bluez.obex.Message1",
745 BT_ERR("Could not create message proxy: %s\n", error->message);
746 result = BLUETOOTH_ERROR_INTERNAL;
748 if (!message_proxy) {
749 BT_ERR("message proxy handle is null\n");
750 result = BLUETOOTH_ERROR_INTERNAL;
752 BT_DBG("message proxy set");
753 GVariant *params = g_variant_new("(sb)", target_file, attachment);
754 GVariant *req_id = g_variant_new("(i)", request_id);
756 g_dbus_proxy_call(message_proxy, "Get", params, G_DBUS_CALL_FLAGS_NONE, -1,
757 NULL, (GAsyncReadyCallback)__bt_get_message_cb, (void*)req_id);
761 g_object_unref(message_proxy);