2019-12-10 11:41:43

by Ajay Kishore

[permalink] [raw]
Subject: [PATCH 1/5] obexd: Add initial support for MAP conversations

Changes made to add a new method for MAP conversation listing i.e
"ListConversations" to handle conversation listing object
"x-bt/MAP-convo-listing".

Co-authored-by: Bharat Bhusan Panda <[email protected]>
Signed-off-by: Ajay Kishore <[email protected]>
---
obexd/client/map.c | 68 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 68 insertions(+)

diff --git a/obexd/client/map.c b/obexd/client/map.c
index 550c5af..57ca77e 100644
--- a/obexd/client/map.c
+++ b/obexd/client/map.c
@@ -54,6 +54,7 @@

#define MAP_INTERFACE "org.bluez.obex.MessageAccess1"
#define MAP_MSG_INTERFACE "org.bluez.obex.Message1"
+#define MAP_CONV_INTERFACE "org.bluez.obex.Conversation1"
#define ERROR_INTERFACE "org.bluez.obex.Error"
#define MAS_UUID "00001132-0000-1000-8000-00805f9b34fb"

@@ -1560,6 +1561,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 +1881,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


2019-12-10 11:41:57

by Ajay Kishore

[permalink] [raw]
Subject: [PATCH 5/5] obexd: Handle MAP Event Report v1.1 and v1.2

Changes made to add handler function for the corresponding
events mentioned in extended event reports 1.1 and 1.2.

Signed-off-by: Ajay Kishore <[email protected]>
---
obexd/client/map-event.h | 8 +++++++-
obexd/client/map.c | 24 ++++++++++++++++++++++++
2 files changed, 31 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 b65131a..b1b4b38 100644
--- a/obexd/client/map.c
+++ b/obexd/client/map.c
@@ -2550,6 +2550,17 @@ 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)
+{
+ struct map_msg *msg;
+
+ msg = g_hash_table_lookup(map->messages, &event->handle);
+
+ if (msg)
+ 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 +2593,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

2019-12-10 11:42:03

by Ajay Kishore

[permalink] [raw]
Subject: [PATCH 3/5] obexd: Get conversation listings

Changes made to build get conversation listing command and its
respective callback function to handle response for conversation
listing.

Co-authored-by: Bharat Bhusan Panda <[email protected]>
Signed-off-by: Ajay Kishore <[email protected]>
---
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 9464606..f2f2b73 100644
--- a/obexd/client/map.c
+++ b/obexd/client/map.c
@@ -1222,6 +1222,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);
@@ -1270,6 +1328,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)
{
@@ -1682,8 +1777,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

2019-12-10 11:42:54

by Ajay Kishore

[permalink] [raw]
Subject: [PATCH 4/5] obexd: Add parser for conversation element

Changes made to define convo parser function to iterate through
all supported conversation elements and parse their values.

Co-authored-by: Bharat Bhusan Panda <[email protected]>
Signed-off-by: Ajay Kishore <[email protected]>
---
obexd/client/map.c | 427 ++++++++++++++++++++++++++++++++++++++++++++++++++++-
obexd/src/map_ap.h | 40 ++---
2 files changed, 446 insertions(+), 21 deletions(-)

diff --git a/obexd/client/map.c b/obexd/client/map.c
index f2f2b73..b65131a 100644
--- a/obexd/client/map.c
+++ b/obexd/client/map.c
@@ -139,12 +139,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)
@@ -837,6 +860,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;
@@ -1074,6 +1099,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);
@@ -1097,6 +1401,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)
@@ -1150,6 +1503,72 @@ 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,
@@ -1268,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

2019-12-10 17:25:01

by Johan Hedberg

[permalink] [raw]
Subject: Re: [PATCH 1/5] obexd: Add initial support for MAP conversations

Hi Ajay,

On Tue, Dec 10, 2019, Ajay Kishore 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".
>
> Co-authored-by: Bharat Bhusan Panda <[email protected]>
> Signed-off-by: Ajay Kishore <[email protected]>
> ---
> obexd/client/map.c | 68 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
> 1 file changed, 68 insertions(+)

Maybe I missed it, but I didn't see a patch to update doc/obex-api.txt.
That's one of the most important changes and what needs to be agreed on
first.

Johan

2019-12-10 19:54:33

by Luiz Augusto von Dentz

[permalink] [raw]
Subject: Re: [PATCH 5/5] obexd: Handle MAP Event Report v1.1 and v1.2

Hi Ajay,

On Tue, Dec 10, 2019 at 1:42 PM Ajay Kishore <[email protected]> wrote:
>
> Changes made to add handler function for the corresponding
> events mentioned in extended event reports 1.1 and 1.2.
>
> Signed-off-by: Ajay Kishore <[email protected]>
> ---
> obexd/client/map-event.h | 8 +++++++-
> obexd/client/map.c | 24 ++++++++++++++++++++++++
> 2 files changed, 31 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 b65131a..b1b4b38 100644
> --- a/obexd/client/map.c
> +++ b/obexd/client/map.c
> @@ -2550,6 +2550,17 @@ 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)
> +{
> + struct map_msg *msg;
> +
> + msg = g_hash_table_lookup(map->messages, &event->handle);
> +
> + if (msg)
> + g_hash_table_remove(map->messages, &event->handle);

I believe you only need the call to remove here otherwise we might
just be doing 2 lookups for no obvious reason since remove already
does that.

> +}
> +
> static void map_handle_notification(struct map_event *event, void *user_data)
> {
> struct map_data *map = user_data;
> @@ -2582,6 +2593,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
>


--
Luiz Augusto von Dentz