Esempio n. 1
0
static inline void start_receiving_response(nxd_http_client_proto* hcp, nxe_loop* loop) {
  nxe_istream_unset_ready(&hcp->data_out);
  nxe_unset_timer(loop, NXWEB_TIMER_WRITE, &hcp->timer_write);
  nxe_set_timer(loop, NXWEB_TIMER_READ, &hcp->timer_read);
  nxe_ostream_set_ready(loop, &hcp->data_in);
  hcp->state=HCP_WAITING_FOR_RESPONSE;
}
Esempio n. 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);
}
Esempio n. 3
0
static inline void wait_for_100_continue(nxd_http_client_proto* hcp, nxe_loop* loop) {
  nxe_istream_unset_ready(&hcp->data_out);
  nxe_unset_timer(loop, NXWEB_TIMER_WRITE, &hcp->timer_write);
  nxe_set_timer(loop, NXWEB_TIMER_100CONTINUE, &hcp->timer_100_continue);
  nxe_ostream_set_ready(loop, &hcp->data_in);
  hcp->receiving_100_continue=1;
  hcp->state=HCP_WAITING_FOR_RESPONSE;
}
Esempio n. 4
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++;
}
Esempio n. 5
0
void nxd_rbuffer_read(nxd_rbuffer* rb, int size) {
  nxweb_log_debug("nxd_rbuffer_read");

  if (size) {
    rb->read_ptr+=size;
    assert(rb->read_ptr <= rb->end_ptr);
    if (rb->read_ptr >= rb->end_ptr) rb->read_ptr=rb->start_ptr;
    rb->last_write=0;
    if (!rb->eof) {
      if (rb->data_in.super.loop) nxe_ostream_set_ready(rb->data_in.super.loop, &rb->data_in);
      else rb->data_in.ready=1;
    }
    if (rb->read_ptr==rb->write_ptr && !rb->eof) { // nxd_rbuffer_is_empty(rb)
      //nxweb_log_error("rb->read_ptr==rb->write_ptr && !rb->eof => closing rb[%p].data_out", rb);
      if (rb->data_out.super.loop) nxe_istream_unset_ready(&rb->data_out);
      else rb->data_out.ready=0;
    }
  }
}
Esempio n. 6
0
static nxe_size_t resp_body_out_read(nxe_istream* is, nxe_ostream* os, void* ptr, nxe_size_t size, nxe_flags_t* flags) {
  nxd_http_client_proto* hcp=(nxd_http_client_proto*)((char*)is-offsetof(nxd_http_client_proto, resp_body_out));
  nxe_loop* loop=is->super.loop;

  if (hcp->request_complete) {
    nxweb_log_error("hcp->request_complete - resp_body_out_read() should not be called");
    *flags|=NXEF_EOF;
    nxe_istream_unset_ready(is);
    return 0;
  }

  if (hcp->state!=HCP_RECEIVING_BODY) {
    nxe_istream_unset_ready(is);
    nxe_ostream_set_ready(loop, &hcp->data_in); // get notified when prev_is ready
    return 0;
  }

  nxe_size_t bytes_received=0;

  if (hcp->first_body_chunk) {
    nxe_size_t first_body_chunk_size=hcp->first_body_chunk_end-hcp->first_body_chunk;
    if (first_body_chunk_size<=size) {
      bytes_received=first_body_chunk_size;
      memcpy(ptr, hcp->first_body_chunk, bytes_received);
      hcp->first_body_chunk=0;
      hcp->first_body_chunk_end=0;
    }
    else {
      bytes_received=size;
      memcpy(ptr, hcp->first_body_chunk, size);
      hcp->first_body_chunk+=size;
    }
    hcp->resp.content_received+=bytes_received;
    if (hcp->response_body_complete) {
      // rearm connection
      request_complete(hcp, loop);
      nxe_istream_unset_ready(is);
      *flags|=NXEF_EOF;
      return bytes_received;
    }
    ptr+=bytes_received;
    size-=bytes_received;
  }

  if (size>0) {
    nxe_istream* prev_is=hcp->data_in.pair;
    if (prev_is) {
      nxe_size_t bytes_received2=0;
      nxe_flags_t rflags=0;
      if (prev_is->ready) bytes_received2=ISTREAM_CLASS(prev_is)->read(prev_is, &hcp->data_in, ptr, size, &rflags);
      if (!prev_is->ready) {
        nxe_istream_unset_ready(is);
        nxe_ostream_set_ready(loop, &hcp->data_in); // get notified when prev_is becomes ready again
      }

      if (hcp->resp.chunked_encoding) {
        int r=_nxweb_decode_chunked_stream(&hcp->resp.cdstate, ptr, &bytes_received2);
        hcp->resp.content_received+=bytes_received2;
        bytes_received+=bytes_received2;
        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 {
        hcp->resp.content_received+=bytes_received2;
        bytes_received+=bytes_received2;
        if (hcp->resp.content_received >= hcp->resp.content_length && hcp->resp.content_length>=0) {
          hcp->response_body_complete=1;
        }
      }
      if (hcp->response_body_complete) {
        // rearm connection
        request_complete(hcp, loop);
        nxe_istream_unset_ready(is);
        *flags|=NXEF_EOF;
        return bytes_received;
      }
    }
    else {
      if (!prev_is) nxweb_log_error("no connected device for hcp->data_in");
      nxe_istream_unset_ready(is);
    }
  }

  return bytes_received;
}
Esempio n. 7
0
static void data_out_do_write(nxe_istream* is, nxe_ostream* os) {
  nxd_http_client_proto* hcp=(nxd_http_client_proto*)((char*)is-offsetof(nxd_http_client_proto, data_out));
  nxe_loop* loop=is->super.loop;

  nxe_unset_timer(loop, NXWEB_TIMER_WRITE, &hcp->timer_write);
  nxe_set_timer(loop, NXWEB_TIMER_WRITE, &hcp->timer_write);

  if (hcp->state==HCP_CONNECTING) {
    nxe_publish(&hcp->events_pub, (nxe_data)NXD_HCP_CONNECTED);
    if (hcp->req) hcp->state=HCP_SENDING_HEADERS;
    else {
      hcp->state=HCP_IDLE;
      nxe_set_timer(loop, NXWEB_TIMER_KEEP_ALIVE, &hcp->timer_keep_alive);
      nxe_istream_unset_ready(is);
      return;
    }
  }

  if (hcp->state==HCP_SENDING_HEADERS) {
    if (hcp->req_headers_ptr && *hcp->req_headers_ptr) {
      int size=strlen(hcp->req_headers_ptr);
      nxe_flags_t flags=0;
      int bytes_sent=OSTREAM_CLASS(os)->write(os, is, 0, (nxe_data)hcp->req_headers_ptr, size, &flags);
      hcp->req_headers_ptr+=bytes_sent;
      if (bytes_sent<size) return;
    }
    // all headers sent
    hcp->req_headers_ptr=0;
    if (!hcp->req->content_length) {
      // no request body => get response
      start_receiving_response(hcp, loop);
      return;
    }
    if (hcp->req->expect_100_continue) {
      nxe_istream_unset_ready(is);
      wait_for_100_continue(hcp, loop);
      return;
    }
    hcp->state=HCP_SENDING_BODY;
  }

  if (hcp->state==HCP_SENDING_BODY) {
    hcp->req_body_sending_started=1;
    nxe_istream* prev_is=hcp->req_body_in.pair;
    if (prev_is) {
      if (prev_is->ready) {
        hcp->req_body_in.ready=1;
        ISTREAM_CLASS(prev_is)->do_write(prev_is, &hcp->req_body_in);
      }
      if (!prev_is->ready) {
        nxe_istream_unset_ready(is);
        nxe_ostream_set_ready(loop, &hcp->req_body_in); // get notified when prev_is becomes ready again
      }
    }
    else {
      nxweb_log_error("no connected device for hcp->req_body_in");
      nxe_istream_unset_ready(is);
    }
  }
  else {
    // wrong state
    nxweb_log_error("called data_out_do_write() at wrong HCP state %d", hcp->state);
    nxe_istream_unset_ready(is);
  }
}