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 */
45 static GSList *transfer_list = NULL;
47 bt_session_info_t *session_info;
49 static void __bt_free_session_info(bt_session_info_t *info)
53 /* TODO: MAP bt_session_info_t, see bt-service-opp-client.c */
55 g_free(info->address);
59 static void __bt_free_session_data(gpointer data)
61 bt_session_data_t *info = data;
65 _bt_delete_request_id(info->request_id);
67 /* TODO: MAP bt_session_data_t, see bt-service-opp-client.c */
69 g_free(info->address);
73 static void __bt_session_release_cb(GDBusProxy *proxy,
74 GAsyncResult *res, gpointer user_data)
77 ret_if(session_info == NULL);
80 int result = BLUETOOTH_ERROR_NONE;
81 GVariant *param = NULL;
82 g_dbus_proxy_call_finish(proxy, res, &error);
84 g_object_unref(proxy);
87 BT_ERR("%s", error->message);
90 result = BLUETOOTH_ERROR_INTERNAL;
92 BT_DBG("Session Removed");
95 session_info->result = result;
96 param = g_variant_new("(isi)", session_info->result,
97 session_info->address,
98 session_info->request_id);
99 /* Send the event in only error none case */
100 _bt_send_event(BT_OPP_CLIENT_EVENT,
101 BLUETOOTH_EVENT_OPC_DISCONNECTED,
104 __bt_free_session_info(session_info);
107 _bt_map_client_event_deinit();
109 /* Operate remain works */
120 static int _bt_remove_session()
122 GDBusConnection *g_conn;
123 GDBusProxy *session_proxy;
126 g_conn = _bt_gdbus_get_session_gconn();
127 retv_if(g_conn == NULL, BLUETOOTH_ERROR_INTERNAL);
128 retv_if(session_info->session_path == NULL, BLUETOOTH_ERROR_INVALID_PARAM);
130 session_proxy = g_dbus_proxy_new_sync(g_conn, G_DBUS_PROXY_FLAGS_NONE,
131 NULL, BT_OBEXD_DBUS_NAME,
133 BT_OBEX_CLIENT_INTERFACE,
136 retv_if(session_proxy == NULL, BLUETOOTH_ERROR_INTERNAL);
138 g_dbus_proxy_call(session_proxy, "RemoveSession",
139 g_variant_new("(o)", session_info->session_path),
140 G_DBUS_CALL_FLAGS_NONE,
142 (GAsyncReadyCallback)__bt_session_release_cb,
145 return BLUETOOTH_ERROR_NONE;
148 void _bt_map_disconnected(const char *session_path)
151 GVariant *param = NULL;
152 ret_if(session_info == NULL);
154 if (g_strcmp0(session_info->session_path,
155 session_path) != 0) {
156 BT_INFO("Path mismatch, previous transfer failed! Returning");
160 param = g_variant_new("(isi)", session_info->result,
161 session_info->address,
162 session_info->request_id);
163 _bt_send_event(BT_MAP_CLIENT_EVENT,
164 BLUETOOTH_EVENT_MAP_DISCONNECTED,
167 __bt_free_session_info(session_info);
173 static void __bt_create_session_cb(GDBusProxy *proxy,
174 GAsyncResult *res, gpointer user_data)
178 GError *error = NULL;
180 int result = BLUETOOTH_ERROR_NONE;
181 char *session_path = NULL;
182 GVariant *param = NULL;
184 value = g_dbus_proxy_call_finish(proxy, res, &error);
186 g_variant_get(value, "(o)", &session_path);
187 g_variant_unref(value);
191 BT_ERR("%s", error->message);
192 g_clear_error(&error);
194 result = BLUETOOTH_ERROR_INTERNAL;
196 BT_DBG("Session created");
197 if (session_info != NULL)
198 session_info->session_path = g_strdup(session_path);
200 g_free(session_path);
201 g_object_unref(proxy);
202 ret_if(session_info == NULL);
204 session_info->result = result;
205 param = g_variant_new("(isi)", result,
206 session_info->address,
207 session_info->request_id);
208 /* Send the event in only error none case */
209 _bt_send_event(BT_MAP_CLIENT_EVENT,
210 BLUETOOTH_EVENT_MAP_CONNECTED,
213 if (result != BLUETOOTH_ERROR_NONE) {
214 BT_ERR("Calling __bt_session_release");
215 gboolean ret = __bt_session_release();
217 __bt_free_session_info(session_info);
221 BT_DBG("ReleaseSession Not called");
222 /* Operate remain works */
236 static int __bt_opp_client_start_XXXXXXXXXX(int request_id, char *address
237 /* parameters................... */)
242 int _bt_create_session_sync(const char* address, char** session_id)
244 BT_DBG("Entered SERVICE create session");
245 GDBusConnection *g_conn;
246 GDBusProxy *session_proxy;
248 const char *session_path;
250 retv_if(address == NULL, BLUETOOTH_ERROR_INVALID_PARAM);
252 g_conn = _bt_gdbus_get_session_gconn();
253 retv_if(g_conn == NULL, BLUETOOTH_ERROR_INTERNAL);
255 session_proxy = g_dbus_proxy_new_sync(g_conn, G_DBUS_PROXY_FLAGS_NONE,
256 NULL, BT_OBEX_SERVICE_NAME,
258 BT_OBEX_CLIENT_INTERFACE,
261 BT_ERR("Unable to create session_proxy: %s", err->message);
263 return BLUETOOTH_ERROR_INTERNAL;
265 retv_if(session_proxy == NULL, BLUETOOTH_ERROR_INTERNAL);
267 GVariantBuilder* builder = g_variant_builder_new (G_VARIANT_TYPE_ARRAY);
268 g_variant_builder_add(builder, "{sv}", "Target",
269 g_variant_new("s", "map"));
270 GVariant *args = g_variant_builder_end(builder);
271 g_variant_builder_unref (builder);
272 GVariant *param = g_variant_new("(s@a{sv})", address, args);
274 char* string = g_variant_print (param, true);
276 GVariant *value = g_dbus_proxy_call_sync(session_proxy, "CreateSession", param,
277 G_DBUS_CALL_FLAGS_NONE, -1, NULL, &err);
279 BT_ERR("Could not create session: %s\n", err->message);
281 return BLUETOOTH_ERROR_INTERNAL;
284 BT_ERR("create session returned value is null\n");
285 return BLUETOOTH_ERROR_INTERNAL;
287 BT_DBG("create session succeed\n");
291 g_variant_get(value, "(&o)", session_id);
292 BT_DBG("session_id = \"%s\"\n", *session_id);
294 return BLUETOOTH_ERROR_NONE;
297 int _bt_destroy_session_sync(const char* session_id)
299 BT_DBG("Entered SERVICE destroy session with id: \"%s\"", session_id);
300 GDBusConnection *g_conn;
301 GDBusProxy *session_proxy;
304 retv_if(session_id == NULL, BLUETOOTH_ERROR_INVALID_PARAM);
306 g_conn = _bt_gdbus_get_session_gconn();
307 retv_if(g_conn == NULL, BLUETOOTH_ERROR_INTERNAL);
309 session_proxy = g_dbus_proxy_new_sync(g_conn, G_DBUS_PROXY_FLAGS_NONE,
310 NULL, BT_OBEX_SERVICE_NAME,
312 BT_OBEX_CLIENT_INTERFACE,
315 BT_ERR("Unable to create session_proxy: %s", err->message);
317 return BLUETOOTH_ERROR_INTERNAL;
319 retv_if(session_proxy == NULL, BLUETOOTH_ERROR_INTERNAL);
321 GVariant *param = g_variant_new("(o)", session_id);
323 GVariant *value = g_dbus_proxy_call_sync(session_proxy, "RemoveSession", param,
324 G_DBUS_CALL_FLAGS_NONE, -1, NULL, &err);
326 BT_ERR("Could not remove session: %s\n", err->message);
328 return BLUETOOTH_ERROR_INTERNAL;
330 BT_DBG("remove session succeed\n");
333 return BLUETOOTH_ERROR_NONE;
336 int _bt_map_client_set_folder(const char* session_id, const char* name)
341 GDBusConnection *g_conn;
342 GDBusProxy *message_proxy;
343 GVariant *ret = NULL;
345 g_conn = _bt_gdbus_get_session_gconn();
346 ret_if(g_conn == NULL);
348 GVariant *param = g_variant_new("(o)", session_id);
350 message_proxy = g_dbus_proxy_new_sync(g_conn,
351 G_DBUS_PROXY_FLAGS_NONE, NULL,
352 BT_OBEX_SERVICE_NAME, session_id,
353 BT_OBEX_MESSAGE_INTERFACE, NULL, &err);
355 retv_if(message_proxy == NULL, BLUETOOTH_ERROR_INTERNAL);
357 ret = g_dbus_proxy_call_sync(message_proxy,
358 "SetFolder", g_variant_new("(s)", name),
359 G_DBUS_CALL_FLAGS_NONE, DBUS_TIMEOUT,
364 BT_ERR("SetFolder Error: %s\n", err->message);
368 g_variant_unref(ret);
371 g_object_unref(message_proxy);
375 return BLUETOOTH_ERROR_NONE;
378 static void __bt_list_folders_cb(GDBusProxy *proxy,
379 GAsyncResult *res, gpointer user_data)
383 GError *error = NULL;
384 GVariant *value, *in_param, *param;
386 int result = BLUETOOTH_ERROR_NONE;
390 in_param = (GVariant*) user_data;
391 g_variant_get(in_param, "(i)", &request_id);
393 value = g_dbus_proxy_call_finish(proxy, res, &error);
396 BT_ERR("%s", error->message);
397 g_clear_error(&error);
398 result = BLUETOOTH_ERROR_INTERNAL;
401 param = g_variant_new("(iiv)", result, request_id, value);
402 BT_DBG("RequestID[%d]", request_id);
403 result = _bt_send_event(BT_MAP_CLIENT_EVENT,
404 BLUETOOTH_EVENT_MAP_LIST_FOLDERS_COMPLETE, param);
406 g_variant_unref(value);
407 g_variant_unref(in_param);
412 int _bt_map_client_list_folders(int request_id, GDBusMethodInvocation *context,
413 const char* session_id, int offset, int maxcount)
415 BT_DBG("Entered _bt_map_list_folders with session id: \"%s\"", session_id);
416 BT_DBG("Entered offset: %d maxcount: %d", offset, maxcount);
417 GDBusConnection *g_conn;
418 GDBusProxy *message_access_proxy;
419 GError *error = NULL;
420 int result = BLUETOOTH_ERROR_NONE;
422 retv_if(session_id == NULL, BLUETOOTH_ERROR_INVALID_PARAM);
424 g_conn = _bt_gdbus_get_session_gconn();
425 retv_if(g_conn == NULL, BLUETOOTH_ERROR_INTERNAL);
427 GVariant *out_param1 = g_variant_new_from_data((const GVariantType *)"ay",
428 &request_id, sizeof(int),
430 g_dbus_method_invocation_return_value(context,
431 g_variant_new("(iv)", result, out_param1));
433 // create message access proxy
434 g_clear_error(&error);
435 message_access_proxy = g_dbus_proxy_new_sync(g_conn, G_DBUS_PROXY_FLAGS_NONE, NULL,
436 BT_OBEX_SERVICE_NAME, session_id, "org.bluez.obex.MessageAccess1",
439 BT_ERR("Could not create message access proxy: %s\n", error->message);
440 result = BLUETOOTH_ERROR_INTERNAL;
442 if (!message_access_proxy) {
443 BT_ERR("message proxy handle is null\n");
444 result = BLUETOOTH_ERROR_INTERNAL;
446 BT_DBG("message proxy set");
447 GVariantBuilder* b = g_variant_builder_new (G_VARIANT_TYPE_ARRAY);
449 g_variant_builder_add(b, "{sv}", "Offset", g_variant_new_uint16(offset));
452 g_variant_builder_add(b, "{sv}", "MaxCount", g_variant_new_uint16(maxcount));
454 GVariant *args = g_variant_builder_end(b);
455 GVariant *params = g_variant_new("(@a{sv})", args);
456 g_variant_builder_unref (b);
458 GVariant *param = g_variant_new("(i)", request_id);
460 g_dbus_proxy_call(message_access_proxy,
461 "ListFolders", params,
462 G_DBUS_CALL_FLAGS_NONE, -1,
464 (GAsyncReadyCallback)__bt_list_folders_cb,
470 g_object_unref(message_access_proxy);
476 static void __bt_list_filter_fields_cb(GDBusProxy *proxy,
477 GAsyncResult *res, gpointer user_data)
481 GError *error = NULL;
482 GVariant *value, *in_param, *param;
484 int result = BLUETOOTH_ERROR_NONE;
486 char** fields = NULL;
489 in_param = (GVariant*) user_data;
490 g_variant_get(in_param, "(i)", &request_id);
492 value = g_dbus_proxy_call_finish(proxy, res, &error);
495 BT_ERR("%s", error->message);
496 g_clear_error(&error);
497 result = BLUETOOTH_ERROR_INTERNAL;
500 param = g_variant_new("(ivi)", result, value, request_id);
502 _bt_send_event(BT_MAP_CLIENT_EVENT, BLUETOOTH_EVENT_MAP_LIST_FILTER_FIELD_COMPLETE,
505 g_variant_unref(value);
506 g_variant_unref(in_param);
511 int _bt_map_client_list_filter_fields(int request_id, GDBusMethodInvocation *context, const char* session_id)
516 GDBusConnection *g_conn;
517 GDBusProxy *message_proxy;
518 GVariantBuilder *builder;
519 GVariant *ret = NULL;
520 int result = BLUETOOTH_ERROR_NONE;
522 retv_if(session_id == NULL, BLUETOOTH_ERROR_INVALID_PARAM);
524 g_conn = _bt_gdbus_get_session_gconn();
525 retv_if(g_conn == NULL, BLUETOOTH_ERROR_INTERNAL);
527 GVariant *out_param = g_variant_new_from_data((const GVariantType *)"ay",
528 &request_id, sizeof(int),
531 g_dbus_method_invocation_return_value(context,
532 g_variant_new("(iv)", result, out_param));
535 message_proxy = g_dbus_proxy_new_sync(g_conn,
536 G_DBUS_PROXY_FLAGS_NONE, NULL,
537 BT_OBEX_SERVICE_NAME, session_id,
538 BT_OBEX_MESSAGE_INTERFACE, NULL, &err);
540 retv_if(message_proxy == NULL, BLUETOOTH_ERROR_INTERNAL);
542 GVariant *param = g_variant_new("(i)", request_id);
544 g_dbus_proxy_call(message_proxy,
545 "ListFilterFields", g_variant_new("()"),
546 G_DBUS_CALL_FLAGS_NONE, -1,
548 (GAsyncReadyCallback)__bt_list_filter_fields_cb,
551 g_object_unref(message_proxy);
555 return BLUETOOTH_ERROR_NONE;
558 static void __bt_list_messages_cb(
559 GDBusProxy *proxy, GAsyncResult *res, gpointer user_data)
563 GError *error = NULL;
564 GVariant *value, *in_param, *param;
566 int result = BLUETOOTH_ERROR_NONE;
570 in_param = (GVariant*) user_data;
571 g_variant_get(in_param, "(i)", &request_id);
573 value = g_dbus_proxy_call_finish(proxy, res, &error);
576 BT_ERR("%s", error->message);
577 g_clear_error(&error);
578 result = BLUETOOTH_ERROR_INTERNAL;
581 param = g_variant_new("(iiv)", result, request_id, value);
582 BT_DBG("RequestID[%d]", request_id);
583 result = _bt_send_event(BT_MAP_CLIENT_EVENT,
584 BLUETOOTH_EVENT_MAP_LIST_MESSAGES_COMPLETE, param);
586 g_variant_unref(value);
587 g_variant_unref(in_param);
592 int _bt_map_client_list_messages(
594 GDBusMethodInvocation *context,
595 const char* session_id,
599 BT_DBG("Entered _bt_map_client_list_messages with session id: \"%s\"", session_id);
600 BT_DBG("Entered folder: %s", folder);
601 GDBusConnection *g_conn;
602 GDBusProxy *message_access_proxy;
603 GError *error = NULL;
604 int result = BLUETOOTH_ERROR_NONE;
606 retv_if(session_id == NULL, BLUETOOTH_ERROR_INVALID_PARAM);
608 g_conn = _bt_gdbus_get_session_gconn();
609 retv_if(g_conn == NULL, BLUETOOTH_ERROR_INTERNAL);
611 GVariant *out_param1 = g_variant_new_from_data((const GVariantType *)"ay",
612 &request_id, sizeof(int),
614 g_dbus_method_invocation_return_value(context,
615 g_variant_new("(iv)", result, out_param1));
617 // create message access proxy
618 g_clear_error(&error);
619 message_access_proxy = g_dbus_proxy_new_sync(g_conn, G_DBUS_PROXY_FLAGS_NONE, NULL,
620 BT_OBEX_SERVICE_NAME, session_id, "org.bluez.obex.MessageAccess1",
623 BT_ERR("Could not create message access proxy: %s\n", error->message);
624 result = BLUETOOTH_ERROR_INTERNAL;
626 if (!message_access_proxy) {
627 BT_ERR("message proxy handle is null\n");
628 result = BLUETOOTH_ERROR_INTERNAL;
630 BT_DBG("message proxy set");
632 GVariant *params = g_variant_new("(s@a{sv})", folder, filter);
633 GVariant *param = g_variant_new("(i)", request_id);
635 g_dbus_proxy_call(message_access_proxy,
636 "ListMessages", params,
637 G_DBUS_CALL_FLAGS_NONE, -1,
639 (GAsyncReadyCallback)__bt_list_messages_cb,
644 g_object_unref(message_access_proxy);
650 int _bt_map_client_update_inbox(const char* session_id)
655 GDBusConnection *g_conn;
656 GDBusProxy *message_proxy;
657 GVariantBuilder *builder;
658 GVariant *ret = NULL;
660 g_conn = _bt_gdbus_get_session_gconn();
661 ret_if(g_conn == NULL);
663 GVariant *param = g_variant_new("(o)", session_id);
665 message_proxy = g_dbus_proxy_new_sync(g_conn,
666 G_DBUS_PROXY_FLAGS_NONE, NULL,
667 BT_OBEX_SERVICE_NAME, session_id,
668 BT_OBEX_MESSAGE_INTERFACE, NULL, &err);
670 retv_if(message_proxy == NULL, BLUETOOTH_ERROR_INTERNAL);
672 ret = g_dbus_proxy_call_sync(message_proxy,
673 "UpdateInbox", g_variant_new("()"),
674 G_DBUS_CALL_FLAGS_NONE, -1,
679 BT_ERR("UpdateInbox Error: %s\n", err->message);
683 g_variant_unref(ret);
686 g_object_unref(message_proxy);
690 return BLUETOOTH_ERROR_NONE;
693 int _bt_map_client_push_message(
694 const char* session_id,
695 const char* source_file,
705 return BLUETOOTH_ERROR_NONE;
708 void _bt_on_get_message_finished(const char* transfer_object_path) {
709 BT_DBG("Entered _bt_on_get_message_finished");
710 BT_DBG("Looking for transfer %s id", transfer_object_path);
713 bt_callback_data_t *callback_data = NULL;
714 GSList* transfer = NULL;
715 for (transfer = transfer_list; transfer != NULL; transfer = g_slist_next(transfer)) {
716 callback_data = transfer->data;
717 if (NULL == callback_data) {
721 if (0 == strcmp(transfer_object_path, callback_data->transfer_path)) {
722 BT_DBG("request id FOUND - triggering event");
724 GVariant *param = g_variant_new("(ii)", BLUETOOTH_ERROR_NONE, callback_data->request_id);
725 _bt_send_event(BT_MAP_CLIENT_EVENT, BLUETOOTH_EVENT_MAP_GET_MESSAGE_COMPLETE, param);
727 // remove callback data from list
728 g_slist_remove(transfer_list, transfer);
730 //free memory and break loop
731 free(callback_data->transfer_path);
732 callback_data->transfer_path = NULL;
740 static void __bt_get_message_cb(GDBusProxy *proxy,
741 GAsyncResult *res, gpointer user_data)
745 GError *error = NULL;
746 GVariant *value, *in_param, *param;
748 char *transfer_object_path = NULL;
749 GVariantIter *iter = NULL;
751 int result = BLUETOOTH_ERROR_NONE;
755 in_param = (GVariant*) user_data;
756 g_variant_get(in_param, "(i)", &request_id);
758 value = g_dbus_proxy_call_finish(proxy, res, &error);
760 BT_ERR("%s", error->message);
761 g_clear_error(&error);
762 result = BLUETOOTH_ERROR_INTERNAL;
766 g_variant_get(value, "(oa{sv})", &transfer_object_path, &iter);
767 g_variant_unref(value);
770 BT_DBG("transfer object path: [%s]", transfer_object_path);
772 BT_DBG("Adding request id %d - transfer [%s]", request_id, transfer_object_path);
773 bt_callback_data_t* callback_data = malloc(sizeof(*callback_data));
774 callback_data->request_id = request_id;
775 callback_data->transfer_path = transfer_object_path;
777 transfer_list = g_slist_append(transfer_list, callback_data);
779 g_variant_unref(value);
780 g_variant_unref(in_param);
785 int _bt_map_client_get_message(
787 GDBusMethodInvocation *context,
788 const char* message_object_name,
789 const char* target_file,
792 BT_DBG("Entered _bt_map_client_get_message");
794 GDBusConnection *g_conn;
795 GDBusProxy *message_proxy;
796 GError *error = NULL;
797 int result = BLUETOOTH_ERROR_NONE;
799 retv_if(message_object_name == NULL, BLUETOOTH_ERROR_INVALID_PARAM);
801 // TODO event listeners registration on first call, where should it be unregistered??
802 _bt_map_client_event_init();
804 g_conn = _bt_gdbus_get_session_gconn();
805 retv_if(g_conn == NULL, BLUETOOTH_ERROR_INTERNAL);
807 GVariant *out_param1 = g_variant_new_from_data((const GVariantType *)"ay",
808 &request_id, sizeof(int),
810 g_dbus_method_invocation_return_value(context, g_variant_new("(iv)", result, out_param1));
812 // create message proxy
813 g_clear_error(&error);
814 message_proxy = g_dbus_proxy_new_sync(g_conn, G_DBUS_PROXY_FLAGS_NONE, NULL,
815 BT_OBEX_SERVICE_NAME, message_object_name, "org.bluez.obex.Message1",
818 BT_ERR("Could not create message proxy: %s\n", error->message);
819 result = BLUETOOTH_ERROR_INTERNAL;
821 if (!message_proxy) {
822 BT_ERR("message proxy handle is null\n");
823 result = BLUETOOTH_ERROR_INTERNAL;
825 BT_DBG("message proxy set");
826 GVariant *params = g_variant_new("(sb)", target_file, attachment);
827 GVariant *req_id = g_variant_new("(i)", request_id);
829 g_dbus_proxy_call(message_proxy, "Get", params, G_DBUS_CALL_FLAGS_NONE, -1,
830 NULL, (GAsyncReadyCallback)__bt_get_message_cb, (void*)req_id);
834 g_object_unref(message_proxy);