upgrade obexd to 0.47
[profile/ivi/obexd.git] / client / map.c
index cdd2725..e606cb2 100644 (file)
 #endif
 
 #include <errno.h>
+#include <string.h>
 #include <glib.h>
 #include <gdbus.h>
 
+#include "dbus.h"
 #include "log.h"
 
 #include "map.h"
        "\xBB\x58\x2B\x40\x42\x0C\x11\xDB\xB0\xDE\x08\x00\x20\x0C\x9A\x66"
 #define OBEX_MAS_UUID_LEN 16
 
-#define MAP_INTERFACE  "org.openobex.MessageAccess"
+#define MAP_INTERFACE "org.bluez.obex.MessageAccess"
+#define MAP_MSG_INTERFACE "org.bluez.obex.Message"
+#define ERROR_INTERFACE "org.bluez.obex.Error"
 #define MAS_UUID "00001132-0000-1000-8000-00805f9b34fb"
 
 struct map_data {
        struct obc_session *session;
        DBusMessage *msg;
+       GHashTable *messages;
+};
+
+#define MAP_MSG_FLAG_PRIORITY  0x01
+#define MAP_MSG_FLAG_READ      0x02
+#define MAP_MSG_FLAG_SENT      0x04
+#define MAP_MSG_FLAG_PROTECTED 0x08
+
+struct map_msg {
+       struct map_data *data;
+       char *path;
+       char *handle;
+       char *subject;
+       char *timestamp;
+       char *sender;
+       char *sender_address;
+       char *replyto;
+       char *recipient;
+       char *recipient_address;
+       char *type;
+       uint64_t size;
+       char *status;
+       uint8_t flags;
+};
+
+struct map_parser {
+       struct map_data *data;
+       DBusMessageIter *iter;
 };
 
 static DBusConnection *conn = NULL;
 
-static void simple_cb(GObex *obex, GError *err, GObexPacket *rsp,
-                                                       gpointer user_data)
+static void simple_cb(struct obc_session *session,
+                                               struct obc_transfer *transfer,
+                                               GError *err, void *user_data)
 {
        DBusMessage *reply;
        struct map_data *map = user_data;
-       guint8 err_code = g_obex_packet_get_operation(rsp, NULL);
 
        if (err != NULL)
                reply = g_dbus_create_error(map->msg,
-                                               "org.openobex.Error.Failed",
+                                               ERROR_INTERFACE ".Failed",
                                                "%s", err->message);
-       else if (err_code != G_OBEX_RSP_SUCCESS)
-               reply = g_dbus_create_error(map->msg,
-                                               "org.openobex.Error.Failed",
-                                               "%s (0x%02x)",
-                                               g_obex_strerror(err_code),
-                                               err_code);
        else
                reply = dbus_message_new_method_return(map->msg);
 
@@ -78,22 +104,19 @@ static DBusMessage *map_setpath(DBusConnection *connection,
 {
        struct map_data *map = user_data;
        const char *folder;
-       GObex *obex;
        GError *err = NULL;
 
        if (dbus_message_get_args(message, NULL, DBUS_TYPE_STRING, &folder,
                                                DBUS_TYPE_INVALID) == FALSE)
                return g_dbus_create_error(message,
-                                       "org.openobex.Error.InvalidArguments",
+                                       ERROR_INTERFACE ".InvalidArguments",
                                        NULL);
 
-       obex = obc_session_get_obex(map->session);
-
-       g_obex_setpath(obex, folder, simple_cb, map, &err);
+       obc_session_setpath(map->session, folder, simple_cb, map, &err);
        if (err != NULL) {
                DBusMessage *reply;
                reply =  g_dbus_create_error(message,
-                                               "org.openobex.Error.Failed",
+                                               ERROR_INTERFACE ".Failed",
                                                "%s", err->message);
                g_error_free(err);
                return reply;
@@ -104,98 +127,540 @@ static DBusMessage *map_setpath(DBusConnection *connection,
        return NULL;
 }
 
-static void buffer_cb(struct obc_session *session, GError *err,
-                                                       void *user_data)
+static void folder_element(GMarkupParseContext *ctxt, const gchar *element,
+                               const gchar **names, const gchar **values,
+                               gpointer user_data, GError **gerr)
+{
+       DBusMessageIter dict, *iter = user_data;
+       const gchar *key;
+       gint i;
+
+       if (strcasecmp("folder", element) != 0)
+               return;
+
+       dbus_message_iter_open_container(iter, DBUS_TYPE_ARRAY,
+                       DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
+                       DBUS_TYPE_STRING_AS_STRING DBUS_TYPE_VARIANT_AS_STRING
+                       DBUS_DICT_ENTRY_END_CHAR_AS_STRING, &dict);
+
+       for (i = 0, key = names[i]; key; key = names[++i]) {
+               if (strcasecmp("name", key) == 0)
+                       obex_dbus_dict_append(&dict, "Name", DBUS_TYPE_STRING,
+                                                               &values[i]);
+       }
+
+       dbus_message_iter_close_container(iter, &dict);
+}
+
+static const GMarkupParser folder_parser = {
+       folder_element,
+       NULL,
+       NULL,
+       NULL,
+       NULL
+};
+
+static void folder_listing_cb(struct obc_session *session,
+                                               struct obc_transfer *transfer,
+                                               GError *err, void *user_data)
 {
-       struct obc_transfer *transfer = obc_session_get_transfer(session);
        struct map_data *map = user_data;
+       GMarkupParseContext *ctxt;
        DBusMessage *reply;
-       const char *buf;
-       int size;
+       DBusMessageIter iter, array;
+       char *contents;
+       size_t size;
+       int perr;
 
        if (err != NULL) {
                reply = g_dbus_create_error(map->msg,
-                                               "org.openobex.Error.Failed",
+                                               ERROR_INTERFACE ".Failed",
                                                "%s", err->message);
                goto done;
        }
 
-       buf = obc_transfer_get_buffer(transfer, &size);
-       if (size == 0)
-               buf = "";
-
-       reply = g_dbus_create_reply(map->msg, DBUS_TYPE_STRING, &buf,
-                                                       DBUS_TYPE_INVALID);
+       perr = obc_transfer_get_contents(transfer, &contents, &size);
+       if (perr < 0) {
+               reply = g_dbus_create_error(map->msg,
+                                               ERROR_INTERFACE ".Failed",
+                                               "Error reading contents: %s",
+                                               strerror(-perr));
+               goto done;
+       }
 
-       obc_transfer_clear_buffer(transfer);
+       reply = dbus_message_new_method_return(map->msg);
+       if (reply == NULL)
+               return;
+
+       dbus_message_iter_init_append(reply, &iter);
+       dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY,
+                       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, &array);
+       ctxt = g_markup_parse_context_new(&folder_parser, 0, &array, 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);
 
 done:
        g_dbus_send_message(conn, reply);
        dbus_message_unref(map->msg);
-       obc_transfer_unregister(transfer);
 }
 
 static DBusMessage *map_get_folder_listing(DBusConnection *connection,
                                        DBusMessage *message, void *user_data)
 {
        struct map_data *map = user_data;
-       int err;
+       struct obc_transfer *transfer;
+       GError *err = NULL;
+       DBusMessage *reply;
 
-       err = obc_session_get(map->session, "x-obex/folder-listing",
-                                                       NULL, NULL, NULL, 0,
-                                                       buffer_cb, map);
-       if (err < 0)
-               return g_dbus_create_error(message, "org.openobex.Error.Failed",
-                                                                       NULL);
+       transfer = obc_transfer_get("x-obex/folder-listing", NULL, NULL, &err);
+       if (transfer == NULL)
+               goto fail;
 
-       map->msg = dbus_message_ref(message);
+       if (obc_session_queue(map->session, transfer, folder_listing_cb, map,
+                                                               &err)) {
+               map->msg = dbus_message_ref(message);
+               return NULL;
+       }
 
-       return NULL;
+fail:
+       reply = g_dbus_create_error(message, ERROR_INTERFACE ".Failed", "%s",
+                                                               err->message);
+       g_error_free(err);
+       return reply;
+}
+
+static void map_msg_free(void *data)
+{
+       struct map_msg *msg = data;
+
+       g_free(msg->path);
+       g_free(msg->subject);
+       g_free(msg->handle);
+       g_free(msg->timestamp);
+       g_free(msg->sender);
+       g_free(msg->sender_address);
+       g_free(msg->replyto);
+       g_free(msg->recipient);
+       g_free(msg->recipient_address);
+       g_free(msg->type);
+       g_free(msg->status);
+       g_free(msg);
+}
+
+static DBusMessage *map_msg_get(DBusConnection *connection,
+                                       DBusMessage *message, void *user_data)
+{
+       struct map_msg *msg = user_data;
+       struct obc_transfer *transfer;
+       const char *target_file;
+       GError *err = NULL;
+       DBusMessage *reply;
+
+       if (dbus_message_get_args(message, NULL,
+                               DBUS_TYPE_STRING, &target_file,
+                               DBUS_TYPE_INVALID) == FALSE)
+               return g_dbus_create_error(message,
+                               ERROR_INTERFACE ".InvalidArguments", NULL);
+
+       transfer = obc_transfer_get("x-bt/message", msg->handle, target_file,
+                                                                       &err);
+       if (transfer == NULL)
+               goto fail;
+
+       if (!obc_session_queue(msg->data->session, transfer, NULL, NULL, &err))
+               goto fail;
+
+       return obc_transfer_create_dbus_reply(transfer, message);
+
+fail:
+       reply = g_dbus_create_error(message, ERROR_INTERFACE ".Failed", "%s",
+                                                               err->message);
+       g_error_free(err);
+       return reply;
+}
+
+static const GDBusMethodTable map_msg_methods[] = {
+       { GDBUS_METHOD("Get",
+                       GDBUS_ARGS({ "targetfile", "s" }),
+                       GDBUS_ARGS({ "transfer", "o" },
+                                               { "properties", "a{sv}" }),
+                       map_msg_get) },
+       { }
+};
+
+static struct map_msg *map_msg_create(struct map_data *data, const char *handle)
+{
+       struct map_msg *msg;
+
+       msg = g_new0(struct map_msg, 1);
+       msg->data = data;
+       msg->path = g_strdup_printf("%s/message%s",
+                                       obc_session_get_path(data->session),
+                                       handle);
+
+       if (!g_dbus_register_interface(conn, msg->path, MAP_MSG_INTERFACE,
+                                               map_msg_methods, NULL, NULL,
+                                               msg, map_msg_free)) {
+               map_msg_free(msg);
+               return NULL;
+       }
+
+       msg->handle = g_strdup(handle);
+       g_hash_table_insert(data->messages, msg->handle, msg);
+
+       return msg;
+}
+
+static void parse_subject(struct map_msg *msg, const char *value,
+                                                       DBusMessageIter *iter)
+{
+       g_free(msg->subject);
+       msg->subject = g_strdup(value);
+       obex_dbus_dict_append(iter, "Subject", DBUS_TYPE_STRING, &value);
+}
+
+static void parse_datetime(struct map_msg *msg, const char *value,
+                                                       DBusMessageIter *iter)
+{
+       g_free(msg->timestamp);
+       msg->timestamp = g_strdup(value);
+       obex_dbus_dict_append(iter, "Timestamp", DBUS_TYPE_STRING, &value);
+}
+
+static void parse_sender(struct map_msg *msg, const char *value,
+                                                       DBusMessageIter *iter)
+{
+       g_free(msg->sender);
+       msg->sender = g_strdup(value);
+       obex_dbus_dict_append(iter, "Sender", DBUS_TYPE_STRING, &value);
+}
+
+static void parse_sender_address(struct map_msg *msg, const char *value,
+                                                       DBusMessageIter *iter)
+{
+       g_free(msg->sender_address);
+       msg->sender_address = g_strdup(value);
+       obex_dbus_dict_append(iter, "SenderAddress", DBUS_TYPE_STRING,
+                                                               &value);
+}
+
+static void parse_replyto(struct map_msg *msg, const char *value,
+                                                       DBusMessageIter *iter)
+{
+       g_free(msg->replyto);
+       msg->replyto = g_strdup(value);
+       obex_dbus_dict_append(iter, "ReplyTo", DBUS_TYPE_STRING, &value);
+}
+
+static void parse_recipient(struct map_msg *msg, const char *value,
+                                                       DBusMessageIter *iter)
+{
+       g_free(msg->recipient);
+       msg->recipient = g_strdup(value);
+       obex_dbus_dict_append(iter, "Recipient", DBUS_TYPE_STRING, &value);
+}
+
+static void parse_recipient_address(struct map_msg *msg, const char *value,
+                                                       DBusMessageIter *iter)
+{
+       g_free(msg->recipient_address);
+       msg->recipient_address = g_strdup(value);
+       obex_dbus_dict_append(iter, "RecipientAddress", DBUS_TYPE_STRING,
+                                                               &value);
+}
+
+static void parse_type(struct map_msg *msg, const char *value,
+                                                       DBusMessageIter *iter)
+{
+       g_free(msg->type);
+       msg->type = g_strdup(value);
+       obex_dbus_dict_append(iter, "Type", DBUS_TYPE_STRING, &value);
+}
+
+static void parse_status(struct map_msg *msg, const char *value,
+                                                       DBusMessageIter *iter)
+{
+       g_free(msg->status);
+       msg->status = g_strdup(value);
+       obex_dbus_dict_append(iter, "Status", DBUS_TYPE_STRING, &value);
+}
+
+static void parse_size(struct map_msg *msg, const char *value,
+                                                       DBusMessageIter *iter)
+{
+       msg->size = g_ascii_strtoll(value, NULL, 10);
+       obex_dbus_dict_append(iter, "Size", DBUS_TYPE_UINT64, &msg->size);
+}
+
+static void parse_priority(struct map_msg *msg, const char *value,
+                                                       DBusMessageIter *iter)
+{
+       gboolean flag = strcasecmp(value, "no");
+
+       if (flag)
+               msg->flags |= MAP_MSG_FLAG_PRIORITY;
+       else
+               msg->flags &= ~MAP_MSG_FLAG_PRIORITY;
+
+       obex_dbus_dict_append(iter, "Priority", DBUS_TYPE_BOOLEAN, &flag);
+}
+
+static void parse_read(struct map_msg *msg, const char *value,
+                                                       DBusMessageIter *iter)
+{
+       gboolean flag = strcasecmp(value, "no");
+
+       if (flag)
+               msg->flags |= MAP_MSG_FLAG_READ;
+       else
+               msg->flags &= ~MAP_MSG_FLAG_READ;
+
+       obex_dbus_dict_append(iter, "Read", DBUS_TYPE_BOOLEAN, &flag);
+}
+
+static void parse_sent(struct map_msg *msg, const char *value,
+                                                       DBusMessageIter *iter)
+{
+       gboolean flag = strcasecmp(value, "no");
+
+       if (flag)
+               msg->flags |= MAP_MSG_FLAG_SENT;
+       else
+               msg->flags &= ~MAP_MSG_FLAG_SENT;
+
+       obex_dbus_dict_append(iter, "Sent", DBUS_TYPE_BOOLEAN, &flag);
+}
+
+static void parse_protected(struct map_msg *msg, const char *value,
+                                                       DBusMessageIter *iter)
+{
+       gboolean flag = strcasecmp(value, "no");
+
+       if (flag)
+               msg->flags |= MAP_MSG_FLAG_PROTECTED;
+       else
+               msg->flags &= ~MAP_MSG_FLAG_PROTECTED;
+
+       obex_dbus_dict_append(iter, "Protected", DBUS_TYPE_BOOLEAN, &flag);
+}
+
+static struct map_msg_parser {
+       const char *name;
+       void (*func) (struct map_msg *msg, const char *value,
+                                                       DBusMessageIter *iter);
+} msg_parsers[] = {
+               { "subject", parse_subject },
+               { "datetime", parse_datetime },
+               { "sender_name", parse_sender },
+               { "sender_addressing", parse_sender_address },
+               { "replyto_addressing", parse_replyto },
+               { "recipient_name", parse_recipient },
+               { "recipient_addressing", parse_recipient_address },
+               { "type", parse_type },
+               { "reception_status", parse_status },
+               { "size", parse_size },
+               { "priority", parse_priority },
+               { "read", parse_read },
+               { "sent", parse_sent },
+               { "protected", parse_protected },
+               { }
+};
+
+static void msg_element(GMarkupParseContext *ctxt, const gchar *element,
+                               const gchar **names, const gchar **values,
+                               gpointer user_data, GError **gerr)
+{
+       struct map_parser *parser = user_data;
+       struct map_data *data = parser->data;
+       DBusMessageIter entry, dict, *iter = parser->iter;
+       struct map_msg *msg;
+       const gchar *key;
+       gint i;
+
+       if (strcasecmp("msg", element) != 0)
+               return;
+
+       for (i = 0, key = names[i]; key; key = names[++i]) {
+               if (strcasecmp(key, "handle") == 0)
+                       break;
+       }
+
+       msg = g_hash_table_lookup(data->messages, key);
+       if (msg == NULL) {
+               msg = map_msg_create(data, values[i]);
+               if (msg == NULL)
+                       return;
+       }
+
+       dbus_message_iter_open_container(iter, DBUS_TYPE_DICT_ENTRY, NULL,
+                                                               &entry);
+
+       dbus_message_iter_append_basic(&entry, DBUS_TYPE_OBJECT_PATH,
+                                                               &msg->path);
+
+       dbus_message_iter_open_container(&entry, DBUS_TYPE_ARRAY,
+                                       DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
+                                       DBUS_TYPE_STRING_AS_STRING
+                                       DBUS_TYPE_VARIANT_AS_STRING
+                                       DBUS_DICT_ENTRY_END_CHAR_AS_STRING,
+                                       &dict);
+
+       for (i = 0, key = names[i]; key; key = names[++i]) {
+               struct map_msg_parser *parser;
+
+               for (parser = msg_parsers; parser && parser->name; parser++) {
+                       if (strcasecmp(key, parser->name) == 0) {
+                               parser->func(msg, values[i], &dict);
+                               break;
+                       }
+               }
+       }
+
+       dbus_message_iter_close_container(&entry, &dict);
+       dbus_message_iter_close_container(iter, &entry);
+}
+
+static const GMarkupParser msg_parser = {
+       msg_element,
+       NULL,
+       NULL,
+       NULL,
+       NULL
+};
+
+static void message_listing_cb(struct obc_session *session,
+                                               struct obc_transfer *transfer,
+                                               GError *err, void *user_data)
+{
+       struct map_data *map = 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(map->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(map->msg,
+                                               ERROR_INTERFACE ".Failed",
+                                               "Error reading contents: %s",
+                                               strerror(-perr));
+               goto done;
+       }
+
+       reply = dbus_message_new_method_return(map->msg);
+       if (reply == NULL)
+               return;
+
+       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);
+
+       parser = g_new(struct map_parser, 1);
+       parser->data = map;
+       parser->iter = &array;
+
+       ctxt = g_markup_parse_context_new(&msg_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:
+       g_dbus_send_message(conn, reply);
+       dbus_message_unref(map->msg);
 }
 
 static DBusMessage *map_get_message_listing(DBusConnection *connection,
                                        DBusMessage *message, void *user_data)
 {
        struct map_data *map = user_data;
-       int err;
+       struct obc_transfer *transfer;
        const char *folder;
        DBusMessageIter msg_iter;
+       GError *err = NULL;
+       DBusMessage *reply;
 
        dbus_message_iter_init(message, &msg_iter);
 
        if (dbus_message_iter_get_arg_type(&msg_iter) != DBUS_TYPE_STRING)
                return g_dbus_create_error(message,
-                               "org.openobex.Error.InvalidArguments", NULL);
+                               ERROR_INTERFACE ".InvalidArguments", NULL);
 
        dbus_message_iter_get_basic(&msg_iter, &folder);
 
-       err = obc_session_get(map->session, "x-bt/MAP-msg-listing", folder,
-                                                       NULL, NULL, 0,
-                                                       buffer_cb, map);
-       if (err < 0)
-               return g_dbus_create_error(message, "org.openobex.Error.Failed",
-                                                                       NULL);
+       transfer = obc_transfer_get("x-bt/MAP-msg-listing", folder, NULL, &err);
+       if (transfer == NULL)
+               goto fail;
 
-       map->msg = dbus_message_ref(message);
+       if (obc_session_queue(map->session, transfer, message_listing_cb, map,
+                                                               &err)) {
+               map->msg = dbus_message_ref(message);
+               return NULL;
+       }
 
-       return NULL;
+fail:
+       reply = g_dbus_create_error(message, ERROR_INTERFACE ".Failed", "%s",
+                                                               err->message);
+       g_error_free(err);
+       return reply;
 }
 
-static GDBusMethodTable map_methods[] = {
-       { "SetFolder",          "s", "",        map_setpath,
-                                               G_DBUS_METHOD_FLAG_ASYNC },
-       { "GetFolderListing",   "a{ss}", "s",   map_get_folder_listing,
-                                               G_DBUS_METHOD_FLAG_ASYNC },
-       { "GetMessageListing",  "sa{ss}", "s",  map_get_message_listing,
-                                               G_DBUS_METHOD_FLAG_ASYNC },
+static const GDBusMethodTable map_methods[] = {
+       { GDBUS_ASYNC_METHOD("SetFolder",
+                               GDBUS_ARGS({ "name", "s" }), NULL,
+                               map_setpath) },
+       { GDBUS_ASYNC_METHOD("GetFolderListing",
+                                       GDBUS_ARGS({ "filter", "a{ss}" }),
+                                       GDBUS_ARGS({ "content", "aa{sv}" }),
+                                       map_get_folder_listing) },
+       { GDBUS_ASYNC_METHOD("GetMessageListing",
+                       GDBUS_ARGS({ "folder", "s" }, { "filter", "a{ss}" }),
+                       GDBUS_ARGS({ "messages", "a{oa{sv}}" }),
+                       map_get_message_listing) },
        { }
 };
 
+static void map_msg_remove(void *data)
+{
+       struct map_msg *msg = data;
+       char *path;
+
+       path = msg->path;
+       msg->path = NULL;
+       g_dbus_unregister_interface(conn, path, MAP_MSG_INTERFACE);
+       g_free(path);
+}
+
 static void map_free(void *data)
 {
        struct map_data *map = data;
 
        obc_session_unref(map->session);
+       g_hash_table_unref(map->messages);
        g_free(map);
 }
 
@@ -213,6 +678,8 @@ static int map_probe(struct obc_session *session)
                return -ENOMEM;
 
        map->session = obc_session_ref(session);
+       map->messages = g_hash_table_new_full(g_str_hash, g_str_equal, NULL,
+                                                               map_msg_remove);
 
        if (!g_dbus_register_interface(conn, path, MAP_INTERFACE, map_methods,
                                        NULL, NULL, map, map_free)) {