1*76404edcSAsim Jamshed /**
2*76404edcSAsim Jamshed  * the HTTP chunk-API
3*76404edcSAsim Jamshed  *
4*76404edcSAsim Jamshed  *
5*76404edcSAsim Jamshed  */
6*76404edcSAsim Jamshed 
7*76404edcSAsim Jamshed #include "server.h"
8*76404edcSAsim Jamshed #include "chunk.h"
9*76404edcSAsim Jamshed #include "http_chunk.h"
10*76404edcSAsim Jamshed #include "log.h"
11*76404edcSAsim Jamshed 
12*76404edcSAsim Jamshed #include <sys/types.h>
13*76404edcSAsim Jamshed #include <sys/stat.h>
14*76404edcSAsim Jamshed 
15*76404edcSAsim Jamshed #include <stdlib.h>
16*76404edcSAsim Jamshed #include <fcntl.h>
17*76404edcSAsim Jamshed #include <unistd.h>
18*76404edcSAsim Jamshed 
19*76404edcSAsim Jamshed #include <stdio.h>
20*76404edcSAsim Jamshed #include <errno.h>
21*76404edcSAsim Jamshed #include <string.h>
22*76404edcSAsim Jamshed 
http_chunk_append_len(server * srv,connection * con,size_t len)23*76404edcSAsim Jamshed static int http_chunk_append_len(server *srv, connection *con, size_t len) {
24*76404edcSAsim Jamshed 	size_t i, olen = len, j;
25*76404edcSAsim Jamshed 	buffer *b;
26*76404edcSAsim Jamshed 
27*76404edcSAsim Jamshed 	b = srv->tmp_chunk_len;
28*76404edcSAsim Jamshed 
29*76404edcSAsim Jamshed 	if (len == 0) {
30*76404edcSAsim Jamshed 		buffer_copy_string_len(b, CONST_STR_LEN("0"));
31*76404edcSAsim Jamshed 	} else {
32*76404edcSAsim Jamshed 		for (i = 0; i < 8 && len; i++) {
33*76404edcSAsim Jamshed 			len >>= 4;
34*76404edcSAsim Jamshed 		}
35*76404edcSAsim Jamshed 
36*76404edcSAsim Jamshed 		/* i is the number of hex digits we have */
37*76404edcSAsim Jamshed 		buffer_prepare_copy(b, i + 1);
38*76404edcSAsim Jamshed 
39*76404edcSAsim Jamshed 		for (j = i-1, len = olen; j+1 > 0; j--) {
40*76404edcSAsim Jamshed 			b->ptr[j] = (len & 0xf) + (((len & 0xf) <= 9) ? '0' : 'a' - 10);
41*76404edcSAsim Jamshed 			len >>= 4;
42*76404edcSAsim Jamshed 		}
43*76404edcSAsim Jamshed 		b->used = i;
44*76404edcSAsim Jamshed 		b->ptr[b->used++] = '\0';
45*76404edcSAsim Jamshed 	}
46*76404edcSAsim Jamshed 
47*76404edcSAsim Jamshed 	buffer_append_string_len(b, CONST_STR_LEN("\r\n"));
48*76404edcSAsim Jamshed 	chunkqueue_append_buffer(con->write_queue, b);
49*76404edcSAsim Jamshed 
50*76404edcSAsim Jamshed 	return 0;
51*76404edcSAsim Jamshed }
52*76404edcSAsim Jamshed 
53*76404edcSAsim Jamshed 
http_chunk_append_file(server * srv,connection * con,buffer * fn,off_t offset,off_t len)54*76404edcSAsim Jamshed int http_chunk_append_file(server *srv, connection *con, buffer *fn, off_t offset, off_t len) {
55*76404edcSAsim Jamshed 	chunkqueue *cq;
56*76404edcSAsim Jamshed 
57*76404edcSAsim Jamshed 	if (!con) return -1;
58*76404edcSAsim Jamshed 
59*76404edcSAsim Jamshed 	cq = con->write_queue;
60*76404edcSAsim Jamshed 
61*76404edcSAsim Jamshed 	if (con->response.transfer_encoding & HTTP_TRANSFER_ENCODING_CHUNKED) {
62*76404edcSAsim Jamshed 		http_chunk_append_len(srv, con, len);
63*76404edcSAsim Jamshed 	}
64*76404edcSAsim Jamshed 
65*76404edcSAsim Jamshed 	chunkqueue_append_file(cq, fn, offset, len);
66*76404edcSAsim Jamshed 
67*76404edcSAsim Jamshed 	if (con->response.transfer_encoding & HTTP_TRANSFER_ENCODING_CHUNKED && len > 0) {
68*76404edcSAsim Jamshed 		chunkqueue_append_mem(cq, "\r\n", 2 + 1);
69*76404edcSAsim Jamshed 	}
70*76404edcSAsim Jamshed 
71*76404edcSAsim Jamshed 	return 0;
72*76404edcSAsim Jamshed }
73*76404edcSAsim Jamshed 
http_chunk_append_buffer(server * srv,connection * con,buffer * mem)74*76404edcSAsim Jamshed int http_chunk_append_buffer(server *srv, connection *con, buffer *mem) {
75*76404edcSAsim Jamshed 	chunkqueue *cq;
76*76404edcSAsim Jamshed 
77*76404edcSAsim Jamshed 	if (!con) return -1;
78*76404edcSAsim Jamshed 
79*76404edcSAsim Jamshed 	cq = con->write_queue;
80*76404edcSAsim Jamshed 
81*76404edcSAsim Jamshed 	if (con->response.transfer_encoding & HTTP_TRANSFER_ENCODING_CHUNKED) {
82*76404edcSAsim Jamshed 		http_chunk_append_len(srv, con, mem->used - 1);
83*76404edcSAsim Jamshed 	}
84*76404edcSAsim Jamshed 
85*76404edcSAsim Jamshed 	chunkqueue_append_buffer(cq, mem);
86*76404edcSAsim Jamshed 
87*76404edcSAsim Jamshed 	if (con->response.transfer_encoding & HTTP_TRANSFER_ENCODING_CHUNKED && mem->used > 0) {
88*76404edcSAsim Jamshed 		chunkqueue_append_mem(cq, "\r\n", 2 + 1);
89*76404edcSAsim Jamshed 	}
90*76404edcSAsim Jamshed 
91*76404edcSAsim Jamshed 	return 0;
92*76404edcSAsim Jamshed }
93*76404edcSAsim Jamshed 
http_chunk_append_mem(server * srv,connection * con,const char * mem,size_t len)94*76404edcSAsim Jamshed int http_chunk_append_mem(server *srv, connection *con, const char * mem, size_t len) {
95*76404edcSAsim Jamshed 	chunkqueue *cq;
96*76404edcSAsim Jamshed 
97*76404edcSAsim Jamshed 	if (!con) return -1;
98*76404edcSAsim Jamshed 
99*76404edcSAsim Jamshed 	cq = con->write_queue;
100*76404edcSAsim Jamshed 
101*76404edcSAsim Jamshed 	if (len == 0) {
102*76404edcSAsim Jamshed 		if (con->response.transfer_encoding & HTTP_TRANSFER_ENCODING_CHUNKED) {
103*76404edcSAsim Jamshed 			chunkqueue_append_mem(cq, "0\r\n\r\n", 5 + 1);
104*76404edcSAsim Jamshed 		} else {
105*76404edcSAsim Jamshed 			chunkqueue_append_mem(cq, "", 1);
106*76404edcSAsim Jamshed 		}
107*76404edcSAsim Jamshed 		return 0;
108*76404edcSAsim Jamshed 	}
109*76404edcSAsim Jamshed 
110*76404edcSAsim Jamshed 	if (con->response.transfer_encoding & HTTP_TRANSFER_ENCODING_CHUNKED) {
111*76404edcSAsim Jamshed 		http_chunk_append_len(srv, con, len - 1);
112*76404edcSAsim Jamshed 	}
113*76404edcSAsim Jamshed 
114*76404edcSAsim Jamshed 	chunkqueue_append_mem(cq, mem, len);
115*76404edcSAsim Jamshed 
116*76404edcSAsim Jamshed 	if (con->response.transfer_encoding & HTTP_TRANSFER_ENCODING_CHUNKED) {
117*76404edcSAsim Jamshed 		chunkqueue_append_mem(cq, "\r\n", 2 + 1);
118*76404edcSAsim Jamshed 	}
119*76404edcSAsim Jamshed 
120*76404edcSAsim Jamshed 	return 0;
121*76404edcSAsim Jamshed }
122*76404edcSAsim Jamshed 
123*76404edcSAsim Jamshed 
http_chunkqueue_length(server * srv,connection * con)124*76404edcSAsim Jamshed off_t http_chunkqueue_length(server *srv, connection *con) {
125*76404edcSAsim Jamshed 	if (!con) {
126*76404edcSAsim Jamshed 		log_error_write(srv, __FILE__, __LINE__, "s", "connection is NULL!!");
127*76404edcSAsim Jamshed 
128*76404edcSAsim Jamshed 		return 0;
129*76404edcSAsim Jamshed 	}
130*76404edcSAsim Jamshed 
131*76404edcSAsim Jamshed 	return chunkqueue_length(con->write_queue);
132*76404edcSAsim Jamshed }
133