* [PATCH v2 1/6] obexd: Add initial support for MAP conversations @ 2020-02-11 6:36 Ajay Kishore 2020-02-11 6:36 ` [PATCH v2 2/6] obexd: Add parsers for conversation filters Ajay Kishore ` (5 more replies) 0 siblings, 6 replies; 8+ messages in thread From: Ajay Kishore @ 2020-02-11 6:36 UTC (permalink / raw) To: linux-bluetooth Changes made to add a new method for MAP conversation listing i.e "ListConversations" to handle conversation listing object "x-bt/MAP-convo-listing". --- obexd/client/map.c | 67 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 67 insertions(+) diff --git a/obexd/client/map.c b/obexd/client/map.c index 550c5af..adf62d9 100644 --- a/obexd/client/map.c +++ b/obexd/client/map.c @@ -1560,6 +1560,69 @@ static DBusMessage *map_list_messages(DBusConnection *connection, return get_message_listing(map, message, folder, apparam); } +static GObexApparam *parse_conversation_filters(GObexApparam *apparam, + DBusMessageIter *iter) +{ + DBusMessageIter array; + + if (dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_ARRAY) { + DBG("Not of type array"); + return NULL; + } + + dbus_message_iter_recurse(iter, &array); + + while (dbus_message_iter_get_arg_type(&array) == DBUS_TYPE_DICT_ENTRY) { + const char *key; + DBusMessageIter value, entry; + + dbus_message_iter_recurse(&array, &entry); + dbus_message_iter_get_basic(&entry, &key); + + dbus_message_iter_next(&entry); + dbus_message_iter_recurse(&entry, &value); + + /* TODO: Parse conversation filters */ + + dbus_message_iter_next(&array); + } + return apparam; +} + +static DBusMessage *map_list_conversations(DBusConnection *connection, + DBusMessage *message, + void *user_data) +{ + struct map_data *map = user_data; + const char *folder; + GObexApparam *apparam; + DBusMessageIter args; + + dbus_message_iter_init(message, &args); + + if (dbus_message_iter_get_arg_type(&args) != DBUS_TYPE_STRING) + return g_dbus_create_error(message, + ERROR_INTERFACE ".InvalidArguments", NULL); + + dbus_message_iter_get_basic(&args, &folder); + + apparam = g_obex_apparam_set_uint16(NULL, MAP_AP_MAXLISTCOUNT, + DEFAULT_COUNT); + apparam = g_obex_apparam_set_uint16(apparam, MAP_AP_STARTOFFSET, + DEFAULT_OFFSET); + + dbus_message_iter_next(&args); + + if (parse_conversation_filters(apparam, &args) == NULL) { + g_obex_apparam_free(apparam); + return g_dbus_create_error(message, + ERROR_INTERFACE ".InvalidArguments", NULL); + } + + /*TODO: Return conversation listing */ + return NULL; +} + static char **get_filter_strs(uint64_t filter, int *size) { char **list, **item; @@ -1817,6 +1880,10 @@ static const GDBusMethodTable map_methods[] = { GDBUS_ARGS({ "folder", "s" }, { "filter", "a{sv}" }), GDBUS_ARGS({ "messages", "a{oa{sv}}" }), map_list_messages) }, + { GDBUS_ASYNC_METHOD("ListConversations", + GDBUS_ARGS({ "folder", "s" }, { "filter", "a{sv}" }), + GDBUS_ARGS({ "conversations", "a{oa{sv}}" }), + map_list_conversations) }, { GDBUS_METHOD("ListFilterFields", NULL, GDBUS_ARGS({ "fields", "as" }), -- 2.7.4 ^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH v2 2/6] obexd: Add parsers for conversation filters 2020-02-11 6:36 [PATCH v2 1/6] obexd: Add initial support for MAP conversations Ajay Kishore @ 2020-02-11 6:36 ` Ajay Kishore 2020-02-11 6:36 ` [PATCH v2 3/6] obexd: Get conversation listings Ajay Kishore ` (4 subsequent siblings) 5 siblings, 0 replies; 8+ messages in thread From: Ajay Kishore @ 2020-02-11 6:36 UTC (permalink / raw) To: linux-bluetooth Changes made to add a new method to parse the map conversation filters. Filters LastActivityBegin and LastActivityEnd is used to filter the conversations that are returned in the Conversation-Listing object by LastActivity. --- obexd/client/map.c | 66 ++++++++++++++++++++++++++++++++++++++++++++++++++++-- obexd/src/map_ap.h | 3 +++ 2 files changed, 67 insertions(+), 2 deletions(-) diff --git a/obexd/client/map.c b/obexd/client/map.c index adf62d9..6e84a73 100644 --- a/obexd/client/map.c +++ b/obexd/client/map.c @@ -1369,6 +1369,21 @@ static GObexApparam *parse_filter_type(GObexApparam *apparam, types); } +static GObexApparam *parse_la_begin(GObexApparam *apparam, + DBusMessageIter *iter) +{ + const char *string; + + if (dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_STRING) + return NULL; + + dbus_message_iter_get_basic(iter, &string); + + return g_obex_apparam_set_string(apparam, + MAP_AP_FILTERLASTACTIVITYBEGIN, + string); +} + static GObexApparam *parse_period_begin(GObexApparam *apparam, DBusMessageIter *iter) { @@ -1397,6 +1412,20 @@ static GObexApparam *parse_period_end(GObexApparam *apparam, string); } +static GObexApparam *parse_la_end(GObexApparam *apparam, + DBusMessageIter *iter) +{ + const char *string; + + if (dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_STRING) + return NULL; + + dbus_message_iter_get_basic(iter, &string); + + return g_obex_apparam_set_string(apparam, MAP_AP_FILTERLASTACTIVITYEND, + string); +} + static GObexApparam *parse_filter_read(GObexApparam *apparam, DBusMessageIter *iter) { @@ -1560,6 +1589,19 @@ static DBusMessage *map_list_messages(DBusConnection *connection, return get_message_listing(map, message, folder, apparam); } +static GObexApparam *parse_filter_conv_id(GObexApparam *apparam, + DBusMessageIter *iter) +{ + guint8 id; + + if (dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_BYTE) + return NULL; + + dbus_message_iter_get_basic(iter, &id); + + return g_obex_apparam_set_uint8(apparam, MAP_AP_CONVERSATIONID, id); +} + static GObexApparam *parse_conversation_filters(GObexApparam *apparam, DBusMessageIter *iter) { @@ -1582,8 +1624,28 @@ static GObexApparam *parse_conversation_filters(GObexApparam *apparam, dbus_message_iter_next(&entry); dbus_message_iter_recurse(&entry, &value); - /* TODO: Parse conversation filters */ - + if (strcasecmp(key, "Offset") == 0) { + if (parse_offset(apparam, &value) == NULL) + return NULL; + } else if (strcasecmp(key, "MaxCount") == 0) { + if (parse_max_count(apparam, &value) == NULL) + return NULL; + } else if (strcasecmp(key, "LastActivityBegin") == 0) { + if (parse_la_begin(apparam, &value) == NULL) + return NULL; + } else if (strcasecmp(key, "FilterLastActivityEnd") == 0) { + if (parse_la_end(apparam, &value) == NULL) + return NULL; + } else if (strcasecmp(key, "Read") == 0) { + if (parse_filter_read(apparam, &value) == NULL) + return NULL; + } else if (strcasecmp(key, "Recipient") == 0) { + if (parse_filter_recipient(apparam, &value) == NULL) + return NULL; + } else if (strcasecmp(key, "ConversationId") == 0) { + if (parse_filter_conv_id(apparam, &value) == NULL) + return NULL; + } dbus_message_iter_next(&array); } return apparam; diff --git a/obexd/src/map_ap.h b/obexd/src/map_ap.h index da108fe..3773859 100644 --- a/obexd/src/map_ap.h +++ b/obexd/src/map_ap.h @@ -31,6 +31,8 @@ enum map_ap_tag { MAP_AP_FILTERREADSTATUS = 0x06, /* uint8_t */ MAP_AP_FILTERRECIPIENT = 0x07, /* char * */ MAP_AP_FILTERORIGINATOR = 0x08, /* char * */ + MAP_AP_FILTERLASTACTIVITYBEGIN = 0x08, /* char * */ + MAP_AP_FILTERLASTACTIVITYEND = 0x09, /* char * */ MAP_AP_FILTERPRIORITY = 0x09, /* uint8_t */ MAP_AP_ATTACHMENT = 0x0A, /* uint8_t */ MAP_AP_TRANSPARENT = 0x0B, /* uint8_t */ @@ -48,4 +50,5 @@ enum map_ap_tag { MAP_AP_STATUSINDICATOR = 0x17, /* uint8_t */ MAP_AP_STATUSVALUE = 0x18, /* uint8_t */ MAP_AP_MSETIME = 0x19, /* char * */ + MAP_AP_CONVERSATIONID = 0x1C, /* uint32_t */ }; -- 2.7.4 ^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH v2 3/6] obexd: Get conversation listings 2020-02-11 6:36 [PATCH v2 1/6] obexd: Add initial support for MAP conversations Ajay Kishore 2020-02-11 6:36 ` [PATCH v2 2/6] obexd: Add parsers for conversation filters Ajay Kishore @ 2020-02-11 6:36 ` Ajay Kishore 2020-02-11 6:36 ` [PATCH v2 5/6] obexd: Handle MAP Event Report v1.1 and v1.2 Ajay Kishore ` (3 subsequent siblings) 5 siblings, 0 replies; 8+ messages in thread From: Ajay Kishore @ 2020-02-11 6:36 UTC (permalink / raw) To: linux-bluetooth Changes made to build get conversation listing command and its respective callback function to handle response for conversation listing. --- obexd/client/map.c | 98 ++++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 96 insertions(+), 2 deletions(-) diff --git a/obexd/client/map.c b/obexd/client/map.c index 6e84a73..4f3d6c5 100644 --- a/obexd/client/map.c +++ b/obexd/client/map.c @@ -1221,6 +1221,64 @@ clean: pending_request_free(request); } +static void conversation_listing_cb(struct obc_session *session, + struct obc_transfer *transfer, + GError *err, void *user_data) +{ + struct pending_request *request = user_data; + struct map_parser *parser; + GMarkupParseContext *ctxt; + DBusMessage *reply; + DBusMessageIter iter, array; + char *contents; + size_t size; + int perr; + + if (err != NULL) { + reply = g_dbus_create_error(request->msg, + ERROR_INTERFACE ".Failed", + "%s", err->message); + goto done; + } + + perr = obc_transfer_get_contents(transfer, &contents, &size); + if (perr < 0) { + reply = g_dbus_create_error(request->msg, + ERROR_INTERFACE ".Failed", + "Error reading contents: %s", + strerror(-perr)); + goto done; + } + + reply = dbus_message_new_method_return(request->msg); + if (reply == NULL) { + g_free(contents); + goto clean; + } + + dbus_message_iter_init_append(reply, &iter); + dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, + DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING + DBUS_TYPE_OBJECT_PATH_AS_STRING + DBUS_TYPE_ARRAY_AS_STRING + DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING + DBUS_TYPE_STRING_AS_STRING + DBUS_TYPE_VARIANT_AS_STRING + DBUS_DICT_ENTRY_END_CHAR_AS_STRING + DBUS_DICT_ENTRY_END_CHAR_AS_STRING, + &array); + + dbus_message_iter_close_container(&iter, &array); + g_free(contents); + +done: + if (convo_element_end) + if (g_dbus_send_message(conn, reply)) + convo_element_end = FALSE; +clean: + pending_request_free(request); +} + static char *get_absolute_folder(struct map_data *map, const char *subfolder) { const char *root = obc_session_get_folder(map->session); @@ -1269,6 +1327,43 @@ fail: return reply; } +static DBusMessage *get_conversations_listing(struct map_data *map, + DBusMessage *message, + const char *folder, + GObexApparam *apparam) +{ + struct pending_request *request; + struct obc_transfer *transfer; + GError *err = NULL; + DBusMessage *reply; + + transfer = obc_transfer_get("x-bt/MAP-convo-listing", folder, NULL, + &err); + + if (transfer == NULL) { + g_obex_apparam_free(apparam); + goto fail; + } + obc_transfer_set_apparam(transfer, apparam); + + request = pending_request_new(map, message); + request->folder = get_absolute_folder(map, folder); + + if (!obc_session_queue(map->session, transfer, + conversation_listing_cb, request, &err)) { + pending_request_free(request); + goto fail; + } + + return NULL; + +fail: + reply = g_dbus_create_error(message, ERROR_INTERFACE ".Failed", "%s", + err->message); + g_error_free(err); + return reply; +} + static GObexApparam *parse_subject_length(GObexApparam *apparam, DBusMessageIter *iter) { @@ -1681,8 +1776,7 @@ static DBusMessage *map_list_conversations(DBusConnection *connection, ERROR_INTERFACE ".InvalidArguments", NULL); } - /*TODO: Return conversation listing */ - return NULL; + return get_conversations_listing(map, message, folder, apparam); } static char **get_filter_strs(uint64_t filter, int *size) -- 2.7.4 ^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH v2 5/6] obexd: Handle MAP Event Report v1.1 and v1.2 2020-02-11 6:36 [PATCH v2 1/6] obexd: Add initial support for MAP conversations Ajay Kishore 2020-02-11 6:36 ` [PATCH v2 2/6] obexd: Add parsers for conversation filters Ajay Kishore 2020-02-11 6:36 ` [PATCH v2 3/6] obexd: Get conversation listings Ajay Kishore @ 2020-02-11 6:36 ` Ajay Kishore 2020-02-11 6:36 ` [PATCH v3 4/6] obexd: Add parser for conversation element Ajay Kishore ` (2 subsequent siblings) 5 siblings, 0 replies; 8+ messages in thread From: Ajay Kishore @ 2020-02-11 6:36 UTC (permalink / raw) To: linux-bluetooth Changes made to add handler function for the corresponding events mentioned in extended event reports 1.1 and 1.2. --- obexd/client/map-event.h | 8 +++++++- obexd/client/map.c | 19 +++++++++++++++++++ 2 files changed, 26 insertions(+), 1 deletion(-) diff --git a/obexd/client/map-event.h b/obexd/client/map-event.h index 5414b26..c41bb67 100644 --- a/obexd/client/map-event.h +++ b/obexd/client/map-event.h @@ -32,7 +32,13 @@ enum map_event_type { MAP_ET_MEMORY_FULL, MAP_ET_MEMORY_AVAILABLE, MAP_ET_MESSAGE_DELETED, - MAP_ET_MESSAGE_SHIFT + MAP_ET_MESSAGE_SHIFT, + MAP_ET_READ_STATUS_CHANGED, + MAP_ET_MESSAGE_REMOVED, + MAP_ET_MESSAGE_EXTENDED_DATA_CHANGED, + MAP_ET_PARTICIPANT_PRESENCE_CHANGED, + MAP_ET_PARTICIPANT_CHAT_STATE_CHANGED, + MAP_ET_CONVERSATION_CHANGED }; struct map_event { diff --git a/obexd/client/map.c b/obexd/client/map.c index 8a059ab..3bcb4a3 100644 --- a/obexd/client/map.c +++ b/obexd/client/map.c @@ -2550,6 +2550,12 @@ static void map_handle_folder_changed(struct map_data *map, "Folder"); } +static void map_handle_remove_message(struct map_data *map, + struct map_event *event) +{ + g_hash_table_remove(map->messages, &event->handle); +} + static void map_handle_notification(struct map_event *event, void *user_data) { struct map_data *map = user_data; @@ -2582,6 +2588,19 @@ static void map_handle_notification(struct map_event *event, void *user_data) case MAP_ET_MESSAGE_SHIFT: map_handle_folder_changed(map, event, event->folder); break; + case MAP_ET_READ_STATUS_CHANGED: + map_handle_status_changed(map, event, "read"); + break; + case MAP_ET_MESSAGE_REMOVED: + map_handle_remove_message(map, event); + break; + case MAP_ET_MESSAGE_EXTENDED_DATA_CHANGED: + map_handle_status_changed(map, event, + "message-extended-data-changed"); + break; + case MAP_ET_PARTICIPANT_PRESENCE_CHANGED: + case MAP_ET_PARTICIPANT_CHAT_STATE_CHANGED: + case MAP_ET_CONVERSATION_CHANGED: case MAP_ET_MEMORY_FULL: case MAP_ET_MEMORY_AVAILABLE: default: -- 2.7.4 ^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH v3 4/6] obexd: Add parser for conversation element 2020-02-11 6:36 [PATCH v2 1/6] obexd: Add initial support for MAP conversations Ajay Kishore ` (2 preceding siblings ...) 2020-02-11 6:36 ` [PATCH v2 5/6] obexd: Handle MAP Event Report v1.1 and v1.2 Ajay Kishore @ 2020-02-11 6:36 ` Ajay Kishore 2020-02-11 6:36 ` [PATCH v3 6/6] doc/obex-api: Update documentation Ajay Kishore 2020-02-11 19:27 ` [PATCH v2 1/6] obexd: Add initial support for MAP conversations Luiz Augusto von Dentz 5 siblings, 0 replies; 8+ messages in thread From: Ajay Kishore @ 2020-02-11 6:36 UTC (permalink / raw) To: linux-bluetooth Changes made to define convo parser function to iterate through all supported conversation elements and parse their values. --- obexd/client/map.c | 428 ++++++++++++++++++++++++++++++++++++++++++++++++++++- obexd/src/map_ap.h | 40 ++--- 2 files changed, 447 insertions(+), 21 deletions(-) diff --git a/obexd/client/map.c b/obexd/client/map.c index 4f3d6c5..8a059ab 100644 --- a/obexd/client/map.c +++ b/obexd/client/map.c @@ -138,12 +138,35 @@ struct map_msg { GDBusPendingPropertySet pending; }; +struct map_convo { + struct map_data *data; + char *path; + uint64_t id; + char *convo_name; + char *convo_last_activity; + char *read_status; + char *summary; + char *uci; + char *display_name; + uint8_t chat_state; + char *last_activity; + char *x_bt_uid; + char *name; + uint8_t presence_availability; + char *presence_text; + int8_t priority; + char *folder; +}; + struct map_parser { struct pending_request *request; DBusMessageIter *iter; }; static DBusConnection *conn = NULL; +DBusMessageIter convo_entry, *convo_iter; +struct map_convo *conversation; +static bool convo_element_end = FALSE; static struct pending_request *pending_request_new(struct map_data *map, DBusMessage *message) @@ -836,6 +859,8 @@ static void parse_type(struct map_msg *msg, const char *value) type = "email"; else if (strcasecmp(value, "MMS") == 0) type = "mms"; + else if (strcasecmp(value, "IM") == 0) + type = "IM"; if (g_strcmp0(msg->type, type) == 0) return; @@ -1073,6 +1098,285 @@ static void parse_protected(struct map_msg *msg, const char *value) MAP_MSG_INTERFACE, "Protected"); } +static void map_convo_free(void *data) +{ + struct map_convo *convo = data; + + g_free(convo->path); + g_free(convo->convo_name); + g_free(convo->folder); + g_free(convo->convo_last_activity); + g_free(convo->read_status); + g_free(convo->summary); + g_free(convo->uci); + g_free(convo->display_name); + g_free(convo->last_activity); + g_free(convo->x_bt_uid); + g_free(convo->name); + g_free(convo->presence_text); + g_free(convo); +} + +static gboolean convo_name_exists(const GDBusPropertyTable *property, + void *data) +{ + struct map_convo *convo = data; + + return convo->convo_name != NULL; +} + +static gboolean get_convo_name(const GDBusPropertyTable *property, + DBusMessageIter *iter, void *data) +{ + struct map_convo *convo = data; + + dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING, + &convo->convo_name); + + return TRUE; +} + +static gboolean summary_exists(const GDBusPropertyTable *property, + void *data) +{ + struct map_convo *convo = data; + + return convo->summary != NULL; +} + +static gboolean get_summary(const GDBusPropertyTable *property, + DBusMessageIter *iter, void *data) +{ + struct map_convo *convo = data; + + dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING, + &convo->summary); + + return TRUE; +} + +static gboolean uci_exists(const GDBusPropertyTable *property, void *data) +{ + struct map_convo *convo = data; + + return convo->uci != NULL; +} + +static gboolean get_uci(const GDBusPropertyTable *property, + DBusMessageIter *iter, void *data) +{ + struct map_convo *convo = data; + + dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING, + &convo->uci); + + return TRUE; +} + +static gboolean display_name_exists(const GDBusPropertyTable *property, + void *data) +{ + struct map_convo *convo = data; + + return convo->display_name != NULL; +} + +static gboolean get_display_name(const GDBusPropertyTable *property, + DBusMessageIter *iter, void *data) +{ + struct map_convo *convo = data; + + dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING, + &convo->display_name); + + return TRUE; +} + +static gboolean x_bt_uid_exists(const GDBusPropertyTable *property, void *data) +{ + struct map_convo *convo = data; + + return convo->x_bt_uid != NULL; +} + +static gboolean get_x_bt_uid(const GDBusPropertyTable *property, + DBusMessageIter *iter, void *data) +{ + struct map_convo *convo = data; + + dbus_message_iter_append_basic(iter, DBUS_TYPE_UINT64, + &convo->x_bt_uid); + + return TRUE; +} + +static const GDBusPropertyTable map_convo_properties[] = { + { "ConvoName", "s", get_convo_name, NULL, convo_name_exists }, + { "Summary", "s", get_summary, NULL, summary_exists }, + { "Uci", "s", get_uci, NULL, uci_exists }, + { "DisplayName", "s", get_display_name, NULL, display_name_exists }, + { "XBtUid", "s", get_x_bt_uid, NULL, x_bt_uid_exists}, + { } +}; + +static void parse_convo_name(struct map_convo *convo, const char *value) +{ + if (g_strcmp0(convo->convo_name, value) == 0) + return; + g_free(convo->convo_name); + convo->convo_name = g_strdup(value); + + g_dbus_emit_property_changed(conn, convo->path, + MAP_MSG_INTERFACE, "ConvoName"); +} + +static void parse_convo_last_activity(struct map_convo *convo, + const char *value) +{ + if (g_strcmp0(convo->convo_last_activity, value) == 0) + return; + + g_free(convo->convo_last_activity); + convo->convo_last_activity = g_strdup(value); + + g_dbus_emit_property_changed(conn, convo->path, + MAP_MSG_INTERFACE, "ConvoLastActivity"); +} + +static void parse_read_status(struct map_convo *convo, const char *value) +{ + if (g_strcmp0(convo->read_status, value) == 0) + return; + + g_free(convo->read_status); + convo->read_status = g_strdup(value); + + g_dbus_emit_property_changed(conn, convo->path, + MAP_MSG_INTERFACE, "ReadStatus"); +} + +static void parse_summary(struct map_convo *convo, const char *value) +{ + if (g_strcmp0(convo->summary, value) == 0) + return; + + g_free(convo->summary); + convo->summary = g_strdup(value); + + g_dbus_emit_property_changed(conn, convo->path, + MAP_MSG_INTERFACE, "Summary"); +} + +static void parse_uci(struct map_convo *convo, const char *value) +{ + if (g_strcmp0(convo->uci, value) == 0) + return; + + g_free(convo->uci); + convo->uci = g_strdup(value); + + g_dbus_emit_property_changed(conn, convo->path, + MAP_MSG_INTERFACE, "Uci"); +} + +static void parse_display_name(struct map_convo *convo, const char *value) +{ + if (g_strcmp0(convo->display_name, value) == 0) + return; + + g_free(convo->display_name); + convo->display_name = g_strdup(value); + + g_dbus_emit_property_changed(conn, convo->path, + MAP_MSG_INTERFACE, "DisplayName"); +} + +static void parse_chat_state(struct map_convo *convo, const char *value) +{ + uint8_t chat_state = g_ascii_strtoll(value, NULL, 10); + + if (convo->chat_state == chat_state) + return; + + convo->chat_state = chat_state; + + g_dbus_emit_property_changed(conn, convo->path, + MAP_MSG_INTERFACE, "ChatState"); +} + +static void parse_last_activity(struct map_convo *convo, const char *value) +{ + if (g_strcmp0(convo->last_activity, value) == 0) + return; + + g_free(convo->last_activity); + convo->last_activity = g_strdup(value); + + g_dbus_emit_property_changed(conn, convo->path, + MAP_MSG_INTERFACE, "LastActivity"); +} + +static void parse_x_bt_uid(struct map_convo *convo, const char *value) +{ + if (g_strcmp0(convo->x_bt_uid, value) == 0) + return; + + g_free(convo->x_bt_uid); + convo->x_bt_uid = g_strdup(value); + g_dbus_emit_property_changed(conn, convo->path, + MAP_MSG_INTERFACE, "X_BT_UID"); +} + +static void parse_name(struct map_convo *convo, const char *value) +{ + if (g_strcmp0(convo->name, value) == 0) + return; + + g_free(convo->name); + convo->name = g_strdup(value); + + g_dbus_emit_property_changed(conn, convo->path, + MAP_MSG_INTERFACE, "Name"); +} + +static void parse_presence_availability(struct map_convo *convo, + const char *value) +{ + uint8_t presence_availability = g_ascii_strtoll(value, NULL, 10); + + if (convo->presence_availability == presence_availability) + return; + + convo->presence_availability = presence_availability; + g_dbus_emit_property_changed(conn, convo->path, + MAP_MSG_INTERFACE, + "PresenceAvailability"); +} + +static void parse_presence_text(struct map_convo *convo, const char *value) +{ + if (g_strcmp0(convo->presence_text, value) == 0) + return; + + g_free(convo->presence_text); + convo->presence_text = g_strdup(value); + + g_dbus_emit_property_changed(conn, convo->path, + MAP_MSG_INTERFACE, "PresenceText"); +} + +static void parse_convo_priority(struct map_convo *convo, const char *value) +{ + int8_t priority = g_ascii_strtoll(value, NULL, 10); + + if (convo->priority == priority) + return; + + convo->priority = priority; + g_dbus_emit_property_changed(conn, convo->path, + MAP_MSG_INTERFACE, "Priority"); +} + static struct map_msg_parser { const char *name; void (*func) (struct map_msg *msg, const char *value); @@ -1096,6 +1400,55 @@ static struct map_msg_parser { { } }; +static struct map_convo_parser { + const char *name; + void (*func)(struct map_convo *convo, const char *value); +} convo_parsers[] = { + { "name", parse_convo_name }, + { "last_activity", parse_convo_last_activity }, + { "read_status", parse_read_status }, + { "summary", parse_summary }, + { "x_bt_uci", parse_uci }, + { "display_name", parse_display_name }, + { "chat_state", parse_chat_state }, + { "last_activity", parse_last_activity }, + { "x_bt_uid", parse_x_bt_uid }, + { "name", parse_name }, + { "presence_availability", parse_presence_availability }, + { "presence_text", parse_presence_text }, + { "priority", parse_convo_priority }, + { } +}; + +static struct map_convo *map_convo_create(struct map_data *data, + uint64_t id, + const char *folder, + const char *type) +{ + struct map_convo *convo; + + convo = g_new0(struct map_convo, 1); + convo->data = data; + convo->id = id; + + convo->path = g_strdup_printf("%s/message%" PRIu64, + obc_session_get_path(data->session), + convo->id); + + convo->folder = g_strdup(folder); + + if (!g_dbus_register_interface(conn, convo->path, MAP_MSG_INTERFACE, + map_msg_methods, NULL, + map_convo_properties, + convo, map_convo_free)) { + map_convo_free(convo); + return NULL; + } + g_hash_table_insert(data->messages, &convo->id, convo); + + return convo; +} + static void msg_element(GMarkupParseContext *ctxt, const char *element, const char **names, const char **values, gpointer user_data, GError **gerr) @@ -1149,6 +1502,73 @@ static void msg_element(GMarkupParseContext *ctxt, const char *element, dbus_message_iter_close_container(iter, &entry); } +static void start_convo_element(GMarkupParseContext *ctxt, const char *element, + const char **names, const char **values, + gpointer user_data, GError **gerr) +{ + struct map_parser *parser = user_data; + struct map_data *data = parser->request->map; + uint32_t id = 0; + const char *key; + int i; + DBusMessageIter *iter = parser->iter; + + for (i = 0, key = names[i]; key; key = names[++i]) { + if (strcasecmp(key, "id") == 0) { + id = strtoull(values[i], NULL, 32); + break; + } + } + + if (id == 0) + return; + + conversation = g_hash_table_lookup(data->messages, &id); + if (conversation == NULL) { + conversation = map_convo_create(data, id, + parser->request->folder, NULL); + if (conversation == NULL) + return; + } + + dbus_message_iter_open_container(iter, DBUS_TYPE_DICT_ENTRY, NULL, + &convo_entry); + dbus_message_iter_append_basic(&convo_entry, DBUS_TYPE_OBJECT_PATH, + &conversation->path); + + for (i = 0, key = names[i]; key; key = names[++i]) { + struct map_convo_parser *parser; + + for (parser = convo_parsers; parser && parser->name; parser++) { + if (strcasecmp(key, parser->name) == 0) { + if (values[i]) { + parser->func(conversation, values[i]); + break; + } + } + } + } + + g_dbus_get_properties(conn, conversation->path, MAP_MSG_INTERFACE, + &convo_entry); + dbus_message_iter_close_container(iter, &convo_entry); +} + +static void end_convo_element(GMarkupParseContext *ctxt, const char *element, + gpointer user_data, GError **gerr) +{ + if (strcasecmp("MAP-convo-listing", element) == 0) + convo_element_end = TRUE; +} + +static const GMarkupParser convo_parser = { + start_convo_element, + end_convo_element, + NULL, + NULL, + NULL +}; + static const GMarkupParser msg_parser = { msg_element, NULL, @@ -1267,9 +1687,15 @@ static void conversation_listing_cb(struct obc_session *session, DBUS_DICT_ENTRY_END_CHAR_AS_STRING DBUS_DICT_ENTRY_END_CHAR_AS_STRING, &array); - + parser = g_new(struct map_parser, 1); + parser->request = request; + parser->iter = &array; + ctxt = g_markup_parse_context_new(&convo_parser, 0, parser, NULL); + g_markup_parse_context_parse(ctxt, contents, size, NULL); + g_markup_parse_context_free(ctxt); dbus_message_iter_close_container(&iter, &array); g_free(contents); + g_free(parser); done: if (convo_element_end) diff --git a/obexd/src/map_ap.h b/obexd/src/map_ap.h index 3773859..d6577fd 100644 --- a/obexd/src/map_ap.h +++ b/obexd/src/map_ap.h @@ -30,25 +30,25 @@ enum map_ap_tag { MAP_AP_FILTERPERIODEND = 0x05, /* char * */ MAP_AP_FILTERREADSTATUS = 0x06, /* uint8_t */ MAP_AP_FILTERRECIPIENT = 0x07, /* char * */ - MAP_AP_FILTERORIGINATOR = 0x08, /* char * */ - MAP_AP_FILTERLASTACTIVITYBEGIN = 0x08, /* char * */ - MAP_AP_FILTERLASTACTIVITYEND = 0x09, /* char * */ - MAP_AP_FILTERPRIORITY = 0x09, /* uint8_t */ - MAP_AP_ATTACHMENT = 0x0A, /* uint8_t */ - MAP_AP_TRANSPARENT = 0x0B, /* uint8_t */ - MAP_AP_RETRY = 0x0C, /* uint8_t */ - MAP_AP_NEWMESSAGE = 0x0D, /* uint8_t */ - MAP_AP_NOTIFICATIONSTATUS = 0x0E, /* uint8_t */ - MAP_AP_MASINSTANCEID = 0x0F, /* uint8_t */ - MAP_AP_PARAMETERMASK = 0x10, /* uint32_t */ - MAP_AP_FOLDERLISTINGSIZE = 0x11, /* uint16_t */ - MAP_AP_MESSAGESLISTINGSIZE = 0x12, /* uint16_t */ - MAP_AP_SUBJECTLENGTH = 0x13, /* uint8_t */ - MAP_AP_CHARSET = 0x14, /* uint8_t */ - MAP_AP_FRACTIONREQUEST = 0x15, /* uint8_t */ - MAP_AP_FRACTIONDELIVER = 0x16, /* uint8_t */ - MAP_AP_STATUSINDICATOR = 0x17, /* uint8_t */ - MAP_AP_STATUSVALUE = 0x18, /* uint8_t */ - MAP_AP_MSETIME = 0x19, /* char * */ + MAP_AP_FILTERLASTACTIVITYBEGIN = 0x08, /* char * */ + MAP_AP_FILTERLASTACTIVITYEND = 0x09, /* char * */ + MAP_AP_FILTERORIGINATOR = 0x0A, /* char * */ + MAP_AP_FILTERPRIORITY = 0x0B, /* uint8_t */ + MAP_AP_ATTACHMENT = 0x0C, /* uint8_t */ + MAP_AP_TRANSPARENT = 0x0D, /* uint8_t */ + MAP_AP_RETRY = 0x0E, /* uint8_t */ + MAP_AP_NEWMESSAGE = 0x0F, /* uint8_t */ + MAP_AP_NOTIFICATIONSTATUS = 0x10, /* uint8_t */ + MAP_AP_MASINSTANCEID = 0x11, /* uint8_t */ + MAP_AP_PARAMETERMASK = 0x12, /* uint32_t */ + MAP_AP_FOLDERLISTINGSIZE = 0x13, /* uint16_t */ + MAP_AP_MESSAGESLISTINGSIZE = 0x14, /* uint16_t */ + MAP_AP_SUBJECTLENGTH = 0x15, /* uint8_t */ + MAP_AP_CHARSET = 0x16, /* uint8_t */ + MAP_AP_FRACTIONREQUEST = 0x17, /* uint8_t */ + MAP_AP_FRACTIONDELIVER = 0x18, /* uint8_t */ + MAP_AP_STATUSINDICATOR = 0x19, /* uint8_t */ + MAP_AP_STATUSVALUE = 0x1A, /* uint8_t */ + MAP_AP_MSETIME = 0x1B, /* char * */ MAP_AP_CONVERSATIONID = 0x1C, /* uint32_t */ }; -- 2.7.4 ^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH v3 6/6] doc/obex-api: Update documentation 2020-02-11 6:36 [PATCH v2 1/6] obexd: Add initial support for MAP conversations Ajay Kishore ` (3 preceding siblings ...) 2020-02-11 6:36 ` [PATCH v3 4/6] obexd: Add parser for conversation element Ajay Kishore @ 2020-02-11 6:36 ` Ajay Kishore 2020-02-11 19:27 ` [PATCH v2 1/6] obexd: Add initial support for MAP conversations Luiz Augusto von Dentz 5 siblings, 0 replies; 8+ messages in thread From: Ajay Kishore @ 2020-02-11 6:36 UTC (permalink / raw) To: linux-bluetooth This adds documentation with the conversation listing feature --- doc/obex-api.txt | 50 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) diff --git a/doc/obex-api.txt b/doc/obex-api.txt index f39355a..ef81460 100644 --- a/doc/obex-api.txt +++ b/doc/obex-api.txt @@ -712,6 +712,44 @@ Methods void SetFolder(string name) Possible errors: org.bluez.obex.Error.InvalidArguments org.bluez.obex.Error.Failed + array{object, dict} ListConversations(string folder, dict filter) + + Returns an array containing the conversations found in the + given subfolder of the current folder, or in the current + folder if folder is empty. + + Possible Filters: MaxListCount, LastActivityBegin, LastActivityEnd, + ReadStatus, Recipient + + Each message is represented by an object path followed + by a dictionary of the properties. + + Properties: + + string id: + + Conversation unique identification + + string last_activity: + + Conversation timestamp for the last activity + + string chat_state: + + Conversation current chat state of the participants + + string presence_availability: + + Conversation participants availability + + string presence_text: + + User defined status of the conversation + + Possible errors: org.bluez.obex.Error.InvalidArguments + org.bluez.obex.Error.Failed + + void UpdateInbox(void) Request remote to update its inbox. @@ -799,6 +837,18 @@ Filter: uint16 Offset: Possible values: True for high priority or False for non-high priority + string LastActivityBegin: + + Filter conversations by starting period. + + Possible values: Date in "YYYYMMDDTHHMMSS" format. + + string LastActivityEnd: + + Filter conversations by ending period. + + Possible values: Date in "YYYYMMDDTHHMMSS" format. + Message hierarchy ================= -- 2.7.4 ^ permalink raw reply related [flat|nested] 8+ messages in thread
* Re: [PATCH v2 1/6] obexd: Add initial support for MAP conversations 2020-02-11 6:36 [PATCH v2 1/6] obexd: Add initial support for MAP conversations Ajay Kishore ` (4 preceding siblings ...) 2020-02-11 6:36 ` [PATCH v3 6/6] doc/obex-api: Update documentation Ajay Kishore @ 2020-02-11 19:27 ` Luiz Augusto von Dentz 2020-03-05 9:20 ` Kishore, Ajay 5 siblings, 1 reply; 8+ messages in thread From: Luiz Augusto von Dentz @ 2020-02-11 19:27 UTC (permalink / raw) To: Ajay Kishore; +Cc: linux-bluetooth Hi Ajay, On Mon, Feb 10, 2020 at 11:32 PM Ajay Kishore <ajay.kishore@intel.com> wrote: > > Changes made to add a new method for MAP conversation listing i.e > "ListConversations" to handle conversation listing object > "x-bt/MAP-convo-listing". > --- > obexd/client/map.c | 67 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ > 1 file changed, 67 insertions(+) > > diff --git a/obexd/client/map.c b/obexd/client/map.c > index 550c5af..adf62d9 100644 > --- a/obexd/client/map.c > +++ b/obexd/client/map.c > @@ -1560,6 +1560,69 @@ static DBusMessage *map_list_messages(DBusConnection *connection, > return get_message_listing(map, message, folder, apparam); > } > > +static GObexApparam *parse_conversation_filters(GObexApparam *apparam, > + DBusMessageIter *iter) > +{ > + DBusMessageIter array; > + > + if (dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_ARRAY) { > + DBG("Not of type array"); > + return NULL; > + } > + > + dbus_message_iter_recurse(iter, &array); > + > + while (dbus_message_iter_get_arg_type(&array) == DBUS_TYPE_DICT_ENTRY) { > + const char *key; > + DBusMessageIter value, entry; > + > + dbus_message_iter_recurse(&array, &entry); > + dbus_message_iter_get_basic(&entry, &key); > + > + dbus_message_iter_next(&entry); > + dbus_message_iter_recurse(&entry, &value); > + > + /* TODO: Parse conversation filters */ > + > + dbus_message_iter_next(&array); > + } > + return apparam; > +} > + > +static DBusMessage *map_list_conversations(DBusConnection *connection, > + DBusMessage *message, > + void *user_data) > +{ > + struct map_data *map = user_data; > + const char *folder; > + GObexApparam *apparam; > + DBusMessageIter args; > + > + dbus_message_iter_init(message, &args); > + > + if (dbus_message_iter_get_arg_type(&args) != DBUS_TYPE_STRING) > + return g_dbus_create_error(message, > + ERROR_INTERFACE ".InvalidArguments", NULL); > + > + dbus_message_iter_get_basic(&args, &folder); > + > + apparam = g_obex_apparam_set_uint16(NULL, MAP_AP_MAXLISTCOUNT, > + DEFAULT_COUNT); > + apparam = g_obex_apparam_set_uint16(apparam, MAP_AP_STARTOFFSET, > + DEFAULT_OFFSET); > + > + dbus_message_iter_next(&args); > + > + if (parse_conversation_filters(apparam, &args) == NULL) { > + g_obex_apparam_free(apparam); > + return g_dbus_create_error(message, > + ERROR_INTERFACE ".InvalidArguments", NULL); > + } > + > + /*TODO: Return conversation listing */ > + return NULL; > +} > + > static char **get_filter_strs(uint64_t filter, int *size) > { > char **list, **item; > @@ -1817,6 +1880,10 @@ static const GDBusMethodTable map_methods[] = { > GDBUS_ARGS({ "folder", "s" }, { "filter", "a{sv}" }), > GDBUS_ARGS({ "messages", "a{oa{sv}}" }), > map_list_messages) }, > + { GDBUS_ASYNC_METHOD("ListConversations", > + GDBUS_ARGS({ "folder", "s" }, { "filter", "a{sv}" }), > + GDBUS_ARGS({ "conversations", "a{oa{sv}}" }), > + map_list_conversations) }, > { GDBUS_METHOD("ListFilterFields", > NULL, > GDBUS_ARGS({ "fields", "as" }), > -- > 2.7.4 I see some mix of v2 and v3 patches, I recommend updating the whole set to v3 to make easier to review. -- Luiz Augusto von Dentz ^ permalink raw reply [flat|nested] 8+ messages in thread
* RE: [PATCH v2 1/6] obexd: Add initial support for MAP conversations 2020-02-11 19:27 ` [PATCH v2 1/6] obexd: Add initial support for MAP conversations Luiz Augusto von Dentz @ 2020-03-05 9:20 ` Kishore, Ajay 0 siblings, 0 replies; 8+ messages in thread From: Kishore, Ajay @ 2020-03-05 9:20 UTC (permalink / raw) To: Luiz Augusto von Dentz; +Cc: linux-bluetooth Hi Luiz, > -----Original Message----- > From: linux-bluetooth-owner@vger.kernel.org <linux-bluetooth- > owner@vger.kernel.org> On Behalf Of Luiz Augusto von Dentz > Sent: Wednesday, February 12, 2020 12:58 AM > To: Kishore, Ajay <ajay.kishore@intel.com> > Cc: linux-bluetooth@vger.kernel.org > Subject: Re: [PATCH v2 1/6] obexd: Add initial support for MAP conversations > > Hi Ajay, > > On Mon, Feb 10, 2020 at 11:32 PM Ajay Kishore <ajay.kishore@intel.com> > wrote: > > > > Changes made to add a new method for MAP conversation listing i.e > > "ListConversations" to handle conversation listing object > > "x-bt/MAP-convo-listing". > > --- > > obexd/client/map.c | 67 > > ++++++++++++++++++++++++++++++++++++++++++++++++++++++ > > 1 file changed, 67 insertions(+) > > > > diff --git a/obexd/client/map.c b/obexd/client/map.c index > > 550c5af..adf62d9 100644 > > --- a/obexd/client/map.c > > +++ b/obexd/client/map.c > > @@ -1560,6 +1560,69 @@ static DBusMessage > *map_list_messages(DBusConnection *connection, > > return get_message_listing(map, message, folder, apparam); } > > > > +static GObexApparam *parse_conversation_filters(GObexApparam > *apparam, > > + > > +DBusMessageIter *iter) { > > + DBusMessageIter array; > > + > > + if (dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_ARRAY) { > > + DBG("Not of type array"); > > + return NULL; > > + } > > + > > + dbus_message_iter_recurse(iter, &array); > > + > > + while (dbus_message_iter_get_arg_type(&array) == > DBUS_TYPE_DICT_ENTRY) { > > + const char *key; > > + DBusMessageIter value, entry; > > + > > + dbus_message_iter_recurse(&array, &entry); > > + dbus_message_iter_get_basic(&entry, &key); > > + > > + dbus_message_iter_next(&entry); > > + dbus_message_iter_recurse(&entry, &value); > > + > > + /* TODO: Parse conversation filters */ > > + > > + dbus_message_iter_next(&array); > > + } > > + return apparam; > > +} > > + > > +static DBusMessage *map_list_conversations(DBusConnection *connection, > > + DBusMessage *message, > > + void *user_data) { > > + struct map_data *map = user_data; > > + const char *folder; > > + GObexApparam *apparam; > > + DBusMessageIter args; > > + > > + dbus_message_iter_init(message, &args); > > + > > + if (dbus_message_iter_get_arg_type(&args) != DBUS_TYPE_STRING) > > + return g_dbus_create_error(message, > > + ERROR_INTERFACE ".InvalidArguments", NULL); > > + > > + dbus_message_iter_get_basic(&args, &folder); > > + > > + apparam = g_obex_apparam_set_uint16(NULL, > MAP_AP_MAXLISTCOUNT, > > + DEFAULT_COUNT); > > + apparam = g_obex_apparam_set_uint16(apparam, > MAP_AP_STARTOFFSET, > > + > > + DEFAULT_OFFSET); > > + > > + dbus_message_iter_next(&args); > > + > > + if (parse_conversation_filters(apparam, &args) == NULL) { > > + g_obex_apparam_free(apparam); > > + return g_dbus_create_error(message, > > + ERROR_INTERFACE ".InvalidArguments", NULL); > > + } > > + > > + /*TODO: Return conversation listing */ > > + return NULL; > > +} > > + > > static char **get_filter_strs(uint64_t filter, int *size) { > > char **list, **item; > > @@ -1817,6 +1880,10 @@ static const GDBusMethodTable map_methods[] = > { > > GDBUS_ARGS({ "folder", "s" }, { "filter", "a{sv}" }), > > GDBUS_ARGS({ "messages", "a{oa{sv}}" }), > > map_list_messages) }, > > + { GDBUS_ASYNC_METHOD("ListConversations", > > + GDBUS_ARGS({ "folder", "s" }, { "filter", "a{sv}" }), > > + GDBUS_ARGS({ "conversations", "a{oa{sv}}" }), > > + map_list_conversations) }, > > { GDBUS_METHOD("ListFilterFields", > > NULL, > > GDBUS_ARGS({ "fields", "as" }), > > -- > > 2.7.4 > > I see some mix of v2 and v3 patches, I recommend updating the whole set to v3 > to make easier to review. Done. > > > -- > Luiz Augusto von Dentz Thanks. Ajay ^ permalink raw reply [flat|nested] 8+ messages in thread
end of thread, other threads:[~2020-03-05 9:20 UTC | newest] Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2020-02-11 6:36 [PATCH v2 1/6] obexd: Add initial support for MAP conversations Ajay Kishore 2020-02-11 6:36 ` [PATCH v2 2/6] obexd: Add parsers for conversation filters Ajay Kishore 2020-02-11 6:36 ` [PATCH v2 3/6] obexd: Get conversation listings Ajay Kishore 2020-02-11 6:36 ` [PATCH v2 5/6] obexd: Handle MAP Event Report v1.1 and v1.2 Ajay Kishore 2020-02-11 6:36 ` [PATCH v3 4/6] obexd: Add parser for conversation element Ajay Kishore 2020-02-11 6:36 ` [PATCH v3 6/6] doc/obex-api: Update documentation Ajay Kishore 2020-02-11 19:27 ` [PATCH v2 1/6] obexd: Add initial support for MAP conversations Luiz Augusto von Dentz 2020-03-05 9:20 ` Kishore, Ajay
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for NNTP newsgroup(s).