diff mbox

[OpenWrt-Devel,1/2] uhttpd: use separate ustream for chunked transfer encoding

Message ID 1443738134-5929-1-git-send-email-ak77@tnode.com
State Changes Requested
Headers show

Commit Message

Andrej Krpic Oct. 1, 2015, 10:22 p.m. UTC
Hi,

this patch simplifies chunk printing when chunked transfer encoding is used
in a response... And it comes handy when gzip content encoding will be used.


Signed-off-by: Andrej Krpic <ak77@tnode.com>
---
 client.c | 17 +++++++++++++++++
 file.c   |  6 ++++--
 uhttpd.h |  1 +
 utils.c  | 31 +++++++------------------------
 4 files changed, 29 insertions(+), 26 deletions(-)

Comments

Felix Fietkau Nov. 22, 2015, 12:03 p.m. UTC | #1
On 2015-10-02 00:22, Andrej Krpic wrote:
> Hi,
> 
> this patch simplifies chunk printing when chunked transfer encoding is used
> in a response... And it comes handy when gzip content encoding will be used.
> 
> Signed-off-by: Andrej Krpic <ak77@tnode.com>
I like the idea, there's one change I'd like you to make to it though:
Please add a pointer to the client struct cl->us_data and make that
point to cl->us for the non-chunked case and &cl->chunked for the
chunked case. That way you can avoid repeating the tests for chunked
encoding in the places that write data.
This will also simplify the follow-up patch with gzip encoding by
getting rid of some unnecessary #if tests.

- Felix
diff mbox

Patch

diff --git a/client.c b/client.c
index dbdd1a3..8569b21 100644
--- a/client.c
+++ b/client.c
@@ -42,6 +42,21 @@  const char * const http_methods[] = {
 	[UH_HTTP_MSG_OPTIONS] = "OPTIONS",
 };
 
+static int chunked_write_cb(struct ustream *s, const char *buf, int len, bool more)
+{
+	struct client *cl = container_of(s, struct client, chunked);
+	ustream_printf(cl->us, "%X\r\n", len);
+	ustream_write(cl->us, buf, len, more);
+	ustream_printf(cl->us, "\r\n");
+	return len;
+}
+
+static void chunked_init(struct client *cl)
+{
+	ustream_init_defaults(&cl->chunked);
+	cl->chunked.write = &chunked_write_cb;
+}
+
 void uh_http_header(struct client *cl, int code, const char *summary)
 {
 	struct http_request *r = &cl->request;
@@ -52,6 +67,8 @@  void uh_http_header(struct client *cl, int code, const char *summary)
 
 	if (!cl->request.respond_chunked)
 		enc = "";
+	else
+		chunked_init(cl);
 
 	if (r->connection_close)
 		conn = "Connection: close";
diff --git a/file.c b/file.c
index 9a2880f..9254e63 100644
--- a/file.c
+++ b/file.c
@@ -579,8 +579,10 @@  static void uh_file_data(struct client *cl, struct path_info *pi, int fd)
 	ustream_printf(cl->us, "Content-Type: %s\r\n",
 			   uh_file_mime_lookup(pi->name));
 
-	ustream_printf(cl->us, "Content-Length: %" PRIu64 "\r\n\r\n",
-			   pi->stat.st_size);
+	if (!cl->request.respond_chunked)
+		ustream_printf(cl->us, "Content-Length: %" PRIu64 "\r\n",
+                               pi->stat.st_size);
+	ustream_printf(cl->us, "\r\n");
 
 
 	/* send body */
diff --git a/uhttpd.h b/uhttpd.h
index fbcb1ed..dd41c25 100644
--- a/uhttpd.h
+++ b/uhttpd.h
@@ -236,6 +236,7 @@  struct client {
 
 	struct ustream *us;
 	struct ustream_fd sfd;
+	struct ustream chunked;
 #ifdef HAVE_TLS
 	struct ustream_ssl ssl;
 #endif
diff --git a/utils.c b/utils.c
index 857e326..572beb9 100644
--- a/utils.c
+++ b/utils.c
@@ -37,44 +37,27 @@  bool uh_use_chunked(struct client *cl)
 
 void uh_chunk_write(struct client *cl, const void *data, int len)
 {
-	bool chunked = cl->request.respond_chunked;
-
 	if (cl->state == CLIENT_STATE_CLEANUP)
 		return;
 
 	uloop_timeout_set(&cl->timeout, conf.network_timeout * 1000);
-	if (chunked)
-		ustream_printf(cl->us, "%X\r\n", len);
-	ustream_write(cl->us, data, len, true);
-	if (chunked)
-		ustream_printf(cl->us, "\r\n", len);
+
+	if (!cl->request.respond_chunked)
+		ustream_write(cl->us, data, len, true);
+	else
+		ustream_write(&cl->chunked, data, len, true);
 }
 
 void uh_chunk_vprintf(struct client *cl, const char *format, va_list arg)
 {
-	char buf[256];
-	va_list arg2;
-	int len;
-
 	if (cl->state == CLIENT_STATE_CLEANUP)
 		return;
 
 	uloop_timeout_set(&cl->timeout, conf.network_timeout * 1000);
-	if (!cl->request.respond_chunked) {
+	if (!cl->request.respond_chunked)
 		ustream_vprintf(cl->us, format, arg);
-		return;
-	}
-
-	va_copy(arg2, arg);
-	len = vsnprintf(buf, sizeof(buf), format, arg2);
-	va_end(arg2);
-
-	ustream_printf(cl->us, "%X\r\n", len);
-	if (len < sizeof(buf))
-		ustream_write(cl->us, buf, len, true);
 	else
-		ustream_vprintf(cl->us, format, arg);
-	ustream_printf(cl->us, "\r\n", len);
+		ustream_vprintf(&cl->chunked, format, arg);
 }
 
 void uh_chunk_printf(struct client *cl, const char *format, ...)