From 686ce025a22f4a933fee4f3895f3b690ec628979 Mon Sep 17 00:00:00 2001 From: Piotr Dabrowski Date: Wed, 9 Nov 2016 16:39:46 +0100 Subject: [PATCH] [bluetooth-frwk] listMessages Change-Id: Ibc633c9c9e930da5cc296917d7821d0f2294971a --- bt-api/bt-event-handler.c | 143 ++++++++++++++++++++++++++++- bt-api/bt-map-client.c | 30 +++++- bt-api/bt-request-sender.c | 5 +- bt-service/bt-request-handler.c | 12 ++- bt-service/bt-service-event-sender.c | 5 +- bt-service/bt-service-map-client.c | 84 ++++++++++++++++- bt-service/include/bt-service-map-client.h | 2 + include/bluetooth-api.h | 72 ++++++++++++++- include/bt-internal-types.h | 2 +- 9 files changed, 340 insertions(+), 15 deletions(-) diff --git a/bt-api/bt-event-handler.c b/bt-api/bt-event-handler.c index c6c77b4..c34b91b 100644 --- a/bt-api/bt-event-handler.c +++ b/bt-api/bt-event-handler.c @@ -2126,9 +2126,148 @@ void __bt_map_client_event_filter(GDBusConnection *connection, __bt_remove_push_request_id(request_id); g_variant_unref(value); - } + } else if (strcasecmp(signal_name, BT_MAP_LIST_MESSAGES_COMPLETE) == 0) { + int request_id = 0; + GVariant* messages_list_var = NULL; + g_variant_get(parameters, "(iiv)", &result, &request_id, &messages_list_var); + if (__bt_is_request_id_exist(request_id) == FALSE) { + BT_ERR("Different request id!"); + return; + } + + bt_map_client_message_items_s messages_struct = {0,}; - // TODO MAP place for you else 2 + GVariantIter* iter; + g_variant_get(messages_list_var, "(a{oa{sv}})", &iter); + messages_struct.size = g_variant_iter_n_children(iter); + messages_struct.message_items = (bt_map_client_message_item_t*) + malloc(messages_struct.size * sizeof(*(messages_struct.message_items))); + BT_DBG("g_variant_iter_n_children: %d", messages_struct.size); + + char *object = NULL; + GVariantIter *properites = NULL; + int i = 0; + while (g_variant_iter_loop(iter, "{oa{sv}}", &object, &properites)) { + messages_struct.message_items[i].message_object_name = strdup(object); + BT_DBG("Message found: %s", messages_struct.message_items[i].message_object_name); + messages_struct.message_items[i].folder = NULL; + messages_struct.message_items[i].subject = NULL; + messages_struct.message_items[i].timestamp = NULL; + messages_struct.message_items[i].sender = NULL; + messages_struct.message_items[i].sender_address = NULL; + messages_struct.message_items[i].reply_to = NULL; + messages_struct.message_items[i].recipient = NULL; + messages_struct.message_items[i].recipient_address = NULL; + messages_struct.message_items[i].type = NULL; + messages_struct.message_items[i].size = -1; + messages_struct.message_items[i].is_text = -1; + messages_struct.message_items[i].status = NULL; + messages_struct.message_items[i].attachment_size = -1; + messages_struct.message_items[i].is_priority = -1; + messages_struct.message_items[i].is_read = -1; + messages_struct.message_items[i].is_sent = -1; + messages_struct.message_items[i].is_protected = -1; + char *key = NULL; + GVariant *value = NULL; + while (g_variant_iter_loop(properites, "{sv}", &key, &value)) { + char *value_string = NULL; + uint64_t value_int = -1; + bool value_bool = false; + if (strcmp(key, "Folder") == 0) { + g_variant_get(value, "s", &value_string); + messages_struct.message_items[i].folder = strdup(value_string); + BT_DBG(" Folder: %s", value_string); + } else if (strcmp(key, "Subject") == 0) { + g_variant_get(value, "s", &value_string); + messages_struct.message_items[i].subject = strdup(value_string); + BT_DBG(" Subject: %s", value_string); + } else if (strcmp(key, "Timestamp") == 0) { + g_variant_get(value, "s", &value_string); + messages_struct.message_items[i].timestamp = strdup(value_string); + BT_DBG(" Timestamp: %s", value_string); + } else if (strcmp(key, "Sender") == 0) { + g_variant_get(value, "s", &value_string); + messages_struct.message_items[i].sender = strdup(value_string); + BT_DBG(" Sender: %s", value_string); + } else if (strcmp(key, "SenderAddress") == 0) { + g_variant_get(value, "s", &value_string); + messages_struct.message_items[i].sender_address = strdup(value_string); + BT_DBG(" SenderAddress: %s", value_string); + } else if (strcmp(key, "ReplyTo") == 0) { + g_variant_get(value, "s", &value_string); + messages_struct.message_items[i].reply_to = strdup(value_string); + BT_DBG(" ReplyTo: %s", value_string); + } else if (strcmp(key, "Recipient") == 0) { + g_variant_get(value, "s", &value_string); + messages_struct.message_items[i].recipient = strdup(value_string); + BT_DBG(" Recipient: %s", value_string); + } else if (strcmp(key, "RecipientAddress") == 0) { + g_variant_get(value, "s", &value_string); + messages_struct.message_items[i].recipient_address = strdup(value_string); + BT_DBG(" RecipientAddress: %s", value_string); + } else if (strcmp(key, "Type") == 0) { + g_variant_get(value, "s", &value_string); + messages_struct.message_items[i].type = strdup(value_string); + BT_DBG(" Type: %s", value_string); + } else if (strcmp(key, "Size") == 0) { + g_variant_get(value, "t", &value_int); + messages_struct.message_items[i].size = value_int; + BT_DBG(" Size: %d", value_int); + } else if (strcmp(key, "Text") == 0) { + g_variant_get(value, "b", &value_bool); + messages_struct.message_items[i].is_text = value_bool ? 1 : 0; + BT_DBG(" Text: %s", value_bool ? "true" : "false"); + } else if (strcmp(key, "Status") == 0) { + g_variant_get(value, "s", &value_string); + messages_struct.message_items[i].status = strdup(value_string); + BT_DBG(" Status: %s", value_string); + } else if (strcmp(key, "AttachmentSize") == 0) { + g_variant_get(value, "t", &value_int); + messages_struct.message_items[i].attachment_size = value_int; + BT_DBG(" AttachmentSize: %d", value_int); + } else if (strcmp(key, "Priority") == 0) { + g_variant_get(value, "b", &value_bool); + messages_struct.message_items[i].is_priority = value_bool ? 1 : 0; + BT_DBG(" Priority: %s", value_bool ? "true" : "false"); + } else if (strcmp(key, "Read") == 0) { + g_variant_get(value, "b", &value_bool); + messages_struct.message_items[i].is_read = value_bool ? 1 : 0; + BT_DBG(" Read: %s", value_bool ? "true" : "false"); + } else if (strcmp(key, "Sent") == 0) { + g_variant_get(value, "b", &value_bool); + messages_struct.message_items[i].is_sent = value_bool ? 1 : 0; + BT_DBG(" Sent: %s", value_bool ? "true" : "false"); + } else if (strcmp(key, "Protected") == 0) { + g_variant_get(value, "b", &value_bool); + messages_struct.message_items[i].is_protected = value_bool ? 1 : 0; + BT_DBG(" Protected: %s", value_bool ? "true" : "false"); + } + } + ++i; + } + + _bt_common_event_cb(BLUETOOTH_EVENT_MAP_LIST_MESSAGES_COMPLETE, + result, &messages_struct, + event_info->cb, event_info->user_data); + + __bt_remove_push_request_id(request_id); + + while (--i >= 0) { + free(messages_struct.message_items[i].folder); + free(messages_struct.message_items[i].subject); + free(messages_struct.message_items[i].timestamp); + free(messages_struct.message_items[i].sender); + free(messages_struct.message_items[i].sender_address); + free(messages_struct.message_items[i].reply_to); + free(messages_struct.message_items[i].recipient); + free(messages_struct.message_items[i].recipient_address); + free(messages_struct.message_items[i].type); + free(messages_struct.message_items[i].status); + } + free(messages_struct.message_items); + + g_variant_unref(messages_list_var); + } // TODO MAP place for you else 3 // TODO MAP place for you else 4 // TODO MAP place for you else 5 diff --git a/bt-api/bt-map-client.c b/bt-api/bt-map-client.c index 8d4610e..78b66e7 100644 --- a/bt-api/bt-map-client.c +++ b/bt-api/bt-map-client.c @@ -194,12 +194,34 @@ BT_EXPORT_API int bluetooth_map_client_list_messages( const char *folder, GVariant *filter) { - BT_DBG("bluetooth_map_client_list_messages"); - int result = BLUETOOTH_ERROR_INTERNAL; + BT_DBG("bluetooth_map_client_list_messages"); + int result = 0; - /* TODO: MAP */ + BT_CHECK_ENABLED(return); + BT_CHECK_PARAMETER(session->session_path, return); + BT_CHECK_PARAMETER(folder, return); + BT_CHECK_PARAMETER(filter, return); - return result; + bt_user_info_t *user_info = _bt_get_user_data(BT_COMMON); + retv_if(user_info->cb == NULL, BLUETOOTH_ERROR_INTERNAL); + + BT_INIT_PARAMS(); + BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param); + + char *filter_string = g_variant_print(filter, TRUE); + + g_array_append_vals(in_param1, session->session_path, strlen(session->session_path)+1); + g_array_append_vals(in_param2, folder, strlen(folder)+1); + g_array_append_vals(in_param3, filter_string, strlen(filter_string)+1); + + result = _bt_send_request_async(BT_OBEX_SERVICE, BT_MAP_LIST_MESSAGES, + in_param1, in_param2, in_param3, in_param4, user_info->cb, user_info->user_data); + + BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param); + + free(filter_string); + + return result; } BT_EXPORT_API int bluetooth_map_client_update_inbox( diff --git a/bt-api/bt-request-sender.c b/bt-api/bt-request-sender.c index 294b8ad..0f2bcf1 100644 --- a/bt-api/bt-request-sender.c +++ b/bt-api/bt-request-sender.c @@ -325,8 +325,11 @@ static void __send_request_cb(GDBusProxy *proxy, request_id = g_array_index(out_param1, int, 0); BT_DBG("request_id : %d", request_id); _bt_add_push_request_id(request_id); + } else if (cb_data->service_function == BT_MAP_LIST_MESSAGES) { + request_id = g_array_index(out_param1, int, 0); + BT_DBG("request_id : %d", request_id); + _bt_add_push_request_id(request_id); } - // TODO MAP place for your own if 1 // TODO MAP place for your own if 2 // TODO MAP place for your own if 3 // TODO MAP place for your own if 4 diff --git a/bt-service/bt-request-handler.c b/bt-service/bt-request-handler.c index ba982f6..8565ce8 100644 --- a/bt-service/bt-request-handler.c +++ b/bt-service/bt-request-handler.c @@ -2324,9 +2324,17 @@ int __bt_obexd_request(int function_name, case BT_MAP_LIST_MESSAGES: { BT_DBG("BT_MAP_LIST_MESSAGES"); - /* TODO: MAP */ + char* session_id = (char*)g_variant_get_data(in_param1); + char* folder = (char*)g_variant_get_data(in_param2); + char* filter_string = (char*)g_variant_get_data(in_param3); + GVariant *filter = g_variant_parse(NULL, filter_string, NULL, NULL, NULL); - result = BLUETOOTH_ERROR_NOT_SUPPORT; + result = _bt_map_client_list_messages(request_id, context, session_id, folder, filter); + if (result == BLUETOOTH_ERROR_NONE) { + BT_DBG("_bt_map_client_list_messages succeed"); + } else { + BT_DBG("_bt_map_client_list_messages failed"); + } break; } diff --git a/bt-service/bt-service-event-sender.c b/bt-service/bt-service-event-sender.c index ac53303..937df18 100644 --- a/bt-service/bt-service-event-sender.c +++ b/bt-service/bt-service-event-sender.c @@ -336,7 +336,10 @@ int _bt_send_event(int event_type, int event, GVariant *param) signal = BT_MAP_FILTER_FIELDS_COMPLETE; BT_INFO_C("Completed list filters field operation[MAP]"); break; - // TODO MAP place for your own case 2 + case BLUETOOTH_EVENT_MAP_LIST_MESSAGES_COMPLETE: + signal = BT_MAP_LIST_MESSAGES_COMPLETE; + BT_INFO_C("Completed list messages operation [MAP]"); + break; // TODO MAP place for your own case 3 // TODO MAP place for your own case 4 // TODO MAP place for your own case 5 diff --git a/bt-service/bt-service-map-client.c b/bt-service/bt-service-map-client.c index d554e3d..f457155 100644 --- a/bt-service/bt-service-map-client.c +++ b/bt-service/bt-service-map-client.c @@ -546,18 +546,96 @@ int _bt_map_client_list_filter_fields(int request_id, GDBusMethodInvocation *con return BLUETOOTH_ERROR_NONE; } +static void __bt_list_messages_cb( + GDBusProxy *proxy, GAsyncResult *res, gpointer user_data) +{ + BT_DBG("+"); + + GError *error = NULL; + GVariant *value, *in_param, *param; + + int result = BLUETOOTH_ERROR_NONE; + int request_id; + int size = 0; + + in_param = (GVariant*) user_data; + g_variant_get(in_param, "(i)", &request_id); + + value = g_dbus_proxy_call_finish(proxy, res, &error); + + if (error) { + BT_ERR("%s", error->message); + g_clear_error(&error); + result = BLUETOOTH_ERROR_INTERNAL; + } + + param = g_variant_new("(iiv)", result, request_id, value); + BT_DBG("RequestID[%d]", request_id); + result = _bt_send_event(BT_MAP_CLIENT_EVENT, + BLUETOOTH_EVENT_MAP_LIST_MESSAGES_COMPLETE, param); + + g_variant_unref(value); + g_variant_unref(in_param); + + BT_DBG("-"); +} + int _bt_map_client_list_messages( + int request_id, + GDBusMethodInvocation *context, const char* session_id, const char* folder, GVariant *filter) { - BT_DBG("+"); + BT_DBG("Entered _bt_map_client_list_messages with session id: \"%s\"", session_id); + BT_DBG("Entered folder: %s", folder); + GDBusConnection *g_conn; + GDBusProxy *message_access_proxy; + GError *error = NULL; + int result = BLUETOOTH_ERROR_NONE; - /* TODO: MAP */ + retv_if(session_id == NULL, BLUETOOTH_ERROR_INVALID_PARAM); + + g_conn = _bt_gdbus_get_session_gconn(); + retv_if(g_conn == NULL, BLUETOOTH_ERROR_INTERNAL); + + GVariant *out_param1 = g_variant_new_from_data((const GVariantType *)"ay", + &request_id, sizeof(int), + TRUE, NULL, NULL); + g_dbus_method_invocation_return_value(context, + g_variant_new("(iv)", result, out_param1)); + // create message access proxy + g_clear_error(&error); + message_access_proxy = g_dbus_proxy_new_sync(g_conn, G_DBUS_PROXY_FLAGS_NONE, NULL, + BT_OBEX_SERVICE_NAME, session_id, "org.bluez.obex.MessageAccess1", + NULL, &error); + if (error != NULL) { + BT_ERR("Could not create message access proxy: %s\n", error->message); + result = BLUETOOTH_ERROR_INTERNAL; + } else { + if (!message_access_proxy) { + BT_ERR("message proxy handle is null\n"); + result = BLUETOOTH_ERROR_INTERNAL; + } else { + BT_DBG("message proxy set"); + + GVariant *params = g_variant_new("(s@a{sv})", folder, filter); + GVariant *param = g_variant_new("(i)", request_id); + + g_dbus_proxy_call(message_access_proxy, + "ListMessages", params, + G_DBUS_CALL_FLAGS_NONE, -1, + NULL, + (GAsyncReadyCallback)__bt_list_messages_cb, + (void*)param); + } + } + + g_object_unref(message_access_proxy); BT_DBG("-"); - return BLUETOOTH_ERROR_NONE; + return result; } int _bt_map_client_update_inbox(const char* session_id) diff --git a/bt-service/include/bt-service-map-client.h b/bt-service/include/bt-service-map-client.h index 4d9c772..fdfe63a 100644 --- a/bt-service/include/bt-service-map-client.h +++ b/bt-service/include/bt-service-map-client.h @@ -69,6 +69,8 @@ int _bt_map_client_list_folders(int request_id, GDBusMethodInvocation *context, int _bt_map_client_list_filter_fields(int request_id, GDBusMethodInvocation *context, const char* session_id); int _bt_map_client_list_messages( + int request_id, + GDBusMethodInvocation *context, const char* session_id, const char* folder, GVariant *filter); diff --git a/include/bluetooth-api.h b/include/bluetooth-api.h index a386950..74d330c 100644 --- a/include/bluetooth-api.h +++ b/include/bluetooth-api.h @@ -1805,10 +1805,80 @@ typedef struct { } bt_map_client_session_info_s; typedef struct { + int16_t offset; + int16_t maxcount; +} bt_map_client_list_folders_filter_t; + +typedef struct { + int16_t offset; + int16_t max_count; + int8_t subject_length; + char *fields; + char *types; + char *period_begin; + char *period_end; + int is_read; + char *recipient; + char *sender; + int is_priority; +} bt_map_client_list_messages_filter_t; + +typedef struct { + char *message_object_name; + char *folder; + char *subject; + char *timestamp; + char *sender; + char *sender_address; + char *reply_to; + char *recipient; + char *recipient_address; + char *type; + int64_t size; + int is_text; + char *status; + int64_t attachment_size; + int is_priority; + int is_read; + int is_sent; + int is_protected; +} bt_map_client_message_item_t; + +typedef struct { + int is_transparent; + int is_retry; + char *charset; +} bt_map_client_push_message_args_t; + +typedef struct { + char *folder; + char *subject; + char *timestamp; + char *sender; + char *sender_address; + char *reply_to; + char *recipient; + char *recipient_address; + char *type; + int64_t size; + char *status; + int is_priority; + int is_read; + int is_deleted; + int is_sent; + int is_protected; +} bt_map_client_message_t; + +typedef struct { char **names; // holding %size null-terminated folder names - int size; + int64_t size; } bt_map_client_folders_s; +typedef struct { + bt_map_client_message_item_t *message_items; + int64_t size; +} bt_map_client_message_items_s; + /** * Callback pointer type diff --git a/include/bt-internal-types.h b/include/bt-internal-types.h index 6bbc033..551e6a5 100644 --- a/include/bt-internal-types.h +++ b/include/bt-internal-types.h @@ -503,7 +503,7 @@ typedef struct { #define BT_MAP_DISCONNECTED "MapDisconnected" #define BT_MAP_LIST_FOLDERS_COMPLETE "ListFoldersComplete" #define BT_MAP_FILTER_FIELDS_COMPLETE "MapListFiltersFieldComplete" -// TODO MAP place for your define 2 +#define BT_MAP_LIST_MESSAGES_COMPLETE "MapListMessagesComplete" // TODO MAP place for your define 3 // TODO MAP place for your define 4 // TODO MAP place for your define 5 -- 2.7.4