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(
414 GDBusMethodInvocation *context,
415 const char* session_id,
416 const char* filter_serialized)
418 BT_DBG("Entered _bt_map_list_folders with session id: \"%s\"", session_id);
419 GDBusConnection *g_conn;
420 GDBusProxy *message_access_proxy;
421 GError *error = NULL;
422 int result = BLUETOOTH_ERROR_NONE;
424 retv_if(session_id == NULL, BLUETOOTH_ERROR_INVALID_PARAM);
426 g_conn = _bt_gdbus_get_session_gconn();
427 retv_if(g_conn == NULL, BLUETOOTH_ERROR_INTERNAL);
429 GVariant *out_param1 = g_variant_new_from_data((const GVariantType *)"ay",
430 &request_id, sizeof(int),
432 g_dbus_method_invocation_return_value(context,
433 g_variant_new("(iv)", result, out_param1));
435 // create message access proxy
436 g_clear_error(&error);
437 message_access_proxy = g_dbus_proxy_new_sync(g_conn, G_DBUS_PROXY_FLAGS_NONE, NULL,
438 BT_OBEX_SERVICE_NAME, session_id, "org.bluez.obex.MessageAccess1",
441 BT_ERR("Could not create message access proxy: %s\n", error->message);
442 result = BLUETOOTH_ERROR_INTERNAL;
444 if (!message_access_proxy) {
445 BT_ERR("message proxy handle is null\n");
446 result = BLUETOOTH_ERROR_INTERNAL;
448 BT_DBG("message proxy set");
450 GVariant *filter_variant = g_variant_parse(NULL, filter_serialized, NULL, NULL, NULL);
452 GVariant *params = g_variant_new("(@a{sv})", filter_variant);
453 GVariant *param = g_variant_new("(i)", request_id);
455 g_dbus_proxy_call(message_access_proxy,
456 "ListFolders", params,
457 G_DBUS_CALL_FLAGS_NONE, -1,
459 (GAsyncReadyCallback)__bt_list_folders_cb,
464 g_object_unref(message_access_proxy);
470 static void __bt_list_filter_fields_cb(GDBusProxy *proxy,
471 GAsyncResult *res, gpointer user_data)
475 GError *error = NULL;
476 GVariant *value, *in_param, *param;
478 int result = BLUETOOTH_ERROR_NONE;
480 char** fields = NULL;
483 in_param = (GVariant*) user_data;
484 g_variant_get(in_param, "(i)", &request_id);
486 value = g_dbus_proxy_call_finish(proxy, res, &error);
489 BT_ERR("%s", error->message);
490 g_clear_error(&error);
491 result = BLUETOOTH_ERROR_INTERNAL;
494 param = g_variant_new("(ivi)", result, value, request_id);
496 _bt_send_event(BT_MAP_CLIENT_EVENT, BLUETOOTH_EVENT_MAP_LIST_FILTER_FIELD_COMPLETE,
499 g_variant_unref(value);
500 g_variant_unref(in_param);
505 int _bt_map_client_list_filter_fields(int request_id, GDBusMethodInvocation *context, const char* session_id)
510 GDBusConnection *g_conn;
511 GDBusProxy *message_proxy;
512 GVariant *ret = NULL;
513 int result = BLUETOOTH_ERROR_NONE;
515 retv_if(session_id == NULL, BLUETOOTH_ERROR_INVALID_PARAM);
517 g_conn = _bt_gdbus_get_session_gconn();
518 retv_if(g_conn == NULL, BLUETOOTH_ERROR_INTERNAL);
520 GVariant *out_param = g_variant_new_from_data((const GVariantType *)"ay",
521 &request_id, sizeof(int),
524 g_dbus_method_invocation_return_value(context,
525 g_variant_new("(iv)", result, out_param));
528 message_proxy = g_dbus_proxy_new_sync(g_conn,
529 G_DBUS_PROXY_FLAGS_NONE, NULL,
530 BT_OBEX_SERVICE_NAME, session_id,
531 BT_OBEX_MESSAGE_INTERFACE, NULL, &err);
533 retv_if(message_proxy == NULL, BLUETOOTH_ERROR_INTERNAL);
535 GVariant *param = g_variant_new("(i)", request_id);
537 g_dbus_proxy_call(message_proxy,
538 "ListFilterFields", g_variant_new("()"),
539 G_DBUS_CALL_FLAGS_NONE, -1,
541 (GAsyncReadyCallback)__bt_list_filter_fields_cb,
544 g_object_unref(message_proxy);
548 return BLUETOOTH_ERROR_NONE;
551 static void __bt_list_messages_cb(
552 GDBusProxy *proxy, GAsyncResult *res, gpointer user_data)
556 GError *error = NULL;
557 GVariant *value, *in_param, *param;
559 int result = BLUETOOTH_ERROR_NONE;
563 in_param = (GVariant*) user_data;
564 g_variant_get(in_param, "(i)", &request_id);
566 value = g_dbus_proxy_call_finish(proxy, res, &error);
569 BT_ERR("%s", error->message);
570 g_clear_error(&error);
571 result = BLUETOOTH_ERROR_INTERNAL;
574 param = g_variant_new("(iiv)", result, request_id, value);
575 BT_DBG("RequestID[%d]", request_id);
576 result = _bt_send_event(BT_MAP_CLIENT_EVENT,
577 BLUETOOTH_EVENT_MAP_LIST_MESSAGES_COMPLETE, param);
579 g_variant_unref(value);
580 g_variant_unref(in_param);
585 int _bt_map_client_list_messages(
587 GDBusMethodInvocation *context,
588 const char* session_id,
590 const char* filter_serialized)
592 BT_DBG("Entered _bt_map_client_list_messages with session id: \"%s\"", session_id);
593 BT_DBG("Entered folder: %s", folder);
594 GDBusConnection *g_conn;
595 GDBusProxy *message_access_proxy;
596 GError *error = NULL;
597 int result = BLUETOOTH_ERROR_NONE;
599 retv_if(session_id == NULL, BLUETOOTH_ERROR_INVALID_PARAM);
601 g_conn = _bt_gdbus_get_session_gconn();
602 retv_if(g_conn == NULL, BLUETOOTH_ERROR_INTERNAL);
604 GVariant *out_param1 = g_variant_new_from_data((const GVariantType *)"ay",
605 &request_id, sizeof(int),
607 g_dbus_method_invocation_return_value(context,
608 g_variant_new("(iv)", result, out_param1));
610 // create message access proxy
611 g_clear_error(&error);
612 message_access_proxy = g_dbus_proxy_new_sync(g_conn, G_DBUS_PROXY_FLAGS_NONE, NULL,
613 BT_OBEX_SERVICE_NAME, session_id, "org.bluez.obex.MessageAccess1",
616 BT_ERR("Could not create message access proxy: %s\n", error->message);
617 result = BLUETOOTH_ERROR_INTERNAL;
619 if (!message_access_proxy) {
620 BT_ERR("message proxy handle is null\n");
621 result = BLUETOOTH_ERROR_INTERNAL;
623 BT_DBG("message proxy set");
625 GVariant *filter_variant = g_variant_parse(NULL, filter_serialized, NULL, NULL, NULL);
627 GVariant *params = g_variant_new("(s@a{sv})", folder, filter_variant);
628 GVariant *param = g_variant_new("(i)", request_id);
630 g_dbus_proxy_call(message_access_proxy,
631 "ListMessages", params,
632 G_DBUS_CALL_FLAGS_NONE, -1,
634 (GAsyncReadyCallback)__bt_list_messages_cb,
639 g_object_unref(message_access_proxy);
645 int _bt_map_client_update_inbox(const char* session_id)
650 GDBusConnection *g_conn;
651 GDBusProxy *message_proxy;
652 GVariant *ret = NULL;
654 g_conn = _bt_gdbus_get_session_gconn();
655 ret_if(g_conn == NULL);
657 GVariant *param = g_variant_new("(o)", session_id);
659 message_proxy = g_dbus_proxy_new_sync(g_conn,
660 G_DBUS_PROXY_FLAGS_NONE, NULL,
661 BT_OBEX_SERVICE_NAME, session_id,
662 BT_OBEX_MESSAGE_INTERFACE, NULL, &err);
664 retv_if(message_proxy == NULL, BLUETOOTH_ERROR_INTERNAL);
666 ret = g_dbus_proxy_call_sync(message_proxy,
667 "UpdateInbox", g_variant_new("()"),
668 G_DBUS_CALL_FLAGS_NONE, -1,
673 BT_ERR("UpdateInbox Error: %s\n", err->message);
677 g_variant_unref(ret);
680 g_object_unref(message_proxy);
684 return BLUETOOTH_ERROR_NONE;
687 int _bt_map_client_push_message(
688 const char* session_id,
689 const char* source_file,
691 const char* args_serialized)
699 return BLUETOOTH_ERROR_NONE;
702 void _bt_on_get_message_finished(const char* transfer_object_path) {
703 BT_DBG("Entered _bt_on_get_message_finished");
704 BT_DBG("Looking for transfer %s id", transfer_object_path);
707 bt_callback_data_t *callback_data = NULL;
708 GSList* transfer = NULL;
709 for (transfer = transfer_list; transfer != NULL; transfer = g_slist_next(transfer)) {
710 callback_data = transfer->data;
711 if (NULL == callback_data) {
715 if (0 == strcmp(transfer_object_path, callback_data->transfer_path)) {
716 BT_DBG("request id FOUND - triggering event");
718 GVariant *param = g_variant_new("(ii)", BLUETOOTH_ERROR_NONE, callback_data->request_id);
719 _bt_send_event(BT_MAP_CLIENT_EVENT, BLUETOOTH_EVENT_MAP_GET_MESSAGE_COMPLETE, param);
721 // remove callback data from list
722 g_slist_remove(transfer_list, transfer);
724 //free memory and break loop
725 free(callback_data->transfer_path);
726 callback_data->transfer_path = NULL;
734 static void __bt_get_message_cb(GDBusProxy *proxy,
735 GAsyncResult *res, gpointer user_data)
739 GError *error = NULL;
740 GVariant *value, *in_param, *param;
742 char *transfer_object_path = NULL;
743 GVariantIter *iter = NULL;
745 int result = BLUETOOTH_ERROR_NONE;
749 in_param = (GVariant*) user_data;
750 g_variant_get(in_param, "(i)", &request_id);
752 value = g_dbus_proxy_call_finish(proxy, res, &error);
754 BT_ERR("%s", error->message);
755 g_clear_error(&error);
756 result = BLUETOOTH_ERROR_INTERNAL;
760 g_variant_get(value, "(oa{sv})", &transfer_object_path, &iter);
761 g_variant_unref(value);
764 BT_DBG("transfer object path: [%s]", transfer_object_path);
766 BT_DBG("Adding request id %d - transfer [%s]", request_id, transfer_object_path);
767 bt_callback_data_t* callback_data = malloc(sizeof(*callback_data));
768 callback_data->request_id = request_id;
769 callback_data->transfer_path = transfer_object_path;
771 transfer_list = g_slist_append(transfer_list, callback_data);
773 g_variant_unref(value);
774 g_variant_unref(in_param);
779 int _bt_map_client_get_message(
781 GDBusMethodInvocation *context,
782 const char* message_object,
783 const char* target_file,
786 BT_DBG("Entered _bt_map_client_get_message");
788 GDBusConnection *g_conn;
789 GDBusProxy *message_proxy;
790 GError *error = NULL;
791 int result = BLUETOOTH_ERROR_NONE;
793 retv_if(message_object == NULL, BLUETOOTH_ERROR_INVALID_PARAM);
795 // TODO event listeners registration on first call, where should it be unregistered??
796 _bt_map_client_event_init();
798 g_conn = _bt_gdbus_get_session_gconn();
799 retv_if(g_conn == NULL, BLUETOOTH_ERROR_INTERNAL);
801 GVariant *out_param1 = g_variant_new_from_data((const GVariantType *)"ay",
802 &request_id, sizeof(int),
804 g_dbus_method_invocation_return_value(context, g_variant_new("(iv)", result, out_param1));
806 // create message proxy
807 g_clear_error(&error);
808 message_proxy = g_dbus_proxy_new_sync(g_conn, G_DBUS_PROXY_FLAGS_NONE, NULL,
809 BT_OBEX_SERVICE_NAME, message_object, "org.bluez.obex.Message1",
812 BT_ERR("Could not create message proxy: %s\n", error->message);
813 result = BLUETOOTH_ERROR_INTERNAL;
815 if (!message_proxy) {
816 BT_ERR("message proxy handle is null\n");
817 result = BLUETOOTH_ERROR_INTERNAL;
819 BT_DBG("message proxy set");
820 GVariant *params = g_variant_new("(sb)", target_file, attachment);
821 GVariant *req_id = g_variant_new("(i)", request_id);
823 g_dbus_proxy_call(message_proxy, "Get", params, G_DBUS_CALL_FLAGS_NONE, -1,
824 NULL, (GAsyncReadyCallback)__bt_get_message_cb, (void*)req_id);
828 g_object_unref(message_proxy);