Deleted
Added
nxt_http_chunk_parse.c (704:1fcac04f0a15) | nxt_http_chunk_parse.c (1505:d18f2b38596b) |
---|---|
1 2/* 3 * Copyright (C) Igor Sysoev 4 * Copyright (C) NGINX, Inc. 5 */ 6 7#include <nxt_main.h> 8 --- 7 unchanged lines hidden (view full) --- 16nxt_size_is_sufficient(cs) \ 17 (cs < ((__typeof__(cs)) 1 << (sizeof(cs) * 8 - 4))) 18 19 20static nxt_int_t nxt_http_chunk_buffer(nxt_http_chunk_parse_t *hcp, 21 nxt_buf_t ***tail, nxt_buf_t *in); 22 23 | 1 2/* 3 * Copyright (C) Igor Sysoev 4 * Copyright (C) NGINX, Inc. 5 */ 6 7#include <nxt_main.h> 8 --- 7 unchanged lines hidden (view full) --- 16nxt_size_is_sufficient(cs) \ 17 (cs < ((__typeof__(cs)) 1 << (sizeof(cs) * 8 - 4))) 18 19 20static nxt_int_t nxt_http_chunk_buffer(nxt_http_chunk_parse_t *hcp, 21 nxt_buf_t ***tail, nxt_buf_t *in); 22 23 |
24static void nxt_http_chunk_buf_completion(nxt_task_t *task, void *obj, 25 void *data); 26 27 |
|
24nxt_buf_t * 25nxt_http_chunk_parse(nxt_task_t *task, nxt_http_chunk_parse_t *hcp, 26 nxt_buf_t *in) 27{ 28 u_char c, ch; 29 nxt_int_t ret; | 28nxt_buf_t * 29nxt_http_chunk_parse(nxt_task_t *task, nxt_http_chunk_parse_t *hcp, 30 nxt_buf_t *in) 31{ 32 u_char c, ch; 33 nxt_int_t ret; |
30 nxt_buf_t *b, *out, *nb, **tail; | 34 nxt_buf_t *b, *out, *next, **tail; |
31 enum { 32 sw_start = 0, 33 sw_chunk_size, 34 sw_chunk_size_linefeed, 35 sw_chunk_end_newline, 36 sw_chunk_end_linefeed, 37 sw_chunk, 38 } state; 39 | 35 enum { 36 sw_start = 0, 37 sw_chunk_size, 38 sw_chunk_size_linefeed, 39 sw_chunk_end_newline, 40 sw_chunk_end_linefeed, 41 sw_chunk, 42 } state; 43 |
44 next = NULL; |
|
40 out = NULL; 41 tail = &out; 42 43 state = hcp->state; 44 | 45 out = NULL; 46 tail = &out; 47 48 state = hcp->state; 49 |
45 for (b = in; b != NULL; b = b->next) { | 50 for (b = in; b != NULL; b = next) { |
46 47 hcp->pos = b->mem.pos; 48 49 while (hcp->pos < b->mem.free) { 50 /* 51 * The sw_chunk state is tested outside the switch 52 * to preserve hcp->pos and to not touch memory. 53 */ 54 if (state == sw_chunk) { 55 ret = nxt_http_chunk_buffer(hcp, &tail, b); 56 57 if (ret == NXT_HTTP_CHUNK_MIDDLE) { 58 goto next; 59 } 60 61 if (nxt_slow_path(ret == NXT_ERROR)) { 62 hcp->error = 1; | 51 52 hcp->pos = b->mem.pos; 53 54 while (hcp->pos < b->mem.free) { 55 /* 56 * The sw_chunk state is tested outside the switch 57 * to preserve hcp->pos and to not touch memory. 58 */ 59 if (state == sw_chunk) { 60 ret = nxt_http_chunk_buffer(hcp, &tail, b); 61 62 if (ret == NXT_HTTP_CHUNK_MIDDLE) { 63 goto next; 64 } 65 66 if (nxt_slow_path(ret == NXT_ERROR)) { 67 hcp->error = 1; |
63 goto done; | 68 return out; |
64 } 65 66 state = sw_chunk_end_newline; 67 68 if (ret == NXT_HTTP_CHUNK_END_ON_BORDER) { 69 goto next; 70 } 71 --- 75 unchanged lines hidden (view full) --- 147 case sw_chunk_end_linefeed: 148 if (nxt_fast_path(ch == '\n')) { 149 150 if (!hcp->last) { 151 state = sw_start; 152 continue; 153 } 154 | 69 } 70 71 state = sw_chunk_end_newline; 72 73 if (ret == NXT_HTTP_CHUNK_END_ON_BORDER) { 74 goto next; 75 } 76 --- 75 unchanged lines hidden (view full) --- 152 case sw_chunk_end_linefeed: 153 if (nxt_fast_path(ch == '\n')) { 154 155 if (!hcp->last) { 156 state = sw_start; 157 continue; 158 } 159 |
155 goto done; | 160 return out; |
156 } 157 158 goto chunk_error; 159 160 case sw_chunk: 161 /* 162 * This state is processed before the switch. 163 * It added here just to suppress a warning. 164 */ 165 continue; 166 } 167 } 168 169 if (b->retain == 0) { 170 /* No chunk data was found in a buffer. */ | 161 } 162 163 goto chunk_error; 164 165 case sw_chunk: 166 /* 167 * This state is processed before the switch. 168 * It added here just to suppress a warning. 169 */ 170 continue; 171 } 172 } 173 174 if (b->retain == 0) { 175 /* No chunk data was found in a buffer. */ |
171 nxt_thread_current_work_queue_add(task->thread, 172 b->completion_handler, 173 task, b, b->parent); | 176 nxt_work_queue_add(&task->thread->engine->fast_work_queue, 177 b->completion_handler, task, b, b->parent); |
174 175 } 176 177 next: 178 | 178 179 } 180 181 next: 182 |
179 continue; | 183 next = b->next; 184 b->next = NULL; |
180 } 181 182 hcp->state = state; 183 184 return out; 185 186chunk_error: 187 188 hcp->chunk_error = 1; 189 | 185 } 186 187 hcp->state = state; 188 189 return out; 190 191chunk_error: 192 193 hcp->chunk_error = 1; 194 |
190done: 191 192 nb = nxt_buf_sync_alloc(hcp->mem_pool, NXT_BUF_SYNC_LAST); 193 194 if (nxt_fast_path(nb != NULL)) { 195 *tail = nb; 196 197 } else { 198 hcp->error = 1; 199 } 200 201 // STUB: hcp->chunk_error = 1; 202 // STUB: hcp->error = 1; 203 | |
204 return out; 205} 206 207 208static nxt_int_t 209nxt_http_chunk_buffer(nxt_http_chunk_parse_t *hcp, nxt_buf_t ***tail, 210 nxt_buf_t *in) 211{ 212 u_char *p; 213 size_t size; 214 nxt_buf_t *b; 215 216 p = hcp->pos; 217 size = in->mem.free - p; 218 | 195 return out; 196} 197 198 199static nxt_int_t 200nxt_http_chunk_buffer(nxt_http_chunk_parse_t *hcp, nxt_buf_t ***tail, 201 nxt_buf_t *in) 202{ 203 u_char *p; 204 size_t size; 205 nxt_buf_t *b; 206 207 p = hcp->pos; 208 size = in->mem.free - p; 209 |
219 if (hcp->chunk_size >= size && in->retain == 0) { 220 /* 221 * Use original buffer if the buffer is lesser than or equal 222 * to a chunk size and this is the first chunk in the buffer. 223 */ 224 in->mem.pos = p; 225 **tail = in; 226 *tail = &in->next; | 210 b = nxt_buf_mem_alloc(hcp->mem_pool, 0, 0); 211 if (nxt_slow_path(b == NULL)) { 212 return NXT_ERROR; 213 } |
227 | 214 |
228 } else { 229 b = nxt_buf_mem_alloc(hcp->mem_pool, 0, 0); 230 if (nxt_slow_path(b == NULL)) { 231 return NXT_ERROR; 232 } | 215 **tail = b; 216 *tail = &b->next; |
233 | 217 |
234 **tail = b; 235 *tail = &b->next; | 218 nxt_mp_retain(hcp->mem_pool); 219 b->completion_handler = nxt_http_chunk_buf_completion; |
236 | 220 |
237 b->parent = in; 238 in->retain++; 239 b->mem.pos = p; 240 b->mem.start = p; | 221 b->parent = in; 222 in->retain++; 223 b->mem.pos = p; 224 b->mem.start = p; |
241 | 225 |
242 if (hcp->chunk_size < size) { 243 p += hcp->chunk_size; 244 hcp->pos = p; | 226 if (hcp->chunk_size < size) { 227 p += hcp->chunk_size; 228 hcp->pos = p; |
245 | 229 |
246 b->mem.free = p; 247 b->mem.end = p; | 230 b->mem.free = p; 231 b->mem.end = p; |
248 | 232 |
249 return NXT_HTTP_CHUNK_END; 250 } 251 252 b->mem.free = in->mem.free; 253 b->mem.end = in->mem.free; | 233 return NXT_HTTP_CHUNK_END; |
254 } 255 | 234 } 235 |
236 b->mem.free = in->mem.free; 237 b->mem.end = in->mem.free; 238 |
|
256 hcp->chunk_size -= size; 257 258 if (hcp->chunk_size == 0) { 259 return NXT_HTTP_CHUNK_END_ON_BORDER; 260 } 261 262 return NXT_HTTP_CHUNK_MIDDLE; 263} | 239 hcp->chunk_size -= size; 240 241 if (hcp->chunk_size == 0) { 242 return NXT_HTTP_CHUNK_END_ON_BORDER; 243 } 244 245 return NXT_HTTP_CHUNK_MIDDLE; 246} |
247 248 249static void 250nxt_http_chunk_buf_completion(nxt_task_t *task, void *obj, void *data) 251{ 252 nxt_mp_t *mp; 253 nxt_buf_t *b, *next, *parent; 254 255 b = obj; 256 parent = data; 257 258 nxt_debug(task, "buf completion: %p %p", b, b->mem.start); 259 260 nxt_assert(data == b->parent); 261 262 do { 263 next = b->next; 264 parent = b->parent; 265 mp = b->data; 266 267 nxt_mp_free(mp, b); 268 nxt_mp_release(mp); 269 270 nxt_buf_parent_completion(task, parent); 271 272 b = next; 273 } while (b != NULL); 274} |
|