]>
Commit | Line | Data |
---|---|---|
f251ba66 | 1 | diff --git a/src/protocol/http/http.c b/src/protocol/http/http.c |
2 | index 1264f6f..6de3078 100644 | |
3 | --- a/src/protocol/http/http.c | |
4 | +++ b/src/protocol/http/http.c | |
5 | @@ -983,29 +983,23 @@ decompress_data(struct connection *conn, | |
6 | int *new_len) | |
7 | { | |
8 | struct http_connection_info *http = conn->info; | |
9 | - /* to_read is number of bytes to be read from the decoder. It is 65536 | |
10 | - * (then we are just emptying the decoder buffer as we finished the walk | |
11 | - * through the incoming stream already) or PIPE_BUF / 2 (when we are | |
12 | - * still walking through the stream - then we write PIPE_BUF / 2 to the | |
13 | - * pipe and read it back to the decoder ASAP; the point is that we can't | |
14 | - * write more than PIPE_BUF to the pipe at once, but we also have to | |
15 | - * never let read_encoded() (gzread(), in fact) to empty the pipe - that | |
16 | - * causes further malfunction of zlib :[ ... so we will make sure that | |
17 | - * we will always have at least PIPE_BUF / 2 + 1 in the pipe (returning | |
18 | - * early otherwise)). */ | |
19 | - int to_read = PIPE_BUF / 2, did_read = 0; | |
20 | + enum { NORMAL, FINISHING } state = NORMAL; | |
21 | + int did_read = 0; | |
22 | int *length_of_block; | |
23 | unsigned char *output = NULL; | |
24 | ||
25 | - length_of_block = (http->length == LEN_CHUNKED ? &http->chunk_remaining | |
26 | - : &http->length); | |
27 | - | |
28 | #define BIG_READ 65536 | |
29 | - if (!*length_of_block) { | |
30 | - /* Going to finish this decoding bussiness. */ | |
31 | - /* Some nicely big value - empty encoded output queue by reading | |
32 | - * big chunks from it. */ | |
33 | - to_read = BIG_READ; | |
34 | + | |
35 | + if (http->length == LEN_CHUNKED) { | |
36 | + if (http->chunk_remaining == CHUNK_ZERO_SIZE) | |
37 | + state = FINISHING; | |
38 | + length_of_block = &http->chunk_remaining; | |
39 | + } else { | |
40 | + length_of_block = &http->length; | |
41 | + if (!*length_of_block) { | |
42 | + /* Going to finish this decoding bussiness. */ | |
43 | + state = FINISHING; | |
44 | + } | |
45 | } | |
46 | ||
47 | if (conn->content_encoding == ENCODING_NONE) { | |
48 | @@ -1024,14 +1018,13 @@ #define BIG_READ 65536 | |
49 | } | |
50 | ||
51 | do { | |
52 | - int init = 0; | |
53 | + unsigned char *tmp; | |
54 | ||
55 | - if (to_read == PIPE_BUF / 2) { | |
56 | + if (state == NORMAL) { | |
57 | /* ... we aren't finishing yet. */ | |
58 | - int written = safe_write(conn->stream_pipes[1], data, | |
59 | - len > to_read ? to_read : len); | |
60 | + int written = safe_write(conn->stream_pipes[1], data, len); | |
61 | ||
62 | - if (written > 0) { | |
63 | + if (written >= 0) { | |
64 | data += written; | |
65 | len -= written; | |
66 | ||
67 | @@ -1042,7 +1035,7 @@ #define BIG_READ 65536 | |
68 | * non-keep-alive and chunked */ | |
69 | if (!http->length) { | |
70 | /* That's all, folks - let's finish this. */ | |
71 | - to_read = BIG_READ; | |
72 | + state = FINISHING; | |
73 | } else if (!len) { | |
74 | /* We've done for this round (but not done | |
75 | * completely). Thus we will get out with | |
76 | @@ -1061,28 +1054,26 @@ #define BIG_READ 65536 | |
77 | conn->stream = open_encoded(conn->stream_pipes[0], | |
78 | conn->content_encoding); | |
79 | if (!conn->stream) return NULL; | |
80 | - /* On "startup" pipe is treated with care, but if everything | |
81 | - * was already written to the pipe, caution isn't necessary */ | |
82 | - else if (to_read != BIG_READ) init = 1; | |
83 | - } else init = 0; | |
84 | + } | |
85 | ||
86 | - output = (unsigned char *) mem_realloc(output, *new_len + to_read); | |
87 | - if (!output) break; | |
88 | + tmp = mem_realloc(output, *new_len + BIG_READ); | |
89 | + if (!tmp) break; | |
90 | + output = tmp; | |
91 | + | |
92 | + did_read = read_encoded(conn->stream, output + *new_len, BIG_READ); | |
93 | ||
94 | - did_read = read_encoded(conn->stream, output + *new_len, | |
95 | - init ? PIPE_BUF / 32 : to_read); /* on init don't read too much */ | |
96 | if (did_read > 0) *new_len += did_read; | |
97 | - else if (did_read == -1) { | |
98 | - mem_free_set(&output, NULL); | |
99 | - *new_len = 0; | |
100 | - break; /* Loop prevention (bug 517), is this correct ? --Zas */ | |
101 | + else { | |
102 | + if (did_read < 0) state = FINISHING; | |
103 | + break; | |
104 | } | |
105 | - } while (len || did_read == BIG_READ); | |
106 | + } while (len || (did_read == BIG_READ)); | |
107 | ||
108 | - shutdown_connection_stream(conn); | |
109 | + if (state == FINISHING) shutdown_connection_stream(conn); | |
110 | return output; | |
111 | } | |
112 | ||
113 | + | |
114 | static int | |
115 | is_line_in_buffer(struct read_buffer *rb) | |
116 | { | |
117 | @@ -1206,11 +1197,8 @@ read_chunked_http_data(struct connection | |
118 | } else { | |
119 | unsigned char *data; | |
120 | int data_len; | |
121 | - int len; | |
122 | int zero = (http->chunk_remaining == CHUNK_ZERO_SIZE); | |
123 | - | |
124 | - if (zero) http->chunk_remaining = 0; | |
125 | - len = http->chunk_remaining; | |
126 | + int len = zero ? 0 : http->chunk_remaining; | |
127 | ||
128 | /* Maybe everything necessary didn't come yet.. */ | |
129 | int_upper_bound(&len, rb->length); | |
130 | @@ -1850,8 +1838,7 @@ #endif | |
131 | conn->cached->encoding_info = stracpy(get_encoding_name(conn->content_encoding)); | |
132 | } | |
133 | ||
134 | - if (http->length == -1 | |
135 | - || (PRE_HTTP_1_1(http->recv_version) && http->close)) | |
136 | + if (http->length == -1 || http->close) | |
137 | socket->state = SOCKET_END_ONCLOSE; | |
138 | ||
139 | read_http_data(socket, rb); |