2011-12-05 11:41:44

by Bartosz Szatkowski

[permalink] [raw]
Subject: [PATCH obexd 1/6] gobex: Add translating error codes to strings

---
gobex/gobex.c | 56 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
gobex/gobex.h | 2 ++
2 files changed, 58 insertions(+), 0 deletions(-)

diff --git a/gobex/gobex.c b/gobex/gobex.c
index b374b06..9fe7a1a 100644
--- a/gobex/gobex.c
+++ b/gobex/gobex.c
@@ -114,6 +114,62 @@ struct setpath_data {
guint8 constants;
} __attribute__ ((packed));

+struct error_code {
+ guint8 code;
+ const char *name;
+} obex_errors[] = {
+ { G_OBEX_RSP_CONTINUE, "Continue" },
+ { G_OBEX_RSP_SUCCESS, "Success" },
+ { G_OBEX_RSP_CREATED, "Created" },
+ { G_OBEX_RSP_ACCEPTED, "Accepted" },
+ { G_OBEX_RSP_NON_AUTHORITATIVE, "Non Authoritative" },
+ { G_OBEX_RSP_NO_CONTENT, "No Content" },
+ { G_OBEX_RSP_RESET_CONTENT, "Reset Content" },
+ { G_OBEX_RSP_PARTIAL_CONTENT, "Partial Content" },
+ { G_OBEX_RSP_MULTIPLE_CHOICES, "Multiple Choices" },
+ { G_OBEX_RSP_MOVED_PERMANENTLY, "Moved Permanently" },
+ { G_OBEX_RSP_MOVED_TEMPORARILY, "Moved Temporarily" },
+ { G_OBEX_RSP_SEE_OTHER, "See Other" },
+ { G_OBEX_RSP_NOT_MODIFIED, "Not Modified" },
+ { G_OBEX_RSP_USE_PROXY, "Use Proxy" },
+ { G_OBEX_RSP_BAD_REQUEST, "Bad Request" },
+ { G_OBEX_RSP_UNAUTHORIZED, "Unauthorized" },
+ { G_OBEX_RSP_PAYMENT_REQUIRED, "Payment Required" },
+ { G_OBEX_RSP_FORBIDDEN, "Forbidden" },
+ { G_OBEX_RSP_NOT_FOUND, "Not Found" },
+ { G_OBEX_RSP_METHOD_NOT_ALLOWED, "Method Not Allowed" },
+ { G_OBEX_RSP_NOT_ACCEPTABLE, "Not Acceptable" },
+ { G_OBEX_RSP_PROXY_AUTH_REQUIRED, "Proxy Auth Required" },
+ { G_OBEX_RSP_REQUEST_TIME_OUT, "Request Time Out" },
+ { G_OBEX_RSP_CONFLICT, "Conflict" },
+ { G_OBEX_RSP_GONE, "Gone" },
+ { G_OBEX_RSP_LENGTH_REQUIRED, "Length Required" },
+ { G_OBEX_RSP_PRECONDITION_FAILED, "Precondition Failed" },
+ { G_OBEX_RSP_REQ_ENTITY_TOO_LARGE, "Req Entity Too Large" },
+ { G_OBEX_RSP_REQ_URL_TOO_LARGE, "Req Url Too Large" },
+ { G_OBEX_RSP_UNSUPPORTED_MEDIA_TYPE, "Unsupported Media Type" },
+ { G_OBEX_RSP_INTERNAL_SERVER_ERROR, "Internal Server Error" },
+ { G_OBEX_RSP_NOT_IMPLEMENTED, "Not Implemented" },
+ { G_OBEX_RSP_BAD_GATEWAY, "Bad Gateway" },
+ { G_OBEX_RSP_SERVICE_UNAVAILABLE, "Service Unavailable" },
+ { G_OBEX_RSP_GATEWAY_TIMEOUT, "Gateway Timeout" },
+ { G_OBEX_RSP_VERSION_NOT_SUPPORTED, "Version Not Supported" },
+ { G_OBEX_RSP_DATABASE_FULL, "Database Full" },
+ { G_OBEX_RSP_DATABASE_LOCKED, "Database Locked" },
+ { }
+};
+
+const char *g_obex_strerror(guint8 err_code)
+{
+ struct error_code *error;
+
+ for (error = obex_errors; error != NULL; error++)
+ if (error->code == err_code)
+ return error->name;
+
+ return "<unknown>";
+}
+
static ssize_t req_header_offset(guint8 opcode)
{
switch (opcode) {
diff --git a/gobex/gobex.h b/gobex/gobex.h
index 1b20333..81981ea 100644
--- a/gobex/gobex.h
+++ b/gobex/gobex.h
@@ -119,4 +119,6 @@ guint g_obex_get_rsp(GObex *obex, GObexDataProducer data_func,

gboolean g_obex_cancel_transfer(guint id);

+const char *g_obex_strerror(guint8 err_code);
+
#endif /* __GOBEX_H */
--
1.7.4.1



2011-12-05 11:41:49

by Bartosz Szatkowski

[permalink] [raw]
Subject: [PATCH obexd 6/6] Add support for PullMessagesListing in MAP client

---
client/map.c | 31 +++++++++++++++++++++++++++++++
test/map-client | 5 +++++
2 files changed, 36 insertions(+), 0 deletions(-)

diff --git a/client/map.c b/client/map.c
index 397c170..0ce2a14 100644
--- a/client/map.c
+++ b/client/map.c
@@ -144,6 +144,35 @@ static DBusMessage *map_get_folder_listing(DBusConnection *connection,
NULL, NULL, NULL, 0,
buffer_cb, map);
if (err < 0)
+ return g_dbus_create_error(message,
+ "org.openobex.Error.Failed",
+ "Failed");
+
+ map->msg = dbus_message_ref(message);
+
+ return NULL;
+}
+
+static DBusMessage *map_get_messages_listing(DBusConnection *connection,
+ DBusMessage *message, void *user_data)
+{
+ struct map_data *map = user_data;
+ int err;
+ const char *folder;
+ DBusMessageIter msg_iter;
+
+ 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);
+
+ 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, ERROR_FAILED_PATH,
"Failed");

@@ -157,6 +186,8 @@ static GDBusMethodTable map_methods[] = {
G_DBUS_METHOD_FLAG_ASYNC },
{ "GetFolderListing", "a{ss}", "s", map_get_folder_listing,
G_DBUS_METHOD_FLAG_ASYNC },
+ { "GetMessagesListing", "sa{ss}", "s", map_get_messages_listing,
+ G_DBUS_METHOD_FLAG_ASYNC },
{ }
};

diff --git a/test/map-client b/test/map-client
index bcd2e66..1a4afdb 100755
--- a/test/map-client
+++ b/test/map-client
@@ -14,6 +14,8 @@ def parse_options():
parser.add_option("-l", "--lsdir", action="store_true", dest="ls_dir",
help="List folders in current directory")
parser.add_option("-v", "--verbose", action="store_true", dest="verbose")
+ parser.add_option("-L", "--lsmsg", action="store", dest="ls_msg",
+ help="List messages in supplied CWD subdir")

return parser.parse_args()

@@ -54,4 +56,7 @@ if __name__ == '__main__':
if options.ls_dir:
print map.GetFolderListing(dict())

+ if options.ls_msg is not None:
+ print map.GetMessagesListing(options.ls_msg, dict())
+
mainloop.run()
--
1.7.4.1


2011-12-05 11:41:46

by Bartosz Szatkowski

[permalink] [raw]
Subject: [PATCH obexd 3/6] Add support for SetFolder in MAP client

---
client/map.c | 56 ++++++++++++++++++++++++++++++++++++++++++++++++++++
doc/client-api.txt | 5 +++-
2 files changed, 60 insertions(+), 1 deletions(-)

diff --git a/client/map.c b/client/map.c
index bee49c5..bc45a13 100644
--- a/client/map.c
+++ b/client/map.c
@@ -40,6 +40,9 @@
#define OBEX_MAS_UUID_LEN 16

#define MAP_INTERFACE "org.openobex.MessageAccess"
+#define ERROR_INF MAP_INTERFACE ".Error"
+#define ERROR_FAILED_PATH "org.openobex.Error.Failed"
+
#define MAS_UUID "00001132-0000-1000-8000-00805f9b34fb"

struct map_data {
@@ -49,7 +52,60 @@ struct map_data {

static DBusConnection *conn = NULL;

+static void simple_cb(GObex *obex, GError *err, GObexPacket *rsp,
+ gpointer 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, ERROR_FAILED_PATH,
+ "%s", err->message);
+ else if (err_code != G_OBEX_RSP_SUCCESS)
+ reply = g_dbus_create_error(map->msg,
+ "org.openobex.Error.Response",
+ "%s (0x%02x)",
+ g_obex_strerror(err_code),
+ err_code);
+ else
+ reply = dbus_message_new_method_return(map->msg);
+
+ g_dbus_send_message(conn, reply);
+ dbus_message_unref(map->msg);
+}
+
+static DBusMessage *map_setpath(DBusConnection *connection,
+ DBusMessage *message, void *user_data)
+{
+ 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,
+ ERROR_INF ".InvalidArguments", NULL);
+
+ obex = obc_session_get_obex(map->session);
+
+ g_obex_setpath(obex, folder, simple_cb, map, &err);
+ if (err != NULL) {
+ DBusMessage *reply;
+ reply = g_dbus_create_error(message, ERROR_FAILED_PATH,
+ "%s", err->message);
+ g_error_free(err);
+ return reply;
+ }
+
+ map->msg = dbus_message_ref(message);
+
+ return NULL;
+}
+
static GDBusMethodTable map_methods[] = {
+ { "SetFolder", "s", "", map_setpath, G_DBUS_METHOD_FLAG_ASYNC },
{ }
};

diff --git a/doc/client-api.txt b/doc/client-api.txt
index ee8951f..fb5a8b2 100644
--- a/doc/client-api.txt
+++ b/doc/client-api.txt
@@ -258,7 +258,10 @@ Service org.openobex.client
Interface org.openobex.MessageAccess
Object path [variable prefix]/{session0,session1,...}

-Methods
+Methods void SetFolder(string name)
+
+ Set working directory for current session, *name* may
+ be the directory name or '..[/dir]'.

Transfer hierarchy
==================
--
1.7.4.1


2011-12-05 11:41:48

by Bartosz Szatkowski

[permalink] [raw]
Subject: [PATCH obexd 5/6] Add basic support for MAP folder listing

---
client/map.c | 53 ++++++++++++++++++++++++++++++++++++++++++++++++++++-
test/map-client | 5 +++++
2 files changed, 57 insertions(+), 1 deletions(-)

diff --git a/client/map.c b/client/map.c
index bc45a13..397c170 100644
--- a/client/map.c
+++ b/client/map.c
@@ -104,8 +104,59 @@ static DBusMessage *map_setpath(DBusConnection *connection,
return NULL;
}

+static void buffer_cb(struct obc_session *session, GError *err,
+ void *user_data)
+{
+ struct obc_transfer *transfer = obc_session_get_transfer(session);
+ struct map_data *map = user_data;
+ DBusMessage *reply;
+ const char *buf;
+ int size;
+
+ if (err != NULL) {
+ reply = g_dbus_create_error(map->msg, ERROR_FAILED_PATH, "%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);
+
+ obc_transfer_clear_buffer(transfer);
+
+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;
+
+ 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, ERROR_FAILED_PATH,
+ "Failed");
+
+ map->msg = dbus_message_ref(message);
+
+ return NULL;
+}
+
static GDBusMethodTable map_methods[] = {
- { "SetFolder", "s", "", map_setpath, G_DBUS_METHOD_FLAG_ASYNC },
+ { "SetFolder", "s", "", map_setpath,
+ G_DBUS_METHOD_FLAG_ASYNC },
+ { "GetFolderListing", "a{ss}", "s", map_get_folder_listing,
+ G_DBUS_METHOD_FLAG_ASYNC },
{ }
};

diff --git a/test/map-client b/test/map-client
index 5ee4331..bcd2e66 100755
--- a/test/map-client
+++ b/test/map-client
@@ -11,6 +11,8 @@ def parse_options():
help="Device to connect", metavar="DEVICE")
parser.add_option("-c", "--chdir", dest="new_dir",
help="Change current directory to DIR", metavar="DIR")
+ parser.add_option("-l", "--lsdir", action="store_true", dest="ls_dir",
+ help="List folders in current directory")
parser.add_option("-v", "--verbose", action="store_true", dest="verbose")

return parser.parse_args()
@@ -49,4 +51,7 @@ if __name__ == '__main__':
if options.new_dir:
set_folder(map, options.new_dir)

+ if options.ls_dir:
+ print map.GetFolderListing(dict())
+
mainloop.run()
--
1.7.4.1


2011-12-05 11:41:47

by Bartosz Szatkowski

[permalink] [raw]
Subject: [PATCH obexd 4/6] Add simple helper for MAP client

---
Makefile.am | 3 ++-
test/map-client | 52 ++++++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 54 insertions(+), 1 deletions(-)
create mode 100755 test/map-client

diff --git a/Makefile.am b/Makefile.am
index 60c4982..0b0f670 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -9,7 +9,8 @@ doc_files = doc/obexd-api.txt doc/agent-api.txt doc/client-api.txt

test_files = test/simple-agent test/send-files \
test/pull-business-card test/exchange-business-cards \
- test/list-folders test/pbap-client test/ftp-client
+ test/list-folders test/pbap-client test/ftp-client \
+ test/map-client

gdbus_sources = gdbus/gdbus.h gdbus/mainloop.c gdbus/watch.c \
gdbus/object.c gdbus/polkit.c
diff --git a/test/map-client b/test/map-client
new file mode 100755
index 0000000..5ee4331
--- /dev/null
+++ b/test/map-client
@@ -0,0 +1,52 @@
+#!/usr/bin/python
+
+import gobject
+
+import dbus
+import dbus.mainloop.glib
+from optparse import OptionParser
+
+def parse_options():
+ parser.add_option("-d", "--device", dest="device",
+ help="Device to connect", metavar="DEVICE")
+ parser.add_option("-c", "--chdir", dest="new_dir",
+ help="Change current directory to DIR", metavar="DIR")
+ parser.add_option("-v", "--verbose", action="store_true", dest="verbose")
+
+ return parser.parse_args()
+
+def set_folder(session, new_dir):
+ for node in new_dir.split("/"):
+ session.SetFolder(node)
+
+if __name__ == '__main__':
+
+ dbus.mainloop.glib.DBusGMainLoop(set_as_default=True)
+
+ parser = OptionParser()
+
+ (options, args) = parse_options()
+
+ if not options.device:
+ parser.print_help()
+ exit(0)
+
+ bus = dbus.SessionBus()
+ mainloop = gobject.MainLoop()
+
+ client = dbus.Interface(bus.get_object("org.openobex.client", "/"),
+ "org.openobex.Client")
+
+ session_path = client.CreateSession({ "Destination": options.device,
+ "Target": "map"})
+
+ session = dbus.Interface(bus.get_object("org.openobex.client", session_path),
+ "org.openobex.Session")
+
+ map = dbus.Interface(bus.get_object("org.openobex.client", session_path),
+ "org.openobex.MessageAccess")
+
+ if options.new_dir:
+ set_folder(map, options.new_dir)
+
+ mainloop.run()
--
1.7.4.1


2011-12-05 11:41:45

by Bartosz Szatkowski

[permalink] [raw]
Subject: [PATCH obexd 2/6] Add basic support for MAP client in obex-client

---
Makefile.am | 1 +
client/manager.c | 2 +
client/map.c | 135 ++++++++++++++++++++++++++++++++++++++++++++++++++++
client/map.h | 24 +++++++++
doc/client-api.txt | 9 ++++
5 files changed, 171 insertions(+), 0 deletions(-)
create mode 100644 client/map.c
create mode 100644 client/map.h

diff --git a/Makefile.am b/Makefile.am
index af03f2e..60c4982 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -119,6 +119,7 @@ client_obex_client_SOURCES = $(gdbus_sources) $(gobex_sources) \
client/pbap.h client/pbap.c \
client/ftp.h client/ftp.c \
client/opp.h client/opp.c \
+ client/map.h client/map.c \
client/transfer.h client/transfer.c \
client/agent.h client/agent.c \
client/driver.h client/driver.c
diff --git a/client/manager.c b/client/manager.c
index dfb282b..f6628d7 100644
--- a/client/manager.c
+++ b/client/manager.c
@@ -42,6 +42,7 @@
#include "ftp.h"
#include "pbap.h"
#include "sync.h"
+#include "map.h"

#define CLIENT_SERVICE "org.openobex.client"

@@ -567,6 +568,7 @@ static struct target_module {
{ "ftp", ftp_init, ftp_exit },
{ "pbap", pbap_init, pbap_exit },
{ "sync", sync_init, sync_exit },
+ { "map", map_init, map_exit },
{ }
};

diff --git a/client/map.c b/client/map.c
new file mode 100644
index 0000000..bee49c5
--- /dev/null
+++ b/client/map.c
@@ -0,0 +1,135 @@
+/*
+ *
+ * OBEX Client
+ *
+ * Copyright (C) 2011 Bartosz Szatkowski <[email protected]> for Comarch
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <errno.h>
+#include <glib.h>
+#include <gdbus.h>
+
+#include "log.h"
+
+#include "map.h"
+#include "transfer.h"
+#include "session.h"
+#include "driver.h"
+
+#define OBEX_MAS_UUID \
+ "\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 MAS_UUID "00001132-0000-1000-8000-00805f9b34fb"
+
+struct map_data {
+ struct obc_session *session;
+ DBusMessage *msg;
+};
+
+static DBusConnection *conn = NULL;
+
+static GDBusMethodTable map_methods[] = {
+ { }
+};
+
+static void map_free(void *data)
+{
+ struct map_data *map = data;
+
+ obc_session_unref(map->session);
+ g_free(map);
+}
+
+static int map_probe(struct obc_session *session)
+{
+ struct map_data *map;
+ const char *path;
+
+ path = obc_session_get_path(session);
+
+ DBG("%s", path);
+
+ map = g_try_new0(struct map_data, 1);
+ if (!map)
+ return -ENOMEM;
+
+ map->session = obc_session_ref(session);
+
+ if (!g_dbus_register_interface(conn, path, MAP_INTERFACE, map_methods,
+ NULL, NULL, map, map_free)) {
+ map_free(map);
+
+ return -ENOMEM;
+ }
+
+ return 0;
+}
+
+static void map_remove(struct obc_session *session)
+{
+ const char *path = obc_session_get_path(session);
+
+ DBG("%s", path);
+
+ g_dbus_unregister_interface(conn, path, MAP_INTERFACE);
+}
+
+static struct obc_driver map = {
+ .service = "MAP",
+ .uuid = MAS_UUID,
+ .target = OBEX_MAS_UUID,
+ .target_len = OBEX_MAS_UUID_LEN,
+ .probe = map_probe,
+ .remove = map_remove
+};
+
+int map_init(void)
+{
+ int err;
+
+ DBG("");
+
+ conn = dbus_bus_get(DBUS_BUS_SESSION, NULL);
+ if (!conn)
+ return -EIO;
+
+ err = obc_driver_register(&map);
+ if (err < 0) {
+ dbus_connection_unref(conn);
+ conn = NULL;
+ return err;
+ }
+
+ return 0;
+}
+
+void map_exit(void)
+{
+ DBG("");
+
+ dbus_connection_unref(conn);
+ conn = NULL;
+
+ obc_driver_unregister(&map);
+}
diff --git a/client/map.h b/client/map.h
new file mode 100644
index 0000000..86f6b95
--- /dev/null
+++ b/client/map.h
@@ -0,0 +1,24 @@
+/*
+ *
+ * OBEX Client
+ *
+ * Copyright (C) 2011 Bartosz Szatkowski <[email protected]> for Comarch
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+int map_init(void);
+void map_exit(void);
diff --git a/doc/client-api.txt b/doc/client-api.txt
index 3e61cf7..ee8951f 100644
--- a/doc/client-api.txt
+++ b/doc/client-api.txt
@@ -251,6 +251,15 @@ Methods void SetLocation(string location)

Send an entire Phonebook Object store to remote device

+Message Access hierarchy
+=========================
+
+Service org.openobex.client
+Interface org.openobex.MessageAccess
+Object path [variable prefix]/{session0,session1,...}
+
+Methods
+
Transfer hierarchy
==================

--
1.7.4.1