diff --git a/obexd/plugins/irmc.c b/obexd/plugins/irmc.c index e1e83f983..2cf673c3c 100644 --- a/obexd/plugins/irmc.c +++ b/obexd/plugins/irmc.c @@ -197,6 +197,7 @@ static void *irmc_connect(struct obex_session *os, int *err) { struct irmc_session *irmc; struct apparam_field *param; + int ret; DBG(""); @@ -224,6 +225,9 @@ static void *irmc_connect(struct obex_session *os, int *err) irmc->params = param; irmc->request = phonebook_pull("telecom/pb.vcf", irmc->params, phonebook_size_result, irmc, err); + ret = phonebook_pull_read(irmc->request); + if (err) + *err = ret; return irmc; } @@ -313,6 +317,13 @@ static void *irmc_open_pb(const char *name, struct irmc_session *irmc, DBG("phonebook_pull failed..."); goto fail; } + + ret = phonebook_pull_read(irmc->request); + if (ret < 0) { + DBG("phonebook_pull_read failed..."); + goto fail; + } + return irmc; } diff --git a/obexd/plugins/pbap.c b/obexd/plugins/pbap.c index 5775eea6f..b04dca96f 100644 --- a/obexd/plugins/pbap.c +++ b/obexd/plugins/pbap.c @@ -803,6 +803,11 @@ static void *vobject_pull_open(const char *name, int oflag, mode_t mode, request = phonebook_pull(name, pbap->params, cb, pbap, &ret); + if (ret < 0) + goto fail; + + /* reading first part of results from backend */ + ret = phonebook_pull_read(request); if (ret < 0) goto fail; @@ -962,6 +967,7 @@ static ssize_t vobject_pull_read(void *object, void *buf, size_t count, { struct pbap_object *obj = object; struct pbap_session *pbap = obj->session; + int len, ret; DBG("buffer %p maxlistcount %d", obj->buffer, pbap->params->maxlistcount); @@ -987,7 +993,21 @@ static ssize_t vobject_pull_read(void *object, void *buf, size_t count, *hi = OBEX_HDR_BODY; if (flags) *flags = 0; - return string_read(obj->buffer, buf, count); + + len = string_read(obj->buffer, buf, count); + if (len == 0 && !obj->lastpart) { + /* in case when buffer is empty and we know that more + * data is still available in backend, requesting new + * data part via phonebook_pull_read and returning + * -EAGAIN to suspend request for now */ + ret = phonebook_pull_read(obj->request); + if (ret) + return -EPERM; + + return -EAGAIN; + } + + return len; } } diff --git a/obexd/plugins/phonebook-dummy.c b/obexd/plugins/phonebook-dummy.c index 76dd55012..ede4643fe 100644 --- a/obexd/plugins/phonebook-dummy.c +++ b/obexd/plugins/phonebook-dummy.c @@ -52,6 +52,7 @@ struct dummy_data { const struct apparam_field *apparams; char *folder; int fd; + guint id; }; struct cache_query { @@ -449,9 +450,12 @@ done: void phonebook_req_finalize(void *request) { - guint id = GPOINTER_TO_INT(request); + struct dummy_data *dummy = request; - g_source_remove(id); + /* dummy_data will be cleaned when request will be finished via + * g_source_remove */ + if (dummy && dummy->id) + g_source_remove(dummy->id); } void *phonebook_pull(const char *name, const struct apparam_field *params, @@ -459,7 +463,6 @@ void *phonebook_pull(const char *name, const struct apparam_field *params, { struct dummy_data *dummy; char *filename, *folder; - guint ret; /* * Main phonebook objects will be created dinamically based on the @@ -492,13 +495,23 @@ void *phonebook_pull(const char *name, const struct apparam_field *params, dummy->folder = folder; dummy->fd = -1; - ret = g_idle_add_full(G_PRIORITY_DEFAULT_IDLE, read_dir, dummy, - dummy_free); - if (err) *err = 0; - return GINT_TO_POINTER(ret); + return dummy; +} + +int phonebook_pull_read(void *request) +{ + struct dummy_data *dummy = request; + + if (!dummy) + return -ENOENT; + + dummy->id = g_idle_add_full(G_PRIORITY_DEFAULT_IDLE, read_dir, dummy, + dummy_free); + + return 0; } void *phonebook_get_entry(const char *folder, const char *id, diff --git a/obexd/plugins/phonebook-ebook.c b/obexd/plugins/phonebook-ebook.c index 6cc4f3186..82019da24 100644 --- a/obexd/plugins/phonebook-ebook.c +++ b/obexd/plugins/phonebook-ebook.c @@ -453,25 +453,34 @@ void *phonebook_pull(const char *name, const struct apparam_field *params, phonebook_cb cb, void *user_data, int *err) { struct query_context *data; - EBookQuery *query; - - query = e_book_query_any_field_contains(""); data = g_new0(struct query_context, 1); data->contacts_cb = cb; data->params = params; data->user_data = user_data; - e_book_async_get_contacts(ebook, query, ebookpull_cb, data); - - e_book_query_unref(query); - if (err) *err = 0; return data; } +int phonebook_pull_read(void *request) +{ + struct query_context *data = request; + EBookQuery *query; + + if (!data) + return -ENOENT; + + query = e_book_query_any_field_contains(""); + e_book_async_get_contacts(ebook, query, ebookpull_cb, data); + + e_book_query_unref(query); + + return 0; +} + void *phonebook_get_entry(const char *folder, const char *id, const struct apparam_field *params, phonebook_cb cb, void *user_data, int *err) diff --git a/obexd/plugins/phonebook-tracker.c b/obexd/plugins/phonebook-tracker.c index aea23650e..e7f08076a 100644 --- a/obexd/plugins/phonebook-tracker.c +++ b/obexd/plugins/phonebook-tracker.c @@ -918,6 +918,7 @@ struct phonebook_data { phonebook_entry_cb entry_cb; int newmissedcalls; GCancellable *query_canc; + char *req_name; }; struct phonebook_index { @@ -1819,6 +1820,7 @@ void phonebook_req_finalize(void *request) } g_slist_free(data->contacts); + g_free(data->req_name); g_free(data); } @@ -1897,43 +1899,54 @@ void *phonebook_pull(const char *name, const struct apparam_field *params, phonebook_cb cb, void *user_data, int *err) { struct phonebook_data *data; - const char *query; - reply_list_foreach_t pull_cb; - int col_amount, ret; DBG("name %s", name); - if (g_strcmp0(name, "telecom/mch.vcf") == 0) { - query = NEW_MISSED_CALLS_LIST; - col_amount = PULL_QUERY_COL_AMOUNT; - pull_cb = pull_newmissedcalls; - } else if (params->maxlistcount == 0) { - query = name2count_query(name); - col_amount = COUNT_QUERY_COL_AMOUNT; - pull_cb = pull_contacts_size; - } else { - query = name2query(name); - col_amount = PULL_QUERY_COL_AMOUNT; - pull_cb = pull_contacts; - } - - if (query == NULL) { - if (err) - *err = -ENOENT; - return NULL; - } - data = g_new0(struct phonebook_data, 1); data->params = params; data->user_data = user_data; data->cb = cb; - ret = query_tracker(query, col_amount, pull_cb, data); + data->req_name = g_strdup(name); + if (err) - *err = ret; + *err = 0; return data; } +int phonebook_pull_read(void *request) +{ + struct phonebook_data *data = request; + reply_list_foreach_t pull_cb; + const char *query; + int col_amount; + int ret; + + if(!data) + return -ENOENT; + + if (g_strcmp0(data->req_name, "telecom/mch.vcf") == 0) { + query = NEW_MISSED_CALLS_LIST; + col_amount = PULL_QUERY_COL_AMOUNT; + pull_cb = pull_newmissedcalls; + } else if (data->params->maxlistcount == 0) { + query = name2count_query(data->req_name); + col_amount = COUNT_QUERY_COL_AMOUNT; + pull_cb = pull_contacts_size; + } else { + query = name2query(data->req_name); + col_amount = PULL_QUERY_COL_AMOUNT; + pull_cb = pull_contacts; + } + + if (query == NULL) + return -ENOENT; + + ret = query_tracker(query, col_amount, pull_cb, data); + + return ret; +} + void *phonebook_get_entry(const char *folder, const char *id, const struct apparam_field *params, phonebook_cb cb, void *user_data, int *err) diff --git a/obexd/plugins/phonebook.h b/obexd/plugins/phonebook.h index f6df1649e..00abc08a7 100644 --- a/obexd/plugins/phonebook.h +++ b/obexd/plugins/phonebook.h @@ -82,16 +82,28 @@ char *phonebook_set_folder(const char *current_folder, const char *new_folder, uint8_t flags, int *err); /* - * PullPhoneBook never use cached entries. PCE use this function to get all - * entries of a given folder. The back-end MUST return only the content based - * on the application parameters requested by the client. + * phonebook_pull should be used only to prepare pull request - prepared + * request data is returned by this function. Start of fetching data from + * back-end will be done only after calling phonebook_pull_read with this + * returned request given as a parameter. * - * Return value is a pointer to asynchronous request to phonebook back-end. * phonebook_req_finalize MUST always be used to free associated resources. */ void *phonebook_pull(const char *name, const struct apparam_field *params, phonebook_cb cb, void *user_data, int *err); +/* + * phonebook_pull_read should be used to start getting results from back-end. + * The back-end can return data as one response or can return it many parts. + * After obtaining one part, PBAP core need to call phonebook_pull_read with + * the same request again to get more results from back-end. + * The back-end MUST return only the content based on the application + * parameters requested by the client. + * + * Returns error code or 0 in case of success + */ +int phonebook_pull_read(void *request); + /* * Function used to retrieve a contact from the backend. Only contacts * found in the cache are requested to the back-ends. The back-end MUST