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