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