static nxe_ssize_t ssi_buffer_data_in_write(nxe_ostream* os, nxe_istream* is, int fd, nx_file_reader* fr, nxe_data ptr, nxe_size_t size, nxe_flags_t* _flags) { ssi_buffer* ssib=OBJ_PTR_FROM_FLD_PTR(ssi_buffer, data_in, os); //nxe_loop* loop=os->super.loop; nxweb_log_debug("ssi_buffer_data_in_write"); nxe_flags_t flags=*_flags; if (ssib->overflow) { // reached max_ssi_size // swallow input data } else { int wsize=size; if (ssib->data_size+wsize > MAX_SSI_SIZE) wsize=MAX_SSI_SIZE-ssib->data_size; assert(wsize>=0); if (wsize>0) { nx_file_reader_to_mem_ptr(fd, fr, &ptr, &size, &flags); if (((int)size)<wsize) wsize=size; nxb_make_room(ssib->nxb, wsize); char* dptr=nxb_get_room(ssib->nxb, 0); memcpy(dptr, ptr.cptr, wsize); nxb_blank_fast(ssib->nxb, wsize); ssib->data_size+=wsize; while (parse_text(ssib)); if (ssib->data_size >= MAX_SSI_SIZE) { ssib->overflow=1; } } } if (flags&NXEF_EOF) { nxe_ostream_unset_ready(os); int nbytes; char* ptr=nxb_finish_stream(ssib->nxb, &nbytes); if (nbytes) { nxweb_composite_stream_append_bytes(ssib->cs, ptr, nbytes); } nxweb_composite_stream_close(ssib->cs); } return size; }
static void ibuffer_data_in_do_read(nxe_ostream* os, nxe_istream* is) { nxd_ibuffer* ib=(nxd_ibuffer*)((char*)os-offsetof(nxd_ibuffer, data_in)); //nxe_loop* loop=os->super.loop; nxe_flags_t flags=0; if (ib->data_ptr) { // already closed; perhaps reached max_data_size // swallow input data char buf[16384]; is->super.cls.is_cls->read(is, os, buf, sizeof(buf), &flags); if (flags&NXEF_EOF) { nxe_ostream_unset_ready(os); } return; } int size; nxb_make_room(ib->nxb, 32); char* ptr=nxb_get_room(ib->nxb, &size); size--; // for null-terminator if (ib->data_size+size > ib->max_data_size) size=ib->max_data_size-ib->data_size-1; int bytes_received=is->super.cls.is_cls->read(is, os, ptr, size, &flags); if (bytes_received>0) { nxb_blank_fast(ib->nxb, bytes_received); ib->data_size+=bytes_received; if (ib->data_size >= ib->max_data_size-1) { nxb_append_char_fast(ib->nxb, '\0'); ib->data_ptr=nxb_finish_stream(ib->nxb, 0); nxe_publish(&ib->data_complete, (nxe_data)-1); //nxe_ostream_unset_ready(os); } } if (flags&NXEF_EOF) { if (!ib->data_ptr) { nxb_append_char_fast(ib->nxb, '\0'); ib->data_ptr=nxb_finish_stream(ib->nxb, 0); nxe_publish(&ib->data_complete, (nxe_data)0); } nxe_ostream_unset_ready(os); } }
static void data_in_do_read(nxe_ostream* os, nxe_istream* is) { nxd_http_client_proto* hcp=(nxd_http_client_proto*)((char*)os-offsetof(nxd_http_client_proto, data_in)); nxe_loop* loop=os->super.loop; if (hcp->state==HCP_WAITING_FOR_RESPONSE) { nxe_unset_timer(loop, NXWEB_TIMER_READ, &hcp->timer_read); nxe_unset_timer(loop, NXWEB_TIMER_100CONTINUE, &hcp->timer_100_continue); nxe_set_timer(loop, NXWEB_TIMER_READ, &hcp->timer_read); nxb_make_room(hcp->nxb, NXWEB_MAX_REQUEST_HEADERS_SIZE); hcp->state=HCP_RECEIVING_HEADERS; } if (hcp->state==HCP_RECEIVING_HEADERS) { int size; nxe_flags_t flags=0; void* ptr=nxb_get_room(hcp->nxb, &size); int bytes_received=ISTREAM_CLASS(is)->read(is, os, ptr, size, &flags); if (bytes_received) { nxb_blank_fast(hcp->nxb, bytes_received); int read_buf_size; char* read_buf=nxb_get_unfinished(hcp->nxb, &read_buf_size); char* end_of_headers; char* start_of_body; if ((end_of_headers=_nxweb_find_end_of_http_headers(read_buf, read_buf_size, &start_of_body))) { nxb_finish_stream(hcp->nxb, 0); memset(&hcp->resp, 0, sizeof(hcp->resp)); hcp->resp.nxb=hcp->nxb; hcp->resp.cdstate.monitor_only=hcp->chunked_do_not_decode; if (_nxweb_parse_http_response(&hcp->resp, read_buf, end_of_headers)) { // bad response nxe_unset_timer(loop, NXWEB_TIMER_READ, &hcp->timer_read); nxe_ostream_unset_ready(os); nxe_publish(&hcp->events_pub, (nxe_data)NXD_HCP_BAD_RESPONSE); return; } if (hcp->receiving_100_continue) { hcp->receiving_100_continue=0; if (hcp->resp.status_code==100) { // back to sending request body nxe_ostream_unset_ready(&hcp->data_in); nxe_unset_timer(loop, NXWEB_TIMER_READ, &hcp->timer_read); nxe_set_timer(loop, NXWEB_TIMER_WRITE, &hcp->timer_write); nxe_istream_set_ready(loop, &hcp->data_out); hcp->state=HCP_SENDING_BODY; return; } else { nxe_publish(&hcp->events_pub, (nxe_data)NXD_HCP_NO_100CONTINUE); } } char* read_buf_end=read_buf+read_buf_size; if (start_of_body<read_buf_end) { hcp->first_body_chunk=start_of_body; hcp->first_body_chunk_end=read_buf_end; nxe_size_t first_body_chunk_size=hcp->first_body_chunk_end-hcp->first_body_chunk; if (hcp->resp.chunked_encoding) { int r=_nxweb_decode_chunked_stream(&hcp->resp.cdstate, hcp->first_body_chunk, &first_body_chunk_size); hcp->first_body_chunk_end=hcp->first_body_chunk+first_body_chunk_size; if (r<0) nxe_publish(&hcp->events_pub, (nxe_data)NXD_HCP_RESPONSE_CHUNKED_ENCODING_ERROR); else if (r>0) hcp->response_body_complete=1; } else if (first_body_chunk_size >= hcp->resp.content_length && hcp->resp.content_length>=0) { hcp->response_body_complete=1; } } else { hcp->first_body_chunk=0; hcp->first_body_chunk_end=0; } nxe_ostream_unset_ready(os); nxe_publish(&hcp->events_pub, (nxe_data)NXD_HCP_RESPONSE_RECEIVED); if (hcp->resp.content_length && !hcp->req->head_method) { // is body expected? hcp->state=HCP_RECEIVING_BODY; nxe_istream_set_ready(loop, &hcp->resp_body_out); if (hcp->resp_body_out.pair) { nxe_ostream_set_ready(loop, os); } } else { // rearm connection request_complete(hcp, loop); } } else { if (read_buf_size>=NXWEB_MAX_REQUEST_HEADERS_SIZE) { // bad response (headers too large) nxe_unset_timer(loop, NXWEB_TIMER_READ, &hcp->timer_read); nxe_ostream_unset_ready(os); nxe_publish(&hcp->events_pub, (nxe_data)NXD_HCP_BAD_RESPONSE); return; } } } } else if (hcp->state==HCP_RECEIVING_BODY) { nxe_ostream* next_os=hcp->resp_body_out.pair; if (next_os) { if (next_os->ready) OSTREAM_CLASS(next_os)->do_read(next_os, &hcp->resp_body_out); if (!next_os->ready) { nxe_ostream_unset_ready(os); nxe_istream_set_ready(loop, &hcp->resp_body_out); // get notified when next_os becomes ready again } } else { nxweb_log_error("no connected device for hcp->resp_body_out"); nxe_ostream_unset_ready(os); } } }