From: Wilfried Goesgens Date: Tue, 6 Jan 2015 23:59:43 +0000 (+0100) Subject: Gzip stream chunked encoding is working now. X-Git-Tag: v9.01~44 X-Git-Url: https://code.citadel.org/?p=citadel.git;a=commitdiff_plain;h=5249c9ab6b14efd4d0f92cb64afd78bff3f7e163 Gzip stream chunked encoding is working now. --- diff --git a/libcitadel/lib/stringbuf.c b/libcitadel/lib/stringbuf.c index 5d1961123..9ebc2dd59 100644 --- a/libcitadel/lib/stringbuf.c +++ b/libcitadel/lib/stringbuf.c @@ -2898,25 +2898,21 @@ void *StrBufNewStreamContext(eStreamType type) memset(stream, 0, sizeof(z_enc_stream)); stream->OutBuf.BufSize = 4*SIZ; /// todo 64 stream->OutBuf.buf = (char*)malloc(stream->OutBuf.BufSize); - /* write gzip header * / + /* write gzip header */ stream->OutBuf.BufUsed = snprintf (stream->OutBuf.buf, stream->OutBuf.BufSize, "%c%c%c%c%c%c%c%c%c%c", gz_magic[0], gz_magic[1], Z_DEFLATED, - 0 /*flags * / , 0, 0, 0, 0 /*time * / , 0 /* xflags * / , + 0 /*flags */ , 0, 0, 0, 0 /*time */ , 0 /* xflags */ , OS_CODE); -/* + err = deflateInit2(&stream->zstream, ZLibCompressionRatio, Z_DEFLATED, -MAX_WBITS, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY); -*/ - err = deflateInit(&stream->zstream, - ZLibCompressionRatio); - if (err != Z_OK) return NULL;/// tODO cleanup return stream; diff --git a/webcit/tcp_sockets.c b/webcit/tcp_sockets.c index 302c908c1..f744090b4 100644 --- a/webcit/tcp_sockets.c +++ b/webcit/tcp_sockets.c @@ -555,8 +555,14 @@ void serv_read_binary_to_http(StrBuf *MimeType, size_t total_len, int is_static, int first = 1; int client_con_state = 0; int chunked = 0; + int is_gzip = 0; StrBuf *BufHeader = NULL; StrBuf *Buf; + StrBuf *pBuf = NULL; + void *SC = NULL; + IOBuffer ReadBuffer; + IOBuffer WriteBuffer; + Buf = NewStrBuf(); @@ -601,9 +607,25 @@ void serv_read_binary_to_http(StrBuf *MimeType, size_t total_len, int is_static, FreeStrBuf(&Buf); } + if (chunked && !DisableGzip && WCC->Hdr->HR.gzip_ok) + { + is_gzip = 1; + SC = StrBufNewStreamContext (eZLibEncode); + + memset(&ReadBuffer, 0, sizeof(IOBuffer)); + ReadBuffer.Buf = WCC->WBuf; + + memset(&WriteBuffer, 0, sizeof(IOBuffer)); + WriteBuffer.Buf = NewStrBufPlain(NULL, SIZ*2);; + } + else + { + pBuf = WCC->WBuf; + } + if (!detect_mime) { - http_transmit_headers(ChrPtr(MimeType), is_static, chunked); + http_transmit_headers(ChrPtr(MimeType), is_static, chunked, is_gzip); if (send_http(WCC->HBuf) < 0) { @@ -637,24 +659,43 @@ void serv_read_binary_to_http(StrBuf *MimeType, size_t total_len, int is_static, CT = GuessMimeType(SKEY(WCC->WBuf)); StrBufPlain(MimeType, CT, -1); - http_transmit_headers(ChrPtr(MimeType), is_static, chunked); + http_transmit_headers(ChrPtr(MimeType), is_static, chunked, is_gzip); client_con_state = send_http(WCC->HBuf); } - if ((chunked) && (client_con_state == 0)) + if (is_gzip) { - StrBufPrintf(BufHeader, "%s%x\r\n", - (first)?"":"\r\n", - StrLength (WCC->WBuf)); - first = 0; - client_con_state = send_http(BufHeader); + int done = (bytes_read == total_len); + while ((IOBufferStrLength(&ReadBuffer) > 0) && (client_con_state == 0)) { + StrBufStreamTranscode(eZLibEncode, &WriteBuffer, &ReadBuffer, NULL, -1, SC, done); + + StrBufPrintf(BufHeader, "%s%x\r\n", + (first)?"":"\r\n", + StrLength (pBuf)); + first = 0; + client_con_state = send_http(BufHeader); + if (client_con_state == 0) { + client_con_state = send_http(pBuf); + } + } + FlushStrBuf(WCC->WBuf); } + else { + if ((chunked) && (client_con_state == 0)) + { + StrBufPrintf(BufHeader, "%s%x\r\n", + (first)?"":"\r\n", + StrLength (pBuf)); + first = 0; + client_con_state = send_http(BufHeader); + } - if (client_con_state == 0) - client_con_state = send_http(WCC->WBuf); + if (client_con_state == 0) + client_con_state = send_http(pBuf); - FlushStrBuf(WCC->WBuf); + FlushStrBuf(pBuf); + } } if ((chunked) && (client_con_state == 0)) diff --git a/webcit/webcit.c b/webcit/webcit.c index dd0043d29..8a0ba58a9 100644 --- a/webcit/webcit.c +++ b/webcit/webcit.c @@ -249,12 +249,15 @@ void http_transmit_thing(const char *content_type, int is_static) end_burst(); } -void http_transmit_headers(const char *content_type, int is_static, long is_chunked) +void http_transmit_headers(const char *content_type, int is_static, long is_chunked, int is_gzip) { wcsession *WCC = WC; syslog(LOG_DEBUG, "http_transmit_thing(%s)%s", content_type, ((is_static > 0) ? " (static)" : "")); output_headers(0, 0, 0, 0, 0, is_static); + if (is_gzip) + hprintf("Content-encoding: gzip\r\n"); + if (WCC->Hdr->HaveRange) hprintf("Accept-Ranges: bytes\r\n" "Content-Range: bytes %ld-%ld/%ld\r\n", diff --git a/webcit/webcit.h b/webcit/webcit.h index 5df65fe1b..64034c777 100644 --- a/webcit/webcit.h +++ b/webcit/webcit.h @@ -692,7 +692,7 @@ extern char *days[]; long locate_user_vcard_in_this_room(message_summary **VCMsg, wc_mime_attachment **VCAtt); void http_transmit_thing(const char *content_type, int is_static); -void http_transmit_headers(const char *content_type, int is_static, long is_chunked); +void http_transmit_headers(const char *content_type, int is_static, long is_chunked, int is_gzip); long unescape_input(char *buf); void check_thread_pool_size(void); void StrEndTab(StrBuf *Target, int tabnum, int num_tabs);