[PATCH v3] Add support for sending large PBAP response in many parts

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Added file buffer to cache pull results - temporary file will be deleted
when response is sent. Also added partial_resp variable to pbap_session
for holding information if more data will be available from source later.
It was needed to know when sent -EAGAIN to obex, if currently is no data
available in the buffer.
---
 plugins/pbap.c |   89 +++++++++++++++++++++++++++++++++++++++++++++++++------
 1 files changed, 79 insertions(+), 10 deletions(-)

diff --git a/plugins/pbap.c b/plugins/pbap.c
index 3ea7d6b..6742ea7 100644
--- a/plugins/pbap.c
+++ b/plugins/pbap.c
@@ -116,6 +116,8 @@
   </attribute>								\
 </record>"
 
+#define PBAP_BUF_TEMPLATE "pbap_pullXXXXXX"
+
 struct aparam_header {
 	uint8_t tag;
 	uint8_t len;
@@ -143,6 +145,10 @@ struct pbap_session {
 	uint32_t find_handle;
 	GString *buffer;
 	struct cache cache;
+	gboolean partial_resp;
+	int fbuf_w;
+	int fbuf_r;
+	char *buf_path;
 };
 
 static const uint8_t PBAP_TARGET[TARGET_SIZE] = {
@@ -256,11 +262,27 @@ static void query_result(const char *buffer, size_t bufsize, int vcards,
 		return;
 	}
 
-	if (!pbap->buffer)
-		pbap->buffer = g_string_new_len(buffer, bufsize);
-	else
-		pbap->buffer = g_string_append_len(pbap->buffer, buffer,
-								bufsize);
+	if (pbap->fbuf_w < 0) {
+		/* Creating file buffer for results*/
+		pbap->buf_path = g_build_filename(g_get_tmp_dir(),
+						PBAP_BUF_TEMPLATE, NULL);
+		pbap->fbuf_w = g_mkstemp(pbap->buf_path);
+
+		if (pbap->fbuf_w < 0)
+			return -EPERM;
+	}
+
+	write(pbap->fbuf_w, buffer, bufsize);
+
+	/* If partial_resp will be set to TRUE, then we won't end transmission
+	 * after sending one part of results to the client via obex*/
+	pbap->partial_resp = missed ? TRUE : FALSE;
+
+	/* If no more data in future, we close file buffer right now*/
+	if (!pbap->partial_resp) {
+		close(pbap->fbuf_w);
+		pbap->fbuf_w = -1;
+	}
 
 	obex_object_set_io_flags(pbap, G_IO_IN, 0);
 }
@@ -549,6 +571,8 @@ static void *pbap_connect(struct obex_session *os, int *err)
 	pbap = g_new0(struct pbap_session, 1);
 	pbap->folder = g_strdup("/");
 	pbap->find_handle = PHONEBOOK_INVALID_HANDLE;
+	pbap->fbuf_r = -1;
+	pbap->fbuf_w = -1;
 
 	if (err)
 		*err = 0;
@@ -829,6 +853,27 @@ fail:
 	return NULL;
 }
 
+static ssize_t pbap_read_fbuf(struct pbap_session *pbap, void *buf,
+								size_t count)
+{
+	ssize_t len;
+
+	if (pbap->fbuf_r < 0) {
+		pbap->fbuf_r = open(pbap->buf_path, 0);
+
+		if(pbap->fbuf_r < 0)
+			return -EPERM;
+	}
+
+	len = read(pbap->fbuf_r, buf, count);
+
+	if (len == 0 && pbap->partial_resp)
+		/* More data available later */
+		return -EAGAIN;
+	else
+		return len;
+}
+
 static ssize_t vobject_pull_read(void *object, void *buf, size_t count,
 								uint8_t *hi)
 {
@@ -837,17 +882,23 @@ static ssize_t vobject_pull_read(void *object, void *buf, size_t count,
 	DBG("buffer %p maxlistcount %d", pbap->buffer,
 						pbap->params->maxlistcount);
 
-	if (!pbap->buffer)
+	if (!pbap->buf_path && !pbap->buffer)
+		/* No response available now (no memory/file buffer exist)*/
 		return -EAGAIN;
 
-	/* PhoneBookSize */
-	if (pbap->params->maxlistcount == 0)
+	/* Result from pb size query is very short (only number) so it makes no
+	 * sense to create file buffer for it - using memory buff */
+	if (pbap->params->maxlistcount == 0) {
+		/* PhoneBookSize */
 		*hi = OBEX_HDR_APPARAM;
-	else
+
+		return string_read(pbap->buffer, buf, count);
+	} else {
 		/* Stream data */
 		*hi = OBEX_HDR_BODY;
 
-	return string_read(pbap->buffer, buf, count);
+		return pbap_read_fbuf(pbap, buf, count);
+	}
 }
 
 static ssize_t vobject_list_read(void *object, void *buf, size_t count,
@@ -893,6 +944,24 @@ static int vobject_close(void *object)
 		pbap->buffer = NULL;
 	}
 
+	if (pbap->fbuf_r >= 0) {
+		close(pbap->fbuf_r);
+		pbap->fbuf_r = -1;
+	}
+
+	if (pbap->fbuf_w >= 0) {
+		close(pbap->fbuf_w);
+		pbap->fbuf_w = -1;
+	}
+
+	if (pbap->buf_path) {
+		/* remove file buffer for pull queries */
+		unlink(pbap->buf_path);
+
+		g_free(pbap->buf_path);
+		pbap->buf_path = NULL;
+	}
+
 	return 0;
 }
 
-- 
1.7.0.4

--
To unsubscribe from this list: send the line "unsubscribe linux-bluetooth" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Index of Archives]     [Bluez Devel]     [Linux Wireless Networking]     [Linux Wireless Personal Area Networking]     [Linux ATH6KL]     [Linux USB Devel]     [Linux Media Drivers]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [Big List of Linux Books]

  Powered by Linux