upgrade obexd to 0.47
[profile/ivi/obexd.git] / plugins / mas.c
index 9466039..7693f29 100644 (file)
 #include <config.h>
 #endif
 
+#include <string.h>
 #include <errno.h>
 #include <glib.h>
 #include <fcntl.h>
 #include <inttypes.h>
 
+#include <gobex/gobex.h>
+
 #include "obexd.h"
 #include "plugin.h"
 #include "log.h"
 #include "mimetype.h"
 #include "filesystem.h"
 #include "manager.h"
+#include "map_ap.h"
 
 #include "messages.h"
-#ifdef TIZEN_PATCH
-#include "map_ap.h"
-#include "bmessage-parser.h"
-#endif
 
 /* Channel number according to bluez doc/assigned-numbers.txt */
 #define MAS_CHANNEL    16
@@ -112,8 +112,12 @@ struct mas_session {
        gboolean finished;
        gboolean nth_call;
        GString *buffer;
+       map_ap_t *inparams;
+       map_ap_t *outparams;
+       gboolean ap_sent;
 #ifdef TIZEN_PATCH
-       map_ap_t *ap;
+       int notification_status;
+       char *remote_addr;
 #endif
 };
 
@@ -121,14 +125,25 @@ static const uint8_t MAS_TARGET[TARGET_SIZE] = {
                        0xbb, 0x58, 0x2b, 0x40, 0x42, 0x0c, 0x11, 0xdb,
                        0xb0, 0xde, 0x08, 0x00, 0x20, 0x0c, 0x9a, 0x66  };
 
-#ifdef TIZEN_PATCH
-static void bmessage_parser(struct mas_session *mas,
-                          struct bmessage_property *bmessage)
+static int get_params(struct obex_session *os, struct mas_session *mas)
 {
-       /* STRING PARSER : Under implementation */
-       DBG("%s", mas->buffer->str);
+       const uint8_t *buffer;
+       ssize_t size;
+
+       size = obex_get_apparam(os, &buffer);
+       if (size < 0)
+               size = 0;
+
+       mas->inparams = map_ap_decode(buffer, size);
+       if (mas->inparams == NULL) {
+               DBG("Error when parsing parameters!");
+               return -EBADR;
+       }
+
+       mas->outparams = map_ap_new();
+
+       return 0;
 }
-#endif
 
 static void reset_request(struct mas_session *mas)
 {
@@ -136,10 +151,12 @@ static void reset_request(struct mas_session *mas)
                g_string_free(mas->buffer, TRUE);
                mas->buffer = NULL;
        }
-#ifdef TIZEN_PATCH
-       map_ap_free(mas->ap);
-       mas->ap = NULL;
-#endif
+
+       map_ap_free(mas->inparams);
+       mas->inparams = NULL;
+       map_ap_free(mas->outparams);
+       mas->outparams = NULL;
+
        mas->nth_call = FALSE;
        mas->finished = FALSE;
 }
@@ -147,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("");
 
@@ -164,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:
@@ -190,10 +220,6 @@ static int mas_get(struct obex_session *os, void *user_data)
        const char *type = obex_get_type(os);
        const char *name = obex_get_name(os);
        int ret;
-#ifdef TIZEN_PATCH
-       const uint8_t *buffer = NULL;
-       ssize_t rsize = 0;
-#endif
 
        DBG("GET: name %s type %s mas %p",
                        name, type, mas);
@@ -201,22 +227,10 @@ static int mas_get(struct obex_session *os, void *user_data)
        if (type == NULL)
                return -EBADR;
 
-#ifdef TIZEN_PATCH
-       rsize = obex_get_apparam(os, &buffer);
+       ret = get_params(os, mas);
+       if (ret < 0)
+               goto failed;
 
-       if (rsize < 0) {
-               if (g_ascii_strcasecmp(type, "x-bt/message") == 0) {
-                       ret = -EBADR;
-                       goto failed;
-               }
-       } else {
-               mas->ap = map_ap_decode(buffer, rsize);
-               if (mas->ap == NULL) {
-                       ret = -EBADR;
-                       goto failed;
-               }
-       }
-#endif
        ret = obex_get_stream_start(os, name);
        if (ret < 0)
                goto failed;
@@ -235,32 +249,16 @@ static int mas_put(struct obex_session *os, void *user_data)
        const char *type = obex_get_type(os);
        const char *name = obex_get_name(os);
        int ret;
-#ifdef TIZEN_PATCH
-       const uint8_t *buffer = NULL;
-       ssize_t rsize = 0;
-#endif
 
        DBG("PUT: name %s type %s mas %p", name, type, mas);
 
        if (type == NULL)
                return -EBADR;
 
-#ifdef TIZEN_PATCH
-       rsize = obex_get_apparam(os, &buffer);
-       if (rsize < 0) {
-               if (g_ascii_strcasecmp(type, "x-bt/messageStatus") == 0 ||
-                       g_ascii_strcasecmp(type, "x-bt/message") == 0) {
-                       ret = -EBADR;
-                       goto failed;
-               }
-       } else {
-               mas->ap = map_ap_decode(buffer, rsize);
-               if (mas->ap == NULL) {
-                       ret = -EBADR;
-                       goto failed;
-               }
-       }
-#endif
+       ret = get_params(os, mas);
+       if (ret < 0)
+               goto failed;
+
        ret = obex_put_stream_start(os, name);
        if (ret < 0)
                goto failed;
@@ -301,12 +299,22 @@ static void get_messages_listing_cb(void *session, int err, uint16_t size,
                                        void *user_data)
 {
        struct mas_session *mas = user_data;
+       uint16_t max = 1024;
 
        if (err < 0 && err != -EAGAIN) {
                obex_object_set_io_flags(mas, G_IO_ERR, err);
                return;
        }
 
+       map_ap_get_u16(mas->inparams, MAP_AP_MAXLISTCOUNT, &max);
+
+       if (max == 0) {
+               if (!entry)
+                       mas->finished = TRUE;
+
+               goto proceed;
+       }
+
        if (!mas->nth_call) {
                g_string_append(mas->buffer, ML_BODY_BEGIN);
                mas->nth_call = TRUE;
@@ -398,6 +406,13 @@ static void get_messages_listing_cb(void *session, int err, uint16_t size,
        g_string_append(mas->buffer, "/>\n");
 
 proceed:
+       if (!entry) {
+               map_ap_set_u16(mas->outparams, MAP_AP_MESSAGESLISTINGSIZE,
+                                                       size);
+               map_ap_set_u8(mas->outparams, MAP_AP_NEWMESSAGE,
+                                                       newmsg ? 1 : 0);
+       }
+
        if (err != -EAGAIN)
                obex_object_set_io_flags(mas, G_IO_IN, 0);
 }
@@ -430,12 +445,26 @@ static void get_folder_listing_cb(void *session, int err, uint16_t size,
                                        const char *name, void *user_data)
 {
        struct mas_session *mas = user_data;
+       uint16_t max = 1024;
 
        if (err < 0 && err != -EAGAIN) {
                obex_object_set_io_flags(mas, G_IO_ERR, err);
                return;
        }
 
+       map_ap_get_u16(mas->inparams, MAP_AP_MAXLISTCOUNT, &max);
+
+       if (max == 0) {
+               if (err != -EAGAIN)
+                       map_ap_set_u16(mas->outparams,
+                                       MAP_AP_FOLDERLISTINGSIZE, size);
+
+               if (!name)
+                       mas->finished = TRUE;
+
+               goto proceed;
+       }
+
        if (!mas->nth_call) {
                g_string_append(mas->buffer, XML_DECL);
                g_string_append(mas->buffer, FL_DTD);
@@ -493,20 +522,6 @@ static void message_status_cb(void *session, int err, void *user_data)
        else
                obex_object_set_io_flags(mas, G_IO_OUT, 0);
 }
-
-static void folder_size_result_cb(void *session, int err, uint16_t size,
-                                       const char *name, void *user_data)
-{
-       struct mas_session *mas = user_data;
-
-       map_ap_set_u16(mas->ap, MAP_AP_FOLDERLISTINGSIZE,
-                                       GUINT16_FROM_BE(size));
-
-       if (err < 0)
-               obex_object_set_io_flags(mas, G_IO_ERR, err);
-       else
-               obex_object_set_io_flags(mas, G_IO_OUT, 0);
-}
 #endif
 
 static int mas_setpath(struct obex_session *os, void *user_data)
@@ -536,11 +551,9 @@ static void *folder_listing_open(const char *name, int oflag, mode_t mode,
                                void *driver_data, size_t *size, int *err)
 {
        struct mas_session *mas = driver_data;
-#ifdef TIZEN_PATCH
-       messages_folder_listing_cb cb;
-       uint16_t maxlistcount = 1024;
+       /* 1024 is the default when there was no MaxListCount sent */
+       uint16_t max = 1024;
        uint16_t offset = 0;
-#endif
 
        if (oflag != O_RDONLY) {
                *err = -EBADR;
@@ -549,26 +562,11 @@ static void *folder_listing_open(const char *name, int oflag, mode_t mode,
 
        DBG("name = %s", name);
 
-#ifdef TIZEN_PATCH
-       if (mas->ap != NULL) {
-               map_ap_get_u16(mas->ap, MAP_AP_MAXLISTCOUNT, &maxlistcount);
-               map_ap_get_u16(mas->ap, MAP_AP_STARTOFFSET, &offset);
-       }
-
-       DBG("Maxlistcount = %d \n offset = %d\n", maxlistcount, offset);
+       map_ap_get_u16(mas->inparams, MAP_AP_MAXLISTCOUNT, &max);
+       map_ap_get_u16(mas->inparams, MAP_AP_STARTOFFSET, &offset);
 
-       if (maxlistcount == 0)
-               cb = folder_size_result_cb;
-       else
-               cb = get_folder_listing_cb;
-
-       *err = messages_get_folder_listing(mas->backend_data, name,
-                                               maxlistcount, offset, cb, mas);
-#else
-       /* 1024 is the default when there was no MaxListCount sent */
-       *err = messages_get_folder_listing(mas->backend_data, name, 1024, 0,
-                       get_folder_listing_cb, mas);
-#endif
+       *err = messages_get_folder_listing(mas->backend_data, name, max,
+                                       offset, get_folder_listing_cb, mas);
 
        mas->buffer = g_string_new("");
 
@@ -583,6 +581,14 @@ static void *msg_listing_open(const char *name, int oflag, mode_t mode,
 {
        struct mas_session *mas = driver_data;
        struct messages_filter filter = { 0, };
+       /* 1024 is the default when there was no MaxListCount sent */
+       uint16_t max = 1024;
+       uint16_t offset = 0;
+#ifdef TIZEN_PATCH
+       /* If MAP client does not specify the subject length,
+               then subject_len = 0 and subject should be sent unaltered.*/
+       uint8_t subject_len = 0;
+#endif
 
        DBG("");
 
@@ -591,9 +597,37 @@ static void *msg_listing_open(const char *name, int oflag, mode_t mode,
                return NULL;
        }
 
-       *err = messages_get_messages_listing(mas->backend_data, name, 0xffff, 0,
-                       &filter,
+       map_ap_get_u16(mas->inparams, MAP_AP_MAXLISTCOUNT, &max);
+       map_ap_get_u16(mas->inparams, MAP_AP_STARTOFFSET, &offset);
+#ifdef TIZEN_PATCH
+       map_ap_get_u8(mas->inparams, MAP_AP_SUBJECTLENGTH, &subject_len);
+#endif
+
+       map_ap_get_u32(mas->inparams, MAP_AP_PARAMETERMASK,
+                                               &filter.parameter_mask);
+       map_ap_get_u8(mas->inparams, MAP_AP_FILTERMESSAGETYPE,
+                                               &filter.type);
+       filter.period_begin = map_ap_get_string(mas->inparams,
+                                               MAP_AP_FILTERPERIODBEGIN);
+       filter.period_end = map_ap_get_string(mas->inparams,
+                                               MAP_AP_FILTERPERIODEND);
+       map_ap_get_u8(mas->inparams, MAP_AP_FILTERREADSTATUS,
+                                               &filter.read_status);
+       filter.recipient = map_ap_get_string(mas->inparams,
+                                               MAP_AP_FILTERRECIPIENT);
+       filter.originator = map_ap_get_string(mas->inparams,
+                                               MAP_AP_FILTERORIGINATOR);
+       map_ap_get_u8(mas->inparams, MAP_AP_FILTERPRIORITY,
+                                               &filter.priority);
+#ifdef TIZEN_PATCH
+       *err = messages_get_messages_listing(mas->backend_data, name, max,
+                       offset, subject_len, &filter,
+                       get_messages_listing_cb, mas);
+#else
+       *err = messages_get_messages_listing(mas->backend_data, name, max,
+                       offset, &filter,
                        get_messages_listing_cb, mas);
+#endif
 
        mas->buffer = g_string_new("");
 
@@ -603,28 +637,6 @@ static void *msg_listing_open(const char *name, int oflag, mode_t mode,
                return mas;
 }
 
-#ifdef TIZEN_PATCH
-static void message_get(struct mas_session *mas, const char *name, int *err)
-{
-       DBG("");
-
-       /* TODO: check for Mandatory application parameter
-       * Attachment and Charset and optional parameter fraction request */
-       *err = messages_get_message(mas->backend_data, name, 0,
-                       get_message_cb, mas);
-       mas->buffer = g_string_new("");
-}
-
-static void message_put(struct mas_session *mas, const char *name, int *err)
-{
-       DBG("");
-
-       /* TODO: check for Mandatory application parameter
-       * Charset and optional parameter transparent and retry */
-       mas->buffer = g_string_new("");
-}
-#endif
-
 static void *message_open(const char *name, int oflag, mode_t mode,
                                void *driver_data, size_t *size, int *err)
 {
@@ -632,15 +644,9 @@ static void *message_open(const char *name, int oflag, mode_t mode,
 
        DBG("");
 
-#ifdef TIZEN_PATCH
-       if (oflag == O_RDONLY)
-               message_get(mas, name, err);
-       else
-               message_put(mas, name, err);
-#else
        if (oflag != O_RDONLY) {
                DBG("Message pushing unsupported");
-               *err = -EINVAL;
+               *err = -ENOSYS;
 
                return NULL;
        }
@@ -649,7 +655,7 @@ static void *message_open(const char *name, int oflag, mode_t mode,
                        get_message_cb, mas);
 
        mas->buffer = g_string_new("");
-#endif
+
        if (*err < 0)
                return NULL;
        else
@@ -664,7 +670,11 @@ static void *message_update_open(const char *name, int oflag, mode_t mode,
 
        DBG("");
 
-       if (!(oflag & O_WRONLY)) {
+#ifdef TIZEN_PATCH
+       if (oflag == O_RDONLY) {
+#else
+       if (oflag != O_WRONLY) {
+#endif
                *err = -EBADR;
                return NULL;
        }
@@ -686,49 +696,64 @@ static void *message_status_open(const char *name, int oflag, mode_t mode,
        uint8_t indicator;
        uint8_t value;
 
-        if (!(oflag & O_WRONLY)) {
+       DBG("");
+
+       if (!(oflag & O_WRONLY)) {
                *err = -EBADR;
                return NULL;
-        }
+       }
 
-       map_ap_get_u8(mas->ap, MAP_AP_STATUSINDICATOR, &indicator);
-       map_ap_get_u8(mas->ap, MAP_AP_STATUSVALUE, &value);
+       if (!map_ap_get_u8(mas->inparams, MAP_AP_STATUSINDICATOR, &indicator)) {
+               *err = -EBADR;
+               return NULL;
+       }
 
-       DBG("Indicator = %d \n value = %d\n", indicator, value);
+       if (!map_ap_get_u8(mas->inparams, MAP_AP_STATUSVALUE, &value)) {
+               *err = -EBADR;
+               return NULL;
+       }
 
        *err = messages_set_message_status(mas->backend_data, name, indicator,
                                                value, message_status_cb, mas);
-
        if (*err < 0)
                return NULL;
        else
                return mas;
 }
 
-static ssize_t message_write(void *object, const void *buf, size_t count)
+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 = object;
-       GString *string;
+       struct mas_session *mas = driver_data;
+       uint8_t status;
 
-       DBG("");
+       if (oflag == O_RDONLY) {
+               *err = -EBADR;
+               return NULL;
+       }
+
+       if (!map_ap_get_u8(mas->inparams, MAP_AP_NOTIFICATIONSTATUS, &status)) {
+               *err = -EBADR;
+               return NULL;
+       }
 
-       string = g_string_append_len(mas->buffer, buf, count);
+       DBG("status: %d", status);
 
-       return string->len;
+       mas->notification_status = status;
+       *err = 0;
+       mas->finished = TRUE;
+       return mas;
 }
 
-static int message_close(void *obj)
+static int notification_registration_close(void *obj)
 {
        struct mas_session *mas = obj;
-       struct bmessage_property bmessage = { 0, };
 
        DBG("");
 
-       /* Bmessage body parsing */
-       bmessage_parser(mas, &bmessage);
-
-       if (!mas->finished)
-               messages_abort(mas->backend_data);
+       messages_notification_registration(mas->backend_data,
+                               mas->remote_addr, mas->notification_status,
+                               NULL, mas);
 
        reset_request(mas);
 
@@ -736,12 +761,44 @@ static int message_close(void *obj)
 }
 #endif
 
+static ssize_t any_get_next_header(void *object, void *buf, size_t mtu,
+                                                               uint8_t *hi)
+{
+       struct mas_session *mas = object;
+       size_t len;
+       uint8_t *apbuf;
+
+       DBG("");
+
+       if (mas->buffer->len == 0 && !mas->finished)
+               return -EAGAIN;
+
+       *hi = G_OBEX_HDR_APPARAM;
+
+       if (mas->ap_sent)
+               return 0;
+
+       mas->ap_sent = TRUE;
+       apbuf = map_ap_encode(mas->outparams, &len);
+
+       if (len > mtu) {
+               DBG("MTU is to small to fit application parameters header!");
+               g_free(apbuf);
+
+               return -EIO;
+       }
+
+       memcpy(buf, apbuf, len);
+
+       return len;
+}
+
 static void *any_open(const char *name, int oflag, mode_t mode,
                                void *driver_data, size_t *size, int *err)
 {
        DBG("");
 
-       *err = -EINVAL;
+       *err = -ENOSYS;
 
        return NULL;
 }
@@ -812,23 +869,16 @@ static struct obex_mime_type_driver mime_message = {
        .target_size = TARGET_SIZE,
        .mimetype = "x-bt/message",
        .open = message_open,
-#ifdef TIZEN_PATCH
-       .close = message_close,
-#else
        .close = any_close,
-#endif
        .read = any_read,
-#ifdef TIZEN_PATCH
-       .write = message_write,
-#else
        .write = any_write,
-#endif
 };
 
 static struct obex_mime_type_driver mime_folder_listing = {
        .target = MAS_TARGET,
        .target_size = TARGET_SIZE,
        .mimetype = "x-obex/folder-listing",
+       .get_next_header = any_get_next_header,
        .open = folder_listing_open,
        .close = any_close,
        .read = any_read,
@@ -849,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,
 };