/** * the HTTP chunk-API * * */ #include #include #include #include #include #include #include #include #include "server.h" #include "chunk.h" #include "http_chunk.h" #include "log.h" static int http_chunk_append_len(server *srv, connection *con, size_t len) { size_t i, olen = len, j; buffer *b; b = srv->tmp_chunk_len; if (len == 0) { buffer_copy_string(b, "0"); } else { for (i = 0; i < 8 && len; i++) { len >>= 4; } /* i is the number of hex digits we have */ buffer_prepare_copy(b, i + 1); for (j = i-1, len = olen; j+1 > 0; j--) { b->ptr[j] = (len & 0xf) + (((len & 0xf) <= 9) ? '0' : 'a' - 10); len >>= 4; } b->used = i; b->ptr[b->used++] = '\0'; } buffer_append_string(b, "\r\n"); chunkqueue_append_buffer(con->write_queue, b); return 0; } int http_chunk_append_file(server *srv, connection *con, buffer *fn, off_t offset, off_t len) { chunkqueue *cq; if (!con) return -1; cq = con->write_queue; if (con->response.transfer_encoding & HTTP_TRANSFER_ENCODING_CHUNKED) { http_chunk_append_len(srv, con, len); } chunkqueue_append_file(cq, fn, offset, len); if (con->response.transfer_encoding & HTTP_TRANSFER_ENCODING_CHUNKED && len > 0) { chunkqueue_append_mem(cq, "\r\n", 2 + 1); } return 0; } int http_chunk_append_buffer(server *srv, connection *con, buffer *mem) { chunkqueue *cq; if (!con) return -1; cq = con->write_queue; if (con->response.transfer_encoding & HTTP_TRANSFER_ENCODING_CHUNKED) { http_chunk_append_len(srv, con, mem->used - 1); } chunkqueue_append_buffer(cq, mem); if (con->response.transfer_encoding & HTTP_TRANSFER_ENCODING_CHUNKED && mem->used > 0) { chunkqueue_append_mem(cq, "\r\n", 2 + 1); } return 0; } int http_chunk_append_mem(server *srv, connection *con, const char * mem, size_t len) { chunkqueue *cq; if (!con) return -1; cq = con->write_queue; if (len == 0) { if (con->response.transfer_encoding & HTTP_TRANSFER_ENCODING_CHUNKED) { chunkqueue_append_mem(cq, "0\r\n\r\n", 5 + 1); } else { chunkqueue_append_mem(cq, "", 1); } return 0; } if (con->response.transfer_encoding & HTTP_TRANSFER_ENCODING_CHUNKED) { http_chunk_append_len(srv, con, len - 1); } chunkqueue_append_mem(cq, mem, len); if (con->response.transfer_encoding & HTTP_TRANSFER_ENCODING_CHUNKED) { chunkqueue_append_mem(cq, "\r\n", 2 + 1); } return 0; } off_t http_chunkqueue_length(server *srv, connection *con) { if (!con) { log_error_write(srv, __FILE__, __LINE__, "s", "connection is NULL!!"); return 0; } return chunkqueue_length(con->write_queue); }