diff --git a/mio/lib/http-fil.c b/mio/lib/http-fil.c index 9cbb323..8a582b1 100644 --- a/mio/lib/http-fil.c +++ b/mio/lib/http-fil.c @@ -370,15 +370,8 @@ static int file_client_on_write (mio_dev_sck_t* sck, mio_iolen_t wrlen, void* wr MIO_ASSERT (mio, file_state->num_pending_writes_to_client > 0); file_state->num_pending_writes_to_client--; -#if 0 -XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX - if (file_state->peer && file_state->num_pending_writes_to_client == FILE_STATE_PENDING_IO_THRESHOLD) - { - if (!(file_state->over & FILE_STATE_OVER_READ_FROM_PEER) && - mio_dev_pro_read(file_state->peer, MIO_DEV_PRO_OUT, 1) <= -1) goto oops; - } -#endif - file_state_send_contents_to_client (file_state); + if (file_state->req_method == MIO_HTTP_GET) + file_state_send_contents_to_client (file_state); if ((file_state->over & FILE_STATE_OVER_READ_FROM_PEER) && file_state->num_pending_writes_to_client <= 0) { @@ -598,6 +591,7 @@ static int open_peer (file_state_t* file_state, const mio_bch_t* actual_file) switch (file_state->req_method) { case MIO_HTTP_GET: + case MIO_HTTP_HEAD: if (access(actual_file, R_OK) == -1) { file_state_send_final_status_to_client (file_state, ERRNO_TO_STATUS_CODE(errno), 1); /* 404 not found 403 Forbidden */ @@ -613,6 +607,7 @@ static int open_peer (file_state_t* file_state, const mio_bch_t* actual_file) return 0; +#if 0 case MIO_HTTP_PUT: case MIO_HTTP_POST: /* TOOD: this is destructive. jump to default if not allowed by flags... */ @@ -633,6 +628,7 @@ static int open_peer (file_state_t* file_state, const mio_bch_t* actual_file) return -1; } return 0; +#endif #if 0 case MIO_HTTP_DELETE: @@ -654,6 +650,8 @@ static MIO_INLINE void fadvise_on_peer (file_state_t* file_state) int mio_svc_htts_dofile (mio_svc_htts_t* htts, mio_dev_sck_t* csck, mio_htre_t* req, const mio_bch_t* docroot, const mio_bch_t* file) { +/* TODO: ETag, Last-Modified... */ + mio_t* mio = htts->mio; mio_svc_htts_cli_t* cli = mio_dev_sck_getxtn(csck); file_state_t* file_state = MIO_NULL; @@ -708,23 +706,10 @@ int mio_svc_htts_dofile (mio_svc_htts_t* htts, mio_dev_sck_t* csck, mio_htre_t* if (req->flags & MIO_HTRE_ATTR_EXPECT100) { -/* TODO: check method. if GET, file contents can be transmitted without 100 continue ... */ if (mio_comp_http_version_numbers(&req->version, 1, 1) >= 0 && - (file_state->req_content_length_unlimited || file_state->req_content_length > 0)) + (file_state->req_content_length_unlimited || file_state->req_content_length > 0) && + (file_state->req_method != MIO_HTTP_GET && file_state->req_method != MIO_HTTP_HEAD)) { - /* - * Don't send 100 Continue if http verions is lower than 1.1 - * [RFC7231] - * A server that receives a 100-continue expectation in an HTTP/1.0 - * request MUST ignore that expectation. - * - * Don't send 100 Continue if expected content lenth is 0. - * [RFC7231] - * A server MAY omit sending a 100 (Continue) response if it has - * already received some or all of the message body for the - * corresponding request, or if the framing indicates that there is - * no message body. - */ mio_bch_t msgbuf[64]; mio_oow_t msglen; @@ -788,6 +773,11 @@ int mio_svc_htts_dofile (mio_svc_htts_t* htts, mio_dev_sck_t* csck, mio_htre_t* if (file_state_send_header_to_client(file_state, 200, 0) <= -1 || file_state_send_contents_to_client(file_state) <= -1) goto oops; } + else if (file_state->req_method == MIO_HTTP_HEAD) + { + if (file_state_send_header_to_client(file_state, 200, 0) <= -1) goto oops; + file_state_mark_over (file_state, FILE_STATE_OVER_READ_FROM_PEER | FILE_STATE_OVER_WRITE_TO_PEER); + } /* TODO: store current input watching state and use it when destroying the file_state data */ if (mio_dev_sck_read(csck, !(file_state->over & FILE_STATE_OVER_READ_FROM_CLIENT)) <= -1) goto oops; diff --git a/mio/lib/http-svr.c b/mio/lib/http-svr.c index 063e0e1..7058e01 100644 --- a/mio/lib/http-svr.c +++ b/mio/lib/http-svr.c @@ -153,7 +153,6 @@ static int listener_on_read (mio_dev_sck_t* sck, const void* buf, mio_iolen_t le if ((x = mio_htrd_feed(cli->htrd, buf, len, &rem)) <= -1) { -printf ("** HTTS - client htrd feed failure socket(%p) - %d\n", sck, x); goto oops; } @@ -172,7 +171,6 @@ printf ("** HTTS - client htrd feed failure socket(%p) - %d\n", sck, x); return 0; oops: -printf ("HALTING CLIENT SOCKEXXT %p\n", sck); mio_dev_sck_halt (sck); return 0; } diff --git a/mio/lib/http-thr.c b/mio/lib/http-thr.c index fec2109..9d41cb7 100644 --- a/mio/lib/http-thr.c +++ b/mio/lib/http-thr.c @@ -879,7 +879,7 @@ int mio_svc_htts_dothr (mio_svc_htts_t* htts, mio_dev_sck_t* csck, mio_htre_t* r MIO_SVC_HTTS_RSRC_ATTACH (thr_state, cli->rsrc); thr_state->peer = mio_dev_thr_make(mio, MIO_SIZEOF(*thr_peer), &mi); - if (MIO_UNLIKELY(!thr_state->peer)) goto oops; + if (MIO_UNLIKELY(!thr_state->peer)) { printf ("dev thr make failure. \n"); goto oops; } tfs = MIO_NULL; /* mark that tfs is delegated to the thread */ diff --git a/mio/lib/mio.c b/mio/lib/mio.c index c8d13bd..32fbe43 100644 --- a/mio/lib/mio.c +++ b/mio/lib/mio.c @@ -1231,14 +1231,130 @@ static void on_write_timeout (mio_t* mio, const mio_ntime_t* now, mio_tmrjob_t* if (x <= -1) mio_dev_halt (dev); } +static MIO_INLINE int __enqueue_completed_write (mio_dev_t* dev, mio_iolen_t len, void* wrctx, const mio_devaddr_t* dstaddr) +{ + mio_t* mio = dev->mio; + mio_cwq_t* cwq; + mio_oow_t cwq_extra_aligned, cwqfl_index; + + cwq_extra_aligned = (dstaddr? dstaddr->len: 0); + cwq_extra_aligned = MIO_ALIGN_POW2(cwq_extra_aligned, MIO_CWQFL_ALIGN); + cwqfl_index = cwq_extra_aligned / MIO_CWQFL_SIZE; + + if (cwqfl_index < MIO_COUNTOF(mio->cwqfl) && mio->cwqfl[cwqfl_index]) + { + /* take an available cwq object from the free cwq list */ + cwq = dev->mio->cwqfl[cwqfl_index]; + dev->mio->cwqfl[cwqfl_index] = cwq->q_next; + } + else + { + cwq = (mio_cwq_t*)mio_allocmem(mio, MIO_SIZEOF(*cwq) + cwq_extra_aligned); + if (MIO_UNLIKELY(!cwq)) return -1; + } + + MIO_MEMSET (cwq, 0, MIO_SIZEOF(*cwq)); + cwq->dev = dev; + cwq->ctx = wrctx; + if (dstaddr) + { + cwq->dstaddr.ptr = (mio_uint8_t*)(cwq + 1); + cwq->dstaddr.len = dstaddr->len; + MIO_MEMCPY (cwq->dstaddr.ptr, dstaddr->ptr, dstaddr->len); + } + else + { + cwq->dstaddr.len = 0; + } + + cwq->olen = len; + + MIO_CWQ_ENQ (&dev->mio->cwq, cwq); + dev->cw_count++; /* increment the number of complete write operations */ + return 0; +} + +static MIO_INLINE int __enqueue_pending_write (mio_dev_t* dev, mio_iolen_t olen, mio_iolen_t urem, mio_iovec_t* iov, mio_iolen_t iov_cnt, mio_iolen_t iov_index, const mio_ntime_t* tmout, void* wrctx, const mio_devaddr_t* dstaddr) +{ + mio_t* mio = dev->mio; + mio_wq_t* q; + mio_iolen_t i, j; + + if (dev->dev_cap & MIO_DEV_CAP_OUT_UNQUEUEABLE) + { + /* writing queuing is not requested. so return failure */ + mio_seterrbfmt (mio, MIO_ENOCAPA, "device incapable of queuing"); + return -1; + } + + /* queue the remaining data*/ + q = (mio_wq_t*)mio_allocmem(mio, MIO_SIZEOF(*q) + (dstaddr? dstaddr->len: 0) + urem); + if (MIO_UNLIKELY(!q)) return -1; + + q->tmridx = MIO_TMRIDX_INVALID; + q->dev = dev; + q->ctx = wrctx; + + if (dstaddr) + { + q->dstaddr.ptr = (mio_uint8_t*)(q + 1); + q->dstaddr.len = dstaddr->len; + MIO_MEMCPY (q->dstaddr.ptr, dstaddr->ptr, dstaddr->len); + } + else + { + q->dstaddr.len = 0; + } + + q->ptr = (mio_uint8_t*)(q + 1) + q->dstaddr.len; + q->len = urem; + q->olen = olen; /* original length to use when invoking on_write() */ + for (i = iov_index, j = 0; i < iov_cnt; i++) + { + MIO_MEMCPY (&q->ptr[j], iov[i].iov_ptr, iov[i].iov_len); + j += iov[i].iov_len; + } + + if (tmout && MIO_IS_POS_NTIME(tmout)) + { + mio_tmrjob_t tmrjob; + + MIO_MEMSET (&tmrjob, 0, MIO_SIZEOF(tmrjob)); + tmrjob.ctx = q; + mio_gettime (mio, &tmrjob.when); + MIO_ADD_NTIME (&tmrjob.when, &tmrjob.when, tmout); + tmrjob.handler = on_write_timeout; + tmrjob.idxptr = &q->tmridx; + + q->tmridx = mio_instmrjob(mio, &tmrjob); + if (q->tmridx == MIO_TMRIDX_INVALID) + { + mio_freemem (mio, q); + return -1; + } + } + + MIO_WQ_ENQ (&dev->wq, q); + if (!(dev->dev_cap & MIO_DEV_CAP_OUT_WATCHED)) + { + /* if output is not being watched, arrange to do so */ + if (mio_dev_watch(dev, MIO_DEV_WATCH_RENEW, MIO_DEV_EVENT_IN) <= -1) + { + unlink_wq (mio, q); + mio_freemem (mio, q); + return -1; + } + } + + return 0; /* request pused to a write queue. */ +} + static int __dev_write (mio_dev_t* dev, const void* data, mio_iolen_t len, const mio_ntime_t* tmout, void* wrctx, const mio_devaddr_t* dstaddr) { mio_t* mio = dev->mio; const mio_uint8_t* uptr; mio_iolen_t urem, ulen; - mio_wq_t* q; - mio_cwq_t* cwq; - mio_oow_t cwq_extra_aligned, cwqfl_index; + mio_iovec_t iov; int x; if (dev->dev_cap & MIO_DEV_CAP_OUT_CLOSED) @@ -1317,120 +1433,22 @@ static int __dev_write (mio_dev_t* dev, const void* data, mio_iolen_t len, const goto enqueue_completed_write; } - return 1; /* written immediately and called on_write callback */ + return 1; /* written immediately and called on_write callback. but this line will never be reached */ enqueue_data: - if (dev->dev_cap & MIO_DEV_CAP_OUT_UNQUEUEABLE) - { - /* writing queuing is not requested. so return failure */ - mio_seterrbfmt (mio, MIO_ENOCAPA, "device incapable of queuing"); - return -1; - } - - /* queue the remaining data*/ - q = (mio_wq_t*)mio_allocmem(mio, MIO_SIZEOF(*q) + (dstaddr? dstaddr->len: 0) + urem); - if (!q) return -1; - - q->tmridx = MIO_TMRIDX_INVALID; - q->dev = dev; - q->ctx = wrctx; - - if (dstaddr) - { - q->dstaddr.ptr = (mio_uint8_t*)(q + 1); - q->dstaddr.len = dstaddr->len; - MIO_MEMCPY (q->dstaddr.ptr, dstaddr->ptr, dstaddr->len); - } - else - { - q->dstaddr.len = 0; - } - - q->ptr = (mio_uint8_t*)(q + 1) + q->dstaddr.len; - q->len = urem; - q->olen = len; - MIO_MEMCPY (q->ptr, uptr, urem); - - if (tmout && MIO_IS_POS_NTIME(tmout)) - { - mio_tmrjob_t tmrjob; - - MIO_MEMSET (&tmrjob, 0, MIO_SIZEOF(tmrjob)); - tmrjob.ctx = q; - mio_gettime (mio, &tmrjob.when); - MIO_ADD_NTIME (&tmrjob.when, &tmrjob.when, tmout); - tmrjob.handler = on_write_timeout; - tmrjob.idxptr = &q->tmridx; - - q->tmridx = mio_instmrjob(mio, &tmrjob); - if (q->tmridx == MIO_TMRIDX_INVALID) - { - mio_freemem (mio, q); - return -1; - } - } - - MIO_WQ_ENQ (&dev->wq, q); - if (!(dev->dev_cap & MIO_DEV_CAP_OUT_WATCHED)) - { - /* if output is not being watched, arrange to do so */ - if (mio_dev_watch(dev, MIO_DEV_WATCH_RENEW, MIO_DEV_EVENT_IN) <= -1) - { - unlink_wq (mio, q); - mio_freemem (mio, q); - return -1; - } - } - - return 0; /* request pused to a write queue. */ + iov.iov_ptr = (void*)uptr; + iov.iov_len = urem; + return __enqueue_pending_write(dev, len, urem, &iov, 1, 0, tmout, wrctx, dstaddr); enqueue_completed_write: - /* queue the remaining data*/ - cwq_extra_aligned = (dstaddr? dstaddr->len: 0); - cwq_extra_aligned = MIO_ALIGN_POW2(cwq_extra_aligned, MIO_CWQFL_ALIGN); - cwqfl_index = cwq_extra_aligned / MIO_CWQFL_SIZE; - - if (cwqfl_index < MIO_COUNTOF(mio->cwqfl) && mio->cwqfl[cwqfl_index]) - { - /* take an available cwq object from the free cwq list */ - cwq = dev->mio->cwqfl[cwqfl_index]; - dev->mio->cwqfl[cwqfl_index] = cwq->q_next; - } - else - { - cwq = (mio_cwq_t*)mio_allocmem(mio, MIO_SIZEOF(*cwq) + cwq_extra_aligned); - if (MIO_UNLIKELY(!cwq)) return -1; - } - - MIO_MEMSET (cwq, 0, MIO_SIZEOF(*cwq)); - cwq->dev = dev; - cwq->ctx = wrctx; - if (dstaddr) - { - cwq->dstaddr.ptr = (mio_uint8_t*)(cwq + 1); - cwq->dstaddr.len = dstaddr->len; - MIO_MEMCPY (cwq->dstaddr.ptr, dstaddr->ptr, dstaddr->len); - } - else - { - cwq->dstaddr.len = 0; - } - - cwq->olen = len; - - MIO_CWQ_ENQ (&dev->mio->cwq, cwq); - dev->cw_count++; /* increment the number of complete write operations */ - return 0; + return __enqueue_completed_write(dev, len, wrctx, dstaddr); } static int __dev_writev (mio_dev_t* dev, mio_iovec_t* iov, mio_iolen_t iovcnt, const mio_ntime_t* tmout, void* wrctx, const mio_devaddr_t* dstaddr) { mio_t* mio = dev->mio; mio_iolen_t urem, len; - mio_iolen_t index = 0, i, j; - mio_wq_t* q; - mio_cwq_t* cwq; - mio_oow_t cwq_extra_aligned, cwqfl_index; + mio_iolen_t index = 0, i; int x; if (dev->dev_cap & MIO_DEV_CAP_OUT_CLOSED) @@ -1522,117 +1540,41 @@ static int __dev_writev (mio_dev_t* dev, mio_iovec_t* iov, mio_iolen_t iovcnt, c goto enqueue_completed_write; } - return 1; /* written immediately and called on_write callback */ + return 1; /* written immediately and called on_write callback. but this line will never be reached */ enqueue_data: - if (dev->dev_cap & MIO_DEV_CAP_OUT_UNQUEUEABLE) + return __enqueue_pending_write(dev, len, urem, iov, iovcnt, index, tmout, wrctx, dstaddr); + +enqueue_completed_write: + return __enqueue_completed_write(dev, len, wrctx, dstaddr); +} + +static int __dev_sendfile (mio_dev_t* dev, mio_syshnd_t in_fd, mio_uintmax_t offset, mio_iolen_t len, const mio_ntime_t* tmout, void* wrctx, const mio_devaddr_t* dstaddr) +{ + mio_t* mio = dev->mio; + + if (dev->dev_cap & MIO_DEV_CAP_OUT_CLOSED) { - /* writing queuing is not requested. so return failure */ - mio_seterrbfmt (mio, MIO_ENOCAPA, "device incapable of queuing"); + mio_seterrbfmt (mio, MIO_ENOCAPA, "unable to write to closed device"); return -1; } - /* queue the remaining data*/ - q = (mio_wq_t*)mio_allocmem(mio, MIO_SIZEOF(*q) + (dstaddr? dstaddr->len: 0) + urem); - if (MIO_UNLIKELY(!q)) return -1; - - q->tmridx = MIO_TMRIDX_INVALID; - q->dev = dev; - q->ctx = wrctx; - - if (dstaddr) + if (!MIO_WQ_IS_EMPTY(&dev->wq)) { - q->dstaddr.ptr = (mio_uint8_t*)(q + 1); - q->dstaddr.len = dstaddr->len; - MIO_MEMCPY (q->dstaddr.ptr, dstaddr->ptr, dstaddr->len); - } - else - { - q->dstaddr.len = 0; + /* if the writing queue is not empty, enqueue this request immediately */ + goto enqueue_data; } - q->ptr = (mio_uint8_t*)(q + 1) + q->dstaddr.len; - q->len = urem; - q->olen = len; /* original length to use when invoking on_write() */ - for (i = index, j = 0; i < iovcnt; i++) - { - MIO_MEMCPY (&q->ptr[j], iov[i].iov_ptr, iov[i].iov_len); - j += iov[i].iov_len; - } + return 1; - if (tmout && MIO_IS_POS_NTIME(tmout)) - { - mio_tmrjob_t tmrjob; - - MIO_MEMSET (&tmrjob, 0, MIO_SIZEOF(tmrjob)); - tmrjob.ctx = q; - mio_gettime (mio, &tmrjob.when); - MIO_ADD_NTIME (&tmrjob.when, &tmrjob.when, tmout); - tmrjob.handler = on_write_timeout; - tmrjob.idxptr = &q->tmridx; - - q->tmridx = mio_instmrjob(mio, &tmrjob); - if (q->tmridx == MIO_TMRIDX_INVALID) - { - mio_freemem (mio, q); - return -1; - } - } - - MIO_WQ_ENQ (&dev->wq, q); - if (!(dev->dev_cap & MIO_DEV_CAP_OUT_WATCHED)) - { - /* if output is not being watched, arrange to do so */ - if (mio_dev_watch(dev, MIO_DEV_WATCH_RENEW, MIO_DEV_EVENT_IN) <= -1) - { - unlink_wq (mio, q); - mio_freemem (mio, q); - return -1; - } - } - - return 0; /* request pused to a write queue. */ +enqueue_data: + /*return __enqueue_pending_write(dev, len, urem, iov, iovcnt, index, tmout, wrctx, dstaddr);*/ enqueue_completed_write: - /* queue the remaining data*/ - cwq_extra_aligned = (dstaddr? dstaddr->len: 0); - cwq_extra_aligned = MIO_ALIGN_POW2(cwq_extra_aligned, MIO_CWQFL_ALIGN); - cwqfl_index = cwq_extra_aligned / MIO_CWQFL_SIZE; - - if (cwqfl_index < MIO_COUNTOF(mio->cwqfl) && mio->cwqfl[cwqfl_index]) - { - /* take an available cwq object from the free cwq list */ - cwq = dev->mio->cwqfl[cwqfl_index]; - dev->mio->cwqfl[cwqfl_index] = cwq->q_next; - } - else - { - cwq = (mio_cwq_t*)mio_allocmem(mio, MIO_SIZEOF(*cwq) + cwq_extra_aligned); - if (!cwq) return -1; - } - - MIO_MEMSET (cwq, 0, MIO_SIZEOF(*cwq)); - cwq->dev = dev; - cwq->ctx = wrctx; - if (dstaddr) - { - cwq->dstaddr.ptr = (mio_uint8_t*)(cwq + 1); - cwq->dstaddr.len = dstaddr->len; - MIO_MEMCPY (cwq->dstaddr.ptr, dstaddr->ptr, dstaddr->len); - } - else - { - cwq->dstaddr.len = 0; - } - - cwq->olen = len; - - MIO_CWQ_ENQ (&dev->mio->cwq, cwq); - dev->cw_count++; /* increment the number of complete write operations */ + /*return __enqueue_completed_write(dev, len, wrctx, dstaddr);*/ return 0; } - int mio_dev_write (mio_dev_t* dev, const void* data, mio_iolen_t len, void* wrctx, const mio_devaddr_t* dstaddr) { return __dev_write(dev, data, len, MIO_NULL, wrctx, dstaddr);