2009-10-20 02:58:19

by Forrest Zhao

[permalink] [raw]
Subject: [PATCH] Implements the OBEX server/SyncML client binding for syncEvolution (http://syncevolution.org/).

In particular this patch supports Server Alerted Sync(SAN).
With server alerted sync, the SyncML server initiates the OBEX link,
so it is the OBEX client. On the other hand the SyncML client waits
for the request from SyncML server, so it is the OBEX server.

OBEX/SyncML binding spec is at http://www.openmobilealliance.net/
Technical/release_program/docs/Common/V1_2_1-20070813-A/OMA-TS-SyncML_OBEXBinding-V1_2-20070221-A.pdf
---
Makefile.am | 2 +-
src/main.c | 16 ++-
src/manager.c | 33 +++++
src/obex.c | 47 +++++--
src/obex.h | 10 ++
src/syncevolution.c | 362 +++++++++++++++++++++++++++++++++++++++++++++++++++
6 files changed, 457 insertions(+), 13 deletions(-)
create mode 100644 src/syncevolution.c

diff --git a/Makefile.am b/Makefile.am
index 63f7478..49817ee 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -31,7 +31,7 @@ src_obexd_SOURCES = $(gdbus_sources) \
src/main.c src/obexd.h src/plugin.h src/plugin.c \
src/logging.h src/logging.c src/btio.h src/btio.c \
src/dbus.h src/manager.c src/obex.h src/obex.c \
- src/opp.c src/ftp.c src/pbap.c \
+ src/opp.c src/ftp.c src/pbap.c src/syncevolution.c \
src/bluetooth.h src/bluetooth.c \
src/phonebook.h src/phonebook.c

diff --git a/src/main.c b/src/main.c
index abd2bcc..36d814f 100644
--- a/src/main.c
+++ b/src/main.c
@@ -53,6 +53,7 @@
#define OPP_CHANNEL 9
#define FTP_CHANNEL 10
#define PBAP_CHANNEL 15
+#define SYNCEVOLUTION_CHANNEL 16
#define PCSUITE_CHANNEL 24

#define DEFAULT_ROOT_PATH "/tmp"
@@ -172,6 +173,7 @@ static gboolean option_ftp = FALSE;
static gboolean option_pbap = FALSE;
static gboolean option_pcsuite = FALSE;
static gboolean option_symlinks = FALSE;
+static gboolean option_syncevolution = FALSE;

static GOptionEntry options[] = {
{ "nodaemon", 'n', G_OPTION_FLAG_REVERSE,
@@ -199,6 +201,8 @@ static GOptionEntry options[] = {
"Enable Phonebook Access server" },
{ "pcsuite", 's', 0, G_OPTION_ARG_NONE, &option_pcsuite,
"Enable PC Suite Services server" },
+ { "syncevolution", 'e', 0, G_OPTION_ARG_NONE, &option_syncevolution,
+ "Enable OBEX server for Syncevolution client" },
{ NULL },
};

@@ -337,9 +341,9 @@ int main(int argc, char *argv[])
log_option |= LOG_PERROR;

if (option_opp == FALSE && option_ftp == FALSE &&
- option_pbap == FALSE) {
+ option_pbap == FALSE && option_syncevolution == FALSE) {
fprintf(stderr, "No server selected (use either "
- "--opp or --ftp or both)\n");
+ "--opp, --ftp, --pbap or --syncevolution)\n");
exit(EXIT_FAILURE);
}

@@ -408,6 +412,14 @@ int main(int argc, char *argv[])
option_capability);
}

+ if (option_syncevolution == TRUE) {
+ services |= OBEX_SYNCEVOLUTION;
+ bluetooth_init(OBEX_SYNCEVOLUTION, "OBEX server for"
+ " Syncevolution client", NULL,
+ SYNCEVOLUTION_CHANNEL, TRUE, FALSE, FALSE,
+ NULL);
+ }
+
if (option_devnode)
devnode_setup();

diff --git a/src/manager.c b/src/manager.c
index 24ed3db..c36ecfd 100644
--- a/src/manager.c
+++ b/src/manager.c
@@ -216,6 +216,35 @@ static const gchar *pcsuite_record =
</attribute> \
</record>";

+static const gchar *syncevolution_record =
+"<?xml version=\"1.0\" encoding=\"UTF-8\" ?> \
+<record> \
+ <attribute id=\"0x0001\"> \
+ <sequence> \
+ <uuid value=\"00000002-0000-1000-8000-0002ee000002\"/> \
+ </sequence> \
+ </attribute> \
+ \
+ <attribute id=\"0x0004\"> \
+ <sequence> \
+ <sequence> \
+ <uuid value=\"0x0100\"/> \
+ </sequence> \
+ <sequence> \
+ <uuid value=\"0x0003\"/> \
+ <uint8 value=\"%u\" name=\"channel\"/> \
+ </sequence> \
+ <sequence> \
+ <uuid value=\"0x0008\"/> \
+ </sequence> \
+ </sequence> \
+ </attribute> \
+ \
+ <attribute id=\"0x0100\"> \
+ <text value=\"%s\" name=\"name\"/> \
+ </attribute> \
+</record>";
+
#define TRANSFER_INTERFACE OPENOBEX_SERVICE ".Transfer"
#define SESSION_INTERFACE OPENOBEX_SERVICE ".Session"

@@ -525,6 +554,10 @@ static gchar *create_xml_record(const char *name,
case OBEX_PCSUITE:
xml = g_markup_printf_escaped(pcsuite_record, channel, name);
break;
+ case OBEX_SYNCEVOLUTION:
+ xml = g_markup_printf_escaped(syncevolution_record, channel,
+ name);
+ break;
default:
xml = NULL;
break;
diff --git a/src/obex.c b/src/obex.c
index 9ec9c5b..61fc5c5 100644
--- a/src/obex.c
+++ b/src/obex.c
@@ -53,6 +53,7 @@
#define DEFAULT_TX_MTU 32767

#define TARGET_SIZE 16
+#define SYNCML_TARGET_SIZE 11

static const guint8 FTP_TARGET[TARGET_SIZE] = {
0xF9, 0xEC, 0x7B, 0xC4, 0x95, 0x3C, 0x11, 0xD2,
@@ -62,6 +63,10 @@ static const guint8 PBAP_TARGET[TARGET_SIZE] = {
0x79, 0x61, 0x35, 0xF0, 0xF0, 0xC5, 0x11, 0xD8,
0x09, 0x66, 0x08, 0x00, 0x20, 0x0C, 0x9A, 0x66 };

+static const guint8 SYNCML_TARGET[SYNCML_TARGET_SIZE] = {
+ 0x53, 0x59, 0x4E, 0x43, 0x4D, 0x4C, 0x2D, 0x53,
+ 0x59, 0x4E, 0x43 };
+
/* Connection ID */
static guint32 cid = 0x0000;

@@ -91,6 +96,11 @@ struct obex_commands pbap = {
.setpath = pbap_setpath,
};

+struct obex_commands synce = {
+ .put = synce_put,
+ .get = synce_get,
+};
+
static void os_reset_session(struct obex_session *os)
{
if (os->fd > 0) {
@@ -119,6 +129,7 @@ static void os_reset_session(struct obex_session *os)
os->offset = 0;
os->size = OBJECT_SIZE_DELETE;
os->finished = 0;
+ os->reply_received = 0;
}

static void os_session_mark_aborted(struct obex_session *os)
@@ -145,6 +156,9 @@ static void obex_session_free(struct obex_session *os)

if (os->target && !memcmp(os->target, PBAP_TARGET, TARGET_SIZE))
pbap_phonebook_context_destroy(os);
+ else if (os->target && !memcmp(os->target, SYNCML_TARGET,
+ SYNCML_TARGET_SIZE))
+ synce_destroy(os);

g_free(os);
}
@@ -202,7 +216,7 @@ static void cmd_connect(struct obex_session *os,
obex_connect_hdr_t *nonhdr;
obex_headerdata_t hd;
uint8_t *buffer;
- guint hlen, newsize;
+ guint hlen, newsize, target_size;
guint16 mtu;
guint8 hi;

@@ -227,8 +241,20 @@ static void cmd_connect(struct obex_session *os,
os->cid = ++cid;

while (OBEX_ObjectGetNextHeader(obex, obj, &hi, &hd, &hlen)) {
- if (hi != OBEX_HDR_TARGET || hlen != TARGET_SIZE)
+ if (hi != OBEX_HDR_TARGET || (hlen != TARGET_SIZE &&
+ hlen != SYNCML_TARGET_SIZE))
continue;
+ target_size = hlen;
+
+ if (memcmp(hd.bs, SYNCML_TARGET, SYNCML_TARGET_SIZE) == 0 &&
+ os->server->services & OBEX_SYNCEVOLUTION) {
+ if (!synce_connect(os))
+ break;
+
+ os->target = SYNCML_TARGET;
+ os->cmds = &synce;
+ break;
+ }

if (memcmp(hd.bs, FTP_TARGET, TARGET_SIZE) == 0 &&
os->server->services &
@@ -270,7 +296,7 @@ static void cmd_connect(struct obex_session *os,
/* Append received UUID in WHO header */
hd.bs = os->target;
OBEX_ObjectAddHeader(obex, obj,
- OBEX_HDR_WHO, hd, TARGET_SIZE,
+ OBEX_HDR_WHO, hd, target_size,
OBEX_FL_FIT_ONE_PACKET);
hd.bq4 = cid;
OBEX_ObjectAddHeader(obex, obj,
@@ -337,7 +363,7 @@ static void cmd_get(struct obex_session *os, obex_t *obex, obex_object_t *obj)
os->name = NULL;
}

- if (os->buf) {
+ if (os->buf && memcmp(os->target, SYNCML_TARGET, SYNCML_TARGET_SIZE)) {
g_free(os->buf);
os->buf = NULL;
}
@@ -599,15 +625,15 @@ static gint obex_read_stream(struct obex_session *os, obex_t *obex,
}

if (os->fd < 0 && size > 0) {
- if (os->buf) {
+ if (os->buf && memcmp(os->target, SYNCML_TARGET,
+ SYNCML_TARGET_SIZE)) {
error("Got more data but there is still a pending buffer");
return -EIO;
}

- os->buf = g_malloc0(os->rx_mtu);
- memcpy(os->buf, buffer, size);
- os->offset = size;
-
+ os->buf = g_realloc(os->buf, os->offset + size);
+ memcpy(os->buf + os->offset, buffer, size);
+ os->offset += size;
debug("Stored %u bytes into temporary buffer", size);

return 0;
@@ -710,7 +736,8 @@ static gboolean check_put(obex_t *obex, obex_object_t *obj)

OBEX_ObjectReParseHeaders(obex, obj);

- if (!os->name) {
+ if (!os->name && memcmp(os->target, SYNCML_TARGET,
+ SYNCML_TARGET_SIZE)) {
OBEX_ObjectSetRsp(obj, OBEX_RSP_BAD_REQUEST,
OBEX_RSP_BAD_REQUEST);
g_free(os->type);
diff --git a/src/obex.h b/src/obex.h
index 94a273e..b9af4ed 100644
--- a/src/obex.h
+++ b/src/obex.h
@@ -27,6 +27,7 @@
#include <config.h>
#endif

+#include <dbus/dbus.h>
#include <glib.h>

#include "phonebook.h"
@@ -36,6 +37,7 @@
#define OBEX_BIP (1 << 3)
#define OBEX_PBAP (1 << 4)
#define OBEX_PCSUITE (1 << 5)
+#define OBEX_SYNCEVOLUTION (1 << 6)

#define OBJECT_SIZE_UNKNOWN -1
#define OBJECT_SIZE_DELETE -2
@@ -86,6 +88,9 @@ struct obex_session {
obex_t *obex;
struct phonebook_context *pbctx;
gboolean finished;
+ DBusConnection *dbus_conn;
+ gchar *conn_obj;
+ gboolean reply_received;
};

gint obex_session_start(GIOChannel *io, struct server *server);
@@ -106,6 +111,11 @@ gboolean pbap_phonebook_context_create(struct obex_session *session);
void pbap_phonebook_context_destroy(struct obex_session *session);
struct obex_session *pbap_get_session(struct phonebook_context *context);

+gboolean synce_connect(struct obex_session *os);
+void synce_put(obex_t *obex, obex_object_t *obj);
+void synce_get(obex_t *obex, obex_object_t *obj);
+void synce_destroy(struct obex_session *os);
+
gint os_prepare_get(struct obex_session *os, gchar *file, guint32 *size);
gint os_prepare_put(struct obex_session *os);

diff --git a/src/syncevolution.c b/src/syncevolution.c
new file mode 100644
index 0000000..c65fce9
--- /dev/null
+++ b/src/syncevolution.c
@@ -0,0 +1,362 @@
+/*
+ *
+ * OBEX Server
+ *
+ * Copyright (C) 2007-2008 Intel Corporation
+ * Copyright (C) 2007-2009 Marcel Holtmann <[email protected]>
+ *
+ *
+ * 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 <string.h>
+#include <stdio.h>
+#include <glib.h>
+
+#include <bluetooth/bluetooth.h>
+
+#include <openobex/obex.h>
+#include <openobex/obex_const.h>
+
+#include "logging.h"
+#include "obex.h"
+#include "obexd.h"
+#include "dbus.h"
+#include "btio.h"
+
+#define SYNCE_BUS_NAME "org.syncevolution"
+#define SYNCE_PATH "/org/syncevolution/Server"
+#define SYNCE_SERVER_INTERFACE "org.syncevolution.Server"
+#define SYNCE_CONN_INTERFACE "org.syncevolution.Connection"
+
+static char match_string[256];
+
+struct cb_data {
+ struct obex_session *os;
+ obex_object_t *obj;
+} process_cb_data;
+
+static GSList *os_list = NULL;
+
+static void dbus_message_iter_append_dict_entry(DBusMessageIter *dict,
+ const char *key, int type, void *val)
+{
+ DBusMessageIter entry;
+
+ dbus_message_iter_open_container(dict, DBUS_TYPE_DICT_ENTRY,
+ NULL, &entry);
+ dbus_message_iter_append_basic(&entry, DBUS_TYPE_STRING, &key);
+ dbus_message_iter_append_basic(&entry, DBUS_TYPE_STRING, &val);
+ dbus_message_iter_close_container(dict, &entry);
+}
+
+static void handle_connection_reply_signal(DBusMessage *msg,
+ const char *obj_path, void *data)
+{
+ struct obex_session *os = data;
+ DBusMessageIter iter, array_iter;
+ gchar *value;
+ gint length = 0;
+
+ if (strcmp(os->conn_obj, obj_path))
+ return;
+
+ dbus_message_iter_init(msg, &iter);
+
+ if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY) {
+ error("Unexpected signature in Reply signal");
+ }
+
+ dbus_message_iter_recurse(&iter, &array_iter);
+ dbus_message_iter_get_fixed_array(&array_iter, &value, &length);
+
+ if (length) {
+ os->buf = g_try_malloc(length);
+ memcpy(os->buf, value, length);
+ os->size = length;
+ os->reply_received = TRUE;
+ os->finished = TRUE;
+ OBEX_ResumeRequest(os->obex);
+ }
+}
+
+static void handle_connection_abort_signal(DBusMessage *msg,
+ const char *obj_path, void *data)
+{
+ struct obex_session *os = data;
+
+ OBEX_TransportDisconnect(os->obex);
+}
+
+static DBusHandlerResult signal_filter(DBusConnection *conn,
+ DBusMessage *msg, void *data)
+{
+ const char *path = dbus_message_get_path(msg);
+ struct obex_session *os = NULL;
+ GSList *l;
+
+ if (dbus_message_get_type(msg) != DBUS_MESSAGE_TYPE_SIGNAL)
+ return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+
+ for (l = os_list; l != NULL; l = l->next) {
+ struct obex_session *tmp_os = l->data;
+ if (!strcmp(tmp_os->conn_obj, path)) {
+ os = tmp_os;
+ break;
+ }
+ }
+ if (!os)
+ return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+
+ if (dbus_message_is_signal(msg, SYNCE_CONN_INTERFACE, "Reply")) {
+ debug("Reply signal is received.");
+ handle_connection_reply_signal(msg, path, os);
+ } else if (dbus_message_is_signal(msg, SYNCE_CONN_INTERFACE, "Abort")) {
+ debug("Abort signal is received.");
+ handle_connection_abort_signal(msg, path, os);
+ }
+
+ return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+}
+
+static void connect_cb(DBusPendingCall *call, void *user_data)
+{
+ static gboolean signal_filter_added = FALSE;
+ struct obex_session *os = user_data;
+ DBusConnection *conn = os->dbus_conn;
+ DBusMessage *reply;
+ gchar *path;
+
+ reply = dbus_pending_call_steal_reply(call);
+
+ dbus_message_get_args(reply, NULL, DBUS_TYPE_OBJECT_PATH, &path,
+ DBUS_TYPE_INVALID);
+ info("Got conn object %s from syncevolution", path);
+ os->conn_obj = g_strdup(path);
+
+ /* add signal filter */
+ if (!signal_filter_added) {
+ if (!dbus_connection_add_filter(conn, signal_filter,
+ os, NULL)) {
+ error("Can't add signal filter");
+ dbus_message_unref(reply);
+ return;
+ }
+ signal_filter_added = TRUE;
+ }
+ os_list = g_slist_append(os_list, os);
+ snprintf(match_string, sizeof(match_string), "type=signal,interface=%s,"
+ "path=%s", SYNCE_CONN_INTERFACE, os->conn_obj);
+ dbus_bus_add_match(conn, match_string, NULL);
+ dbus_connection_flush(conn);
+
+ dbus_message_unref(reply);
+}
+
+static void process_cb(DBusPendingCall *call, void *user_data)
+{
+ DBusMessage *reply;
+ DBusError derr;
+
+ info("At the begin of process_cb().");
+ reply = dbus_pending_call_steal_reply(call);
+ dbus_error_init(&derr);
+ if (dbus_set_error_from_message(&derr, reply)) {
+ error("process_cb(): syncevolution replied with an error:"
+ " %s, %s", derr.name, derr.message);
+ dbus_error_free(&derr);
+ }
+ dbus_message_unref(reply);
+}
+
+gboolean synce_connect(struct obex_session *os)
+{
+ DBusConnection *conn = NULL;
+ GError *err = NULL;
+ char address[18];
+ guint8 channel;
+ DBusMessage *msg;
+ DBusMessageIter iter, dict;
+ gchar id[36];
+ gchar transport[36];
+ gchar transport_description[24];
+ gboolean authenticate = FALSE;
+ char *session = "";
+ DBusPendingCall *call;
+
+ conn = dbus_bus_get(DBUS_BUS_SESSION, NULL);
+ if (conn == NULL)
+ return FALSE;
+
+ bt_io_get(os->io, BT_IO_RFCOMM, &err,
+ BT_IO_OPT_DEST, address,
+ BT_IO_OPT_CHANNEL, &channel,
+ BT_IO_OPT_INVALID);
+
+ msg = dbus_message_new_method_call(SYNCE_BUS_NAME, SYNCE_PATH,
+ SYNCE_SERVER_INTERFACE, "Connect");
+ dbus_message_iter_init_append(msg, &iter);
+ dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY,
+ DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
+ DBUS_TYPE_STRING_AS_STRING DBUS_TYPE_STRING_AS_STRING
+ DBUS_DICT_ENTRY_END_CHAR_AS_STRING, &dict);
+
+ snprintf(id, sizeof(id), "%s+%u", address, channel);
+ dbus_message_iter_append_dict_entry(&dict, "id", DBUS_TYPE_STRING, id);
+
+ snprintf(transport, sizeof(transport), "%s.obexd",
+ OPENOBEX_SERVICE);
+ dbus_message_iter_append_dict_entry(&dict, "transport",
+ DBUS_TYPE_STRING, transport);
+
+ snprintf(transport_description, sizeof(transport_description),
+ "version %s", VERSION);
+ dbus_message_iter_append_dict_entry(&dict, "transport_description",
+ DBUS_TYPE_STRING, transport_description);
+ dbus_message_iter_close_container(&iter, &dict);
+ dbus_message_append_args(msg, DBUS_TYPE_BOOLEAN, &authenticate,
+ DBUS_TYPE_STRING, &session, DBUS_TYPE_INVALID);
+
+ if (!dbus_connection_send_with_reply(conn, msg, &call, -1)) {
+ error("D-Bus call to %s failed.", SYNCE_SERVER_INTERFACE);
+ dbus_message_unref(msg);
+ return FALSE;
+ }
+
+ dbus_pending_call_set_notify(call, connect_cb, os, NULL);
+
+ os->dbus_conn = conn;
+
+ dbus_pending_call_unref(call);
+ dbus_message_unref(msg);
+ return TRUE;
+}
+
+void synce_put(obex_t *obex, obex_object_t *obj)
+{
+ struct obex_session *os;
+ DBusMessage *msg;
+ DBusMessageIter iter, array_iter;
+ DBusPendingCall *call;
+
+ os = OBEX_GetUserData(obex);
+ if (os == NULL)
+ return;
+
+ if (!os->conn_obj) {
+ OBEX_ObjectSetRsp(obj, OBEX_RSP_SERVICE_UNAVAILABLE,
+ OBEX_RSP_SERVICE_UNAVAILABLE);
+ return;
+ }
+
+ msg = dbus_message_new_method_call(SYNCE_BUS_NAME, os->conn_obj,
+ SYNCE_CONN_INTERFACE, "Process");
+ dbus_message_iter_init_append(msg, &iter);
+ dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY,
+ DBUS_TYPE_BYTE_AS_STRING, &array_iter);
+ dbus_message_iter_append_fixed_array(&array_iter, DBUS_TYPE_BYTE,
+ &os->buf, os->offset);
+ dbus_message_iter_close_container(&iter, &array_iter);
+
+ dbus_message_append_args(msg, DBUS_TYPE_STRING, &os->type,
+ DBUS_TYPE_INVALID);
+
+ if (!dbus_connection_send_with_reply(os->dbus_conn, msg, &call, -1)) {
+ error("D-Bus call to %s failed.", SYNCE_CONN_INTERFACE);
+ dbus_message_unref(msg);
+ OBEX_ObjectSetRsp(obj, OBEX_RSP_FORBIDDEN, OBEX_RSP_FORBIDDEN);
+ return;
+ }
+
+ dbus_pending_call_set_notify(call, process_cb, os, NULL);
+
+ dbus_message_unref(msg);
+ dbus_pending_call_unref(call);
+
+ OBEX_ObjectSetRsp(obj, OBEX_RSP_CONTINUE, OBEX_RSP_SUCCESS);
+ return;
+}
+
+void synce_get(obex_t *obex, obex_object_t *obj)
+{
+ obex_headerdata_t hd;
+ struct obex_session *os;
+
+ os = OBEX_GetUserData(obex);
+ if (os == NULL)
+ return;
+
+ if (!os->reply_received) {
+ debug("in synce_get() OBEX_SuspendRequest() is called");
+ OBEX_SuspendRequest(obex, obj);
+ }
+
+ hd.bs = NULL;
+ OBEX_ObjectAddHeader(obex, obj, OBEX_HDR_BODY, hd, 0,
+ OBEX_FL_STREAM_START);
+
+ OBEX_ObjectSetRsp(obj, OBEX_RSP_CONTINUE, OBEX_RSP_SUCCESS);
+ return;
+}
+
+static void close_cb(DBusPendingCall *call, void *user_data)
+{
+ DBusMessage *reply;
+ DBusError derr;
+
+ reply = dbus_pending_call_steal_reply(call);
+ dbus_error_init(&derr);
+ if (dbus_set_error_from_message(&derr, reply)) {
+ error("close_cb(): syncevolution replied with an error:"
+ " %s, %s", derr.name, derr.message);
+ dbus_error_free(&derr);
+ }
+
+ dbus_message_unref(reply);
+}
+
+void synce_destroy(struct obex_session *os)
+{
+ DBusMessage *msg;
+ gboolean normal = TRUE;
+ gchar *error = "none";
+ DBusPendingCall *call;
+
+ debug("At the begin of synce_destroy().");
+ if (os->conn_obj) {
+ msg = dbus_message_new_method_call(SYNCE_BUS_NAME, os->conn_obj,
+ SYNCE_CONN_INTERFACE, "Close");
+ dbus_message_append_args(msg, DBUS_TYPE_BOOLEAN, &normal,
+ DBUS_TYPE_STRING, &error, DBUS_TYPE_INVALID);
+ dbus_connection_send_with_reply(os->dbus_conn, msg, &call, -1);
+ dbus_pending_call_set_notify(call, close_cb, NULL, NULL);
+ dbus_message_unref(msg);
+ dbus_pending_call_unref(call);
+
+ snprintf(match_string, sizeof(match_string),
+ "type=signal,interface=%s,path=%s",
+ SYNCE_CONN_INTERFACE, os->conn_obj);
+ dbus_bus_remove_match(os->dbus_conn, match_string, NULL);
+ g_free(os->conn_obj);
+ os->conn_obj = NULL;
+ }
+ dbus_connection_unref(os->dbus_conn);
+ os_list = g_slist_remove(os_list, os);
+}
--
1.5.4.5



2009-10-21 01:26:00

by Zhao Forrest

[permalink] [raw]
Subject: Re: [PATCH] Implements the OBEX server/SyncML client binding for syncEvolution (http://syncevolution.org/).

>>>
>>>> + ? ? ? if (option_syncevolution == TRUE) {
>>>> + ? ? ? ? ? ? ? services |= OBEX_SYNCEVOLUTION;
>>>> + ? ? ? ? ? ? ? bluetooth_init(OBEX_SYNCEVOLUTION, "OBEX server for"
>>>> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? " Syncevolution client", NULL,
>>>> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? SYNCEVOLUTION_CHANNEL, TRUE, FALSE, FALSE,
>>>> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? NULL);
>>>> + ? ? ? }
>>>> +
>>>
>>> Which string is going to appear in the service description (the SDP
>>> part)? This one here? Mentioning "SyncML" would be useful. So I suggest
>>> "OBEX server for SyncML, using SyncEvolution". Leave out the
>>> "SyncEvolution client", because the term client is a) overloaded
>>> (SyncML/OBEX/D-Bus) and b) SyncEvolution could be both client and server
>>> in this context (SAN => SyncML client, SyncML message => SyncML server).
>>>
>> OK. Will expose service name as "OBEX server for SyncML, using SyncEvolution"
>> since ProviderName attribute is not supported by obexd now.
>
> If it's consensus the right way would be exposing SyncEvolution
> through ProviderName, please add a comment to the code telling that,
> so someone remember to fix it by the time obexd supports it.
>
Thank you for reminding. A FIXME comment will be put here.

2009-10-20 13:18:33

by João Paulo Rechi Vita

[permalink] [raw]
Subject: Re: [PATCH] Implements the OBEX server/SyncML client binding for syncEvolution (http://syncevolution.org/).

On Tue, Oct 20, 2009 at 7:05 AM, Zhao Forrest <[email protected]> wrote:
>>> --- a/src/main.c
>>> +++ b/src/main.c
>>> @@ -53,6 +53,7 @@
>>>  #define OPP_CHANNEL    9
>>>  #define FTP_CHANNEL    10
>>>  #define PBAP_CHANNEL   15
>>> +#define SYNCEVOLUTION_CHANNEL  16
>>>  #define PCSUITE_CHANNEL        24
>>
>> Do we want to call this "SYNCEVOLUTION" or "SYNCML"? Both has pros and
>> cons. Treating it as generic SyncML capability hides the detail that
>> it's currently based on SyncEvolution. Exposing SyncEvolution itself
>> would allow to activate multiple different SyncML implementations at the
>> same time.
>>
>> My preference would be to keep it as is, but I wanted to ask anyway.
> I have the same idea as you do, and prefer to keep it as "SYNCEVOLUTION".
>
>>
>> Off topic: what is the "PC Suite Services server"?
>>
> It's Nokia OBEX PC Suite Services. Johan may know more details about it.
>
>>> +       { "syncevolution", 'e', 0, G_OPTION_ARG_NONE, &option_syncevolution,
>>> +                               "Enable OBEX server for Syncevolution client" },
>>
>> Mind the spelling: "syncevolution" (lower case) is the command line
>> tool, "SyncEvolution" (camel case) the project. "Syncevolution" is a
>> typo ;-)
>>
> Will fix it ASAP.
>
>> Is there documentation that should be updated together with introducing
>> the new feature?
> The patch does not introduce any new d-bus API to obexd, so no doc need to
> be updated.
>
>>
>>> +       if (option_syncevolution == TRUE) {
>>> +               services |= OBEX_SYNCEVOLUTION;
>>> +               bluetooth_init(OBEX_SYNCEVOLUTION, "OBEX server for"
>>> +                               " Syncevolution client", NULL,
>>> +                               SYNCEVOLUTION_CHANNEL, TRUE, FALSE, FALSE,
>>> +                               NULL);
>>> +       }
>>> +
>>
>> Which string is going to appear in the service description (the SDP
>> part)? This one here? Mentioning "SyncML" would be useful. So I suggest
>> "OBEX server for SyncML, using SyncEvolution". Leave out the
>> "SyncEvolution client", because the term client is a) overloaded
>> (SyncML/OBEX/D-Bus) and b) SyncEvolution could be both client and server
>> in this context (SAN => SyncML client, SyncML message => SyncML server).
>>
> OK. Will expose service name as "OBEX server for SyncML, using SyncEvolution"
> since ProviderName attribute is not supported by obexd now.

If it's consensus the right way would be exposing SyncEvolution
through ProviderName, please add a comment to the code telling that,
so someone remember to fix it by the time obexd supports it.

--
João Paulo Rechi Vita
MSc Computer Science Student
Computer Engineer
IC / Unicamp
http://jprvita.wordpress.com/

2009-10-20 09:05:31

by Zhao Forrest

[permalink] [raw]
Subject: Re: [PATCH] Implements the OBEX server/SyncML client binding for syncEvolution (http://syncevolution.org/).

>> --- a/src/main.c
>> +++ b/src/main.c
>> @@ -53,6 +53,7 @@
>> ?#define OPP_CHANNEL ? ?9
>> ?#define FTP_CHANNEL ? ?10
>> ?#define PBAP_CHANNEL ? 15
>> +#define SYNCEVOLUTION_CHANNEL ?16
>> ?#define PCSUITE_CHANNEL ? ? ? ?24
>
> Do we want to call this "SYNCEVOLUTION" or "SYNCML"? Both has pros and
> cons. Treating it as generic SyncML capability hides the detail that
> it's currently based on SyncEvolution. Exposing SyncEvolution itself
> would allow to activate multiple different SyncML implementations at the
> same time.
>
> My preference would be to keep it as is, but I wanted to ask anyway.
I have the same idea as you do, and prefer to keep it as "SYNCEVOLUTION".

>
> Off topic: what is the "PC Suite Services server"?
>
It's Nokia OBEX PC Suite Services. Johan may know more details about it.

>> + ? ? ? { "syncevolution", 'e', 0, G_OPTION_ARG_NONE, &option_syncevolution,
>> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? "Enable OBEX server for Syncevolution client" },
>
> Mind the spelling: "syncevolution" (lower case) is the command line
> tool, "SyncEvolution" (camel case) the project. "Syncevolution" is a
> typo ;-)
>
Will fix it ASAP.

> Is there documentation that should be updated together with introducing
> the new feature?
The patch does not introduce any new d-bus API to obexd, so no doc need to
be updated.

>
>> + ? ? ? if (option_syncevolution == TRUE) {
>> + ? ? ? ? ? ? ? services |= OBEX_SYNCEVOLUTION;
>> + ? ? ? ? ? ? ? bluetooth_init(OBEX_SYNCEVOLUTION, "OBEX server for"
>> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? " Syncevolution client", NULL,
>> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? SYNCEVOLUTION_CHANNEL, TRUE, FALSE, FALSE,
>> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? NULL);
>> + ? ? ? }
>> +
>
> Which string is going to appear in the service description (the SDP
> part)? This one here? Mentioning "SyncML" would be useful. So I suggest
> "OBEX server for SyncML, using SyncEvolution". Leave out the
> "SyncEvolution client", because the term client is a) overloaded
> (SyncML/OBEX/D-Bus) and b) SyncEvolution could be both client and server
> in this context (SAN => SyncML client, SyncML message => SyncML server).
>
OK. Will expose service name as "OBEX server for SyncML, using SyncEvolution"
since ProviderName attribute is not supported by obexd now.

2009-10-20 07:39:10

by Iain Hibbert

[permalink] [raw]
Subject: Re: [PATCH] Implements the OBEX server/SyncML client binding for syncEvolution (http://syncevolution.org/).

On Tue, 20 Oct 2009, Patrick Ohly wrote:

> > + if (option_syncevolution == TRUE) {
> > + services |= OBEX_SYNCEVOLUTION;
> > + bluetooth_init(OBEX_SYNCEVOLUTION, "OBEX server for"
> > + " Syncevolution client", NULL,
> > + SYNCEVOLUTION_CHANNEL, TRUE, FALSE, FALSE,
> > + NULL);
> > + }
> > +
>
> Which string is going to appear in the service description (the SDP
> part)? This one here? Mentioning "SyncML" would be useful. So I suggest
> "OBEX server for SyncML, using SyncEvolution". Leave out the
> "SyncEvolution client", because the term client is a) overloaded
> (SyncML/OBEX/D-Bus) and b) SyncEvolution could be both client and server
> in this context (SAN => SyncML client, SyncML message => SyncML server).

see SDP specification, you can provide ServiceName ("SyncML") and
ProviderName ("SyncEvolution") attributes in the service record..

iain



2009-10-20 07:18:39

by Patrick Ohly

[permalink] [raw]
Subject: Re: [PATCH] Implements the OBEX server/SyncML client binding for syncEvolution (http://syncevolution.org/).

Hello Forrest!

I hope those more familiar with OBEX will comment on those aspects. I
have some questions pertaining to SyncEvolution and the usage of this
new feature.

On Tue, 2009-10-20 at 03:58 +0100, Zhao, Forrest wrote:
[...]
> diff --git a/src/main.c b/src/main.c
> index abd2bcc..36d814f 100644
> --- a/src/main.c
> +++ b/src/main.c
> @@ -53,6 +53,7 @@
> #define OPP_CHANNEL 9
> #define FTP_CHANNEL 10
> #define PBAP_CHANNEL 15
> +#define SYNCEVOLUTION_CHANNEL 16
> #define PCSUITE_CHANNEL 24

Do we want to call this "SYNCEVOLUTION" or "SYNCML"? Both has pros and
cons. Treating it as generic SyncML capability hides the detail that
it's currently based on SyncEvolution. Exposing SyncEvolution itself
would allow to activate multiple different SyncML implementations at the
same time.

My preference would be to keep it as is, but I wanted to ask anyway.

Off topic: what is the "PC Suite Services server"?

> + { "syncevolution", 'e', 0, G_OPTION_ARG_NONE, &option_syncevolution,
> + "Enable OBEX server for Syncevolution client" },

Mind the spelling: "syncevolution" (lower case) is the command line
tool, "SyncEvolution" (camel case) the project. "Syncevolution" is a
typo ;-)

Is there documentation that should be updated together with introducing
the new feature?

> + if (option_syncevolution == TRUE) {
> + services |= OBEX_SYNCEVOLUTION;
> + bluetooth_init(OBEX_SYNCEVOLUTION, "OBEX server for"
> + " Syncevolution client", NULL,
> + SYNCEVOLUTION_CHANNEL, TRUE, FALSE, FALSE,
> + NULL);
> + }
> +

Which string is going to appear in the service description (the SDP
part)? This one here? Mentioning "SyncML" would be useful. So I suggest
"OBEX server for SyncML, using SyncEvolution". Leave out the
"SyncEvolution client", because the term client is a) overloaded
(SyncML/OBEX/D-Bus) and b) SyncEvolution could be both client and server
in this context (SAN => SyncML client, SyncML message => SyncML server).

--
Best Regards, Patrick Ohly

The content of this message is my personal opinion only and although
I am an employee of Intel, the statements I make here in no way
represent Intel's position on the issue, nor am I authorized to speak
on behalf of Intel on this matter.