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:
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:
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:
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:
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:
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: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>