Return-Path: MIME-Version: 1.0 In-Reply-To: <1256006947-19065-1-git-send-email-forrest.zhao@intel.com> References: <1256006947-19065-1-git-send-email-forrest.zhao@intel.com> Date: Tue, 20 Oct 2009 11:05:24 +0800 Message-ID: Subject: Re: [PATCH] Implements the OBEX server/SyncML client binding for From: Zhao Forrest To: Forrest Zhao Cc: linux-bluetooth@vger.kernel.org, patrick.ohly@intel.com Content-Type: text/plain; charset=ISO-8859-1 Sender: linux-bluetooth-owner@vger.kernel.org List-ID: There're some issues with email subject, please ignore this email. Will send out the patch later. On Tue, Oct 20, 2009 at 10:49 AM, Forrest Zhao wrote: > 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 = > ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? \ > ?"; > > +static const gchar *syncevolution_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 > ?#endif > > +#include > ?#include > > ?#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 > + * > + * > + * ?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 > +#endif > + > +#include > +#include > +#include > + > +#include > + > +#include > +#include > + > +#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 > >