X-Git-Url: https://code.citadel.org/?a=blobdiff_plain;f=webcit%2Ftcp_sockets.c;h=f744090b4b20ba3bb6c9c519b39ff968487818a3;hb=5249c9ab6b14efd4d0f92cb64afd78bff3f7e163;hp=963007f87a759a39414e58453a1e043fb5e391af;hpb=44bd452609c8e429d324d4205460c656dd91bd5f;p=citadel.git diff --git a/webcit/tcp_sockets.c b/webcit/tcp_sockets.c index 963007f87..f744090b4 100644 --- a/webcit/tcp_sockets.c +++ b/webcit/tcp_sockets.c @@ -482,12 +482,12 @@ int client_write(StrBuf *ThisBuf) } if ((WCC->Hdr->http_sock == -1) || - (res = write(WCC->Hdr->http_sock, - ptr, - count)) == -1) { + ((res = write(WCC->Hdr->http_sock, ptr, count)), + (res == -1))) + { syslog(LOG_INFO, "client_write: Socket write failed (%s)\n", strerror(errno)); wc_backtrace(LOG_INFO); - return res; + return -1; } count -= res; ptr += res; @@ -495,22 +495,76 @@ int client_write(StrBuf *ThisBuf) return 0; } + +int +read_serv_chunk( + + StrBuf *Buf, + size_t total_len, + size_t *bytes_read + ) +{ + int rc; + int ServerRc; + wcsession *WCC = WC; + + serv_printf("READ "SIZE_T_FMT"|"SIZE_T_FMT, *bytes_read, total_len-(*bytes_read)); + if ( (rc = StrBuf_ServGetln(Buf) > 0) && + (ServerRc = GetServerStatus(Buf, NULL), ServerRc == 6) ) + { + size_t this_block = 0; + + if (rc < 0) + return rc; + + StrBufCutLeft(Buf, 4); + this_block = StrTol(Buf); + rc = StrBuf_ServGetBLOBBuffered(WCC->WBuf, this_block); + if (rc < 0) { + syslog(LOG_INFO, "Server connection broken during download\n"); + wc_backtrace(LOG_INFO); + if (WCC->serv_sock > 0) close(WCC->serv_sock); + WCC->serv_sock = (-1); + WCC->connected = 0; + WCC->logged_in = 0; + return rc; + } + *bytes_read += rc; + } + return 6; +} + +static inline int send_http(StrBuf *Buf) +{ +#ifdef HAVE_OPENSSL + if (is_https) + return client_write_ssl(Buf); + else +#endif + return client_write(Buf); +} /* * Read binary data from server into memory using a series of server READ commands. * returns the read content as StrBuf */ void serv_read_binary_to_http(StrBuf *MimeType, size_t total_len, int is_static, int detect_mime) { + int ServerRc = 6; wcsession *WCC = WC; size_t bytes_read = 0; - size_t this_block = 0; - int rc = 6; - int ServerRc = 6; int first = 1; + int client_con_state = 0; int chunked = 0; - StrBuf *BufHeader; + int is_gzip = 0; + StrBuf *BufHeader = NULL; StrBuf *Buf; + StrBuf *pBuf = NULL; + void *SC = NULL; + IOBuffer ReadBuffer; + IOBuffer WriteBuffer; + + Buf = NewStrBuf(); if (WCC->Hdr->HaveRange) { @@ -529,84 +583,131 @@ void serv_read_binary_to_http(StrBuf *MimeType, size_t total_len, int is_static, { BufHeader=NewStrBuf(); } - Buf = NewStrBuf(); - http_transmit_headers(ChrPtr(MimeType), is_static, chunked); -#ifdef HAVE_OPENSSL - if (is_https) - client_write_ssl(WCC->HBuf); + if ((detect_mime != 0) && (bytes_read != 0)) + { + /* need to read first chunk to detect mime, though the client doesn't care */ + size_t bytes_read = 0; + const char *CT; + + ServerRc = read_serv_chunk( + Buf, + total_len, + &bytes_read); + + if (ServerRc != 6) + { + FreeStrBuf(&Buf); + return; + } + CT = GuessMimeType(SKEY(WCC->WBuf)); + FlushStrBuf(WCC->WBuf); + StrBufPlain(MimeType, CT, -1); + detect_mime = 0; + 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 -#endif - client_write(WCC->HBuf); + { + pBuf = WCC->WBuf; + } - while ((bytes_read < total_len) && (ServerRc == 6)) { + if (!detect_mime) + { + http_transmit_headers(ChrPtr(MimeType), is_static, chunked, is_gzip); + + if (send_http(WCC->HBuf) < 0) + { + FreeStrBuf(&Buf); + return; + } + } + + while ((bytes_read < total_len) && + (ServerRc == 6) && + (client_con_state == 0)) + { if (WCC->serv_sock==-1) { FlushStrBuf(WCC->WBuf); + FreeStrBuf(&Buf); return; } - serv_printf("READ "SIZE_T_FMT"|"SIZE_T_FMT, bytes_read, total_len-bytes_read); - if ( (rc = StrBuf_ServGetln(Buf) > 0) && - (ServerRc = GetServerStatus(Buf, NULL), ServerRc == 6) ) + ServerRc = read_serv_chunk( + Buf, + total_len, + &bytes_read); + if (ServerRc != 6) + break; + + if (detect_mime) { - if (rc < 0) - return; - StrBufCutLeft(Buf, 4); - this_block = StrTol(Buf); - rc = StrBuf_ServGetBLOBBuffered(WCC->WBuf, this_block); - if (rc < 0) { - syslog(LOG_INFO, "Server connection broken during download\n"); - wc_backtrace(LOG_INFO); - if (WCC->serv_sock > 0) close(WCC->serv_sock); - WCC->serv_sock = (-1); - WCC->connected = 0; - WCC->logged_in = 0; - return; - } - bytes_read += rc; + const char *CT; + detect_mime = 0; + CT = GuessMimeType(SKEY(WCC->WBuf)); + StrBufPlain(MimeType, CT, -1); + http_transmit_headers(ChrPtr(MimeType), is_static, chunked, is_gzip); + + client_con_state = send_http(WCC->HBuf); } - if (chunked) + if (is_gzip) { - StrBufPrintf(BufHeader, "%s%x\r\n", - (first)?"":"\r\n", - StrLength (WCC->WBuf)); -#ifdef HAVE_OPENSSL - if (is_https) - rc = client_write_ssl(BufHeader); - else -#endif - rc = client_write(BufHeader); - if (rc < 0) - break; + 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); + } -#ifdef HAVE_OPENSSL - if (is_https) - rc = client_write_ssl(WCC->WBuf); - else -#endif - rc = client_write(WCC->WBuf); + if (client_con_state == 0) + client_con_state = send_http(pBuf); - if (rc < 0) - break; - first = 0; - FlushStrBuf(WCC->WBuf); + FlushStrBuf(pBuf); + } } - if (chunked) + if ((chunked) && (client_con_state == 0)) { - StrBufPrintf(BufHeader, "\r\n0\r\n\r\n"); -#ifdef HAVE_OPENSSL - if (is_https) - rc = client_write_ssl(BufHeader); - else -#endif - rc = client_write(BufHeader); + StrBufPlain(BufHeader, HKEY("\r\n0\r\n\r\n")); + if (send_http(BufHeader) < 0) + { + FreeStrBuf(&Buf); + return; + } } - + FreeStrBuf(&Buf); } int ClientGetLine(ParsedHttpHdrs *Hdr, StrBuf *Target) @@ -1016,7 +1117,7 @@ long end_burst(void) /* * lingering_close() a`la Apache. see - * http://www.apache.org/docs/misc/fin_wait_2.html for rationale + * http://httpd.apache.org/docs/2.0/misc/fin_wait_2.html for rationale */ int lingering_close(int fd) {