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

Andrej Krpic ak77 at tnode.com
Thu Oct 1 18:22:13 EDT 2015


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 at tnode.com>
---
 client.c | 17 +++++++++++++++++
 file.c   |  6 ++++--
 uhttpd.h |  1 +
 utils.c  | 31 +++++++------------------------
 4 files changed, 29 insertions(+), 26 deletions(-)

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, ...)
-- 
2.4.6
_______________________________________________
openwrt-devel mailing list
openwrt-devel at lists.openwrt.org
https://lists.openwrt.org/cgi-bin/mailman/listinfo/openwrt-devel



More information about the openwrt-devel mailing list