--- httptunnel-3.0.5/tunnel.c 2000-09-14 12:27:27.000000000 +0000 +++ httptunnel-3.0.5.chunked/tunnel.c 2005-02-14 09:05:54.000000000 +0000 @@ -90,6 +90,7 @@ int strict_content_length; int keep_alive; int max_connection_age; + int transfer_encoding_chunked_in; }; static const size_t sizeof_header = sizeof (Request) + sizeof (Length); @@ -801,6 +810,12 @@ return 0; } +int chunk_size=0; + +#define H2D(foo) (('0'<=foo && req<=foo) ? (foo-'0') : \ + ('a'<=foo && foo<='f') ? (foo-'a'+10) : \ + ('A'<=foo && foo<='F') ? (foo-'A'+10) : 0) + static int tunnel_read_request (Tunnel *tunnel, enum tunnel_request *request, unsigned char *buf, size_t *length) @@ -831,6 +846,45 @@ errno = EAGAIN; return -1; } + + if(tunnel->transfer_encoding_chunked_in == TRUE){ + if(chunk_size<=0){ + if(req==0x0d){ + n = read (tunnel->in_fd, &req, 1); // 0x0a + log_annoying ("[%x, %c] <- 0x0a ?", req, req); + n = read (tunnel->in_fd, &req, 1); + if (n == -1) { + if (errno != EAGAIN) + log_error ("tunnel_read_request: error reading request: %s", + strerror (errno)); + return n; + } + } + chunk_size=0; + while(1){ + if(n==-1){ + if(errno!=EAGAIN) break; + n = read (tunnel->in_fd, &req, 1); + continue; + } + log_annoying ("n=%d [%x, %c]", n, req, req); + if(req==0x0d){ + n = read (tunnel->in_fd, &req, 1); // 0x0a + log_annoying ("[%x, %c] <- 0x0a ?", req, req); + n = read (tunnel->in_fd, &req, 1); + chunk_size--; + break; + } + chunk_size=chunk_size*10+H2D(req); + n = read (tunnel->in_fd, &req, 1); + } + } + else{ + chunk_size--; + } + log_annoying ("chunk_size=%d", chunk_size); + } + *request = req; tunnel->in_total_raw += n; log_annoying ("request = 0x%x (%s)", req, REQ_TO_STRING (req)); @@ -853,6 +907,11 @@ errno = EIO; return -1; } + + if(tunnel->transfer_encoding_chunked_in == TRUE){ + chunk_size-=n; + } + len = ntohs (len); *length = len; tunnel->in_total_raw += n; @@ -860,7 +919,50 @@ if (len > 0) { - n = read_all (tunnel->in_fd, buf, (size_t)len); + if(tunnel->transfer_encoding_chunked_in == TRUE){ + log_annoying ("@1 chunk_size = %d", chunk_size); + if(chunk_size<=0){ + n = read (tunnel->in_fd, buf, 1); + if(buf[0]==0x0d){ + n = read (tunnel->in_fd, buf, 1); // 0x0a + log_annoying ("[%x, %c] <- 0x0a ?", buf[0], buf[0]); + n = read (tunnel->in_fd, buf, 1); + } + log_annoying ("?? n=%d", n); + chunk_size=0; + while(1){ + if(n==-1){ + if(errno!=EAGAIN) break; + n = read (tunnel->in_fd, buf, 1); + continue; + } + log_annoying ("n=%d [%x, %c]", n, buf[0], buf[0]); + if(buf[0]==0x0d){ + n = read (tunnel->in_fd, buf, 1); // 0x0a + log_annoying ("[%x, %c] <- 0x0a ?", buf[0], buf[0]); + n = read (tunnel->in_fd, buf, 1); + tunnel->in_total_raw++; + chunk_size--; + break; + } + chunk_size=chunk_size*10+H2D(buf[0]); + n = read (tunnel->in_fd, buf, 1); + } + log_annoying ("@2 chunk_size = %d", chunk_size); + if(len-1>0){ + n = read_all (tunnel->in_fd, buf+1, (size_t)len-1); + chunk_size-=n; + } + } + else{ + n = read_all (tunnel->in_fd, buf, (size_t)len); + chunk_size-=n; + } + } + else{ + n = read_all (tunnel->in_fd, buf, (size_t)len); + } + if (n <= 0) { log_error ("tunnel_read_request: error reading request data: %s", @@ -1141,6 +1243,19 @@ tunnel->in_total_raw); #endif + if(request->header!=NULL){ + Http_header *h=request->header; + while(h){ + log_annoying ("header: %s:%s", h->name, h->value); + if(strcmp(h->name, "Transfer-Encoding")==0 && + strcmp(h->value, " chunked")==0){ + tunnel->transfer_encoding_chunked_in = TRUE; + break; + } + h=h->next; + } + } + fcntl (tunnel->in_fd, F_SETFL, fcntl (tunnel->in_fd, F_GETFL) | O_NONBLOCK); @@ -1148,6 +1263,33 @@ tunnel_in_setsockopts (tunnel->in_fd); log_debug ("tunnel_accept: input connected"); + + { + char str[1024]; + sprintf (str, +"HTTP/1.1 200 OK\r\n" +/* "Date: %s\r\n" */ +/* "Server: %s\r\n" */ +/* "Last-Modified: %s\r\n" */ +/* "ETag: %s\r\n" */ +/* "Accept-Ranges: %s\r\n" */ +"Content-Length: %d\r\n" +"Connection: close\r\n" +"Pragma: no-cache\r\n" +"Cache-Control: no-cache, no-store, must-revalidate\r\n" +"Expires: 0\r\n" /* FIXME: "0" is not a legitimate HTTP date. */ +"Content-Type: text/html\r\n" +"\r\n", + /* +1 to allow for TUNNEL_DISCONNECT */ + 0); + if (write_all (tunnel->in_fd, str, strlen (str)) <= 0) + { + log_error ("tunnel_accept: couldn't write POST header: %s", + strerror (errno)); + close (tunnel->in_fd); + tunnel->in_fd = -1; + } + } } else { @@ -1274,6 +1416,8 @@ return NULL; } + tunnel->transfer_encoding_chunked_in = FALSE; + return tunnel; }