Diff between 03097edb9486f1608eac8b63bca0e3716894804f and 9d5bf74cd95d02937a53b0c8a25e8b055a820f61

Changed Files

File Additions Deletions Status
obexd/plugins/ebook.c +29 -17 modified
obexd/src/obex.c +10 -1 modified
obexd/src/obex.h +8 -0 modified
obexd/src/pbap.c +57 -34 modified
obexd/src/phonebook.c +28 -9 modified
obexd/src/phonebook.h +5 -3 modified

Full Patch

diff --git a/obexd/plugins/ebook.c b/obexd/plugins/ebook.c
index 7c78a57..abb16cb 100644
--- a/obexd/plugins/ebook.c
+++ b/obexd/plugins/ebook.c
@@ -45,23 +45,14 @@ static void ebook_destroy(struct phonebook_context *context)
 	DBG("context %p", context);
 }
 
-static int ebook_pullphonebook(struct phonebook_context *context)
+static void ebooklist_cb(EBook *book, EBookStatus status, GList *list,
+				gpointer user_data)
 {
-	EBook *book;
-	EBookQuery *query;
-	GList *contacts = NULL;
+	struct phonebook_context *context = user_data;
+	GList *contacts = list;
 	GString *pb;
 	gchar *result;
-
-	DBG("context %p", context);
-
-	book = e_book_new_default_addressbook(NULL);
-
-	e_book_open(book, FALSE, NULL);
-
-	query = e_book_query_any_field_contains("");
-
-	e_book_get_contacts(book, query, &contacts, NULL);
+	gint32 str_len;
 
 	pb = g_string_new(NULL);
 
@@ -76,12 +67,33 @@ static int ebook_pullphonebook(struct phonebook_context *context)
 	}
 
 	result = g_string_free(pb, FALSE);
-	phonebook_return(context, result, strlen(result));
-	g_free(result);
+	str_len = strlen(result);
+	phonebook_return(context, result, str_len);
 
-	e_book_query_unref(query);
+	if (str_len != 0)
+		phonebook_return(context, NULL, 0);
 
+	g_free(result);
+	phonebook_unref(context);
 	g_object_unref(book);
+}
+
+static int ebook_pullphonebook(struct phonebook_context *context)
+{
+	EBook *book;
+	EBookQuery *query;
+
+	DBG("context %p", context);
+
+	phonebook_ref(context);
+
+	book = e_book_new_default_addressbook(NULL);
+
+	e_book_open(book, FALSE, NULL);
+
+	query = e_book_query_any_field_contains("");
+
+	e_book_async_get_contacts(book, query, ebooklist_cb, context);
 
 	return 0;
 }
diff --git a/obexd/src/obex.c b/obexd/src/obex.c
index 84409ff..a0e5e75 100644
--- a/obexd/src/obex.c
+++ b/obexd/src/obex.c
@@ -134,6 +134,9 @@ static void obex_session_free(struct obex_session *os)
 	if (os->current_folder)
 		g_free(os->current_folder);
 
+	if (!memcmp(os->target, PBAP_TARGET, TARGET_SIZE))
+		pbap_phonebook_context_destroy(os);
+
 	g_free(os);
 }
 
@@ -230,6 +233,7 @@ static void cmd_connect(struct obex_session *os,
 				os->server->services & OBEX_PBAP) {
 			os->target = PBAP_TARGET;
 			os->cmds = &pbap;
+			pbap_phonebook_context_create(os);
 			break;
 		}
 
@@ -466,7 +470,7 @@ static gint obex_write_stream(struct obex_session *os,
 		return -EPERM;
 
 	if (os->fd < 0) {
-		if (os->buf == NULL)
+		if (os->buf == NULL && os->finished == FALSE)
 			return -EIO;
 
 		len = MIN(os->size - os->offset, os->tx_mtu);
@@ -502,6 +506,10 @@ add_header:
 	OBEX_ObjectAddHeader(obex, obj, OBEX_HDR_BODY, hd, len,
 				OBEX_FL_STREAM_DATA);
 
+	if (!memcmp(os->target, PBAP_TARGET, TARGET_SIZE))
+		if (os->offset == os->size && os->finished == FALSE)
+			OBEX_SuspendRequest(obex, obj);
+
 	return len;
 }
 
@@ -982,6 +990,7 @@ gint obex_session_start(gint fd, struct server *server)
 	}
 
 	OBEX_SetUserData(obex, os);
+	os->handle = obex;
 
 	OBEX_SetTransportMTU(obex, os->rx_mtu, os->tx_mtu);
 
diff --git a/obexd/src/obex.h b/obexd/src/obex.h
index d903095..188e0a8 100644
--- a/obexd/src/obex.h
+++ b/obexd/src/obex.h
@@ -29,6 +29,8 @@
 
 #include <glib.h>
 
+#include "phonebook.h"
+
 #define OBEX_OPP	(1 << 0)
 #define OBEX_FTP	(1 << 2)
 #define OBEX_BIP	(1 << 3)
@@ -79,6 +81,9 @@ struct obex_session {
 	struct obex_commands *cmds;
 	struct server *server;
 	gboolean	checked;
+	obex_t		*handle;
+	struct phonebook_context *pbctx;
+	gboolean	finished;
 };
 
 gint obex_session_start(gint fd, struct server *server);
@@ -94,6 +99,9 @@ gint ftp_chkput(obex_t *obex, obex_object_t *obj);
 void ftp_setpath(obex_t *obex, obex_object_t *obj);
 
 void pbap_get(obex_t *obex, obex_object_t *obj);
+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 os_prepare_get(struct obex_session *os, gchar *file, guint32 *size);
 gint os_prepare_put(struct obex_session *os);
diff --git a/obexd/src/pbap.c b/obexd/src/pbap.c
index 9c2126a..ac288f0 100644
--- a/obexd/src/pbap.c
+++ b/obexd/src/pbap.c
@@ -30,60 +30,40 @@
 
 #include <glib.h>
 
-#include "phonebook.h"
 #include "logging.h"
 #include "obex.h"
 
 #define PHONEBOOK_TYPE "x-bt/phonebook"
 
-static void test_phonebook(void)
-{
-	struct phonebook_context *context;
-	struct phonebook_driver *driver;
-
-	driver = phonebook_get_driver(NULL);
-	if (driver == NULL)
-		return;
-
-	context = phonebook_create(driver);
-	if (context == NULL)
-		return;
-
-	phonebook_pullphonebook(context);
-
-	phonebook_unref(context);
-}
+static GSList *session_list = NULL;
 
 void pbap_get(obex_t *obex, obex_object_t *obj)
 {
-	struct obex_session *os;
+	struct obex_session *session;
 	obex_headerdata_t hv;
-	guint32 size;
+	int ret;
 
-	os = OBEX_GetUserData(obex);
-	if (os == NULL)
+	session = OBEX_GetUserData(obex);
+	if (session == NULL)
 		return;
 
-	if (os->type == NULL)
+	if (session->type == NULL)
 		goto fail;
 
-	if (g_str_equal(os->type, PHONEBOOK_TYPE) == FALSE)
+	if (g_str_equal(session->type, PHONEBOOK_TYPE) == FALSE)
 		goto fail;
 
-	test_phonebook();
-	size = 0;
+	ret = phonebook_pullphonebook(session->pbctx);
 
-	hv.bq4 = size;
-	OBEX_ObjectAddHeader(obex, obj, OBEX_HDR_LENGTH, hv, 4, 0);
+	if (!ret)
+		OBEX_SuspendRequest(obex, obj);
+	else
+		goto fail;
 
 	/* Add body header */
 	hv.bs = NULL;
-	if (size == 0)
-		OBEX_ObjectAddHeader(obex, obj, OBEX_HDR_BODY,
-						hv, 0, OBEX_FL_FIT_ONE_PACKET);
-	else
-		OBEX_ObjectAddHeader(obex, obj, OBEX_HDR_BODY,
-						hv, 0, OBEX_FL_STREAM_START);
+	OBEX_ObjectAddHeader(obex, obj, OBEX_HDR_BODY,
+					hv, 0, OBEX_FL_STREAM_START);
 
 	OBEX_ObjectSetRsp(obj, OBEX_RSP_CONTINUE, OBEX_RSP_SUCCESS);
 
@@ -92,3 +72,46 @@ void pbap_get(obex_t *obex, obex_object_t *obj)
 fail:
 	OBEX_ObjectSetRsp(obj, OBEX_RSP_FORBIDDEN, OBEX_RSP_FORBIDDEN);
 }
+
+gboolean pbap_phonebook_context_create(struct obex_session *session)
+{
+	struct phonebook_context *context;
+	struct phonebook_driver *driver;
+
+	driver = phonebook_get_driver(NULL);
+	if (driver == NULL)
+		return FALSE;
+
+	context = phonebook_create(driver);
+	if (context == NULL)
+		return FALSE;
+
+	session->pbctx = context;
+
+	session_list = g_slist_append(session_list, session);
+
+	return TRUE;
+}
+
+void pbap_phonebook_context_destroy(struct obex_session *session)
+{
+	struct phonebook_context *context;
+
+	context = session->pbctx;
+	phonebook_unref(context);
+
+	session_list = g_slist_remove(session_list, session);
+}
+
+struct obex_session *pbap_get_session(struct phonebook_context *context)
+{
+	GSList *current;
+
+	for (current = session_list; current != NULL; current = current->next) {
+		struct obex_session *session = current->data;
+		if (session->pbctx == context)
+			return session;
+	}
+
+	return NULL;
+}
diff --git a/obexd/src/phonebook.c b/obexd/src/phonebook.c
index 2dab918..4b760b2 100644
--- a/obexd/src/phonebook.c
+++ b/obexd/src/phonebook.c
@@ -25,10 +25,15 @@
 #include <config.h>
 #endif
 
+#include <string.h>
 #include <glib.h>
+#include <stdlib.h>
+
+#include <openobex/obex.h>
+#include <openobex/obex_const.h>
 
 #include "logging.h"
-#include "phonebook.h"
+#include "obex.h"
 
 static GSList *driver_list = NULL;
 
@@ -96,23 +101,37 @@ void phonebook_unref(struct phonebook_context *context)
 	}
 }
 
-void phonebook_pullphonebook(struct phonebook_context *context)
+int phonebook_pullphonebook(struct phonebook_context *context)
 {
-	DBG("context %p", context);
-
-	if (context->driver->pullphonebook) {
-		phonebook_ref(context);
+	if (!context->driver->pullphonebook)
+		return -1;
 
-		context->driver->pullphonebook(context);
-	}
+	return context->driver->pullphonebook(context);
 }
 
+/* if buf is NULL or size is 0, this indicate that no more result will
+ * be returned by PBAP plugin
+ * */
 void phonebook_return(struct phonebook_context *context,
 						char *buf, int size)
 {
 	DBG("context %p", context);
 
-	phonebook_unref(context);
+	struct obex_session *session;
+
+	session = pbap_get_session(context);
+
+	if (buf == NULL || size == 0) {
+		session->finished = 1;
+		OBEX_ResumeRequest(session->handle);
+		return;
+	}
+
+	session->buf = g_realloc(session->buf, session->size + size);
+	memcpy(session->buf + session->size, buf, size);
+	session->size += size;
+
+	OBEX_ResumeRequest(session->handle);
 }
 
 struct phonebook_driver *phonebook_get_driver(const char *name)
diff --git a/obexd/src/phonebook.h b/obexd/src/phonebook.h
index fbc98f4..440d857 100644
--- a/obexd/src/phonebook.h
+++ b/obexd/src/phonebook.h
@@ -32,8 +32,10 @@ struct phonebook_context {
 	void *driver_data;
 };
 
-extern struct phonebook_context *phonebook_create(struct phonebook_driver *driver);
-extern struct phonebook_context *phonebook_ref(struct phonebook_context *context);
+extern struct phonebook_context *phonebook_create(
+			struct phonebook_driver *driver);
+extern struct phonebook_context *phonebook_ref(
+			struct phonebook_context *context);
 extern void phonebook_unref(struct phonebook_context *context);
 
 static inline void *phonebook_get_data(struct phonebook_context *context)
@@ -47,7 +49,7 @@ static inline void phonebook_set_data(struct phonebook_context *context,
 	context->driver_data = data;
 }
 
-extern void phonebook_pullphonebook(struct phonebook_context *context);
+extern int phonebook_pullphonebook(struct phonebook_context *context);
 extern void phonebook_return(struct phonebook_context *context,
 						char *buf, int size);