Exemple #1
0
static void fwbuffer_data_in_do_read(nxe_ostream* os, nxe_istream* is) {
  nxd_fwbuffer* fwb=OBJ_PTR_FROM_FLD_PTR(nxd_fwbuffer, data_in, os);
  char buf[16384];
  nxe_size_t max_bytes_to_store=fwb->max_size > fwb->size ? fwb->max_size-fwb->size : 0;
  if (max_bytes_to_store>sizeof(buf)) max_bytes_to_store=sizeof(buf);
  // NB: continue reading even after reaching max_size; just swallow the input
  nxe_flags_t flags=0;
  nxe_ssize_t bytes_received=ISTREAM_CLASS(is)->read(is, os, buf, sizeof(buf), &flags);
  if (bytes_received>0) {
    fwb->size+=bytes_received;
    size_t bytes_to_store;
    if (fwb->error) {
      bytes_to_store=0;
    }
    else if (bytes_received>max_bytes_to_store) { // max_size reached
      fwb->error=EFBIG;
      bytes_to_store=max_bytes_to_store;
    }
    else {
      bytes_to_store=bytes_received;
    }
    if (bytes_to_store) {
      if (write(fwb->fd, buf, bytes_to_store)!=bytes_to_store) {
        fwb->error=errno;
      }
    }
  }
  if (flags&NXEF_EOF) {
    nxe_ostream_unset_ready(os);
  }
}
Exemple #2
0
void nxd_http_client_proto_rearm(nxd_http_client_proto* hcp) {
  assert(hcp->nxb);
  nxb_empty(hcp->nxb);
  nxp_free(hcp->nxb_pool, hcp->nxb);
  hcp->nxb=0;
  memset(&hcp->_req, 0, sizeof(hcp->_req));
  hcp->_req.nxb=hcp->nxb;
  hcp->_req.host=0;
  hcp->resp.nxb=hcp->nxb;
  while (hcp->events_pub.sub) nxe_unsubscribe(&hcp->events_pub, hcp->events_pub.sub);
  if (hcp->req_body_in.pair) nxe_disconnect_streams(hcp->req_body_in.pair, &hcp->req_body_in);
  if (hcp->resp_body_out.pair) nxe_disconnect_streams(&hcp->resp_body_out, hcp->resp_body_out.pair);
  nxe_ostream_unset_ready(&hcp->req_body_in);
  nxe_istream_unset_ready(&hcp->resp_body_out);
  nxe_ostream_unset_ready(&hcp->data_in);
  nxe_istream_unset_ready(&hcp->data_out);
}
Exemple #3
0
static inline void request_complete(nxd_http_client_proto* hcp, nxe_loop* loop) {
  nxe_publish(&hcp->events_pub, (nxe_data)NXD_HCP_REQUEST_COMPLETE);
  if (hcp->queued_error_message.i) nxe_publish(&hcp->events_pub, hcp->queued_error_message);
  nxe_ostream_unset_ready(&hcp->data_in);
  nxe_istream_unset_ready(&hcp->data_out);
  nxe_unset_timer(loop, NXWEB_TIMER_READ, &hcp->timer_read);
  nxe_set_timer(loop, NXWEB_TIMER_KEEP_ALIVE, &hcp->timer_keep_alive);
  hcp->request_complete=1;
  hcp->state=HCP_IDLE;
  hcp->request_count++;
}
Exemple #4
0
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);
  }
}
Exemple #5
0
static nxe_ssize_t req_body_in_write(nxe_ostream* os, nxe_istream* is, int fd, nxe_data ptr, nxe_size_t size, nxe_flags_t* flags) {
  //nxweb_log_error("req_body_in_write(%d)", size);
  nxd_http_client_proto* hcp=(nxd_http_client_proto*)((char*)os-offsetof(nxd_http_client_proto, req_body_in));
  nxe_loop* loop=os->super.loop;
  if (hcp->state!=HCP_SENDING_BODY) {
    nxe_ostream_unset_ready(os);
    nxe_istream_set_ready(loop, &hcp->data_out); // get notified when next_os ready
    return 0;
  }
  hcp->req_body_sending_started=1;
  nxe_unset_timer(loop, NXWEB_TIMER_WRITE, &hcp->timer_write);
  nxe_ssize_t bytes_sent=0;
  if (size>0) {
    nxe_ostream* next_os=hcp->data_out.pair;
    if (next_os) {
      nxe_flags_t wflags=*flags;
      if (next_os->ready) bytes_sent=OSTREAM_CLASS(next_os)->write(next_os, &hcp->data_out, 0, (nxe_data)ptr, size, &wflags);
      if (!next_os->ready) {
        //nxweb_log_error("req_body_in_write(%d) - next_os unready", size);
        nxe_ostream_unset_ready(os);
        nxe_istream_set_ready(loop, &hcp->data_out); // get notified when next_os becomes ready again
      }
    }
    else {
      nxweb_log_error("no connected device for hcp->data_out");
      nxe_ostream_unset_ready(os);
    }
  }
  if (*flags&NXEF_EOF && bytes_sent==size) {
    // end of request => get response
    nxe_ostream_unset_ready(os);
    start_receiving_response(hcp, loop);
    return bytes_sent;
  }
  nxe_set_timer(loop, NXWEB_TIMER_WRITE, &hcp->timer_write);
  return bytes_sent;
}
Exemple #6
0
void nxd_rbuffer_write(nxd_rbuffer* rb, int size) {
  nxweb_log_debug("nxd_rbuffer_write");

  if (size) {
    rb->write_ptr+=size;
    assert(rb->write_ptr <= rb->end_ptr);
    if (rb->write_ptr >= rb->end_ptr) rb->write_ptr=rb->start_ptr;
    rb->last_write=1;
    if (rb->data_out.super.loop) nxe_istream_set_ready(rb->data_out.super.loop, &rb->data_out);
    else rb->data_out.ready=1;
    if (rb->read_ptr==rb->write_ptr) { // nxd_rbuffer_is_full(rb)
      if (rb->data_in.super.loop) nxe_ostream_unset_ready(&rb->data_in);
      else rb->data_in.ready=0;
    }
  }
}
Exemple #7
0
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;
}
Exemple #8
0
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);
    }
  }
}