Add notification feature and SendEvent MNS method 2.0alpha master 2.0_alpha submit/master/20120920.151048
authorJaekyun Lee <jkyun.lee@samsung.com>
Tue, 28 Aug 2012 06:07:32 +0000 (15:07 +0900)
committerJaekyun Lee <jkyun.lee@samsung.com>
Tue, 28 Aug 2012 06:07:32 +0000 (15:07 +0900)
client/mns.c
debian/changelog
doc/client-api.txt
packaging/obexd.spec
plugins/mas.c
plugins/messages-dummy.c
plugins/messages-tizen.c
plugins/messages-tracker.c
plugins/messages.h

index 7aac94e..9eed124 100644 (file)
 #include <errno.h>
 #include <glib.h>
 #include <gdbus.h>
+#include <string.h>
 
 #include "log.h"
 
 #include "transfer.h"
 #include "session.h"
 #include "driver.h"
+#include "map_ap.h"
 #include "mns.h"
 
 #define OBEX_MNS_UUID \
 #define OBEX_MNS_UUID_LEN 16
 
 #define MNS_INTERFACE  "org.openobex.MessageNotification"
+#define ERROR_INF MNS_INTERFACE ".Error"
 #define MNS_UUID "00001133-0000-1000-8000-00805f9b34fb"
 
+enum msg_event_type {
+       EVENT_TYPE_NEW_MESSAGE,
+       EVENT_TYPE_DELIVERY_SUCCESS,
+       EVENT_TYPE_SENDING_SUCCESS,
+       EVENT_TYPE_DELIVERY_FAILURE,
+       EVENT_TYPE_SENDING_FAILURE,
+       EVENT_TYPE_MEMORY_FULL,
+       EVENT_TYPE_MEMORY_AVAILABLE,
+       EVENT_TYPE_MESSAGE_DELETED,
+       EVENT_TYPE_MESSAGE_SHIFT,
+       EVENT_TYPE_UNKNOWN,
+};
+
+struct sendevent_apparam {
+       uint8_t     masinstanceid_tag;
+       uint8_t     masinstanceid_len;
+       uint8_t     masinstanceid;
+} __attribute__ ((packed));
+
 struct mns_data {
        struct obc_session *session;
        DBusMessage *msg;
@@ -49,14 +71,124 @@ struct mns_data {
 
 static DBusConnection *conn = NULL;
 
+static int get_event_type(gchar *event_type)
+{
+       DBG("event_type = %s\n", event_type);
+
+       if (!g_strcmp0(event_type, "NewMessage"))
+               return EVENT_TYPE_NEW_MESSAGE;
+       else if (!g_strcmp0(event_type, "DeliverySuccess"))
+               return EVENT_TYPE_DELIVERY_SUCCESS;
+       else if (!g_strcmp0(event_type, "SendingSuccess"))
+               return EVENT_TYPE_SENDING_SUCCESS;
+       else if (!g_strcmp0(event_type, "DeliveryFailure"))
+               return EVENT_TYPE_DELIVERY_FAILURE;
+       else if (!g_strcmp0(event_type, "SendingFailure"))
+               return EVENT_TYPE_SENDING_FAILURE;
+       else if (!g_strcmp0(event_type, "MemoryFull"))
+               return EVENT_TYPE_MEMORY_FULL;
+       else if (!g_strcmp0(event_type, "MemoryAvailable"))
+               return EVENT_TYPE_MEMORY_AVAILABLE;
+       else if (!g_strcmp0(event_type, "MessageDeleted"))
+               return EVENT_TYPE_MESSAGE_DELETED;
+       else if (!g_strcmp0(event_type, "MessageShift"))
+               return EVENT_TYPE_MESSAGE_SHIFT;
+       else
+               return EVENT_TYPE_UNKNOWN;
+
+}
+
+static gchar *generate_event_report(gchar *event_type,
+                               gchar *handle, gchar *folder,
+                               gchar *old_folder, gchar *msg_type)
+{
+       GString *buf;
+       int event;
+
+       event = get_event_type(event_type);
+       if (event == EVENT_TYPE_UNKNOWN)
+               return NULL;
+
+       buf = g_string_new("<MAP-event-report version=\"1.0\">\n");
+       g_string_append_printf(buf, "<event type=\"%s\" ", event_type);
+
+       if (event == EVENT_TYPE_MEMORY_FULL ||
+                       event == EVENT_TYPE_MEMORY_AVAILABLE)
+               goto done;
+
+       g_string_append_printf(buf, "handle=\"%s\" ", handle);
+       g_string_append_printf(buf, "folder=\"%s\" ", folder);
+
+       if (event == EVENT_TYPE_MESSAGE_SHIFT)
+               g_string_append_printf(buf, " old_folder=\"%s\" ", old_folder);
+
+       g_string_append_printf(buf, "msg_type=\"%s\" ", msg_type);
+
+done:
+       g_string_append(buf, "/>\n</MAP-event-report>\n");
+
+       return g_string_free(buf, FALSE);
+}
+
 static DBusMessage *send_event(DBusConnection *connection,
                                        DBusMessage *message, void *user_data)
 {
-       return NULL;
+       struct mns_data *mns = user_data;
+       struct obc_transfer *transfer;
+       struct sendevent_apparam apparam;
+       gchar *event_type;
+       gchar *handle;
+       gchar *folder;
+       gchar *old_folder;
+       gchar *msg_type;
+       gchar *buf;
+       GError *err;
+       DBusMessage *reply;
+
+       if (dbus_message_get_args(message, NULL,
+                       DBUS_TYPE_STRING, &event_type,
+                       DBUS_TYPE_STRING, &handle,
+                       DBUS_TYPE_STRING, &folder,
+                       DBUS_TYPE_STRING, &old_folder,
+                       DBUS_TYPE_STRING, &msg_type,
+                       DBUS_TYPE_INVALID) == FALSE)
+               return g_dbus_create_error(message,
+                                       "org.openobex.Error.InvalidArguments",
+                                       NULL);
+
+       buf = generate_event_report(event_type, handle, folder,
+                               old_folder, msg_type);
+       if (!buf)
+               return g_dbus_create_error(message,
+                               "org.openobex.Error.InvalidArguments", NULL);
+
+       transfer = obc_transfer_put("x-bt/MAP-event-report", NULL, NULL,
+                               buf, strlen(buf), &err);
+
+       g_free(buf);
+
+       if (transfer == NULL)
+               goto fail;
+
+       apparam.masinstanceid_tag = MAP_AP_MASINSTANCEID;
+       apparam.masinstanceid_len = 1;
+       /* Obexd currently supports single SDP for MAS */
+       apparam.masinstanceid = 0;
+
+       obc_transfer_set_params(transfer, &apparam, sizeof(apparam));
+
+       if (obc_session_queue(mns->session, transfer, NULL, NULL, &err))
+               return dbus_message_new_method_return(message);
+
+fail:
+       reply = g_dbus_create_error(message, ERROR_INF ".Failed", "%s",
+                                                               err->message);
+       g_error_free(err);
+       return reply;
 }
 
 static GDBusMethodTable mns_methods[] = {
-       { "SendEvent",  "s", "",        send_event,
+       { "SendEvent",  "sssss", "",    send_event,
                                                G_DBUS_METHOD_FLAG_ASYNC },
        { }
 };
index d774842..70587c0 100644 (file)
@@ -1,3 +1,11 @@
+obexd (0.46-slp2+3) unstable; urgency=low
+
+  * Upload the package
+  * Git: framework/connectivity/obexd
+  * Tag: obexd_0.46-slp2+3
+
+ -- Jaekyun Lee <jkyun.lee@samsung.com>  Thu, 23 Aug 2012 16:48:11 +0900
+
 obexd (0.46-slp2+2) unstable; urgency=low
 
   * Upload the package
index 7dd83d9..b2633c5 100644 (file)
@@ -272,6 +272,20 @@ Methods            void SetFolder(string name)
                        Set working directory for current session, *name* may
                        be the directory name or '..[/dir]'.
 
+#ifdef TIZEN_PATCH
+Message Notification hierarchy
+=========================
+
+Service                org.openobex.client
+Interface      org.openobex.MessageNotification
+Object path    [variable prefix]/{session0,session1,...}
+
+Methods                void SendEvent(string event_type, string handle,
+                                       string folder, string old_folder, string msg_type)
+
+                       Send event reports to registered MAP Client.
+#endif
+
 Transfer hierarchy
 ==================
 
index 6db2a05..659ff08 100644 (file)
@@ -1,7 +1,7 @@
 Name:       obexd
 Summary:    OBEX Server A basic OBEX server implementation
 Version: 0.46
-Release:    2
+Release:    3
 Group:      TO_BE/FILLED_IN
 License:    TO BE FILLED IN
 Source0:    %{name}-%{version}.tar.gz
index 5b21d2d..7693f29 100644 (file)
@@ -115,6 +115,10 @@ struct mas_session {
        map_ap_t *inparams;
        map_ap_t *outparams;
        gboolean ap_sent;
+#ifdef TIZEN_PATCH
+       int notification_status;
+       char *remote_addr;
+#endif
 };
 
 static const uint8_t MAS_TARGET[TARGET_SIZE] = {
@@ -160,12 +164,18 @@ static void reset_request(struct mas_session *mas)
 static void mas_clean(struct mas_session *mas)
 {
        reset_request(mas);
+#ifdef TIZEN_PATCH
+       g_free(mas->remote_addr);
+#endif
        g_free(mas);
 }
 
 static void *mas_connect(struct obex_session *os, int *err)
 {
        struct mas_session *mas;
+#ifdef TIZEN_PATCH
+       char *address;
+#endif
 
        DBG("");
 
@@ -177,6 +187,13 @@ static void *mas_connect(struct obex_session *os, int *err)
 
        manager_register_session(os);
 
+#ifdef TIZEN_PATCH
+       if (obex_getpeername(os, &address) == 0) {
+               mas->remote_addr = address;
+               DBG("mas->remote_addr = %s \n", mas->remote_addr);
+       }
+#endif
+
        return mas;
 
 failed:
@@ -703,6 +720,45 @@ static void *message_status_open(const char *name, int oflag, mode_t mode,
        else
                return mas;
 }
+
+static void *notification_registration_open(const char *name, int oflag,
+               mode_t mode, void *driver_data, size_t *size, int *err)
+{
+       struct mas_session *mas = driver_data;
+       uint8_t status;
+
+       if (oflag == O_RDONLY) {
+               *err = -EBADR;
+               return NULL;
+       }
+
+       if (!map_ap_get_u8(mas->inparams, MAP_AP_NOTIFICATIONSTATUS, &status)) {
+               *err = -EBADR;
+               return NULL;
+       }
+
+       DBG("status: %d", status);
+
+       mas->notification_status = status;
+       *err = 0;
+       mas->finished = TRUE;
+       return mas;
+}
+
+static int notification_registration_close(void *obj)
+{
+       struct mas_session *mas = obj;
+
+       DBG("");
+
+       messages_notification_registration(mas->backend_data,
+                               mas->remote_addr, mas->notification_status,
+                               NULL, mas);
+
+       reset_request(mas);
+
+       return 0;
+}
 #endif
 
 static ssize_t any_get_next_header(void *object, void *buf, size_t mtu,
@@ -843,8 +899,13 @@ static struct obex_mime_type_driver mime_notification_registration = {
        .target = MAS_TARGET,
        .target_size = TARGET_SIZE,
        .mimetype = "x-bt/MAP-NotificationRegistration",
+#ifdef TIZEN_PATCH
+       .open = notification_registration_open,
+       .close = notification_registration_close,
+#else
        .open = any_open,
        .close = any_close,
+#endif
        .read = any_read,
        .write = any_write,
 };
index 5ec8703..7f9adad 100644 (file)
@@ -368,6 +368,14 @@ int messages_set_message_status(void *session, const char *handle,
 {
        return -ENOSYS;
 }
+
+int messages_notification_registration(void *session,
+                               char *address, int status,
+                               messages_notification_registration_cb callback,
+                               void *user_data)
+{
+       return -ENOSYS;
+}
 #endif
 
 void messages_abort(void *s)
index 40bf46d..7805d5a 100644 (file)
@@ -39,6 +39,7 @@
 #define QUERY_GET_MESSAGE "GetMessage"
 #define QUERY_UPDATE_MESSAGE "UpdateMessage"
 #define QUERY_MESSAGE_STATUS "MessageStatus"
+#define QUERY_NOTI_REGISTRATION "NotiRegistration"
 
 #define BT_MAP_SERVICE_OBJECT_PATH "/org/bluez/map_agent"
 #define BT_MAP_SERVICE_NAME "org.bluez.map_agent"
 
 static DBusConnection *g_conn = NULL;
 
+struct mns_reg_data {
+       int notification_status;
+       char *remote_addr;
+};
+
 struct message_folder {
        char *name;
        GSList *subfolders;
@@ -716,6 +722,64 @@ int messages_set_message_status(void *session, const char *handle,
        return 1;
 }
 
+static gboolean notification_registration(gpointer user_data)
+{
+       DBG("+\n");
+       DBusMessage *message = NULL;
+       gboolean reg;
+       struct mns_reg_data *data = (struct mns_reg_data *)user_data;
+
+       message = dbus_message_new_method_call(BT_MAP_SERVICE_NAME,
+                                       BT_MAP_SERVICE_OBJECT_PATH,
+                                       BT_MAP_SERVICE_INTERFACE,
+                                       QUERY_NOTI_REGISTRATION);
+       if (!message) {
+               error("Can't allocate new message");
+               goto done;
+       }
+
+       DBG("data->notification_status = %d\n", data->notification_status);
+
+       if (data->notification_status == 1)
+               reg = TRUE;
+       else
+               reg = FALSE;
+
+       dbus_message_append_args(message, DBUS_TYPE_STRING, &data->remote_addr,
+                                               DBUS_TYPE_BOOLEAN, &reg,
+                                               DBUS_TYPE_INVALID);
+
+       if (dbus_connection_send(g_conn, message, NULL) == FALSE)
+               error("Could not send dbus message");
+
+done:
+       if (message)
+               dbus_message_unref(message);
+
+       g_free(data->remote_addr);
+       g_free(data);
+
+       DBG("-\n");
+       return FALSE;
+}
+
+int messages_notification_registration(void *session,
+                               char *address, int status,
+                               messages_notification_registration_cb callback,
+                               void *user_data)
+{
+       DBG("+\n");
+       struct mns_reg_data *data = g_new0(struct mns_reg_data, 1);
+       data->notification_status = status;
+       data->remote_addr = g_strdup(address);
+
+       DBG("status = %d\n", status);
+
+       g_idle_add(notification_registration, data);
+       DBG("-\n");
+       return 1;
+}
+
 void messages_abort(void *session)
 {
 }
index 0936b50..bd18955 100644 (file)
@@ -344,6 +344,14 @@ int messages_set_message_status(void *session, const char *handle,
 {
        return -ENOSYS;
 }
+
+int messages_notification_registration(void *session,
+                               char *address, int status,
+                               messages_notification_registration_cb callback,
+                               void *user_data)
+{
+       return -ENOSYS;
+}
 #endif
 
 void messages_abort(void *session)
index a023d58..e85233f 100644 (file)
@@ -310,6 +310,26 @@ int messages_set_message_status(void *session, const char *handle,
                                        void *user_data);
 #endif
 
+
+#ifdef TIZEN_PATCH
+
+/* Informs Message Server to modify status of the message.
+ *
+ * session: Backend session.
+ * address: Remote device address that request notification registraton.
+ * status: To indicate message notification service
+ * Callback shall be called for every notification registration request.
+ * user_data: User data if any to be sent.
+ */
+typedef void (*messages_notification_registration_cb)(void *session, int err,
+               void *user_data);
+
+int messages_notification_registration(void *session,
+                                       char *address, int status,
+                                       messages_notification_registration_cb callback,
+                                       void *user_data);
+#endif
+
 /* Aborts currently pending request.
  *
  * session: Backend session.