From 9d5bf74cd95d02937a53b0c8a25e8b055a820f61 Mon Sep 17 00:00:00 2001 From: Forrest Zhao Date: Fri, 21 Nov 2008 12:26:38 +0800 Subject: [PATCH] obexd: implement the support for async PBAP plugin --- obexd/plugins/ebook.c | 46 ++++++++++++++-------- obexd/src/obex.c | 11 +++++- obexd/src/obex.h | 8 ++++ obexd/src/pbap.c | 91 +++++++++++++++++++++++++++---------------- obexd/src/phonebook.c | 37 +++++++++++++----- obexd/src/phonebook.h | 8 ++-- 6 files changed, 137 insertions(+), 64 deletions(-) diff --git a/obexd/plugins/ebook.c b/obexd/plugins/ebook.c index 7c78a5722..abb16cb41 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 84409ff18..a0e5e7566 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 d90309539..188e0a88b 100644 --- a/obexd/src/obex.h +++ b/obexd/src/obex.h @@ -29,6 +29,8 @@ #include +#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 9c2126a45..ac288f08b 100644 --- a/obexd/src/pbap.c +++ b/obexd/src/pbap.c @@ -30,60 +30,40 @@ #include -#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 2dab9183e..4b760b288 100644 --- a/obexd/src/phonebook.c +++ b/obexd/src/phonebook.c @@ -25,10 +25,15 @@ #include #endif +#include #include +#include + +#include +#include #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 fbc98f416..440d857a9 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); -- 2.47.3