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 BT_ERR("Could not create session: %s\n", err->message);
121 return BLUETOOTH_ERROR_INTERNAL;
124 BT_ERR("create session returned value is null\n");
125 return BLUETOOTH_ERROR_INTERNAL;
127 BT_DBG("create session succeed\n");
131 g_variant_get(value, "(&o)", session_id);
132 BT_DBG("session_id = \"%s\"\n", *session_id);
134 return BLUETOOTH_ERROR_NONE;
137 int _bt_destroy_session_sync(const char* session_id)
139 BT_DBG("Entered SERVICE destroy session with id: \"%s\"", session_id);
140 GDBusConnection *g_conn;
141 GDBusProxy *session_proxy;
144 retv_if(session_id == NULL, BLUETOOTH_ERROR_INVALID_PARAM);
146 g_conn = _bt_gdbus_get_session_gconn();
147 retv_if(g_conn == NULL, BLUETOOTH_ERROR_INTERNAL);
149 session_proxy = g_dbus_proxy_new_sync(g_conn, G_DBUS_PROXY_FLAGS_NONE,
150 NULL, BT_OBEX_SERVICE_NAME,
152 BT_OBEX_CLIENT_INTERFACE,
155 BT_ERR("Unable to create session_proxy: %s", err->message);
157 return BLUETOOTH_ERROR_INTERNAL;
159 retv_if(session_proxy == NULL, BLUETOOTH_ERROR_INTERNAL);
161 GVariant *param = g_variant_new("(o)", session_id);
163 g_dbus_proxy_call_sync(session_proxy, "RemoveSession", param,
164 G_DBUS_CALL_FLAGS_NONE, -1, NULL, &err);
166 BT_ERR("Could not remove session: %s\n", err->message);
168 return BLUETOOTH_ERROR_INTERNAL;
170 BT_DBG("remove session succeed\n");
173 return BLUETOOTH_ERROR_NONE;
176 int _bt_map_client_set_folder(const char* session_id, const char* name)
181 GDBusConnection *g_conn;
182 GDBusProxy *message_proxy;
183 GVariant *ret = NULL;
185 g_conn = _bt_gdbus_get_session_gconn();
186 retv_if(g_conn == NULL, BLUETOOTH_ERROR_INTERNAL);
188 message_proxy = g_dbus_proxy_new_sync(g_conn,
189 G_DBUS_PROXY_FLAGS_NONE, NULL,
190 BT_OBEX_SERVICE_NAME, session_id,
191 BT_OBEX_MESSAGE_INTERFACE, NULL, &err);
193 retv_if(message_proxy == NULL, BLUETOOTH_ERROR_INTERNAL);
195 ret = g_dbus_proxy_call_sync(message_proxy,
196 "SetFolder", g_variant_new("(s)", name),
197 G_DBUS_CALL_FLAGS_NONE, DBUS_TIMEOUT,
202 BT_ERR("SetFolder Error: %s\n", err->message);
206 g_variant_unref(ret);
209 g_object_unref(message_proxy);
213 return BLUETOOTH_ERROR_NONE;
216 static void __bt_list_folders_cb(GDBusProxy *proxy,
217 GAsyncResult *res, gpointer user_data)
221 GError *error = NULL;
222 GVariant *value, *in_param, *param;
224 int result = BLUETOOTH_ERROR_NONE;
227 in_param = (GVariant*) user_data;
228 g_variant_get(in_param, "(i)", &request_id);
230 value = g_dbus_proxy_call_finish(proxy, res, &error);
233 BT_ERR("%s", error->message);
234 g_clear_error(&error);
235 result = BLUETOOTH_ERROR_INTERNAL;
238 param = g_variant_new("(iiv)", result, request_id, value);
239 BT_DBG("RequestID[%d]", request_id);
240 result = _bt_send_event(BT_MAP_CLIENT_EVENT,
241 BLUETOOTH_EVENT_MAP_LIST_FOLDERS_COMPLETE, param);
243 g_variant_unref(value);
244 g_variant_unref(in_param);
249 int _bt_map_client_list_folders(
251 GDBusMethodInvocation *context,
252 const char* session_id,
253 const char* filter_serialized)
255 BT_DBG("Entered _bt_map_list_folders with session id: \"%s\"", session_id);
256 GDBusConnection *g_conn;
257 GDBusProxy *message_access_proxy;
258 GError *error = NULL;
259 int result = BLUETOOTH_ERROR_NONE;
261 retv_if(session_id == NULL, BLUETOOTH_ERROR_INVALID_PARAM);
263 g_conn = _bt_gdbus_get_session_gconn();
264 retv_if(g_conn == NULL, BLUETOOTH_ERROR_INTERNAL);
266 GVariant *out_param1 = g_variant_new_from_data((const GVariantType *)"ay",
267 &request_id, sizeof(int),
269 g_dbus_method_invocation_return_value(context,
270 g_variant_new("(iv)", result, out_param1));
272 // create message access proxy
273 g_clear_error(&error);
274 message_access_proxy = g_dbus_proxy_new_sync(g_conn, G_DBUS_PROXY_FLAGS_NONE, NULL,
275 BT_OBEX_SERVICE_NAME, session_id, "org.bluez.obex.MessageAccess1",
278 BT_ERR("Could not create message access proxy: %s\n", error->message);
279 result = BLUETOOTH_ERROR_INTERNAL;
281 if (!message_access_proxy) {
282 BT_ERR("message proxy handle is null\n");
283 result = BLUETOOTH_ERROR_INTERNAL;
285 BT_DBG("message proxy set");
287 GVariant *filter_variant = g_variant_parse(NULL, filter_serialized, NULL, NULL, NULL);
289 GVariant *params = g_variant_new("(@a{sv})", filter_variant);
290 GVariant *param = g_variant_new("(i)", request_id);
292 g_dbus_proxy_call(message_access_proxy,
293 "ListFolders", params,
294 G_DBUS_CALL_FLAGS_NONE, -1,
296 (GAsyncReadyCallback)__bt_list_folders_cb,
301 g_object_unref(message_access_proxy);
307 static void __bt_list_filter_fields_cb(GDBusProxy *proxy,
308 GAsyncResult *res, gpointer user_data)
312 GError *error = NULL;
313 GVariant *value, *in_param, *param;
315 int result = BLUETOOTH_ERROR_NONE;
318 in_param = (GVariant*) user_data;
319 g_variant_get(in_param, "(i)", &request_id);
321 value = g_dbus_proxy_call_finish(proxy, res, &error);
324 BT_ERR("%s", error->message);
325 g_clear_error(&error);
326 result = BLUETOOTH_ERROR_INTERNAL;
329 param = g_variant_new("(ivi)", result, value, request_id);
331 _bt_send_event(BT_MAP_CLIENT_EVENT, BLUETOOTH_EVENT_MAP_LIST_FILTER_FIELD_COMPLETE,
334 g_variant_unref(value);
335 g_variant_unref(in_param);
340 int _bt_map_client_list_filter_fields(int request_id, GDBusMethodInvocation *context, const char* session_id)
345 GDBusConnection *g_conn;
346 GDBusProxy *message_proxy;
347 int result = BLUETOOTH_ERROR_NONE;
349 retv_if(session_id == NULL, BLUETOOTH_ERROR_INVALID_PARAM);
351 g_conn = _bt_gdbus_get_session_gconn();
352 retv_if(g_conn == NULL, BLUETOOTH_ERROR_INTERNAL);
354 GVariant *out_param = g_variant_new_from_data((const GVariantType *)"ay",
355 &request_id, sizeof(int),
358 g_dbus_method_invocation_return_value(context,
359 g_variant_new("(iv)", result, out_param));
362 message_proxy = g_dbus_proxy_new_sync(g_conn,
363 G_DBUS_PROXY_FLAGS_NONE, NULL,
364 BT_OBEX_SERVICE_NAME, session_id,
365 BT_OBEX_MESSAGE_INTERFACE, NULL, &err);
367 retv_if(message_proxy == NULL, BLUETOOTH_ERROR_INTERNAL);
369 GVariant *param = g_variant_new("(i)", request_id);
371 g_dbus_proxy_call(message_proxy,
372 "ListFilterFields", g_variant_new("()"),
373 G_DBUS_CALL_FLAGS_NONE, -1,
375 (GAsyncReadyCallback)__bt_list_filter_fields_cb,
378 g_object_unref(message_proxy);
382 return BLUETOOTH_ERROR_NONE;
385 static void __bt_list_messages_cb(
386 GDBusProxy *proxy, GAsyncResult *res, gpointer user_data)
390 GError *error = NULL;
391 GVariant *value, *in_param, *param;
393 int result = BLUETOOTH_ERROR_NONE;
396 in_param = (GVariant*) user_data;
397 g_variant_get(in_param, "(i)", &request_id);
399 value = g_dbus_proxy_call_finish(proxy, res, &error);
402 BT_ERR("%s", error->message);
403 g_clear_error(&error);
404 result = BLUETOOTH_ERROR_INTERNAL;
407 param = g_variant_new("(iiv)", result, request_id, value);
408 BT_DBG("RequestID[%d]", request_id);
409 result = _bt_send_event(BT_MAP_CLIENT_EVENT,
410 BLUETOOTH_EVENT_MAP_LIST_MESSAGES_COMPLETE, param);
412 g_variant_unref(value);
413 g_variant_unref(in_param);
418 int _bt_map_client_list_messages(
420 GDBusMethodInvocation *context,
421 const char* session_id,
423 const char* filter_serialized)
425 BT_DBG("Entered _bt_map_client_list_messages with session id: \"%s\"", session_id);
426 BT_DBG("Entered folder: %s", folder);
427 GDBusConnection *g_conn;
428 GDBusProxy *message_access_proxy;
429 GError *error = NULL;
430 int result = BLUETOOTH_ERROR_NONE;
432 retv_if(session_id == NULL, BLUETOOTH_ERROR_INVALID_PARAM);
434 g_conn = _bt_gdbus_get_session_gconn();
435 retv_if(g_conn == NULL, BLUETOOTH_ERROR_INTERNAL);
437 GVariant *out_param1 = g_variant_new_from_data((const GVariantType *)"ay",
438 &request_id, sizeof(int),
440 g_dbus_method_invocation_return_value(context,
441 g_variant_new("(iv)", result, out_param1));
443 // create message access proxy
444 g_clear_error(&error);
445 message_access_proxy = g_dbus_proxy_new_sync(g_conn, G_DBUS_PROXY_FLAGS_NONE, NULL,
446 BT_OBEX_SERVICE_NAME, session_id, "org.bluez.obex.MessageAccess1",
449 BT_ERR("Could not create message access proxy: %s\n", error->message);
450 result = BLUETOOTH_ERROR_INTERNAL;
452 if (!message_access_proxy) {
453 BT_ERR("message proxy handle is null\n");
454 result = BLUETOOTH_ERROR_INTERNAL;
456 BT_DBG("message proxy set");
458 GVariant *filter_variant = g_variant_parse(NULL, filter_serialized, NULL, NULL, NULL);
460 GVariant *params = g_variant_new("(s@a{sv})", folder, filter_variant);
461 GVariant *param = g_variant_new("(i)", request_id);
463 g_dbus_proxy_call(message_access_proxy,
464 "ListMessages", params,
465 G_DBUS_CALL_FLAGS_NONE, -1,
467 (GAsyncReadyCallback)__bt_list_messages_cb,
472 g_object_unref(message_access_proxy);
478 int _bt_map_client_update_inbox(const char* session_id)
483 GDBusConnection *g_conn;
484 GDBusProxy *message_proxy;
485 GVariant *ret = NULL;
487 g_conn = _bt_gdbus_get_session_gconn();
488 retv_if(g_conn == NULL, BLUETOOTH_ERROR_INTERNAL);
490 message_proxy = g_dbus_proxy_new_sync(g_conn,
491 G_DBUS_PROXY_FLAGS_NONE, NULL,
492 BT_OBEX_SERVICE_NAME, session_id,
493 BT_OBEX_MESSAGE_INTERFACE, NULL, &err);
495 retv_if(message_proxy == NULL, BLUETOOTH_ERROR_INTERNAL);
497 ret = g_dbus_proxy_call_sync(message_proxy,
498 "UpdateInbox", g_variant_new("()"),
499 G_DBUS_CALL_FLAGS_NONE, -1,
504 BT_ERR("UpdateInbox Error: %s\n", err->message);
508 g_variant_unref(ret);
511 g_object_unref(message_proxy);
515 return BLUETOOTH_ERROR_NONE;
518 void _bt_map_on_transfer_finished(const char *transfer_object_path, const int error)
520 BT_DBG("Entered _bt_map_on_transfer_finished");
521 BT_DBG("Looking for transfer %s id", transfer_object_path);
523 bt_map_callback_data_t *callback_data = NULL;
524 GSList* transfer = NULL;
525 for (transfer = transfer_list; transfer != NULL; transfer = g_slist_next(transfer)) {
526 callback_data = transfer->data;
527 if (NULL == callback_data)
530 if (0 == strcmp(transfer_object_path, callback_data->transfer_path)) {
531 BT_DBG("request id FOUND - triggering event");
533 GVariant *param = g_variant_new("(ii)", error, callback_data->request_id);
536 switch (callback_data->transfer_type) {
537 case BT_MAP_TRANSFER_GET_MESSAGE:
538 event = BLUETOOTH_EVENT_MAP_GET_MESSAGE_COMPLETE;
540 case BT_MAP_TRANSFER_PUSH_MESSAGE:
541 event = BLUETOOTH_EVENT_MAP_PUSH_MESSAGE_COMPLETE;
545 _bt_send_event(BT_MAP_CLIENT_EVENT, event, param);
547 // remove callback data from list
548 transfer_list = g_slist_remove(transfer_list, transfer);
550 //free memory and break loop
551 free(callback_data->transfer_path);
552 callback_data->transfer_path = NULL;
560 static void __bt_push_message_cb(GDBusProxy *proxy,
561 GAsyncResult *res, gpointer user_data)
565 GError *error = NULL;
566 GVariant *value, *in_param;
568 char *transfer_object_path = NULL;
569 GVariantIter *iter = NULL;
573 in_param = (GVariant*) user_data;
574 g_variant_get(in_param, "(i)", &request_id);
576 value = g_dbus_proxy_call_finish(proxy, res, &error);
578 BT_ERR("%s", error->message);
579 g_clear_error(&error);
583 g_variant_get(value, "(oa{sv})", &transfer_object_path, &iter);
584 g_variant_unref(value);
587 BT_DBG("transfer object path: [%s]", transfer_object_path);
589 BT_DBG("Adding request id %d - transfer [%s]", request_id, transfer_object_path);
590 bt_map_callback_data_t* callback_data = malloc(sizeof(*callback_data));
591 callback_data->transfer_type = BT_MAP_TRANSFER_PUSH_MESSAGE;
592 callback_data->request_id = request_id;
593 callback_data->transfer_path = transfer_object_path;
595 transfer_list = g_slist_append(transfer_list, callback_data);
597 g_variant_unref(value);
598 g_variant_unref(in_param);
603 int _bt_map_client_push_message(
605 GDBusMethodInvocation *context,
606 const char* session_id,
607 const char* source_file,
609 const char* args_serialized)
611 BT_DBG("Entered _bt_map_client_push_message with session id: \"%s\"", session_id);
612 BT_DBG("Entered source_file: %s", source_file);
613 BT_DBG("Entered folder: %s", folder);
615 GDBusConnection *g_conn;
616 GDBusProxy *message_access_proxy;
617 GError *error = NULL;
618 int result = BLUETOOTH_ERROR_NONE;
620 retv_if(session_id == NULL, BLUETOOTH_ERROR_INVALID_PARAM);
622 // TODO event listeners registration on first call, where should it be unregistered??
623 _bt_map_client_event_init();
625 g_conn = _bt_gdbus_get_session_gconn();
626 retv_if(g_conn == NULL, BLUETOOTH_ERROR_INTERNAL);
628 GVariant *out_param1 = g_variant_new_from_data((const GVariantType *)"ay",
629 &request_id, sizeof(int),
631 g_dbus_method_invocation_return_value(context, g_variant_new("(iv)", result, out_param1));
633 // create message access proxy
634 g_clear_error(&error);
635 message_access_proxy = g_dbus_proxy_new_sync(g_conn, G_DBUS_PROXY_FLAGS_NONE, NULL,
636 BT_OBEX_SERVICE_NAME, session_id, BT_OBEX_MESSAGE_INTERFACE,
639 BT_ERR("Could not create message access proxy: %s\n", error->message);
640 result = BLUETOOTH_ERROR_INTERNAL;
642 if (!message_access_proxy) {
643 BT_ERR("message proxy handle is null\n");
644 result = BLUETOOTH_ERROR_INTERNAL;
646 BT_DBG("message proxy set");
648 GVariant *args_variant = g_variant_parse(NULL, args_serialized, NULL, NULL, NULL);
650 GVariant *params = g_variant_new("(ss@a{sv})", source_file, folder, args_variant);
651 GVariant *req_id = g_variant_new("(i)", request_id);
653 g_dbus_proxy_call(message_access_proxy,
654 "PushMessage", params,
655 G_DBUS_CALL_FLAGS_NONE, -1,
656 NULL, (GAsyncReadyCallback)__bt_push_message_cb,
661 g_object_unref(message_access_proxy);
667 static void __bt_get_message_cb(GDBusProxy *proxy,
668 GAsyncResult *res, gpointer user_data)
672 GError *error = NULL;
673 GVariant *value, *in_param;
675 char *transfer_object_path = NULL;
676 GVariantIter *iter = NULL;
680 in_param = (GVariant*) user_data;
681 g_variant_get(in_param, "(i)", &request_id);
683 value = g_dbus_proxy_call_finish(proxy, res, &error);
685 BT_ERR("%s", error->message);
686 g_clear_error(&error);
690 g_variant_get(value, "(oa{sv})", &transfer_object_path, &iter);
691 g_variant_unref(value);
694 BT_DBG("transfer object path: [%s]", transfer_object_path);
696 BT_DBG("Adding request id %d - transfer [%s]", request_id, transfer_object_path);
697 bt_map_callback_data_t* callback_data = malloc(sizeof(*callback_data));
698 callback_data->transfer_type = BT_MAP_TRANSFER_GET_MESSAGE;
699 callback_data->request_id = request_id;
700 callback_data->transfer_path = transfer_object_path;
702 transfer_list = g_slist_append(transfer_list, callback_data);
704 g_variant_unref(value);
705 g_variant_unref(in_param);
710 int _bt_map_client_get_message(
712 GDBusMethodInvocation *context,
713 const char* message_object,
714 const char* target_file,
717 BT_DBG("Entered _bt_map_client_get_message");
719 GDBusConnection *g_conn;
720 GDBusProxy *message_proxy;
721 GError *error = NULL;
722 int result = BLUETOOTH_ERROR_NONE;
724 retv_if(message_object == NULL, BLUETOOTH_ERROR_INVALID_PARAM);
726 // TODO event listeners registration on first call, where should it be unregistered??
727 _bt_map_client_event_init();
729 g_conn = _bt_gdbus_get_session_gconn();
730 retv_if(g_conn == NULL, BLUETOOTH_ERROR_INTERNAL);
732 GVariant *out_param1 = g_variant_new_from_data((const GVariantType *)"ay",
733 &request_id, sizeof(int),
735 g_dbus_method_invocation_return_value(context, g_variant_new("(iv)", result, out_param1));
737 // create message proxy
738 g_clear_error(&error);
739 message_proxy = g_dbus_proxy_new_sync(g_conn, G_DBUS_PROXY_FLAGS_NONE, NULL,
740 BT_OBEX_SERVICE_NAME, message_object, "org.bluez.obex.Message1",
743 BT_ERR("Could not create message proxy: %s\n", error->message);
744 result = BLUETOOTH_ERROR_INTERNAL;
746 if (!message_proxy) {
747 BT_ERR("message proxy handle is null\n");
748 result = BLUETOOTH_ERROR_INTERNAL;
750 BT_DBG("message proxy set");
751 GVariant *params = g_variant_new("(sb)", target_file, attachment);
752 GVariant *req_id = g_variant_new("(i)", request_id);
754 g_dbus_proxy_call(message_proxy, "Get", params, G_DBUS_CALL_FLAGS_NONE, -1,
755 NULL, (GAsyncReadyCallback)__bt_get_message_cb, (void*)req_id);
759 g_object_unref(message_proxy);