changed to clear the on_write callbacks for completed write requestrs after having triggered timer callbacks collectively and also before triggering on_read() for each device
cleaned up debugging messages in dns-cli.c experimenting with http server implementation
This commit is contained in:
parent
cc74d317a2
commit
57ca185651
@ -924,7 +924,7 @@ int main (int argc, char* argv[])
|
||||
setup_arp_tester(mio);
|
||||
setup_ping4_tester(mio);
|
||||
|
||||
#if 1
|
||||
#if 0
|
||||
for (i = 0; i < 5; i++)
|
||||
{
|
||||
mio_dev_pro_t* pro;
|
||||
@ -978,6 +978,7 @@ for (i = 0; i < 5; i++)
|
||||
dnc = mio_svc_dnc_start(mio, &servaddr, MIO_NULL, &send_tmout, &reply_tmout, 2); /* option - send to all, send one by one */
|
||||
htts = mio_svc_htts_start(mio, &htts_bind_addr);
|
||||
mio_svc_htts_setservernamewithbcstr (htts, "MIO-HTTP");
|
||||
|
||||
#if 1
|
||||
{
|
||||
mio_dns_bqr_t qrs[] =
|
||||
|
@ -150,7 +150,7 @@ static void release_dns_msg (mio_svc_dnc_t* dnc, mio_dns_msg_t* msg)
|
||||
mio_t* mio = dnc->mio;
|
||||
dnc_dns_msg_xtn_t* msgxtn = dnc_dns_msg_getxtn(msg);
|
||||
|
||||
MIO_DEBUG1 (mio, "releasing dns msg %d\n", (int)mio_ntoh16(mio_dns_msg_to_pkt(msg)->id));
|
||||
MIO_DEBUG1 (mio, "DNC - releasing dns message - msgid:%d\n", (int)mio_ntoh16(mio_dns_msg_to_pkt(msg)->id));
|
||||
|
||||
if (msg == dnc->pending_req || msgxtn->next || msgxtn->prev)
|
||||
{
|
||||
@ -179,13 +179,13 @@ static int handle_tcp_packet (mio_dev_sck_t* dev, mio_dns_pkt_t* pkt, mio_uint16
|
||||
|
||||
if (!pkt->qr)
|
||||
{
|
||||
MIO_DEBUG0 (mio, "dropping dns request received over tcp ...\n"); /* TODO: add source info */
|
||||
MIO_DEBUG0 (mio, "DNC - dropping dns request received over tcp ...\n"); /* TODO: add source info */
|
||||
return 0; /* drop request. nothing to do */
|
||||
}
|
||||
|
||||
id = mio_ntoh16(pkt->id);
|
||||
|
||||
MIO_DEBUG1 (mio, "<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<GOT DATA>>>>>>>>>>>id [%d] >>>>>>>>>>>>>>>>>>\n", id);
|
||||
MIO_DEBUG1 (mio, "DNC - got dns response over tcp - msgid:%d\n", id);
|
||||
|
||||
reqmsg = dnc->pending_req;
|
||||
while (reqmsg)
|
||||
@ -203,7 +203,7 @@ MIO_DEBUG1 (mio, "<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<GOT DATA>>>>>>>>>>>id [%d] >>>>
|
||||
reqmsg = reqmsgxtn->next;
|
||||
}
|
||||
|
||||
MIO_DEBUG1 (mio, "unknown dns response over tcp... %d\n", pkt->id); /* TODO: add source info */
|
||||
MIO_DEBUG1 (mio, "DNC - unknown dns response over tcp... msgid:%d\n", id); /* TODO: add source info */
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -240,12 +240,12 @@ static int on_tcp_read (mio_dev_sck_t* dev, const void* data, mio_iolen_t dlen,
|
||||
|
||||
if (MIO_UNLIKELY(dlen <= -1))
|
||||
{
|
||||
MIO_DEBUG1 (mio, "dns tcp read error ....%js\n", mio_geterrmsg(mio)); /* TODO: add source packet */
|
||||
MIO_DEBUG1 (mio, "DNC - dns tcp read error ....%js\n", mio_geterrmsg(mio)); /* TODO: add source packet */
|
||||
goto oops;
|
||||
}
|
||||
else if (MIO_UNLIKELY(dlen == 0))
|
||||
{
|
||||
MIO_DEBUG0 (mio, "dns tcp read error ...premature socket hangul\n"); /* TODO: add source packet */
|
||||
MIO_DEBUG0 (mio, "DNC - dns tcp read error ...premature tcp socket end\n"); /* TODO: add source packet */
|
||||
goto oops;
|
||||
}
|
||||
|
||||
@ -311,7 +311,7 @@ static void on_tcp_reply_timeout (mio_t* mio, const mio_ntime_t* now, mio_tmrjob
|
||||
MIO_ASSERT (mio, reqmsgxtn->rtmridx == MIO_TMRIDX_INVALID);
|
||||
MIO_ASSERT (mio, dev == dnc->tcp_sck);
|
||||
|
||||
MIO_DEBUG0 (mio, "*** TIMEOUT ==> unable to receive dns response in time over TCP...\n");
|
||||
MIO_DEBUG1 (mio, "DNC - unable to receive dns response in time over TCP - msgid:%d\n", (int)mio_ntoh16(mio_dns_msg_to_pkt(reqmsg)->id));
|
||||
|
||||
if (MIO_LIKELY(reqmsgxtn->on_done)) reqmsgxtn->on_done (dnc, reqmsg, MIO_ETMOUT, MIO_NULL, 0);
|
||||
release_dns_msg (dnc, reqmsg);
|
||||
@ -336,6 +336,8 @@ static int on_tcp_write (mio_dev_sck_t* dev, mio_iolen_t wrlen, void* wrctx, con
|
||||
/* question. schedule to wait for response */
|
||||
mio_tmrjob_t tmrjob;
|
||||
|
||||
MIO_DEBUG1 (mio, "DNC - sent dns question over tcp - msgid:%d\n", (int)mio_ntoh16(mio_dns_msg_to_pkt(msg)->id));
|
||||
|
||||
MIO_MEMSET (&tmrjob, 0, MIO_SIZEOF(tmrjob));
|
||||
tmrjob.ctx = msg;
|
||||
mio_gettime (mio, &tmrjob.when);
|
||||
@ -347,7 +349,7 @@ static int on_tcp_write (mio_dev_sck_t* dev, mio_iolen_t wrlen, void* wrctx, con
|
||||
{
|
||||
/* call the callback to indicate this operation failure in the middle of transaction */
|
||||
status = mio_geterrnum(mio);
|
||||
MIO_DEBUG0 (mio, "unable to schedule tcp timeout...\n");
|
||||
MIO_DEBUG1 (mio, "DNC - unable to schedule tcp timeout - msgid: %d\n", (int)mio_ntoh16(mio_dns_msg_to_pkt(msg)->id));
|
||||
goto finalize;
|
||||
}
|
||||
|
||||
@ -356,6 +358,7 @@ static int on_tcp_write (mio_dev_sck_t* dev, mio_iolen_t wrlen, void* wrctx, con
|
||||
else
|
||||
{
|
||||
/* no error. successfuly sent a message. no reply is expected */
|
||||
MIO_DEBUG1 (mio, "DNC - sent dns message over tcp - msgid:%d\n", (int)mio_ntoh16(mio_dns_msg_to_pkt(msg)->id));
|
||||
status = MIO_ENOERR;
|
||||
goto finalize;
|
||||
}
|
||||
@ -375,6 +378,8 @@ static int write_dns_msg_over_tcp (mio_dev_sck_t* dev, mio_dns_msg_t* msg)
|
||||
mio_uint16_t pktlen;
|
||||
mio_iovec_t iov[2];
|
||||
|
||||
MIO_DEBUG1 (mio, "DNC - sending dns message over tcp - msgid:%d\n", (int)mio_ntoh16(mio_dns_msg_to_pkt(msg)->id));
|
||||
|
||||
pktlen = mio_hton16(msg->pktlen);
|
||||
|
||||
MIO_ASSERT (mio, msgxtn->rtries == 0);
|
||||
@ -426,11 +431,11 @@ static void on_tcp_disconnect (mio_dev_sck_t* dev)
|
||||
|
||||
if (status == MIO_ENOERR)
|
||||
{
|
||||
MIO_DEBUG0 (mio, "TCP DISCONNECTED\n");
|
||||
MIO_DEBUG0 (mio, "DNC - TCP DISCONNECTED\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
MIO_DEBUG2 (mio, "TCP UNABLED TO CONNECT %d -> %js\n", status, mio_errnum_to_errstr(status));
|
||||
MIO_DEBUG2 (mio, "DNC - TCP UNABLE TO CONNECT %d -> %js\n", status, mio_errnum_to_errstr(status));
|
||||
}
|
||||
|
||||
reqmsg = dnc->pending_req;
|
||||
@ -509,7 +514,7 @@ static int switch_reqmsg_transport_to_tcp (mio_svc_dnc_t* dnc, mio_dns_msg_t* re
|
||||
reqmsgxtn->rtries = 0;
|
||||
if (!reqmsgxtn->pending && mio_dns_msg_to_pkt(reqmsg)->qr == 0) chain_pending_dns_reqmsg (dnc, reqmsg);
|
||||
|
||||
printf ("SWITCHED >>>>>>>>>>>>>>>>> %p %p %p %p %p\n", reqmsg, reqmsgxtn, reqmsgxtn->dev, dnc->udp_sck, dnc->tcp_sck);
|
||||
MIO_DEBUG6 (mio, "DNC - switched transport to tcp - msgid:%d %p %p %p %p %p\n", (int)mio_ntoh16(mio_dns_msg_to_pkt(reqmsg)->id), reqmsg, reqmsgxtn, reqmsgxtn->dev, dnc->udp_sck, dnc->tcp_sck);
|
||||
|
||||
if (MIO_DEV_SCK_GET_PROGRESS(dnc->tcp_sck) & MIO_DEV_SCK_CONNECTED)
|
||||
{
|
||||
@ -536,19 +541,19 @@ static int on_udp_read (mio_dev_sck_t* dev, const void* data, mio_iolen_t dlen,
|
||||
|
||||
if (MIO_UNLIKELY(dlen <= -1))
|
||||
{
|
||||
MIO_DEBUG1 (mio, "dns read error ....%js\n", mio_geterrmsg(mio)); /* TODO: add source packet */
|
||||
MIO_DEBUG1 (mio, "DNC - dns read error ....%js\n", mio_geterrmsg(mio)); /* TODO: add source packet */
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (MIO_UNLIKELY(dlen < MIO_SIZEOF(*pkt)))
|
||||
{
|
||||
MIO_DEBUG0 (mio, "dns packet too small from ....\n"); /* TODO: add source packet */
|
||||
MIO_DEBUG0 (mio, "DNC - dns packet too small from ....\n"); /* TODO: add source packet */
|
||||
return 0; /* drop */
|
||||
}
|
||||
pkt = (mio_dns_pkt_t*)data;
|
||||
if (!pkt->qr)
|
||||
{
|
||||
MIO_DEBUG0 (mio, "dropping dns request received ...\n"); /* TODO: add source info */
|
||||
MIO_DEBUG0 (mio, "DNC - dropping dns request received ...\n"); /* TODO: add source info */
|
||||
return 0; /* drop request */
|
||||
}
|
||||
|
||||
@ -583,7 +588,7 @@ static int on_udp_read (mio_dev_sck_t* dev, const void* data, mio_iolen_t dlen,
|
||||
/* TODO: add an option to call an error callback with TRUNCATION error code instead of fallback to received UDP truncated message */
|
||||
}
|
||||
|
||||
MIO_DEBUG1 (mio, "received dns response over udp..id %d\n", id);
|
||||
MIO_DEBUG1 (mio, "DNC - received dns response over udp for msgid:%d\n", id);
|
||||
if (MIO_LIKELY(reqmsgxtn->on_done)) reqmsgxtn->on_done (dnc, reqmsg, MIO_ENOERR, data, dlen);
|
||||
release_dns_msg (dnc, reqmsg);
|
||||
return 0;
|
||||
@ -593,7 +598,7 @@ MIO_DEBUG1 (mio, "received dns response over udp..id %d\n", id);
|
||||
}
|
||||
|
||||
/* the response id didn't match the ID of pending requests - need to wait longer? */
|
||||
MIO_DEBUG1 (mio, "unknown dns response... %d\n", pkt->id); /* TODO: add source info */
|
||||
MIO_DEBUG1 (mio, "DNC - unknown dns response over udp... msgid:%d\n", id); /* TODO: add source info */
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -608,12 +613,13 @@ static void on_udp_reply_timeout (mio_t* mio, const mio_ntime_t* now, mio_tmrjob
|
||||
MIO_ASSERT (mio, msgxtn->rtmridx == MIO_TMRIDX_INVALID);
|
||||
MIO_ASSERT (mio, dev == dnc->udp_sck);
|
||||
|
||||
MIO_DEBUG0 (mio, "*** TIMEOUT ==> unable to receive dns response in time...\n");
|
||||
MIO_DEBUG1 (mio, "DNC - unable to receive dns response in time over udp - msgid:%d\n", (int)mio_ntoh16(mio_dns_msg_to_pkt(reqmsg)->id));
|
||||
if (msgxtn->rtries < msgxtn->rmaxtries)
|
||||
{
|
||||
mio_ntime_t* tmout;
|
||||
|
||||
tmout = MIO_IS_POS_NTIME(&msgxtn->wtmout)? &msgxtn->wtmout: MIO_NULL;
|
||||
MIO_DEBUG1 (mio, "DNC - sending dns question again over udp - msgid:%d\n", (int)mio_ntoh16(mio_dns_msg_to_pkt(reqmsg)->id));
|
||||
if (mio_dev_sck_timedwrite(dev, mio_dns_msg_to_pkt(reqmsg), reqmsg->pktlen, tmout, reqmsg, &msgxtn->servaddr) >= 0) return; /* resent */
|
||||
|
||||
/* retry failed */
|
||||
@ -624,7 +630,6 @@ MIO_DEBUG0 (mio, "*** TIMEOUT ==> unable to receive dns response in time...\n");
|
||||
release_dns_msg (dnc, reqmsg);
|
||||
}
|
||||
|
||||
|
||||
static int on_udp_write (mio_dev_sck_t* dev, mio_iolen_t wrlen, void* wrctx, const mio_skad_t* dstaddr)
|
||||
{
|
||||
mio_t* mio = dev->mio;
|
||||
@ -646,7 +651,7 @@ static int on_udp_write (mio_dev_sck_t* dev, mio_iolen_t wrlen, void* wrctx, con
|
||||
/* question. schedule to wait for response */
|
||||
mio_tmrjob_t tmrjob;
|
||||
|
||||
MIO_DEBUG1 (mio, "sent dns question %d\n", (int)mio_ntoh16(mio_dns_msg_to_pkt(msg)->id));
|
||||
MIO_DEBUG1 (mio, "DNC - sent dns question over udp - msgid:%d\n", (int)mio_ntoh16(mio_dns_msg_to_pkt(msg)->id));
|
||||
MIO_MEMSET (&tmrjob, 0, MIO_SIZEOF(tmrjob));
|
||||
tmrjob.ctx = msg;
|
||||
mio_gettime (mio, &tmrjob.when);
|
||||
@ -658,10 +663,10 @@ MIO_DEBUG1 (mio, "sent dns question %d\n", (int)mio_ntoh16(mio_dns_msg_to_pkt(ms
|
||||
{
|
||||
/* call the callback to indicate this operation failure in the middle of transaction */
|
||||
status = mio_geterrnum(mio);
|
||||
MIO_DEBUG0 (mio, "unable to schedule timeout...\n");
|
||||
MIO_DEBUG1 (mio, "DNC - unable to schedule udp timeout - msgid:%d\n", (int)mio_ntoh16(mio_dns_msg_to_pkt(msg)->id));
|
||||
goto finalize;
|
||||
}
|
||||
|
||||
|
||||
if (msgxtn->rtries == 0)
|
||||
{
|
||||
/* this is the first wait */
|
||||
@ -673,7 +678,7 @@ MIO_DEBUG1 (mio, "sent dns question %d\n", (int)mio_ntoh16(mio_dns_msg_to_pkt(ms
|
||||
}
|
||||
else
|
||||
{
|
||||
MIO_DEBUG1 (mio, "sent dns message %d\n", (int)mio_ntoh16(mio_dns_msg_to_pkt(msg)->id));
|
||||
MIO_DEBUG1 (mio, "DNC - sent dns message over udp - msgid:%d\n", (int)mio_ntoh16(mio_dns_msg_to_pkt(msg)->id));
|
||||
/* sent an answer. however this may be a question if msgxtn->rmaxtries is 0. */
|
||||
status = MIO_ENOERR;
|
||||
goto finalize;
|
||||
@ -693,7 +698,7 @@ static void on_udp_connect (mio_dev_sck_t* dev)
|
||||
|
||||
static void on_udp_disconnect (mio_dev_sck_t* dev)
|
||||
{
|
||||
mio_t* mio = dev->mio;
|
||||
/*mio_t* mio = dev->mio;*/
|
||||
mio_svc_dnc_t* dnc = ((dnc_sck_xtn_t*)mio_dev_sck_getxtn(dev))->dnc;
|
||||
mio_dns_msg_t* reqmsg;
|
||||
|
||||
@ -763,6 +768,7 @@ mio_svc_dnc_t* mio_svc_dnc_start (mio_t* mio, const mio_skad_t* serv_addr, const
|
||||
}
|
||||
|
||||
MIO_SVCL_APPEND_SVC (&mio->actsvc, (mio_svc_t*)dnc);
|
||||
MIO_DEBUG1 (mio, "DNC - STARTED SERVICE %p\n", dnc);
|
||||
return dnc;
|
||||
|
||||
oops:
|
||||
@ -778,6 +784,7 @@ void mio_svc_dnc_stop (mio_svc_dnc_t* dnc)
|
||||
{
|
||||
mio_t* mio = dnc->mio;
|
||||
|
||||
MIO_DEBUG1 (mio, "DNC - STOPPING SERVICE %p\n", dnc);
|
||||
if (dnc->udp_sck) mio_dev_sck_kill (dnc->udp_sck);
|
||||
if (dnc->tcp_sck) mio_dev_sck_kill (dnc->tcp_sck);
|
||||
while (dnc->pending_req) release_dns_msg (dnc, dnc->pending_req);
|
||||
@ -793,6 +800,8 @@ static MIO_INLINE int send_dns_msg (mio_svc_dnc_t* dnc, mio_dns_msg_t* msg, int
|
||||
|
||||
if ((send_flags & MIO_SVC_DNC_SEND_FLAG_PREFER_TCP) && switch_reqmsg_transport_to_tcp(dnc, msg) >= 0) return 0;
|
||||
|
||||
MIO_DEBUG1 (dnc->mio, "DNC - sending dns message over udp - msgid:%d\n", (int)mio_ntoh16(mio_dns_msg_to_pkt(msg)->id));
|
||||
|
||||
tmout = MIO_IS_POS_NTIME(&msgxtn->wtmout)? &msgxtn->wtmout: MIO_NULL;
|
||||
/* TODO: optionally, override dnc->serv_addr and use the target address passed as a parameter */
|
||||
return mio_dev_sck_timedwrite(dnc->udp_sck, mio_dns_msg_to_pkt(msg), msg->pktlen, tmout, msg, &msgxtn->servaddr);
|
||||
|
@ -728,7 +728,7 @@ static mio_htb_pair_t* hdr_cbserter (
|
||||
}
|
||||
else
|
||||
{
|
||||
if (capture_key_header (tx->htrd, p) <= -1)
|
||||
if (capture_key_header(tx->htrd, p) <= -1)
|
||||
{
|
||||
/* Destroy the pair created here
|
||||
* as it is not added to the hash table yet */
|
||||
@ -793,7 +793,7 @@ static mio_htb_pair_t* hdr_cbserter (
|
||||
/* append it to the list*/
|
||||
tmp->next = val;
|
||||
|
||||
if (capture_key_header (tx->htrd, pair) <= -1) return MIO_NULL;
|
||||
if (capture_key_header(tx->htrd, pair) <= -1) return MIO_NULL;
|
||||
return pair;
|
||||
}
|
||||
}
|
||||
@ -1102,7 +1102,7 @@ done:
|
||||
}
|
||||
|
||||
/* feed the percent encoded string */
|
||||
int mio_htrd_feed (mio_htrd_t* htrd, const mio_bch_t* req, mio_oow_t len)
|
||||
int mio_htrd_feed (mio_htrd_t* htrd, const mio_bch_t* req, mio_oow_t len, mio_oow_t* rem)
|
||||
{
|
||||
const mio_bch_t* end = req + len;
|
||||
const mio_bch_t* ptr = req;
|
||||
@ -1122,7 +1122,7 @@ int mio_htrd_feed (mio_htrd_t* htrd, const mio_bch_t* req, mio_oow_t len)
|
||||
{
|
||||
/* treat everything as contents.
|
||||
* i don't care about headers or whatsoever. */
|
||||
return push_content (htrd, req, len);
|
||||
return push_content(htrd, req, len);
|
||||
}
|
||||
|
||||
/* does this goto drop code maintainability? */
|
||||
@ -1199,7 +1199,7 @@ int mio_htrd_feed (mio_htrd_t* htrd, const mio_bch_t* req, mio_oow_t len)
|
||||
|
||||
/* we got a complete request header. */
|
||||
MIO_ASSERT (htrd->mio, htrd->fed.s.crlf <= 3);
|
||||
|
||||
|
||||
/* reset the crlf state */
|
||||
htrd->fed.s.crlf = 0;
|
||||
/* reset the raw request length */
|
||||
@ -1228,7 +1228,7 @@ int mio_htrd_feed (mio_htrd_t* htrd, const mio_bch_t* req, mio_oow_t len)
|
||||
* reading CGI outputs. So it comes with
|
||||
* awkwardity described above.
|
||||
*/
|
||||
if (ptr < end && push_content (htrd, ptr, end - ptr) <= -1) return -1;
|
||||
if (ptr < end && push_content(htrd, ptr, end - ptr) <= -1) return -1;
|
||||
|
||||
/* i don't really know if it is really completed
|
||||
* with content. MIO_HTRD_PEEKONLY is not compatible
|
||||
@ -1246,7 +1246,7 @@ int mio_htrd_feed (mio_htrd_t* htrd, const mio_bch_t* req, mio_oow_t len)
|
||||
if (htrd->re.flags & MIO_HTRE_ATTR_CHUNKED)
|
||||
{
|
||||
/* transfer-encoding: chunked */
|
||||
MIO_ASSERT (htrd->mio, !(htrd->re.flags & MIO_HTRE_ATTR_LENGTH));
|
||||
/*MIO_ASSERT (htrd->mio, !(htrd->re.flags & MIO_HTRE_ATTR_LENGTH)); <- this assertion is wrong. non-conforming client may include content-length while transfer-encoding is chunked*/
|
||||
|
||||
dechunk_start:
|
||||
htrd->fed.s.chunk.phase = GET_CHUNK_LEN;
|
||||
@ -1254,8 +1254,8 @@ int mio_htrd_feed (mio_htrd_t* htrd, const mio_bch_t* req, mio_oow_t len)
|
||||
htrd->fed.s.chunk.count = 0;
|
||||
|
||||
dechunk_resume:
|
||||
ptr = getchunklen (htrd, ptr, end - ptr);
|
||||
if (ptr == MIO_NULL) return -1;
|
||||
ptr = getchunklen(htrd, ptr, end - ptr);
|
||||
if (MIO_UNLIKELY(!ptr)) return -1;
|
||||
|
||||
if (htrd->fed.s.chunk.phase == GET_CHUNK_LEN)
|
||||
{
|
||||
@ -1274,8 +1274,8 @@ int mio_htrd_feed (mio_htrd_t* htrd, const mio_bch_t* req, mio_oow_t len)
|
||||
htrd->fed.s.crlf = 2;
|
||||
|
||||
dechunk_get_trailers:
|
||||
ptr = get_trailing_headers (htrd, ptr, end);
|
||||
if (ptr == MIO_NULL) return -1;
|
||||
ptr = get_trailing_headers(htrd, ptr, end);
|
||||
if (!MIO_UNLIKELY(ptr)) return -1;
|
||||
|
||||
if (htrd->fed.s.chunk.phase == GET_CHUNK_TRAILERS)
|
||||
{
|
||||
@ -1450,12 +1450,12 @@ XXXXXXXX
|
||||
* plus complete content body and the header
|
||||
* of the next request. */
|
||||
int n;
|
||||
htrd->errnum = MIO_HTRD_ENOERR;
|
||||
htrd->errnum = MIO_HTRD_ENOERR;
|
||||
n = htrd->recbs->peek(htrd, &htrd->re);
|
||||
if (n <= -1)
|
||||
{
|
||||
if (htrd->errnum == MIO_HTRD_ENOERR)
|
||||
htrd->errnum = MIO_HTRD_ERECBS;
|
||||
htrd->errnum = MIO_HTRD_ERECBS;
|
||||
/* need to clear request on error?
|
||||
clear_feed (htrd); */
|
||||
return -1;
|
||||
@ -1472,7 +1472,7 @@ XXXXXXXX
|
||||
if (n <= -1)
|
||||
{
|
||||
if (htrd->errnum == MIO_HTRD_ENOERR)
|
||||
htrd->errnum = MIO_HTRD_ERECBS;
|
||||
htrd->errnum = MIO_HTRD_ERECBS;
|
||||
/* need to clear request on error?
|
||||
clear_feed (htrd); */
|
||||
return -1;
|
||||
@ -1484,28 +1484,37 @@ mio_printf (MIO_T("CONTENT_LENGTH %d, RAW HEADER LENGTH %d\n"),
|
||||
(int)MIO_BECS_LEN(&htrd->re.content),
|
||||
(int)MIO_BECS_LEN(&htrd->fed.b.raw));
|
||||
#endif
|
||||
|
||||
clear_feed (htrd);
|
||||
if (ptr >= end) return 0; /* no more feeds to handle */
|
||||
|
||||
if (htrd->flags & FEEDING_SUSPENDED)
|
||||
if (rem)
|
||||
{
|
||||
/* stop even if there are fed data left */
|
||||
*rem = end - ptr; /* remaining feeds */
|
||||
return 0; /* to indicate completed when the 'rem' is not NULL */
|
||||
}
|
||||
else if (ptr >= end)
|
||||
{
|
||||
/* no more feeds to handle */
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (htrd->flags & FEEDING_SUSPENDED) /* in case the callback called mio_htrd_suspend() */
|
||||
{
|
||||
htrd->errnum = MIO_HTRD_ESUSPENDED;
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*if (htrd->option & MIO_HTRD_DUMMY)*/
|
||||
if (htrd->flags & FEEDING_DUMMIFIED)
|
||||
if (htrd->flags & FEEDING_DUMMIFIED) /* in case the callback called mio_htrd_dummify() */
|
||||
{
|
||||
/* once the mode changes to RAW in a callback,
|
||||
* left-over is pushed as contents */
|
||||
if (ptr < end)
|
||||
return push_content (htrd, ptr, end - ptr);
|
||||
return push_content(htrd, ptr, end - ptr);
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* let ptr point to the next character to LF or
|
||||
* the optional contents */
|
||||
req = ptr;
|
||||
@ -1537,31 +1546,32 @@ mio_printf (MIO_T("CONTENT_LENGTH %d, RAW HEADER LENGTH %d\n"),
|
||||
if (ptr > req)
|
||||
{
|
||||
/* enbuffer the incomplete request */
|
||||
if (push_to_buffer (htrd, &htrd->fed.b.raw, req, ptr - req) <= -1) return -1;
|
||||
if (push_to_buffer(htrd, &htrd->fed.b.raw, req, ptr - req) <= -1) return -1;
|
||||
}
|
||||
|
||||
feedme_more:
|
||||
if (header_completed_during_this_feed && htrd->recbs->peek)
|
||||
{
|
||||
int n;
|
||||
htrd->errnum = MIO_HTRD_ENOERR;
|
||||
n = htrd->recbs->peek (htrd, &htrd->re);
|
||||
htrd->errnum = MIO_HTRD_ENOERR;
|
||||
n = htrd->recbs->peek(htrd, &htrd->re);
|
||||
if (n <= -1)
|
||||
{
|
||||
if (htrd->errnum == MIO_HTRD_ENOERR)
|
||||
htrd->errnum = MIO_HTRD_ERECBS;
|
||||
htrd->errnum = MIO_HTRD_ERECBS;
|
||||
/* need to clear request on error?
|
||||
clear_feed (htrd); */
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
if (rem) *rem = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int mio_htrd_halt (mio_htrd_t* htrd)
|
||||
{
|
||||
if (htrd->fed.s.flags & CONSUME_UNTIL_CLOSE || !htrd->clean)
|
||||
if ((htrd->fed.s.flags & CONSUME_UNTIL_CLOSE) || !htrd->clean)
|
||||
{
|
||||
mio_htre_completecontent (&htrd->re);
|
||||
|
||||
@ -1573,7 +1583,7 @@ int mio_htrd_halt (mio_htrd_t* htrd)
|
||||
if (n <= -1)
|
||||
{
|
||||
if (htrd->errnum == MIO_HTRD_ENOERR)
|
||||
htrd->errnum = MIO_HTRD_ERECBS;
|
||||
htrd->errnum = MIO_HTRD_ERECBS;
|
||||
/* need to clear request on error?
|
||||
clear_feed (htrd); */
|
||||
return -1;
|
||||
@ -1657,7 +1667,7 @@ int mio_htrd_scanqparam (mio_htrd_t* htrd, const mio_bcs_t* cstr)
|
||||
MIO_ASSERT (htrd->mio, htrd->recbs->qparamstr != MIO_NULL);
|
||||
|
||||
htrd->errnum = MIO_HTRD_ENOERR;
|
||||
if (htrd->recbs->qparamstr (htrd, &key, &val) <= -1)
|
||||
if (htrd->recbs->qparamstr(htrd, &key, &val) <= -1)
|
||||
{
|
||||
if (htrd->errnum == MIO_HTRD_ENOERR)
|
||||
htrd->errnum = MIO_HTRD_ERECBS;
|
||||
|
@ -172,7 +172,6 @@ if (mio_htre_getcontentlen(req) > 0)
|
||||
* i don't want to delay this until the contents are received.
|
||||
* if you don't like this behavior, you must implement your own
|
||||
* callback function for request handling. */
|
||||
|
||||
#if 0
|
||||
/* TODO support X-HTTP-Method-Override */
|
||||
if (data.method == MIO_HTTP_POST)
|
||||
@ -197,36 +196,22 @@ if (mio_htre_getcontentlen(req) > 0)
|
||||
}
|
||||
else
|
||||
{
|
||||
//mio_svc_htts_sendstatus (htts, csck, 500, mth, mio_htre_getversion(req), (req->flags & MIO_HTRE_ATTR_KEEPALIVE), MIO_NULL);
|
||||
//return 0;
|
||||
if (mth == MIO_HTTP_POST &&
|
||||
!(req->flags & MIO_HTRE_ATTR_LENGTH) &&
|
||||
!(req->flags & MIO_HTRE_ATTR_CHUNKED))
|
||||
if (mth == MIO_HTTP_POST && !(req->flags & (MIO_HTRE_ATTR_LENGTH | MIO_HTRE_ATTR_CHUNKED)))
|
||||
{
|
||||
/* POST without Content-Length nor not chunked */
|
||||
req->flags &= ~MIO_HTRE_ATTR_KEEPALIVE;
|
||||
mio_htre_discardcontent (req);
|
||||
|
||||
mio_htre_discardcontent (req);
|
||||
/* 411 Length Required - can't keep alive. Force disconnect */
|
||||
mio_svc_htts_sendstatus (htts, csck, 411, mth, mio_htre_getversion(req), 0, MIO_NULL); /* TODO: error check... */
|
||||
req->flags &= ~MIO_HTRE_ATTR_KEEPALIVE; /* to cause sendstatus() to close */
|
||||
if (mio_svc_htts_sendstatus(htts, csck, req, 411, MIO_NULL) <= -1) mio_dev_sck_halt (csck); /*TODO: redo this sendstatus */
|
||||
}
|
||||
else
|
||||
{
|
||||
/* TODO: handle 100 continue??? */
|
||||
if ((req->flags & MIO_HTRE_ATTR_EXPECT) &&
|
||||
mio_comp_http_version_numbers(&req->version, 1, 1) >= 0 &&
|
||||
mio_htre_getcontentlen(req) <= 0)
|
||||
{
|
||||
if (req->flags & MIO_HTRE_ATTR_EXPECT100)
|
||||
{
|
||||
mio_dev_sck_write(csck, "HTTP/1.1 100 Continue\r\n", 23, MIO_NULL, MIO_NULL);
|
||||
}
|
||||
else
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
const mio_bch_t* qpath = mio_htre_getqpath(req);
|
||||
if (mio_svc_htts_docgi(htts, csck, req, "") <= -1)
|
||||
{
|
||||
mio_dev_sck_halt (csck);
|
||||
}
|
||||
#if 0
|
||||
/*
|
||||
if (mio_comp_bcstr(qpath, "/testfunc", 0) == 0)
|
||||
{
|
||||
@ -241,54 +226,8 @@ if (mio_htre_getcontentlen(req) > 0)
|
||||
mio_htre_discardcontent (req);
|
||||
mio_dev_sck_halt (csck);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
if (mio_comp_bcstr(qpath, "/mio.c", 0) == 0)
|
||||
{
|
||||
mio_svc_htts_sendfile (htts, csck, "/home/hyung-hwan/projects/mio/lib/mio.c", 200, mth, mio_htre_getversion(req), (req->flags & MIO_HTRE_ATTR_KEEPALIVE));
|
||||
}
|
||||
else
|
||||
{
|
||||
mio_svc_htts_sendstatus (htts, csck, 500, mth, mio_htre_getversion(req), (req->flags & MIO_HTRE_ATTR_KEEPALIVE), MIO_NULL);
|
||||
}*/
|
||||
}
|
||||
#if 0
|
||||
else if (server_xtn->makersrc(htts, client, req, &rsrc) <= -1)
|
||||
{
|
||||
/* failed to make a resource. just send the internal server error.
|
||||
* the makersrc handler can return a negative number to return
|
||||
* '500 Internal Server Error'. If it wants to return a specific
|
||||
* error code, it should return 0 with the MIO_HTTPD_RSRC_ERROR
|
||||
* resource. */
|
||||
mio_htts_discardcontent (req);
|
||||
task = mio_htts_entaskerror(htts, client, MIO_NULL, 500, req);
|
||||
}
|
||||
else
|
||||
{
|
||||
task = MIO_NULL;
|
||||
|
||||
if ((rsrc.flags & MIO_HTTPD_RSRC_100_CONTINUE) &&
|
||||
(task = mio_htts_entaskcontinue(htts, client, task, req)) == MIO_NULL)
|
||||
{
|
||||
/* inject '100 continue' first if it is needed */
|
||||
goto oops;
|
||||
}
|
||||
|
||||
/* arrange the actual resource to be returned */
|
||||
task = mio_htts_entaskrsrc(htts, client, task, &rsrc, req);
|
||||
server_xtn->freersrc (htts, client, req, &rsrc);
|
||||
|
||||
/* if the resource is indicating to return an error,
|
||||
* discard the contents since i won't return them */
|
||||
if (rsrc.type == MIO_HTTPD_RSRC_ERROR)
|
||||
{
|
||||
mio_htre_discardcontent (req);
|
||||
}
|
||||
}
|
||||
|
||||
if (task == MIO_NULL) goto oops;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
@ -296,38 +235,14 @@ if (mio_htre_getcontentlen(req) > 0)
|
||||
/* contents are all received */
|
||||
if (mth == MIO_HTTP_CONNECT)
|
||||
{
|
||||
|
||||
MIO_DEBUG1 (htts->mio, "Switching HTRD to DUMMY for [%hs]\n", mio_htre_getqpath(req));
|
||||
|
||||
/* Switch the http reader to a dummy mode so that the subsqeuent
|
||||
* input(request) is just treated as data to the request just
|
||||
* completed */
|
||||
mio_htrd_dummify (cli->htrd);
|
||||
|
||||
/* connect is not handled in the peek mode. create a proxy resource here */
|
||||
////////
|
||||
#if 0
|
||||
if (server_xtn->makersrc(htts, client, req, &rsrc) <= -1)
|
||||
{
|
||||
MIO_DEBUG1 (htts->mio, "Cannot make resource for [%hs]\n", mio_htre_getqpath(req));
|
||||
|
||||
/* failed to make a resource. just send the internal server error.
|
||||
* the makersrc handler can return a negative number to return
|
||||
* '500 Internal Server Error'. If it wants to return a specific
|
||||
* error code, it should return 0 with the MIO_HTTPD_RSRC_ERROR
|
||||
* resource. */
|
||||
task = mio_htts_entaskerror(htts, client, MIO_NULL, 500, req);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* arrange the actual resource to be returned */
|
||||
task = mio_htts_entaskrsrc (htts, client, MIO_NULL, &rsrc, req);
|
||||
server_xtn->freersrc (htts, client, req, &rsrc);
|
||||
}
|
||||
|
||||
if (task == MIO_NULL) goto oops;
|
||||
#endif
|
||||
////////
|
||||
/* TODO: arrange to forward all raw bytes */
|
||||
}
|
||||
else if (req->flags & MIO_HTRE_ATTR_PROXIED)
|
||||
{
|
||||
@ -446,25 +361,52 @@ static void fini_client (mio_svc_htts_cli_t* cli)
|
||||
|
||||
/* ------------------------------------------------------------------------ */
|
||||
|
||||
static int client_on_read (mio_dev_sck_t* sck, const void* buf, mio_iolen_t len, const mio_skad_t* srcaddr)
|
||||
static int listener_on_read (mio_dev_sck_t* sck, const void* buf, mio_iolen_t len, const mio_skad_t* srcaddr)
|
||||
{
|
||||
/* unlike the function name, this callback is set on both the listener and the client.
|
||||
* however, it must never be triggered for the listener */
|
||||
|
||||
mio_svc_htts_cli_t* cli = mio_dev_sck_getxtn(sck);
|
||||
printf ("** HTTS - client read %p %d -> htts:%p\n", sck, (int)len, cli->htts);
|
||||
mio_oow_t rem;
|
||||
int x;
|
||||
|
||||
MIO_ASSERT (sck->mio, sck != cli->htts->lsck);
|
||||
|
||||
printf ("** HTTS - client read socket(%p) %d -> htts:%p\n", sck, (int)len, cli->htts);
|
||||
{
|
||||
mio_iolen_t i;
|
||||
for (i = 0; i < len; i++)
|
||||
{
|
||||
printf ("%c", ((const mio_uint8_t*)buf)[i]);
|
||||
}
|
||||
}
|
||||
if (len <= 0)
|
||||
{
|
||||
mio_dev_sck_halt (sck);
|
||||
}
|
||||
else if (mio_htrd_feed(cli->htrd, buf, len) <= -1)
|
||||
else if ((x = mio_htrd_feed(cli->htrd, buf, len, &rem)) <= -1)
|
||||
{
|
||||
/* in some cases, we may have to send some http response depending on the failure type */
|
||||
/* BADRE -> bad request? */
|
||||
printf ("** HTTS - client htrd feed failure socket(%p) - %d\n", sck, x);
|
||||
/* TODO: either send bad request or server failure ... */
|
||||
mio_dev_sck_halt (sck);
|
||||
}
|
||||
else if (rem > 0)
|
||||
{
|
||||
/* TODO: store the remaining data in the client's buffer */
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int client_on_write (mio_dev_sck_t* sck, mio_iolen_t wrlen, void* wrctx, const mio_skad_t* dstaddr)
|
||||
static int listener_on_write (mio_dev_sck_t* sck, mio_iolen_t wrlen, void* wrctx, const mio_skad_t* dstaddr)
|
||||
{
|
||||
mio_svc_htts_cli_t* cli = mio_dev_sck_getxtn(sck);
|
||||
mio_svc_htts_rsrc_t* rsrc = (mio_svc_htts_rsrc_t*)wrctx;
|
||||
|
||||
MIO_ASSERT (sck->mio, sck != cli->htts->lsck);
|
||||
|
||||
if (rsrc)
|
||||
{
|
||||
int n;
|
||||
@ -479,18 +421,7 @@ static int client_on_write (mio_dev_sck_t* sck, mio_iolen_t wrlen, void* wrctx,
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------ */
|
||||
|
||||
static int listener_on_read (mio_dev_sck_t* sck, const void* buf, mio_iolen_t len, const mio_skad_t* srcaddr)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int listener_on_write (mio_dev_sck_t* sck, mio_iolen_t wrlen, void* wrctx, const mio_skad_t* dstaddr)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void listener_on_connect (mio_dev_sck_t* sck)
|
||||
@ -502,13 +433,9 @@ static void listener_on_connect (mio_dev_sck_t* sck)
|
||||
/* accepted a new client */
|
||||
MIO_DEBUG3 (sck->mio, "HTTS(%p) - accepted... %p %d \n", cli->htts, sck, sck->hnd);
|
||||
|
||||
/* the accepted socket inherits various event callbacks. switch some of them to avoid sharing */
|
||||
sck->on_read = client_on_read;
|
||||
sck->on_write = client_on_write;
|
||||
|
||||
if (init_client(cli, sck) <= -1)
|
||||
{
|
||||
MIO_INFO2 (sck->mio, "UNABLE TO INITIALIZE NEW CLIENT %p %d\n", sck, (int)sck->hnd);
|
||||
MIO_DEBUG2 (sck->mio, "UNABLE TO INITIALIZE NEW CLIENT %p %d\n", sck, (int)sck->hnd);
|
||||
mio_dev_sck_halt (sck);
|
||||
}
|
||||
}
|
||||
@ -529,21 +456,21 @@ static void listener_on_disconnect (mio_dev_sck_t* sck)
|
||||
{
|
||||
case MIO_DEV_SCK_CONNECTING:
|
||||
/* only for connecting sockets */
|
||||
MIO_INFO1 (sck->mio, "OUTGOING SESSION DISCONNECTED - FAILED TO CONNECT (%d) TO REMOTE SERVER\n", (int)sck->hnd);
|
||||
MIO_DEBUG1 (sck->mio, "OUTGOING SESSION DISCONNECTED - FAILED TO CONNECT (%d) TO REMOTE SERVER\n", (int)sck->hnd);
|
||||
break;
|
||||
|
||||
case MIO_DEV_SCK_CONNECTING_SSL:
|
||||
/* only for connecting sockets */
|
||||
MIO_INFO1 (sck->mio, "OUTGOING SESSION DISCONNECTED - FAILED TO SSL-CONNECT (%d) TO REMOTE SERVER\n", (int)sck->hnd);
|
||||
MIO_DEBUG1 (sck->mio, "OUTGOING SESSION DISCONNECTED - FAILED TO SSL-CONNECT (%d) TO REMOTE SERVER\n", (int)sck->hnd);
|
||||
break;
|
||||
|
||||
case MIO_DEV_SCK_CONNECTED:
|
||||
/* only for connecting sockets */
|
||||
MIO_INFO1 (sck->mio, "OUTGOING CLIENT CONNECTION GOT TORN DOWN %p(%d).......\n", (int)sck->hnd);
|
||||
MIO_DEBUG1 (sck->mio, "OUTGOING CLIENT CONNECTION GOT TORN DOWN %p(%d).......\n", (int)sck->hnd);
|
||||
break;
|
||||
|
||||
case MIO_DEV_SCK_LISTENING:
|
||||
MIO_INFO2 (sck->mio, "LISTNER SOCKET %p(%d) - SHUTTUING DOWN\n", sck, (int)sck->hnd);
|
||||
MIO_DEBUG2 (sck->mio, "LISTNER SOCKET %p(%d) - SHUTTUING DOWN\n", sck, (int)sck->hnd);
|
||||
break;
|
||||
|
||||
case MIO_DEV_SCK_ACCEPTING_SSL: /* special case. */
|
||||
@ -552,17 +479,17 @@ static void listener_on_disconnect (mio_dev_sck_t* sck)
|
||||
* the cli extension are is not initialized yet */
|
||||
MIO_ASSERT (sck->mio, sck != cli->sck);
|
||||
MIO_ASSERT (sck->mio, cli->sck == cli->htts->lsck); /* the field is a copy of the extension are of the listener socket. so it should point to the listner socket */
|
||||
MIO_INFO2 (sck->mio, "LISTENER UNABLE TO SSL-ACCEPT CLIENT %p(%d) ....%p\n", sck, (int)sck->hnd);
|
||||
MIO_DEBUG2 (sck->mio, "LISTENER UNABLE TO SSL-ACCEPT CLIENT %p(%d) ....%p\n", sck, (int)sck->hnd);
|
||||
return;
|
||||
|
||||
case MIO_DEV_SCK_ACCEPTED:
|
||||
/* only for sockets accepted by the listeners. will never come here because
|
||||
* the disconnect call for such sockets have been changed in listener_on_connect() */
|
||||
MIO_INFO2 (sck->mio, "ACCEPTED CLIENT SOCKET %p(%d) GOT DISCONNECTED.......\n", sck, (int)sck->hnd);
|
||||
MIO_DEBUG2 (sck->mio, "ACCEPTED CLIENT SOCKET %p(%d) GOT DISCONNECTED.......\n", sck, (int)sck->hnd);
|
||||
break;
|
||||
|
||||
default:
|
||||
MIO_INFO2 (sck->mio, "SOCKET %p(%d) DISCONNECTED AFTER ALL.......\n", sck, (int)sck->hnd);
|
||||
MIO_DEBUG2 (sck->mio, "SOCKET %p(%d) DISCONNECTED AFTER ALL.......\n", sck, (int)sck->hnd);
|
||||
break;
|
||||
}
|
||||
|
||||
@ -639,7 +566,7 @@ mio_svc_htts_t* mio_svc_htts_start (mio_t* mio, const mio_skad_t* bind_addr)
|
||||
MIO_MEMSET (&info, 0, MIO_SIZEOF(info));
|
||||
info.b.localaddr = *bind_addr;
|
||||
info.b.options = MIO_DEV_SCK_BIND_REUSEADDR | MIO_DEV_SCK_BIND_REUSEPORT;
|
||||
info.b.options |= MIO_DEV_SCK_BIND_SSL;
|
||||
/*info.b.options |= MIO_DEV_SCK_BIND_SSL; */
|
||||
info.b.ssl_certfile = "localhost.crt";
|
||||
info.b.ssl_keyfile = "localhost.key";
|
||||
if (mio_dev_sck_bind(htts->lsck, &info.b) <= -1) goto oops;
|
||||
@ -657,7 +584,7 @@ mio_svc_htts_t* mio_svc_htts_start (mio_t* mio, const mio_skad_t* bind_addr)
|
||||
MIO_SVCL_APPEND_SVC (&mio->actsvc, (mio_svc_t*)htts);
|
||||
CLIL_INIT (&htts->cli);
|
||||
|
||||
MIO_DEBUG3 (mio, "STARTED SVC(HTTS) LISTENER %p LISTENER SOCKET %p(%d)\n", htts, htts->lsck, (int)htts->lsck->hnd);
|
||||
MIO_DEBUG3 (mio, "HTTS - STARTED SERVICE %p - LISTENER SOCKET %p(%d)\n", htts, htts->lsck, (int)htts->lsck->hnd);
|
||||
return htts;
|
||||
|
||||
oops:
|
||||
@ -673,7 +600,7 @@ void mio_svc_htts_stop (mio_svc_htts_t* htts)
|
||||
{
|
||||
mio_t* mio = htts->mio;
|
||||
|
||||
MIO_DEBUG3 (mio, "STOPPING SVC(HTTS) %p LISTENER SOCKET %p(%d)\n", htts, htts->lsck, (int)(htts->lsck? htts->lsck->hnd: -1));
|
||||
MIO_DEBUG3 (mio, "HTTS - STOPPING SERVICE %p - LISTENER SOCKET %p(%d)\n", htts, htts->lsck, (int)(htts->lsck? htts->lsck->hnd: -1));
|
||||
|
||||
/* htts->lsck may be null if the socket has been destroyed for operational error and
|
||||
* forgotten in the disconnect callback thereafter */
|
||||
@ -732,7 +659,7 @@ mio_svc_htts_rsrc_t* mio_svc_htts_rsrc_make (mio_svc_htts_t* htts, mio_dev_sck_t
|
||||
|
||||
void mio_svc_htts_rsrc_kill (mio_svc_htts_rsrc_t* rsrc)
|
||||
{
|
||||
printf ("RSRC KILL >>>>> %p\n", rsrc->htts);
|
||||
printf ("RSRC KILL >>>>> htts=> %p\n", rsrc->htts);
|
||||
mio_t* mio = rsrc->htts->mio;
|
||||
|
||||
if (rsrc->on_kill) rsrc->on_kill (rsrc);
|
||||
@ -936,34 +863,99 @@ int mio_svc_htts_dofile (mio_svc_htts_t* htts, mio_dev_sck_t* csck, mio_htre_t*
|
||||
|
||||
/* ----------------------------------------------------------------- */
|
||||
|
||||
|
||||
struct cgi_state_t
|
||||
{
|
||||
/**** CHANGE THESE FIELDS AFTER RSRC CLEANUP */
|
||||
mio_svc_htts_t* htts;
|
||||
mio_svc_htts_rsrc_t* rsrc_prev;
|
||||
mio_svc_htts_rsrc_t* rsrc_next;
|
||||
mio_svc_htts_rsrc_on_kill_t on_kill;
|
||||
/**** CHANGE THESE FIELDS AFTER RSRC CLEANUP */
|
||||
|
||||
mio_oow_t num_pending_writes_to_client;
|
||||
mio_oow_t num_pending_writes_to_peer;
|
||||
mio_dev_pro_t* peer;
|
||||
mio_htrd_t* peer_htrd;
|
||||
mio_svc_htts_cli_t* cli;
|
||||
mio_htre_t* req;
|
||||
mio_oow_t req_content_length;
|
||||
|
||||
mio_dev_sck_on_read_t cli_org_on_read;
|
||||
mio_dev_sck_on_write_t cli_org_on_write;
|
||||
};
|
||||
typedef struct cgi_state_t cgi_state_t;
|
||||
|
||||
struct cgi_peer_xtn_t
|
||||
{
|
||||
cgi_state_t* state;
|
||||
};
|
||||
typedef struct cgi_peer_xtn_t cgi_peer_xtn_t;
|
||||
|
||||
static void cgi_state_on_kill (cgi_state_t* cgi_state)
|
||||
{
|
||||
printf ("**** CGI_STATE_ON_KILL \n");
|
||||
if (cgi_state->peer)
|
||||
{
|
||||
mio_dev_pro_kill (cgi_state->peer);
|
||||
cgi_state->peer = MIO_NULL;
|
||||
}
|
||||
|
||||
if (cgi_state->peer_htrd)
|
||||
{
|
||||
mio_htrd_close (cgi_state->peer_htrd);
|
||||
cgi_state->peer_htrd = MIO_NULL;
|
||||
}
|
||||
|
||||
if (cgi_state->cli_org_on_read)
|
||||
{
|
||||
cgi_state->cli->sck->on_read = cgi_state->cli_org_on_read;
|
||||
cgi_state->cli_org_on_read = MIO_NULL;
|
||||
}
|
||||
|
||||
if (cgi_state->cli_org_on_write)
|
||||
{
|
||||
cgi_state->cli->sck->on_write = cgi_state->cli_org_on_write;
|
||||
cgi_state->cli_org_on_write = MIO_NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static void cgi_peer_on_close (mio_dev_pro_t* pro, mio_dev_pro_sid_t sid)
|
||||
{
|
||||
mio_t* mio = pro->mio;
|
||||
cgi_peer_xtn_t* cgi_peer = mio_dev_pro_getxtn(pro);
|
||||
|
||||
if (sid == MIO_DEV_PRO_MASTER)
|
||||
MIO_INFO1 (mio, "PROCESS(%d) CLOSE MASTER\n", (int)pro->child_pid);
|
||||
{
|
||||
MIO_DEBUG1 (mio, "PROCESS(%d) CLOSE MASTER\n", (int)pro->child_pid);
|
||||
cgi_peer->state->peer = MIO_NULL; /* clear this peer from the state */
|
||||
}
|
||||
else
|
||||
MIO_INFO2 (mio, "PROCESS(%d) CLOSE SLAVE[%d]\n", (int)pro->child_pid, sid);
|
||||
{
|
||||
MIO_DEBUG2 (mio, "PROCESS(%d) CLOSE SLAVE[%d]\n", (int)pro->child_pid, sid);
|
||||
}
|
||||
}
|
||||
|
||||
static int cgi_peer_on_read (mio_dev_pro_t* pro, mio_dev_pro_sid_t sid, const void* data, mio_iolen_t dlen)
|
||||
{
|
||||
mio_t* mio = pro->mio;
|
||||
cgi_peer_xtn_t* cgi_peer = mio_dev_pro_getxtn(pro);
|
||||
|
||||
if (dlen <= -1)
|
||||
{
|
||||
MIO_INFO1 (mio, "PROCESS(%d): READ TIMED OUT...\n", (int)pro->child_pid);
|
||||
MIO_DEBUG1 (mio, "PROCESS(%d): READ TIMED OUT...\n", (int)pro->child_pid);
|
||||
mio_dev_pro_halt (pro);
|
||||
return 0;
|
||||
}
|
||||
else if (dlen <= 0)
|
||||
{
|
||||
MIO_INFO1 (mio, "PROCESS(%d): EOF RECEIVED...\n", (int)pro->child_pid);
|
||||
MIO_DEBUG1 (mio, "PROCESS(%d): EOF RECEIVED...\n", (int)pro->child_pid);
|
||||
/* no outstanding request. but EOF */
|
||||
mio_dev_pro_halt (pro);
|
||||
return 0;
|
||||
}
|
||||
|
||||
MIO_INFO5 (mio, "PROCESS(%d) READ DATA ON SLAVE[%d] len=%d [%.*hs]\n", (int)pro->child_pid, (int)sid, (int)dlen, dlen, (char*)data);
|
||||
MIO_DEBUG5 (mio, "PROCESS(%d) READ DATA ON SLAVE[%d] len=%d [%.*hs]\n", (int)pro->child_pid, (int)sid, (int)dlen, dlen, (char*)data);
|
||||
if (sid == MIO_DEV_PRO_OUT)
|
||||
{
|
||||
mio_dev_pro_read (pro, sid, 0);
|
||||
@ -975,18 +967,34 @@ static int cgi_peer_on_read (mio_dev_pro_t* pro, mio_dev_pro_sid_t sid, const vo
|
||||
static int cgi_peer_on_write (mio_dev_pro_t* pro, mio_iolen_t wrlen, void* wrctx)
|
||||
{
|
||||
mio_t* mio = pro->mio;
|
||||
cgi_peer_xtn_t* cgi_peer = mio_dev_pro_getxtn(pro);
|
||||
cgi_state_t* cgi_state = cgi_peer->state;
|
||||
mio_ntime_t tmout;
|
||||
|
||||
if (wrlen <= -1)
|
||||
{
|
||||
MIO_INFO1 (mio, "PROCESS(%d): WRITE TIMED OUT...\n", (int)pro->child_pid);
|
||||
MIO_DEBUG1 (mio, "PROCESS(%d): WRITE TIMED OUT...\n", (int)pro->child_pid);
|
||||
mio_dev_pro_halt (pro);
|
||||
return 0;
|
||||
}
|
||||
|
||||
MIO_DEBUG2 (mio, "PROCESS(%d) wrote data of %d bytes\n", (int)pro->child_pid, (int)wrlen);
|
||||
|
||||
#if 0
|
||||
/*mio_dev_pro_read (pro, MIO_DEV_PRO_OUT, 1);*/
|
||||
MIO_INIT_NTIME (&tmout, 5, 0);
|
||||
mio_dev_pro_timedread (pro, MIO_DEV_PRO_OUT, 1, &tmout);
|
||||
#endif
|
||||
|
||||
|
||||
#if 0
|
||||
if (mio_dev_pro_write(pro, cgi_peer->cli->req, length, MIO_NULL) <= -1)
|
||||
{
|
||||
/* halt both peer and cli */
|
||||
}
|
||||
#endif
|
||||
|
||||
cgi_state->num_pending_writes_to_peer--;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -994,84 +1002,211 @@ static int cgi_peer_on_write (mio_dev_pro_t* pro, mio_iolen_t wrlen, void* wrctx
|
||||
static int cgi_client_on_read (mio_dev_sck_t* sck, const void* buf, mio_iolen_t len, const mio_skad_t* srcaddr)
|
||||
{
|
||||
mio_svc_htts_cli_t* cli = mio_dev_sck_getxtn(sck);
|
||||
cgi_state_t* cgi_state = RSRCL_FIRST_RSRC(&cli->rsrc);
|
||||
|
||||
printf ("** HTTS - cgi client read %p %d -> htts:%p\n", sck, (int)len, cli->htts);
|
||||
if (len <= 0)
|
||||
if (len <= -1)
|
||||
{
|
||||
/* read error */
|
||||
mio_dev_sck_halt (sck);
|
||||
goto oops;
|
||||
}
|
||||
else if (mio_htrd_feed(cli->htrd, buf, len) <= -1)
|
||||
else if (len == 0)
|
||||
{
|
||||
mio_dev_sck_halt (sck);
|
||||
/* EOF */
|
||||
}
|
||||
else
|
||||
{
|
||||
#if 0
|
||||
mio_oow_t rem;
|
||||
if (mio_htrd_feed(cli->htrd, buf, len, &rem) <= -1) goto oops;
|
||||
if (rem > 0)
|
||||
{
|
||||
/* TODO: there is left-over data */
|
||||
}
|
||||
#endif
|
||||
|
||||
cgi_state->num_pending_writes_to_peer++;
|
||||
if (mio_dev_pro_write(cgi_state->peer, buf, len, MIO_NULL) <= -1)
|
||||
{
|
||||
cgi_state->num_pending_writes_to_peer--;
|
||||
goto oops;
|
||||
}
|
||||
|
||||
if (cgi_state->num_pending_writes_to_peer > 1)
|
||||
{
|
||||
if (mio_dev_sck_read(sck, 0) <= -1) goto oops; /* disable input watching */
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
oops:
|
||||
/* TODO: arrange to kill the entire cgi_state??? */
|
||||
mio_dev_sck_halt (sck);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cgi_client_on_write (mio_dev_sck_t* sck, mio_iolen_t wrlen, void* wrctx, const mio_skad_t* dstaddr)
|
||||
{
|
||||
mio_svc_htts_cli_t* cli = mio_dev_sck_getxtn(sck);
|
||||
cgi_state_t* cgi_state = RSRCL_FIRST_RSRC(&cli->rsrc);
|
||||
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void cgi_client_on_disconnect (mio_dev_sck_t* sck)
|
||||
static int get_request_content_length (mio_htre_t* req, mio_oow_t* len)
|
||||
{
|
||||
client_on_disconnect (sck);
|
||||
}
|
||||
if (req->state & (MIO_HTRE_COMPLETED | MIO_HTRE_DISCARDED))
|
||||
{
|
||||
/* no more content to receive */
|
||||
*len = mio_htre_getcontentlen(req);
|
||||
}
|
||||
else if (req->flags & MIO_HTRE_ATTR_CHUNKED)
|
||||
{
|
||||
/* "Transfer-Encoding: chunked" take precedence over "Content-Length: XXX".
|
||||
*
|
||||
* [RFC7230]
|
||||
* If a message is received with both a Transfer-Encoding and a
|
||||
* Content-Length header field, the Transfer-Encoding overrides the
|
||||
* Content-Length. */
|
||||
|
||||
typedef int (*mio_htre_concb_t) (
|
||||
mio_htre_t* re,
|
||||
const mio_bch_t* ptr,
|
||||
mio_oow_t len,
|
||||
void* ctx
|
||||
);
|
||||
|
||||
int cgi_forward_client_to_peer (mio_htre_t* re, const mio_bch_t* ptr, mio_oow_t len, void* ctx)
|
||||
{
|
||||
mio_dev_pro_t* pro = (mio_dev_pro_t*)ctx;
|
||||
return mio_dev_pro_write(pro, ptr, len, MIO_NULL);
|
||||
/* TODO: if there are too many pending write requests, stop read event on the client */
|
||||
return -1; /* unable to determine content-length in advance */
|
||||
}
|
||||
else if (req->flags & MIO_HTRE_ATTR_LENGTH)
|
||||
{
|
||||
*len = req->attr.content_length;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* no content */
|
||||
*len = 0;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int mio_svc_htts_docgi (mio_svc_htts_t* htts, mio_dev_sck_t* csck, mio_htre_t* req, const mio_bch_t* docroot)
|
||||
{
|
||||
mio_dev_pro_t* pro = MIO_NULL;
|
||||
mio_t* mio = htts->mio;
|
||||
mio_svc_htts_cli_t* cli = mio_dev_sck_getxtn(csck);
|
||||
cgi_state_t* cgi_state = MIO_NULL;
|
||||
cgi_peer_xtn_t* cgi_peer;
|
||||
mio_oow_t req_content_length;
|
||||
mio_dev_pro_make_t mi;
|
||||
|
||||
if (get_request_content_length(req, &req_content_length) <= -1)
|
||||
{
|
||||
/* chunked - the length is not know in advance */
|
||||
/* don't start the process yet. */
|
||||
|
||||
/* option 1. send 411 Length Required */
|
||||
/* option 2. support chunked message box in the request */
|
||||
/* option 3[non standard]. set CONTENT_LENGTH to -1 and indicate the end of INPUT by sending EOF */
|
||||
req_content_length = MIO_TYPE_MAX(mio_oow_t); /* TODO: change type or add another variable ? */
|
||||
}
|
||||
|
||||
MIO_MEMSET (&mi, 0, MIO_SIZEOF(mi));
|
||||
mi.flags = MIO_DEV_PRO_READOUT /*| MIO_DEV_PRO_READERR*/ | MIO_DEV_PRO_WRITEIN /*| MIO_DEV_PRO_FORGET_CHILD*/;
|
||||
mi.flags = MIO_DEV_PRO_READOUT | MIO_DEV_PRO_ERRTONUL | MIO_DEV_PRO_WRITEIN /*| MIO_DEV_PRO_FORGET_CHILD*/;
|
||||
mi.cmd = mio_htre_getqpath(req); /* TODO: combine it with docroot */
|
||||
mi.on_read = cgi_peer_on_read;
|
||||
mi.on_write = cgi_peer_on_write;
|
||||
mi.on_close = cgi_peer_on_close;
|
||||
|
||||
/* TODO: create cgi environment variables... */
|
||||
pro = mio_dev_pro_make(htts->mio, 0, &mi);
|
||||
if (MIO_UNLIKELY(!pro)) goto oops;
|
||||
cgi_state = mio_callocmem(mio, MIO_SIZEOF(*cgi_state));
|
||||
if (MIO_UNLIKELY(!cgi_state)) goto oops;
|
||||
|
||||
/* THE process device must be ready for I/O */
|
||||
if (mio_htre_getcontentlen(req) > 0)
|
||||
cgi_state->htts = htts; /*TODO: delete this field after rsrd renewal? */
|
||||
cgi_state->on_kill = cgi_state_on_kill;
|
||||
|
||||
cgi_state->cli = cli;
|
||||
/*cgi_state->num_pending_writes_to_client = 0;
|
||||
cgi_state->num_pending_writes_to_peer = 0;*/
|
||||
cgi_state->req = req;
|
||||
cgi_state->req_content_length = req_content_length;
|
||||
|
||||
cgi_state->cli_org_on_read = csck->on_read;
|
||||
cgi_state->cli_org_on_write = csck->on_write;
|
||||
csck->on_read = cgi_client_on_read;
|
||||
csck->on_write = cgi_client_on_write;
|
||||
|
||||
RSRCL_APPEND_RSRC (&cli->rsrc, cgi_state); /* attach it to the client information */
|
||||
|
||||
/* TODO: create cgi environment variables... */
|
||||
/* TODO:
|
||||
* never put Expect: 100-continue to environment variable
|
||||
*/
|
||||
cgi_state->peer = mio_dev_pro_make(mio, MIO_SIZEOF(*cgi_peer), &mi);
|
||||
if (MIO_UNLIKELY(!cgi_state->peer)) goto oops;
|
||||
cgi_peer = mio_dev_pro_getxtn(cgi_state->peer);
|
||||
cgi_peer->state = cgi_state;
|
||||
|
||||
cgi_state->peer_htrd = mio_htrd_open(mio, MIO_SIZEOF(*cgi_peer));
|
||||
if (MIO_UNLIKELY(!cgi_state->peer_htrd)) goto oops;
|
||||
cgi_peer = mio_htrd_getxtn(cgi_state->peer_htrd);
|
||||
cgi_peer->state = cgi_state;
|
||||
/* TODO: any other handling before this? */
|
||||
/* I CAN't SIMPLY WRITE LIKE THIS, the cgi must require this.
|
||||
* send contents depending how cgi want Expect: continue handling to be handled */
|
||||
|
||||
if (req->flags & MIO_HTRE_ATTR_EXPECT100)
|
||||
{
|
||||
if (mio_dev_pro_write(pro, mio_htre_getcontentptr(req), mio_htre_getcontentlen(req), MIO_NULL) <= -1) goto oops;
|
||||
/* TODO: Expect: 100-continue? who should handle this? cgi? or the http server? */
|
||||
if (mio_comp_http_version_numbers(&req->version, 1, 1) >= 0 && req_content_length > 0)
|
||||
{
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
cgi_state->num_pending_writes_to_client++;
|
||||
if (mio_dev_sck_write(csck, "HTTP/1.1 100 Continue\r\n", 23, MIO_NULL, MIO_NULL) <= -1)
|
||||
{
|
||||
cgi_state->num_pending_writes_to_client--;
|
||||
goto oops;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (req->flags & MIO_HTRE_ATTR_EXPECT)
|
||||
{
|
||||
mio_htre_discardcontent (req);
|
||||
req->flags &= ~MIO_HTRE_ATTR_KEEPALIVE; /* to cause sendstatus() to close */
|
||||
if (mio_svc_htts_sendstatus(htts, csck, req, 417, MIO_NULL) <= -1) goto oops;
|
||||
}
|
||||
|
||||
mio_htre_setconcb (req, cgi_forward_client_to_peer, pro);
|
||||
if (req_content_length > 0)
|
||||
{
|
||||
if (mio_htre_getcontentlen(req) > 0)
|
||||
{
|
||||
cgi_state->num_pending_writes_to_peer++;
|
||||
if (mio_dev_pro_write(cgi_state->peer, mio_htre_getcontentptr(req), mio_htre_getcontentlen(req), MIO_NULL) <= -1)
|
||||
{
|
||||
cgi_state->num_pending_writes_to_peer--;
|
||||
goto oops;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#if 0
|
||||
csck->on_read = cgi_client_on_read;
|
||||
cssk->on_write = cgi_client_on_write;
|
||||
csck->on_disconnect = cgi_client_on_disconnect;
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
rsrc = mio_svc_htts_rsrc_make(htts, csck, rsrc_cgi_on_read, rsrc_cgi_on_write, rsrc_cgi_on_kill, MIO_SIZEOF(*rsrc_cgi));
|
||||
if (MIO_UNLIKELY(!rsrc)) goto oops;
|
||||
#endif
|
||||
if (req->state & (MIO_HTRE_COMPLETED | MIO_HTRE_DISCARDED))
|
||||
{
|
||||
/* disable input watching from the client */
|
||||
if (mio_dev_sck_read(csck, 0) <= -1) goto oops;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
|
||||
oops:
|
||||
if (pro) mio_dev_pro_kill (pro);
|
||||
MIO_DEBUG2 (mio, "HTTS(%p) - FAILURE in docgi - socket(%p)\n", htts, csck);
|
||||
cgi_state->on_kill (cgi_state); /* TODO: call rsrc_free... */
|
||||
mio_dev_sck_halt (csck);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -1213,13 +1348,14 @@ oops:
|
||||
return -1;
|
||||
}
|
||||
|
||||
int mio_svc_htts_sendstatus (mio_svc_htts_t* htts, mio_dev_sck_t* csck, int status_code, mio_http_method_t method, const mio_http_version_t* version, int keepalive, void* extra)
|
||||
int mio_svc_htts_sendstatus (mio_svc_htts_t* htts, mio_dev_sck_t* csck, mio_htre_t* req, int status_code, void* extra)
|
||||
{
|
||||
/* TODO: change this to use send status */
|
||||
mio_svc_htts_cli_t* cli = mio_dev_sck_getxtn(csck);
|
||||
mio_bch_t text[1024]; /* TODO: make this buffer dynamic or scalable */
|
||||
mio_bch_t dtbuf[64];
|
||||
mio_oow_t x;
|
||||
mio_http_version_t* version = mio_htre_getversion(req);
|
||||
|
||||
const mio_bch_t* extrapre = "";
|
||||
const mio_bch_t* extrapst = "";
|
||||
@ -1279,7 +1415,7 @@ int mio_svc_htts_sendstatus (mio_svc_htts_t* htts, mio_dev_sck_t* csck, int stat
|
||||
version->major, version->minor, status_code, mio_http_status_to_bcstr(status_code),
|
||||
htts->server_name,
|
||||
dtbuf, /* DATE */
|
||||
(keepalive? "keep-alive": "close"), /* connection */
|
||||
((req->flags & MIO_HTRE_ATTR_KEEPALIVE)? "keep-alive": "close"), /* connection */
|
||||
mio_count_bcstr(text), /* content length */
|
||||
extrapre, extraval, extraval, text
|
||||
);
|
||||
@ -1292,7 +1428,8 @@ int mio_svc_htts_sendstatus (mio_svc_htts_t* htts, mio_dev_sck_t* csck, int stat
|
||||
mio_dev_sck_halt (csck);
|
||||
return -1;
|
||||
}
|
||||
else if (!keepalive)
|
||||
|
||||
if (!(req->flags & MIO_HTRE_ATTR_KEEPALIVE))
|
||||
{
|
||||
/* arrange to close the writing end */
|
||||
if (mio_dev_sck_write(csck, MIO_NULL, 0, MIO_NULL, MIO_NULL) <= -1)
|
||||
|
@ -179,8 +179,9 @@ MIO_EXPORT void mio_htrd_setrecbs (
|
||||
*/
|
||||
MIO_EXPORT int mio_htrd_feed (
|
||||
mio_htrd_t* htrd, /**< htrd */
|
||||
const mio_bch_t* req, /**< request octets */
|
||||
mio_oow_t len /**< number of octets */
|
||||
const mio_bch_t* req, /**< request octets */
|
||||
mio_oow_t len, /**< number of octets */
|
||||
mio_oow_t* rem
|
||||
);
|
||||
|
||||
/**
|
||||
|
@ -37,7 +37,7 @@
|
||||
*/
|
||||
|
||||
/* header and contents of request/response */
|
||||
typedef struct mio_htre_t mio_htre_t;
|
||||
/*typedef struct mio_htre_t mio_htre_t; <--- defined in mio-http.h TODO: remove recursive definition */
|
||||
typedef struct mio_htre_hdrval_t mio_htre_hdrval_t;
|
||||
|
||||
enum mio_htre_state_t
|
||||
|
@ -156,6 +156,7 @@ typedef enum mio_perenc_http_opt_t mio_perenc_bcstr_opt_t;
|
||||
|
||||
|
||||
/* -------------------------------------------------------------- */
|
||||
typedef struct mio_htre_t mio_htre_t;
|
||||
typedef struct mio_svc_htts_t mio_svc_htts_t;
|
||||
typedef struct mio_svc_httc_t mio_svc_httc_t;
|
||||
|
||||
@ -164,6 +165,13 @@ typedef struct mio_svc_httc_t mio_svc_httc_t;
|
||||
typedef struct mio_svc_htts_rsrc_t mio_svc_htts_rsrc_t;
|
||||
typedef mio_uint64_t mio_foff_t ; /* TODO: define this via the main configure.ac ... */
|
||||
|
||||
|
||||
typedef int (*mio_svc_htts_rsrc_on_read_t) (
|
||||
mio_svc_htts_rsrc_t* rsrc,
|
||||
mio_dev_sck_t* sck
|
||||
);
|
||||
|
||||
|
||||
typedef int (*mio_svc_htts_rsrc_on_write_t) (
|
||||
mio_svc_htts_rsrc_t* rsrc,
|
||||
mio_dev_sck_t* sck
|
||||
@ -185,12 +193,14 @@ struct mio_svc_htts_rsrc_t
|
||||
mio_svc_htts_rsrc_t* rsrc_prev;
|
||||
mio_svc_htts_rsrc_t* rsrc_next;
|
||||
|
||||
mio_svc_htts_rsrc_on_kill_t on_kill;
|
||||
mio_svc_htts_rsrc_on_write_t on_write;
|
||||
|
||||
int flags;
|
||||
mio_bch_t* content_type;
|
||||
mio_foff_t content_length;
|
||||
|
||||
mio_svc_htts_rsrc_on_write_t on_write;
|
||||
mio_svc_htts_rsrc_on_kill_t on_kill;
|
||||
|
||||
};
|
||||
|
||||
/* -------------------------------------------------------------- */
|
||||
@ -307,6 +317,14 @@ MIO_EXPORT int mio_svc_htts_setservernamewithbcstr (
|
||||
|
||||
);
|
||||
|
||||
MIO_EXPORT int mio_svc_htts_docgi (
|
||||
mio_svc_htts_t* htts,
|
||||
mio_dev_sck_t* csck,
|
||||
mio_htre_t* req,
|
||||
const mio_bch_t* docroot
|
||||
);
|
||||
|
||||
|
||||
MIO_EXPORT int mio_svc_htts_sendfile (
|
||||
mio_svc_htts_t* htts,
|
||||
mio_dev_sck_t* csck,
|
||||
@ -320,10 +338,8 @@ MIO_EXPORT int mio_svc_htts_sendfile (
|
||||
MIO_EXPORT int mio_svc_htts_sendstatus (
|
||||
mio_svc_htts_t* htts,
|
||||
mio_dev_sck_t* csck,
|
||||
mio_htre_t* req,
|
||||
int status_code,
|
||||
mio_http_method_t method,
|
||||
const mio_http_version_t* version,
|
||||
int keepalive,
|
||||
void* extra
|
||||
);
|
||||
|
||||
|
147
mio/lib/mio.c
147
mio/lib/mio.c
@ -298,6 +298,93 @@ static MIO_INLINE void unlink_wq (mio_t* mio, mio_wq_t* q)
|
||||
MIO_WQ_UNLINK (q);
|
||||
}
|
||||
|
||||
static void fire_cwq_handlers (mio_t* mio)
|
||||
{
|
||||
/* execute callbacks for completed write operations */
|
||||
while (!MIO_CWQ_IS_EMPTY(&mio->cwq))
|
||||
{
|
||||
mio_cwq_t* cwq;
|
||||
mio_oow_t cwqfl_index;
|
||||
mio_dev_t* dev_to_halt;
|
||||
|
||||
cwq = MIO_CWQ_HEAD(&mio->cwq);
|
||||
if (cwq->dev->dev_evcb->on_write(cwq->dev, cwq->olen, cwq->ctx, &cwq->dstaddr) <= -1)
|
||||
{
|
||||
MIO_DEBUG1 (mio, "MIO - Error returned by on_write() of device %p in cwq\n", cwq->dev);
|
||||
dev_to_halt = cwq->dev;
|
||||
}
|
||||
else
|
||||
{
|
||||
dev_to_halt = MIO_NULL;
|
||||
}
|
||||
cwq->dev->cw_count--;
|
||||
MIO_CWQ_UNLINK (cwq);
|
||||
|
||||
cwqfl_index = MIO_ALIGN_POW2(cwq->dstaddr.len, MIO_CWQFL_ALIGN) / MIO_CWQFL_SIZE;
|
||||
if (cwqfl_index < MIO_COUNTOF(mio->cwqfl))
|
||||
{
|
||||
/* reuse the cwq object if dstaddr is 0 in size. chain it to the free list */
|
||||
cwq->q_next = mio->cwqfl[cwqfl_index];
|
||||
mio->cwqfl[cwqfl_index] = cwq;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* TODO: more reuse of objects of different size? */
|
||||
mio_freemem (mio, cwq);
|
||||
}
|
||||
|
||||
if (dev_to_halt) mio_dev_halt (dev_to_halt);
|
||||
}
|
||||
}
|
||||
|
||||
static void fire_cwq_handlers_for_dev (mio_t* mio, mio_dev_t* dev)
|
||||
{
|
||||
mio_cwq_t* cwq, * next;
|
||||
|
||||
MIO_ASSERT (mio, dev->cw_count > 0); /* Ensure to check dev->cw_count before calling this function */
|
||||
|
||||
cwq = MIO_CWQ_HEAD(&mio->cwq);
|
||||
while (cwq != &mio->cwq)
|
||||
{
|
||||
next = MIO_CWQ_NEXT(cwq);
|
||||
if (cwq->dev == dev) /* TODO: THIS LOOP TOO INEFFICIENT??? MAINTAIN PER-DEVICE LIST OF CWQ? */
|
||||
{
|
||||
mio_dev_t* dev_to_halt;
|
||||
mio_oow_t cwqfl_index;
|
||||
|
||||
if (cwq->dev->dev_evcb->on_write(cwq->dev, cwq->olen, cwq->ctx, &cwq->dstaddr) <= -1)
|
||||
{
|
||||
MIO_DEBUG1 (mio, "MIO - Error returned by on_write() of device %p in cwq\n", cwq->dev);
|
||||
dev_to_halt = cwq->dev;
|
||||
}
|
||||
else
|
||||
{
|
||||
dev_to_halt = MIO_NULL;
|
||||
}
|
||||
|
||||
cwq->dev->cw_count--;
|
||||
MIO_CWQ_UNLINK (cwq);
|
||||
|
||||
cwqfl_index = MIO_ALIGN_POW2(cwq->dstaddr.len, MIO_CWQFL_ALIGN) / MIO_CWQFL_SIZE;
|
||||
if (cwqfl_index < MIO_COUNTOF(mio->cwqfl))
|
||||
{
|
||||
/* reuse the cwq object if dstaddr is 0 in size. chain it to the free list */
|
||||
cwq->q_next = mio->cwqfl[cwqfl_index];
|
||||
mio->cwqfl[cwqfl_index] = cwq;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* TODO: more reuse of objects of different size? */
|
||||
mio_freemem (mio, cwq);
|
||||
}
|
||||
|
||||
if (dev_to_halt) mio_dev_halt (dev_to_halt);
|
||||
}
|
||||
cwq = next;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static MIO_INLINE void handle_event (mio_t* mio, mio_dev_t* dev, int events, int rdhup)
|
||||
{
|
||||
MIO_ASSERT (mio, mio == dev->mio);
|
||||
@ -389,7 +476,7 @@ static MIO_INLINE void handle_event (mio_t* mio, mio_dev_t* dev, int events, int
|
||||
|
||||
if (y <= -1)
|
||||
{
|
||||
MIO_DEBUG1 (mio, "Error returned by on_write() of device %p\n", dev);
|
||||
MIO_DEBUG1 (mio, "MIO - Error returned by on_write() of device %p\n", dev);
|
||||
mio_dev_halt (dev);
|
||||
dev = MIO_NULL;
|
||||
break;
|
||||
@ -474,6 +561,19 @@ static MIO_INLINE void handle_event (mio_t* mio, mio_dev_t* dev, int events, int
|
||||
}
|
||||
else /*if (x >= 1) */
|
||||
{
|
||||
/* call on_write() callbacks enqueued fro the device before calling on_read().
|
||||
* if on_write() callback is delayed, there can be out-of-order execution
|
||||
* between on_read() and on_write() callbacks. for instance, if a write request
|
||||
* is started from within on_read() callback, and the input data is available
|
||||
* in the next iteration of this loop, the on_read() callback is triggered
|
||||
* before the on_write() callbacks scheduled before that on_read() callback. */
|
||||
if (dev->cw_count > 0)
|
||||
{
|
||||
fire_cwq_handlers_for_dev (mio, dev);
|
||||
/* it will still invoke the on_read() callbak below even if
|
||||
* the device gets halted inside fire_cwq_handlers_for_dev() */
|
||||
}
|
||||
|
||||
if (len <= 0 && (dev->dev_cap & MIO_DEV_CAP_STREAM))
|
||||
{
|
||||
/* EOF received. for a stream device, a zero-length
|
||||
@ -565,45 +665,15 @@ int mio_exec (mio_t* mio)
|
||||
int ret = 0;
|
||||
|
||||
/* execute callbacks for completed write operations */
|
||||
while (!MIO_CWQ_IS_EMPTY(&mio->cwq))
|
||||
{
|
||||
mio_cwq_t* cwq;
|
||||
mio_oow_t cwqfl_index;
|
||||
mio_dev_t* dev_to_halt;
|
||||
|
||||
cwq = MIO_CWQ_HEAD(&mio->cwq);
|
||||
if (cwq->dev->dev_evcb->on_write(cwq->dev, cwq->olen, cwq->ctx, &cwq->dstaddr) <= -1)
|
||||
{
|
||||
MIO_DEBUG1 (mio, "Error returned by on_write() of device %p in cwq\n", cwq->dev);
|
||||
dev_to_halt = cwq->dev;
|
||||
}
|
||||
else
|
||||
{
|
||||
dev_to_halt = MIO_NULL;
|
||||
}
|
||||
cwq->dev->cw_count--;
|
||||
MIO_CWQ_UNLINK (cwq);
|
||||
|
||||
cwqfl_index = MIO_ALIGN_POW2(cwq->dstaddr.len, MIO_CWQFL_ALIGN) / MIO_CWQFL_SIZE;
|
||||
if (cwqfl_index < MIO_COUNTOF(mio->cwqfl))
|
||||
{
|
||||
/* reuse the cwq object if dstaddr is 0 in size. chain it to the free list */
|
||||
cwq->q_next = mio->cwqfl[cwqfl_index];
|
||||
mio->cwqfl[cwqfl_index] = cwq;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* TODO: more reuse of objects of different size? */
|
||||
mio_freemem (mio, cwq);
|
||||
}
|
||||
|
||||
if (dev_to_halt) mio_dev_halt (dev_to_halt);
|
||||
}
|
||||
fire_cwq_handlers (mio);
|
||||
|
||||
/* execute the scheduled jobs before checking devices with the
|
||||
* multiplexer. the scheduled jobs can safely destroy the devices */
|
||||
mio_firetmrjobs (mio, MIO_NULL, MIO_NULL);
|
||||
|
||||
/* execute callbacks for completed write operations again in case there were some jobs initiaated in the timer jobs */
|
||||
//fire_cwq_handlers (mio);
|
||||
|
||||
if (!MIO_DEVL_IS_EMPTY(&mio->actdev))
|
||||
{
|
||||
/* wait on the multiplexer only if there is at least 1 active device */
|
||||
@ -618,7 +688,7 @@ int mio_exec (mio_t* mio)
|
||||
|
||||
if (mio_sys_waitmux(mio, &tmout, handle_event) <= -1)
|
||||
{
|
||||
MIO_DEBUG0 (mio, "WARNING - Failed to wait on mutiplexer\n");
|
||||
MIO_DEBUG0 (mio, "MIO - WARNING - Failed to wait on mutiplexer\n");
|
||||
ret = -1;
|
||||
}
|
||||
}
|
||||
@ -627,7 +697,7 @@ int mio_exec (mio_t* mio)
|
||||
while (!MIO_DEVL_IS_EMPTY(&mio->hltdev))
|
||||
{
|
||||
mio_dev_t* dev = MIO_DEVL_FIRST_DEV(&mio->hltdev);
|
||||
MIO_DEBUG1 (mio, "Killing HALTED device %p\n", dev);
|
||||
MIO_DEBUG1 (mio, "MIO - Killing HALTED device %p\n", dev);
|
||||
mio_dev_kill (dev);
|
||||
}
|
||||
|
||||
@ -846,6 +916,7 @@ void mio_dev_kill (mio_dev_t* dev)
|
||||
next = MIO_CWQ_NEXT(cwq);
|
||||
if (cwq->dev == dev)
|
||||
{
|
||||
cwq->dev->cw_count--;
|
||||
MIO_CWQ_UNLINK (cwq);
|
||||
mio_freemem (mio, cwq);
|
||||
}
|
||||
@ -906,7 +977,7 @@ void mio_dev_halt (mio_dev_t* dev)
|
||||
|
||||
if (dev->dev_cap & MIO_DEV_CAP_ACTIVE)
|
||||
{
|
||||
MIO_DEBUG1 (mio, "HALTING DEVICE %p\n", dev);
|
||||
MIO_DEBUG1 (mio, "MIO - HALTING DEVICE %p\n", dev);
|
||||
|
||||
/* delink the device object from the active device list */
|
||||
MIO_DEVL_UNLINK_DEV (dev);
|
||||
|
@ -198,9 +198,9 @@ static pid_t standard_fork_and_exec (mio_t* mio, int pfds[], int flags, param_t*
|
||||
(flags & MIO_DEV_PRO_ERRTONUL))
|
||||
{
|
||||
#if defined(O_LARGEFILE)
|
||||
devnull = open ("/dev/null", O_RDWR | O_LARGEFILE, 0);
|
||||
devnull = open("/dev/null", O_RDWR | O_LARGEFILE, 0);
|
||||
#else
|
||||
devnull = open ("/dev/null", O_RDWR, 0);
|
||||
devnull = open("/dev/null", O_RDWR, 0);
|
||||
#endif
|
||||
if (devnull == MIO_SYSHND_INVALID) goto slave_oops;
|
||||
}
|
||||
@ -224,7 +224,7 @@ static int dev_pro_make_master (mio_dev_t* dev, void* ctx)
|
||||
mio_t* mio = dev->mio;
|
||||
mio_dev_pro_t* rdev = (mio_dev_pro_t*)dev;
|
||||
mio_dev_pro_make_t* info = (mio_dev_pro_make_t*)ctx;
|
||||
mio_syshnd_t pfds[6];
|
||||
mio_syshnd_t pfds[6] = { MIO_SYSHND_INVALID, MIO_SYSHND_INVALID, MIO_SYSHND_INVALID, MIO_SYSHND_INVALID, MIO_SYSHND_INVALID, MIO_SYSHND_INVALID };
|
||||
int i, minidx = -1, maxidx = -1;
|
||||
param_t param;
|
||||
pid_t pid;
|
||||
@ -459,7 +459,7 @@ static int dev_pro_kill_master (mio_dev_t* dev, int force)
|
||||
int killed = 0;
|
||||
|
||||
await_child:
|
||||
wpid = waitpid (rdev->child_pid, &status, WNOHANG);
|
||||
wpid = waitpid(rdev->child_pid, &status, WNOHANG);
|
||||
if (wpid == 0)
|
||||
{
|
||||
if (force && !killed)
|
||||
|
Loading…
Reference in New Issue
Block a user