| 40 static int client_io(EventHandler *ev, Event *event); |
40 static int client_io(EventHandler *ev, Event *event); |
| 41 static int client_finished(EventHandler *ev, Event *event); |
41 static int client_finished(EventHandler *ev, Event *event); |
| 42 |
42 |
| 43 static int client_send_request(HttpClient *client); |
43 static int client_send_request(HttpClient *client); |
| 44 static int client_send_request_body(HttpClient *client); |
44 static int client_send_request_body(HttpClient *client); |
| |
45 static int client_read_response_header(HttpClient *client); |
| 45 |
46 |
| 46 HttpClient* http_client_new(EventHandler *ev) { |
47 HttpClient* http_client_new(EventHandler *ev) { |
| 47 CxMempool *mp = cxMempoolCreate(32, CX_MEMPOOL_TYPE_PURE); |
48 CxMempool *mp = cxMempoolCreate(32, CX_MEMPOOL_TYPE_PURE); |
| 48 if(!mp) { |
49 if(!mp) { |
| 49 return NULL; |
50 return NULL; |
| 272 event->events = EVENT_POLLIN; |
273 event->events = EVENT_POLLIN; |
| 273 |
274 |
| 274 |
275 |
| 275 char *buffer; |
276 char *buffer; |
| 276 size_t nbytes; |
277 size_t nbytes; |
| 277 if(client->header_complete) { |
278 if(client->response_header_complete) { |
| 278 buffer = client->buffer.inbuf; |
279 buffer = client->buffer.inbuf; |
| 279 nbytes = client->buffer.maxsize; |
280 nbytes = client->buffer.maxsize; |
| 280 } else { |
281 } else { |
| 281 buffer = client->buffer.inbuf + client->buffer.pos; |
282 buffer = client->buffer.inbuf + client->buffer.pos; |
| 282 nbytes = client->buffer.maxsize - client->buffer.cursize; |
283 nbytes = client->buffer.maxsize - client->buffer.cursize; |
| 284 |
285 |
| 285 |
286 |
| 286 ssize_t r; |
287 ssize_t r; |
| 287 while((r = read(client->socketfd, buffer, nbytes)) > 0) { |
288 while((r = read(client->socketfd, buffer, nbytes)) > 0) { |
| 288 client->buffer.cursize += r; |
289 client->buffer.cursize += r; |
| 289 if(!client->header_complete) { |
290 if(!client->response_header_complete) { |
| 290 switch(http_parser_process(client->parser)) { |
291 switch(http_parser_process(client->parser)) { |
| 291 case 0: { // finish |
292 case 0: { // finish |
| 292 if(!http_parser_validate(client->parser)) { |
293 if(!http_parser_validate(client->parser)) { |
| 293 client->error = 1; |
294 client->error = 1; |
| 294 return 0; |
295 return 0; |
| 295 } |
296 } |
| 296 client->statuscode = client->parser->status; |
297 client->statuscode = client->parser->status; |
| 297 |
298 |
| 298 client->header_complete = 1; |
299 client->response_header_complete = 1; |
| 299 if(client->response_start) { |
300 if(client->response_start) { |
| 300 cxmutstr msg = client->parser->msg; |
301 cxmutstr msg = client->parser->msg; |
| 301 char t = msg.ptr[msg.length]; |
302 char t = msg.ptr[msg.length]; |
| 302 msg.ptr[msg.length] = 0; |
303 msg.ptr[msg.length] = 0; |
| 303 int ret = client->response_start(client, client->statuscode, msg.ptr, client->response_start_userdata); |
304 int ret = client->response_start(client, client->statuscode, msg.ptr, client->response_start_userdata); |
| 462 } |
463 } |
| 463 |
464 |
| 464 return 0; |
465 return 0; |
| 465 } |
466 } |
| 466 |
467 |
| |
468 /* |
| |
469 static int client_read_response_header(HttpClient *client) { |
| |
470 if(client->response_header_complete) { |
| |
471 return 0; |
| |
472 } |
| |
473 |
| |
474 char *buffer = client->buffer.inbuf + client->buffer.pos; |
| |
475 size_t nbytes = client->buffer.maxsize - client->buffer.cursize; |
| |
476 |
| |
477 ssize_t r; |
| |
478 while((r = read(client->socketfd, buffer, nbytes)) > 0) { |
| |
479 client->buffer.cursize += r; |
| |
480 if(!client->response_header_complete) { |
| |
481 switch(http_parser_process(client->parser)) { |
| |
482 case 0: { // finish |
| |
483 if(!http_parser_validate(client->parser)) { |
| |
484 client->error = 1; |
| |
485 return 0; |
| |
486 } |
| |
487 client->statuscode = client->parser->status; |
| |
488 |
| |
489 client->response_header_complete = 1; |
| |
490 if(client->response_start) { |
| |
491 cxmutstr msg = client->parser->msg; |
| |
492 char t = msg.ptr[msg.length]; |
| |
493 msg.ptr[msg.length] = 0; |
| |
494 int ret = client->response_start(client, client->statuscode, msg.ptr, client->response_start_userdata); |
| |
495 msg.ptr[msg.length] = t; |
| |
496 |
| |
497 // TODO: check ret |
| |
498 } |
| |
499 break; |
| |
500 } |
| |
501 case 1: { // need more data |
| |
502 continue; |
| |
503 } |
| |
504 case 2: { // error |
| |
505 client->error = 1; |
| |
506 return 0; |
| |
507 } |
| |
508 } |
| |
509 } |
| |
510 |
| |
511 // header complete |
| |
512 |
| |
513 } |
| |
514 } |
| |
515 */ |
| |
516 |
| 467 /* --------------------------------- Tests --------------------------------- */ |
517 /* --------------------------------- Tests --------------------------------- */ |
| 468 |
518 |
| 469 static CX_TEST(test_http_client_send_request) { |
519 static CX_TEST(test_http_client_send_request) { |
| 470 CX_TEST_DO { |
520 CX_TEST_DO { |
| 471 EventHandler dummy; |
521 EventHandler dummy; |
| 774 if(chunklen == 0) { |
823 if(chunklen == 0) { |
| 775 break; |
824 break; |
| 776 } |
825 } |
| 777 |
826 |
| 778 char *data = str + 4; |
827 char *data = str + 4; |
| |
828 CX_TEST_ASSERT(data + chunklen < buf.space + buf.size); |
| 779 memcpy(test_request_body + pos, data, chunklen); |
829 memcpy(test_request_body + pos, data, chunklen); |
| 780 pos += chunklen; |
830 pos += chunklen; |
| 781 str = data + chunklen; |
831 str = data + chunklen; |
| 782 } |
832 } |
| 783 CX_TEST_ASSERT(!memcmp(request_body, test_request_body, 1024)); |
833 CX_TEST_ASSERT(!memcmp(request_body, test_request_body, 1024)); |