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>
25 #include "bluetooth-api.h"
26 #include "bt-internal-types.h"
28 #include "bt-service-common.h"
29 #include "bt-service-event.h"
30 #include "bt-service-util.h"
31 #include "bt-service-map-client.h"
32 #include "bt-service-obex-agent.h"
33 #include "bt-service-adapter.h"
35 #define DBUS_TIMEOUT 20 * 1000 /* 20 Seconds */
37 enum bt_map_transfer_type {
38 BT_MAP_TRANSFER_GET_MESSAGE = 0,
39 BT_MAP_TRANSFER_PUSH_MESSAGE
43 enum bt_map_transfer_type transfer_type;
46 } bt_map_callback_data_t;
48 static GSList *transfer_list = NULL;
50 bt_session_info_t *session_info;
52 static void __bt_free_session_info(bt_session_info_t *info)
55 g_free(info->address);
59 void _bt_map_disconnected(const char *session_path)
62 GVariant *param = NULL;
63 ret_if(session_info == NULL);
65 if (g_strcmp0(session_info->session_path,
67 BT_INFO("Path mismatch, previous transfer failed! Returning");
71 param = g_variant_new("(isi)", session_info->result,
72 session_info->address,
73 session_info->request_id);
74 _bt_send_event(BT_MAP_CLIENT_EVENT,
75 BLUETOOTH_EVENT_MAP_DISCONNECTED,
78 __bt_free_session_info(session_info);
84 int _bt_create_session_sync(const char* address, char** session_id)
86 BT_DBG("Entered SERVICE create session");
87 GDBusConnection *g_conn;
88 GDBusProxy *session_proxy;
91 retv_if(address == NULL, BLUETOOTH_ERROR_INVALID_PARAM);
93 g_conn = _bt_gdbus_get_session_gconn();
94 retv_if(g_conn == NULL, BLUETOOTH_ERROR_INTERNAL);
96 session_proxy = g_dbus_proxy_new_sync(g_conn, G_DBUS_PROXY_FLAGS_NONE,
97 NULL, BT_OBEX_SERVICE_NAME,
99 BT_OBEX_CLIENT_INTERFACE,
102 BT_ERR("Unable to create session_proxy: %s", err->message);
104 return BLUETOOTH_ERROR_INTERNAL;
106 retv_if(session_proxy == NULL, BLUETOOTH_ERROR_INTERNAL);
108 GVariantBuilder* builder = g_variant_builder_new(G_VARIANT_TYPE_ARRAY);
109 g_variant_builder_add(builder, "{sv}", "Target",
110 g_variant_new("s", "map"));
111 GVariant *args = g_variant_builder_end(builder);
112 g_variant_builder_unref(builder);
113 GVariant *param = g_variant_new("(s@a{sv})", address, args);
115 GVariant *value = g_dbus_proxy_call_sync(session_proxy, "CreateSession", param,
116 G_DBUS_CALL_FLAGS_NONE, -1, NULL, &err);
118 BT_ERR("Could not create session: %s\n", err->message);
120 return BLUETOOTH_ERROR_INTERNAL;
123 BT_ERR("create session returned value is null\n");
124 return BLUETOOTH_ERROR_INTERNAL;
126 BT_DBG("create session succeed\n");
130 g_variant_get(value, "(&o)", session_id);
131 BT_DBG("session_id = \"%s\"\n", *session_id);
133 return BLUETOOTH_ERROR_NONE;
136 int _bt_destroy_session_sync(const char* session_id)
138 BT_DBG("Entered SERVICE destroy session with id: \"%s\"", session_id);
139 GDBusConnection *g_conn;
140 GDBusProxy *session_proxy;
143 retv_if(session_id == NULL, BLUETOOTH_ERROR_INVALID_PARAM);
145 g_conn = _bt_gdbus_get_session_gconn();
146 retv_if(g_conn == NULL, BLUETOOTH_ERROR_INTERNAL);
148 session_proxy = g_dbus_proxy_new_sync(g_conn, G_DBUS_PROXY_FLAGS_NONE,
149 NULL, BT_OBEX_SERVICE_NAME,
151 BT_OBEX_CLIENT_INTERFACE,
154 BT_ERR("Unable to create session_proxy: %s", err->message);
156 return BLUETOOTH_ERROR_INTERNAL;
158 retv_if(session_proxy == NULL, 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 BT_ERR("Could not remove session: %s\n", err->message);
167 return BLUETOOTH_ERROR_INTERNAL;
169 BT_DBG("remove session succeed\n");
172 return BLUETOOTH_ERROR_NONE;
175 int _bt_map_client_set_folder(const char* session_id, const char* name)
180 GDBusConnection *g_conn;
181 GDBusProxy *message_proxy;
182 GVariant *ret = NULL;
184 g_conn = _bt_gdbus_get_session_gconn();
185 retv_if(g_conn == NULL, BLUETOOTH_ERROR_INTERNAL);
187 message_proxy = g_dbus_proxy_new_sync(g_conn,
188 G_DBUS_PROXY_FLAGS_NONE, NULL,
189 BT_OBEX_SERVICE_NAME, session_id,
190 BT_OBEX_MESSAGE_INTERFACE, NULL, &err);
192 retv_if(message_proxy == NULL, BLUETOOTH_ERROR_INTERNAL);
194 ret = g_dbus_proxy_call_sync(message_proxy,
195 "SetFolder", g_variant_new("(s)", name),
196 G_DBUS_CALL_FLAGS_NONE, DBUS_TIMEOUT,
201 BT_ERR("SetFolder Error: %s\n", err->message);
205 g_variant_unref(ret);
208 g_object_unref(message_proxy);
212 return BLUETOOTH_ERROR_NONE;
215 static void __bt_list_folders_cb(GDBusProxy *proxy,
216 GAsyncResult *res, gpointer user_data)
220 GError *error = NULL;
221 GVariant *value, *in_param, *param;
223 int result = BLUETOOTH_ERROR_NONE;
226 in_param = (GVariant*) user_data;
227 g_variant_get(in_param, "(i)", &request_id);
229 value = g_dbus_proxy_call_finish(proxy, res, &error);
232 BT_ERR("%s", error->message);
233 g_clear_error(&error);
234 result = BLUETOOTH_ERROR_INTERNAL;
237 param = g_variant_new("(iiv)", result, request_id, value);
238 BT_DBG("RequestID[%d]", request_id);
239 result = _bt_send_event(BT_MAP_CLIENT_EVENT,
240 BLUETOOTH_EVENT_MAP_LIST_FOLDERS_COMPLETE, param);
242 g_variant_unref(value);
243 g_variant_unref(in_param);
248 int _bt_map_client_list_folders(
250 GDBusMethodInvocation *context,
251 const char* session_id,
252 const char* filter_serialized)
254 BT_DBG("Entered _bt_map_list_folders with session id: \"%s\"", session_id);
255 GDBusConnection *g_conn;
256 GDBusProxy *message_access_proxy;
257 GError *error = NULL;
258 int result = BLUETOOTH_ERROR_NONE;
260 retv_if(session_id == NULL, BLUETOOTH_ERROR_INVALID_PARAM);
262 g_conn = _bt_gdbus_get_session_gconn();
263 retv_if(g_conn == NULL, BLUETOOTH_ERROR_INTERNAL);
265 GVariant *out_param1 = g_variant_new_from_data((const GVariantType *)"ay",
266 &request_id, sizeof(int),
268 g_dbus_method_invocation_return_value(context,
269 g_variant_new("(iv)", result, out_param1));
271 // create message access proxy
272 g_clear_error(&error);
273 message_access_proxy = g_dbus_proxy_new_sync(g_conn, G_DBUS_PROXY_FLAGS_NONE, NULL,
274 BT_OBEX_SERVICE_NAME, session_id, "org.bluez.obex.MessageAccess1",
277 BT_ERR("Could not create message access proxy: %s\n", error->message);
278 result = BLUETOOTH_ERROR_INTERNAL;
280 if (!message_access_proxy) {
281 BT_ERR("message proxy handle is null\n");
282 result = BLUETOOTH_ERROR_INTERNAL;
284 BT_DBG("message proxy set");
286 GVariant *filter_variant = g_variant_parse(NULL, filter_serialized, NULL, NULL, NULL);
288 GVariant *params = g_variant_new("(@a{sv})", filter_variant);
289 GVariant *param = g_variant_new("(i)", request_id);
291 g_dbus_proxy_call(message_access_proxy,
292 "ListFolders", params,
293 G_DBUS_CALL_FLAGS_NONE, -1,
295 (GAsyncReadyCallback)__bt_list_folders_cb,
300 g_object_unref(message_access_proxy);
306 static void __bt_list_filter_fields_cb(GDBusProxy *proxy,
307 GAsyncResult *res, gpointer user_data)
311 GError *error = NULL;
312 GVariant *value, *in_param, *param;
314 int result = BLUETOOTH_ERROR_NONE;
317 in_param = (GVariant*) user_data;
318 g_variant_get(in_param, "(i)", &request_id);
320 value = g_dbus_proxy_call_finish(proxy, res, &error);
323 BT_ERR("%s", error->message);
324 g_clear_error(&error);
325 result = BLUETOOTH_ERROR_INTERNAL;
328 param = g_variant_new("(ivi)", result, value, request_id);
330 _bt_send_event(BT_MAP_CLIENT_EVENT, BLUETOOTH_EVENT_MAP_LIST_FILTER_FIELD_COMPLETE,
333 g_variant_unref(value);
334 g_variant_unref(in_param);
339 int _bt_map_client_list_filter_fields(int request_id, GDBusMethodInvocation *context, const char* session_id)
344 GDBusConnection *g_conn;
345 GDBusProxy *message_proxy;
346 int result = BLUETOOTH_ERROR_NONE;
348 retv_if(session_id == NULL, BLUETOOTH_ERROR_INVALID_PARAM);
350 g_conn = _bt_gdbus_get_session_gconn();
351 retv_if(g_conn == NULL, BLUETOOTH_ERROR_INTERNAL);
353 GVariant *out_param = g_variant_new_from_data((const GVariantType *)"ay",
354 &request_id, sizeof(int),
357 g_dbus_method_invocation_return_value(context,
358 g_variant_new("(iv)", result, out_param));
361 message_proxy = g_dbus_proxy_new_sync(g_conn,
362 G_DBUS_PROXY_FLAGS_NONE, NULL,
363 BT_OBEX_SERVICE_NAME, session_id,
364 BT_OBEX_MESSAGE_INTERFACE, NULL, &err);
366 retv_if(message_proxy == NULL, BLUETOOTH_ERROR_INTERNAL);
368 GVariant *param = g_variant_new("(i)", request_id);
370 g_dbus_proxy_call(message_proxy,
371 "ListFilterFields", g_variant_new("()"),
372 G_DBUS_CALL_FLAGS_NONE, -1,
374 (GAsyncReadyCallback)__bt_list_filter_fields_cb,
377 g_object_unref(message_proxy);
381 return BLUETOOTH_ERROR_NONE;
384 static void __bt_list_messages_cb(
385 GDBusProxy *proxy, GAsyncResult *res, gpointer user_data)
389 GError *error = NULL;
390 GVariant *value, *in_param, *param;
392 int result = BLUETOOTH_ERROR_NONE;
395 in_param = (GVariant*) user_data;
396 g_variant_get(in_param, "(i)", &request_id);
398 value = g_dbus_proxy_call_finish(proxy, res, &error);
401 BT_ERR("%s", error->message);
402 g_clear_error(&error);
403 result = BLUETOOTH_ERROR_INTERNAL;
406 param = g_variant_new("(iiv)", result, request_id, value);
407 BT_DBG("RequestID[%d]", request_id);
408 result = _bt_send_event(BT_MAP_CLIENT_EVENT,
409 BLUETOOTH_EVENT_MAP_LIST_MESSAGES_COMPLETE, param);
411 g_variant_unref(value);
412 g_variant_unref(in_param);
417 int _bt_map_client_list_messages(
419 GDBusMethodInvocation *context,
420 const char* session_id,
422 const char* filter_serialized)
424 BT_DBG("Entered _bt_map_client_list_messages with session id: \"%s\"", session_id);
425 BT_DBG("Entered folder: %s", folder);
426 GDBusConnection *g_conn;
427 GDBusProxy *message_access_proxy;
428 GError *error = NULL;
429 int result = BLUETOOTH_ERROR_NONE;
431 retv_if(session_id == NULL, BLUETOOTH_ERROR_INVALID_PARAM);
433 g_conn = _bt_gdbus_get_session_gconn();
434 retv_if(g_conn == NULL, BLUETOOTH_ERROR_INTERNAL);
436 GVariant *out_param1 = g_variant_new_from_data((const GVariantType *)"ay",
437 &request_id, sizeof(int),
439 g_dbus_method_invocation_return_value(context,
440 g_variant_new("(iv)", result, out_param1));
442 // create message access proxy
443 g_clear_error(&error);
444 message_access_proxy = g_dbus_proxy_new_sync(g_conn, G_DBUS_PROXY_FLAGS_NONE, NULL,
445 BT_OBEX_SERVICE_NAME, session_id, "org.bluez.obex.MessageAccess1",
448 BT_ERR("Could not create message access proxy: %s\n", error->message);
449 result = BLUETOOTH_ERROR_INTERNAL;
451 if (!message_access_proxy) {
452 BT_ERR("message proxy handle is null\n");
453 result = BLUETOOTH_ERROR_INTERNAL;
455 BT_DBG("message proxy set");
457 GVariant *filter_variant = g_variant_parse(NULL, filter_serialized, NULL, NULL, NULL);
459 GVariant *params = g_variant_new("(s@a{sv})", folder, filter_variant);
460 GVariant *param = g_variant_new("(i)", request_id);
462 g_dbus_proxy_call(message_access_proxy,
463 "ListMessages", params,
464 G_DBUS_CALL_FLAGS_NONE, -1,
466 (GAsyncReadyCallback)__bt_list_messages_cb,
471 g_object_unref(message_access_proxy);
477 int _bt_map_client_update_inbox(const char* session_id)
482 GDBusConnection *g_conn;
483 GDBusProxy *message_proxy;
484 GVariant *ret = NULL;
486 g_conn = _bt_gdbus_get_session_gconn();
487 retv_if(g_conn == NULL, BLUETOOTH_ERROR_INTERNAL);
489 message_proxy = g_dbus_proxy_new_sync(g_conn,
490 G_DBUS_PROXY_FLAGS_NONE, NULL,
491 BT_OBEX_SERVICE_NAME, session_id,
492 BT_OBEX_MESSAGE_INTERFACE, NULL, &err);
494 retv_if(message_proxy == NULL, BLUETOOTH_ERROR_INTERNAL);
496 ret = g_dbus_proxy_call_sync(message_proxy,
497 "UpdateInbox", g_variant_new("()"),
498 G_DBUS_CALL_FLAGS_NONE, -1,
503 BT_ERR("UpdateInbox Error: %s\n", err->message);
507 g_variant_unref(ret);
510 g_object_unref(message_proxy);
514 return BLUETOOTH_ERROR_NONE;
517 void _bt_map_on_transfer_finished(const char *transfer_object_path, const int error)
519 BT_DBG("Entered _bt_map_on_transfer_finished");
520 BT_DBG("Looking for transfer %s id", transfer_object_path);
522 bt_map_callback_data_t *callback_data = NULL;
523 GSList* transfer = NULL;
524 for (transfer = transfer_list; transfer != NULL; transfer = g_slist_next(transfer)) {
525 callback_data = transfer->data;
526 if (NULL == callback_data)
529 if (0 == strcmp(transfer_object_path, callback_data->transfer_path)) {
530 BT_DBG("request id FOUND - triggering event");
532 GVariant *param = g_variant_new("(ii)", error, callback_data->request_id);
535 switch (callback_data->transfer_type) {
536 case BT_MAP_TRANSFER_GET_MESSAGE:
537 event = BLUETOOTH_EVENT_MAP_GET_MESSAGE_COMPLETE;
539 case BT_MAP_TRANSFER_PUSH_MESSAGE:
540 event = BLUETOOTH_EVENT_MAP_PUSH_MESSAGE_COMPLETE;
544 _bt_send_event(BT_MAP_CLIENT_EVENT, event, param);
546 // remove callback data from list
547 transfer_list = g_slist_remove(transfer_list, transfer);
549 //free memory and break loop
550 free(callback_data->transfer_path);
551 callback_data->transfer_path = NULL;
559 static void __bt_push_message_cb(GDBusProxy *proxy,
560 GAsyncResult *res, gpointer user_data)
564 GError *error = NULL;
565 GVariant *value, *in_param;
567 char *transfer_object_path = NULL;
568 GVariantIter *iter = NULL;
572 in_param = (GVariant*) user_data;
573 g_variant_get(in_param, "(i)", &request_id);
575 value = g_dbus_proxy_call_finish(proxy, res, &error);
577 BT_ERR("%s", error->message);
578 g_clear_error(&error);
582 g_variant_get(value, "(oa{sv})", &transfer_object_path, &iter);
583 g_variant_unref(value);
586 BT_DBG("transfer object path: [%s]", transfer_object_path);
588 BT_DBG("Adding request id %d - transfer [%s]", request_id, transfer_object_path);
589 bt_map_callback_data_t* callback_data = malloc(sizeof(*callback_data));
590 callback_data->transfer_type = BT_MAP_TRANSFER_PUSH_MESSAGE;
591 callback_data->request_id = request_id;
592 callback_data->transfer_path = transfer_object_path;
594 transfer_list = g_slist_append(transfer_list, callback_data);
596 g_variant_unref(value);
597 g_variant_unref(in_param);
602 int _bt_map_client_push_message(
604 GDBusMethodInvocation *context,
605 const char* session_id,
606 const char* source_file,
608 const char* args_serialized)
610 BT_DBG("Entered _bt_map_client_push_message with session id: \"%s\"", session_id);
611 BT_DBG("Entered source_file: %s", source_file);
612 BT_DBG("Entered folder: %s", folder);
614 GDBusConnection *g_conn;
615 GDBusProxy *message_access_proxy;
616 GError *error = NULL;
617 int result = BLUETOOTH_ERROR_NONE;
619 retv_if(session_id == NULL, BLUETOOTH_ERROR_INVALID_PARAM);
621 // TODO event listeners registration on first call, where should it be unregistered??
622 _bt_map_client_event_init();
624 g_conn = _bt_gdbus_get_session_gconn();
625 retv_if(g_conn == NULL, BLUETOOTH_ERROR_INTERNAL);
627 GVariant *out_param1 = g_variant_new_from_data((const GVariantType *)"ay",
628 &request_id, sizeof(int),
630 g_dbus_method_invocation_return_value(context, g_variant_new("(iv)", result, out_param1));
632 // create message access proxy
633 g_clear_error(&error);
634 message_access_proxy = g_dbus_proxy_new_sync(g_conn, G_DBUS_PROXY_FLAGS_NONE, NULL,
635 BT_OBEX_SERVICE_NAME, session_id, BT_OBEX_MESSAGE_INTERFACE,
638 BT_ERR("Could not create message access proxy: %s\n", error->message);
639 result = BLUETOOTH_ERROR_INTERNAL;
641 if (!message_access_proxy) {
642 BT_ERR("message proxy handle is null\n");
643 result = BLUETOOTH_ERROR_INTERNAL;
645 BT_DBG("message proxy set");
647 GVariant *args_variant = g_variant_parse(NULL, args_serialized, NULL, NULL, NULL);
649 GVariant *params = g_variant_new("(ss@a{sv})", source_file, folder, args_variant);
650 GVariant *req_id = g_variant_new("(i)", request_id);
652 g_dbus_proxy_call(message_access_proxy,
653 "PushMessage", params,
654 G_DBUS_CALL_FLAGS_NONE, -1,
655 NULL, (GAsyncReadyCallback)__bt_push_message_cb,
660 g_object_unref(message_access_proxy);
666 static void __bt_get_message_cb(GDBusProxy *proxy,
667 GAsyncResult *res, gpointer user_data)
671 GError *error = NULL;
672 GVariant *value, *in_param;
674 char *transfer_object_path = NULL;
675 GVariantIter *iter = NULL;
679 in_param = (GVariant*) user_data;
680 g_variant_get(in_param, "(i)", &request_id);
682 value = g_dbus_proxy_call_finish(proxy, res, &error);
684 BT_ERR("%s", error->message);
685 g_clear_error(&error);
689 g_variant_get(value, "(oa{sv})", &transfer_object_path, &iter);
690 g_variant_unref(value);
693 BT_DBG("transfer object path: [%s]", transfer_object_path);
695 BT_DBG("Adding request id %d - transfer [%s]", request_id, transfer_object_path);
696 bt_map_callback_data_t* callback_data = malloc(sizeof(*callback_data));
697 callback_data->transfer_type = BT_MAP_TRANSFER_GET_MESSAGE;
698 callback_data->request_id = request_id;
699 callback_data->transfer_path = transfer_object_path;
701 transfer_list = g_slist_append(transfer_list, callback_data);
703 g_variant_unref(value);
704 g_variant_unref(in_param);
709 int _bt_map_client_get_message(
711 GDBusMethodInvocation *context,
712 const char* message_object,
713 const char* target_file,
716 BT_DBG("Entered _bt_map_client_get_message");
718 GDBusConnection *g_conn;
719 GDBusProxy *message_proxy;
720 GError *error = NULL;
721 int result = BLUETOOTH_ERROR_NONE;
723 retv_if(message_object == NULL, BLUETOOTH_ERROR_INVALID_PARAM);
725 // TODO event listeners registration on first call, where should it be unregistered??
726 _bt_map_client_event_init();
728 g_conn = _bt_gdbus_get_session_gconn();
729 retv_if(g_conn == NULL, BLUETOOTH_ERROR_INTERNAL);
731 GVariant *out_param1 = g_variant_new_from_data((const GVariantType *)"ay",
732 &request_id, sizeof(int),
734 g_dbus_method_invocation_return_value(context, g_variant_new("(iv)", result, out_param1));
736 // create message proxy
737 g_clear_error(&error);
738 message_proxy = g_dbus_proxy_new_sync(g_conn, G_DBUS_PROXY_FLAGS_NONE, NULL,
739 BT_OBEX_SERVICE_NAME, message_object, "org.bluez.obex.Message1",
742 BT_ERR("Could not create message proxy: %s\n", error->message);
743 result = BLUETOOTH_ERROR_INTERNAL;
745 if (!message_proxy) {
746 BT_ERR("message proxy handle is null\n");
747 result = BLUETOOTH_ERROR_INTERNAL;
749 BT_DBG("message proxy set");
750 GVariant *params = g_variant_new("(sb)", target_file, attachment);
751 GVariant *req_id = g_variant_new("(i)", request_id);
753 g_dbus_proxy_call(message_proxy, "Get", params, G_DBUS_CALL_FLAGS_NONE, -1,
754 NULL, (GAsyncReadyCallback)__bt_get_message_cb, (void*)req_id);
758 g_object_unref(message_proxy);