still working on cgi handling in http server
This commit is contained in:
parent
362ae444fc
commit
fc26f4a6c3
@ -472,7 +472,7 @@ static void send_icmp (mio_dev_sck_t* dev, mio_uint16_t seq)
|
||||
icmphdr->u.echo.seq = mio_hton16(seq);
|
||||
|
||||
memset (&buf[MIO_SIZEOF(*icmphdr)], 'A', MIO_SIZEOF(buf) - MIO_SIZEOF(*icmphdr));
|
||||
icmphdr->checksum = mio_checksumip (icmphdr, MIO_SIZEOF(buf));
|
||||
icmphdr->checksum = mio_checksum_ip(icmphdr, MIO_SIZEOF(buf));
|
||||
|
||||
if (mio_dev_sck_write(dev, buf, MIO_SIZEOF(buf), MIO_NULL, &dstaddr) <= -1)
|
||||
{
|
||||
|
@ -254,6 +254,10 @@ static int init_client (mio_svc_htts_cli_t* cli, mio_dev_sck_t* sck)
|
||||
cli->htrd = mio_htrd_open(sck->mio, MIO_SIZEOF(*htrdxtn));
|
||||
if (MIO_UNLIKELY(!cli->htrd)) goto oops;
|
||||
|
||||
/* With MIO_HTRD_TRAILERS, htrd stores trailers in a separate place.
|
||||
* Otherwise, it is merged to the headers. */
|
||||
/*mio_htrd_setopt (cli->htrd, MIO_HTRD_REQUEST | MIO_HTRD_TRAILERS);*/
|
||||
|
||||
cli->sbuf = mio_becs_open(sck->mio, 0, 2048);
|
||||
if (MIO_UNLIKELY(!cli->sbuf)) goto oops;
|
||||
|
||||
@ -616,6 +620,13 @@ typedef enum cgi_state_res_mode_t cgi_state_res_mode_t;
|
||||
|
||||
#define CGI_STATE_PENDING_IO_THRESHOLD 5
|
||||
|
||||
#define CGI_STATE_OVER_READ_FROM_CLIENT (1 << 0)
|
||||
#define CGI_STATE_OVER_READ_FROM_PEER (1 << 1)
|
||||
#define CGI_STATE_OVER_WRITE_TO_CLIENT (1 << 2)
|
||||
#define CGI_STATE_OVER_WRITE_TO_PEER (1 << 3)
|
||||
#define CGI_STATE_OVER_ALL (CGI_STATE_OVER_READ_FROM_CLIENT | CGI_STATE_OVER_READ_FROM_PEER | CGI_STATE_OVER_WRITE_TO_CLIENT | CGI_STATE_OVER_WRITE_TO_PEER)
|
||||
|
||||
|
||||
struct cgi_state_t
|
||||
{
|
||||
MIO_SVC_HTTS_RSRC_HEADER;
|
||||
@ -624,16 +635,17 @@ struct cgi_state_t
|
||||
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_svc_htts_cli_t* client;
|
||||
mio_http_version_t req_version; /* client request */
|
||||
|
||||
unsigned int over: 4; /* must be large enough to accomodate CGI_STATE_OVER_ALL */
|
||||
unsigned int keep_alive: 1;
|
||||
unsigned int req_content_length_unlimited: 1;
|
||||
unsigned int peer_eof: 1;
|
||||
mio_oow_t req_content_length; /* client request content length */
|
||||
cgi_state_res_mode_t res_mode_to_cli;
|
||||
|
||||
mio_dev_sck_on_read_t cli_org_on_read;
|
||||
mio_dev_sck_on_write_t cli_org_on_write;
|
||||
mio_dev_sck_on_read_t client_org_on_read;
|
||||
mio_dev_sck_on_write_t client_org_on_write;
|
||||
};
|
||||
typedef struct cgi_state_t cgi_state_t;
|
||||
|
||||
@ -645,12 +657,12 @@ typedef struct cgi_peer_xtn_t cgi_peer_xtn_t;
|
||||
|
||||
static void cgi_state_halt_participating_devices (cgi_state_t* cgi_state)
|
||||
{
|
||||
MIO_ASSERT (cgi_state->cli->htts->mio, cgi_state->cli != MIO_NULL);
|
||||
MIO_ASSERT (cgi_state->cli->htts->mio, cgi_state->cli->sck != MIO_NULL);
|
||||
MIO_ASSERT (cgi_state->client->htts->mio, cgi_state->client != MIO_NULL);
|
||||
MIO_ASSERT (cgi_state->client->htts->mio, cgi_state->client->sck != MIO_NULL);
|
||||
|
||||
MIO_DEBUG4 (cgi_state->cli->htts->mio, "HTTS(%p) - halting cgi state %p(client=%p,peer=%p)\n", cgi_state->cli->htts, cgi_state, cgi_state->cli->sck, cgi_state->peer);
|
||||
MIO_DEBUG4 (cgi_state->client->htts->mio, "HTTS(%p) - halting cgi state %p(client=%p,peer=%p)\n", cgi_state->client->htts, cgi_state, cgi_state->client->sck, cgi_state->peer);
|
||||
|
||||
mio_dev_sck_halt (cgi_state->cli->sck);
|
||||
mio_dev_sck_halt (cgi_state->client->sck);
|
||||
/* check for peer as it may not have been started */
|
||||
if (cgi_state->peer) mio_dev_pro_halt (cgi_state->peer);
|
||||
|
||||
@ -660,8 +672,9 @@ static void cgi_state_halt_participating_devices (cgi_state_t* cgi_state)
|
||||
|
||||
static int cgi_state_write_to_client (cgi_state_t* cgi_state, const void* data, mio_iolen_t dlen)
|
||||
{
|
||||
printf ("WRIING TO CLIENT %d\n", dlen);
|
||||
cgi_state->num_pending_writes_to_client++;
|
||||
if (mio_dev_sck_write(cgi_state->cli->sck, data, dlen, MIO_NULL, MIO_NULL) <= -1)
|
||||
if (mio_dev_sck_write(cgi_state->client->sck, data, dlen, MIO_NULL, MIO_NULL) <= -1)
|
||||
{
|
||||
cgi_state->num_pending_writes_to_client--;
|
||||
return -1;
|
||||
@ -676,8 +689,9 @@ static int cgi_state_write_to_client (cgi_state_t* cgi_state, const void* data,
|
||||
|
||||
static int cgi_state_writev_to_client (cgi_state_t* cgi_state, mio_iovec_t* iov, mio_iolen_t iovcnt)
|
||||
{
|
||||
printf ("WRITIV TO CLIENT iovcnt = %d\n", (int)iovcnt);
|
||||
cgi_state->num_pending_writes_to_client++;
|
||||
if (mio_dev_sck_writev(cgi_state->cli->sck, iov, iovcnt, MIO_NULL, MIO_NULL) <= -1)
|
||||
if (mio_dev_sck_writev(cgi_state->client->sck, iov, iovcnt, MIO_NULL, MIO_NULL) <= -1)
|
||||
{
|
||||
cgi_state->num_pending_writes_to_client--;
|
||||
return -1;
|
||||
@ -692,6 +706,7 @@ static int cgi_state_writev_to_client (cgi_state_t* cgi_state, mio_iovec_t* iov,
|
||||
|
||||
static int cgi_state_write_to_peer (cgi_state_t* cgi_state, const void* data, mio_iolen_t dlen)
|
||||
{
|
||||
printf ("WRIING TO PEER %d\n", (int)dlen);
|
||||
cgi_state->num_pending_writes_to_peer++;
|
||||
if (mio_dev_pro_write(cgi_state->peer, data, dlen, MIO_NULL) <= -1)
|
||||
{
|
||||
@ -702,14 +717,14 @@ static int cgi_state_write_to_peer (cgi_state_t* cgi_state, const void* data, mi
|
||||
/* TODO: check if it's already finished or something.. */
|
||||
if (cgi_state->num_pending_writes_to_peer > CGI_STATE_PENDING_IO_THRESHOLD)
|
||||
{
|
||||
if (mio_dev_sck_read(cgi_state->cli->sck, 0) <= -1) return -1;
|
||||
if (mio_dev_sck_read(cgi_state->client->sck, 0) <= -1) return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cgi_state_send_final_status_to_client (cgi_state_t* cgi_state, int status_code)
|
||||
{
|
||||
mio_svc_htts_cli_t* cli = cgi_state->cli;
|
||||
mio_svc_htts_cli_t* cli = cgi_state->client;
|
||||
mio_bch_t dtbuf[64];
|
||||
|
||||
mio_svc_htts_fmtgmtime (cli->htts, MIO_NULL, dtbuf, MIO_COUNTOF(dtbuf));
|
||||
@ -722,6 +737,42 @@ static int cgi_state_send_final_status_to_client (cgi_state_t* cgi_state, int st
|
||||
return cgi_state_write_to_client(cgi_state, MIO_BECS_PTR(cli->sbuf), MIO_BECS_LEN(cli->sbuf));
|
||||
}
|
||||
|
||||
static MIO_INLINE void cgi_state_mark_over (cgi_state_t* cgi_state, int over_bits)
|
||||
{
|
||||
cgi_state->over |= over_bits;
|
||||
|
||||
MIO_DEBUG5 (cgi_state->htts->mio, "HTTS(%p) - client=%p peer=%p new-bits=%x over=%x\n", cgi_state->htts, cgi_state->client->sck, cgi_state->peer, (int)over_bits, (int)cgi_state->over);
|
||||
|
||||
|
||||
if (cgi_state->over & CGI_STATE_OVER_READ_FROM_CLIENT)
|
||||
{
|
||||
mio_dev_sck_read (cgi_state->client->sck, 0); /* TODO: error handling */
|
||||
}
|
||||
|
||||
if (cgi_state->over & CGI_STATE_OVER_READ_FROM_PEER)
|
||||
{
|
||||
if (cgi_state->peer) mio_dev_pro_read (cgi_state->peer, MIO_DEV_PRO_OUT, 0); /* TODO: error handling */
|
||||
}
|
||||
|
||||
if (cgi_state->over == CGI_STATE_OVER_ALL)
|
||||
{
|
||||
/* ready to stop */
|
||||
if (cgi_state->peer) mio_dev_pro_halt (cgi_state->peer);
|
||||
|
||||
if (cgi_state->keep_alive)
|
||||
{
|
||||
/* how to arrange to delete this cgi_state object and put the socket back to the normal waiting state??? */
|
||||
printf ("XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\n");
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
mio_dev_sck_shutdown (cgi_state->client->sck, MIO_DEV_SCK_SHUTDOWN_WRITE);
|
||||
mio_dev_sck_halt (cgi_state->client->sck);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void cgi_state_on_kill (cgi_state_t* cgi_state)
|
||||
{
|
||||
printf ("**** CGI_STATE_ON_KILL \n");
|
||||
@ -743,19 +794,19 @@ printf ("**** CGI_STATE_ON_KILL \n");
|
||||
cgi_state->peer_htrd = MIO_NULL;
|
||||
}
|
||||
|
||||
if (cgi_state->cli_org_on_read)
|
||||
if (cgi_state->client_org_on_read)
|
||||
{
|
||||
cgi_state->cli->sck->on_read = cgi_state->cli_org_on_read;
|
||||
cgi_state->cli_org_on_read = MIO_NULL;
|
||||
cgi_state->client->sck->on_read = cgi_state->client_org_on_read;
|
||||
cgi_state->client_org_on_read = MIO_NULL;
|
||||
}
|
||||
|
||||
if (cgi_state->cli_org_on_write)
|
||||
if (cgi_state->client_org_on_write)
|
||||
{
|
||||
cgi_state->cli->sck->on_write = cgi_state->cli_org_on_write;
|
||||
cgi_state->cli_org_on_write = MIO_NULL;
|
||||
cgi_state->client->sck->on_write = cgi_state->client_org_on_write;
|
||||
cgi_state->client_org_on_write = MIO_NULL;
|
||||
}
|
||||
|
||||
mio_htrd_setrecbs (cgi_state->cli->htrd, &client_htrd_recbs); /* restore the callbacks */
|
||||
mio_htrd_setrecbs (cgi_state->client->htrd, &client_htrd_recbs); /* restore the callbacks */
|
||||
}
|
||||
|
||||
static void cgi_peer_on_close (mio_dev_pro_t* pro, mio_dev_pro_sid_t sid)
|
||||
@ -766,32 +817,39 @@ static void cgi_peer_on_close (mio_dev_pro_t* pro, mio_dev_pro_sid_t sid)
|
||||
|
||||
if (!cgi_state) return; /* cgi state already gone */
|
||||
|
||||
printf (">>>>>>>>> PEER ON CLOSE sid=%d\n", (int)sid);
|
||||
printf (">> cgi_state %p\n", cgi_state);
|
||||
printf (">> cgi_state->peer %p\n", cgi_state->peer);
|
||||
printf (">> cgi_state->cli %p\n", cgi_state->cli);
|
||||
printf (">> cgi_state->cli->htts %p\n", cgi_state->cli->htts);
|
||||
|
||||
if (sid == MIO_DEV_PRO_MASTER)
|
||||
switch (sid)
|
||||
{
|
||||
MIO_DEBUG3 (mio, "HTTS(%p) - peer %p(pid=%d) closing master\n", cgi_state->cli->htts, pro, (int)pro->child_pid);
|
||||
cgi_peer->state->peer = MIO_NULL; /* clear this peer from the state */
|
||||
}
|
||||
else
|
||||
{
|
||||
MIO_ASSERT (mio, cgi_state->peer == pro);
|
||||
case MIO_DEV_PRO_MASTER:
|
||||
MIO_DEBUG3 (mio, "HTTS(%p) - peer %p(pid=%d) closing master\n", cgi_state->client->htts, pro, (int)pro->child_pid);
|
||||
cgi_peer->state->peer = MIO_NULL; /* clear this peer from the state */
|
||||
break;
|
||||
|
||||
MIO_DEBUG4 (mio, "HTTS(%p) - peer %p(pid=%d) closing slave[%d]\n", cgi_state->cli->htts, pro, (int)pro->child_pid, sid);
|
||||
if (sid == MIO_DEV_PRO_OUT && !cgi_state->peer_eof)
|
||||
{
|
||||
/* check if it's sending... */
|
||||
cgi_state->peer_eof = 1;
|
||||
if (cgi_state->res_mode_to_cli == CGI_STATE_RES_MODE_CHUNKED &&
|
||||
cgi_state_write_to_client(cgi_state, "0\r\n\r\n", 5) <= -1)
|
||||
case MIO_DEV_PRO_OUT:
|
||||
MIO_ASSERT (mio, cgi_state->peer == pro);
|
||||
MIO_DEBUG4 (mio, "HTTS(%p) - peer %p(pid=%d) closing slave[%d]\n", cgi_state->client->htts, pro, (int)pro->child_pid, sid);
|
||||
|
||||
if (!(cgi_state->over & CGI_STATE_OVER_READ_FROM_PEER))
|
||||
{
|
||||
cgi_state_halt_participating_devices (cgi_state);
|
||||
if (cgi_state->res_mode_to_cli == CGI_STATE_RES_MODE_CHUNKED &&
|
||||
cgi_state_write_to_client(cgi_state, "0\r\n\r\n", 5) <= -1)
|
||||
{
|
||||
cgi_state_halt_participating_devices (cgi_state);
|
||||
}
|
||||
|
||||
cgi_state_mark_over (cgi_state, CGI_STATE_OVER_READ_FROM_PEER);
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case MIO_DEV_PRO_IN:
|
||||
cgi_state_mark_over (cgi_state, CGI_STATE_OVER_WRITE_TO_PEER);
|
||||
break;
|
||||
|
||||
case MIO_DEV_PRO_ERR:
|
||||
default:
|
||||
MIO_DEBUG4 (mio, "HTTS(%p) - peer %p(pid=%d) closing slave[%d]\n", cgi_state->client->htts, pro, (int)pro->child_pid, sid);
|
||||
/* do nothing */
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@ -806,35 +864,40 @@ static int cgi_peer_on_read (mio_dev_pro_t* pro, mio_dev_pro_sid_t sid, const vo
|
||||
printf (">>>>>>>>> PEER ON READ %d\n", dlen);
|
||||
if (dlen <= -1)
|
||||
{
|
||||
MIO_DEBUG3 (mio, "HTTPS(%p) - read error from peer %p(pid=%u)\n", cgi_state->cli->htts, pro, (unsigned int)pro->child_pid);
|
||||
MIO_DEBUG3 (mio, "HTTPS(%p) - read error from peer %p(pid=%u)\n", cgi_state->client->htts, pro, (unsigned int)pro->child_pid);
|
||||
goto oops;
|
||||
}
|
||||
|
||||
if (cgi_state->peer_eof) return 0; /* will ignore */
|
||||
#if 0
|
||||
if (cgi_state->over & CGI_STATE_OVER_READ_FROM_PEER) return 0; /* ignore the read event */
|
||||
#endif
|
||||
|
||||
if (dlen == 0)
|
||||
{
|
||||
MIO_DEBUG3 (mio, "HTTPS(%p) - EOF from peer %p(pid=%u)\n", cgi_state->cli->htts, pro, (unsigned int)pro->child_pid);
|
||||
cgi_state->peer_eof = 1;
|
||||
MIO_DEBUG3 (mio, "HTTPS(%p) - EOF from peer %p(pid=%u)\n", cgi_state->client->htts, pro, (unsigned int)pro->child_pid);
|
||||
|
||||
if (cgi_state->res_mode_to_cli == CGI_STATE_RES_MODE_CHUNKED &&
|
||||
cgi_state_write_to_client(cgi_state, "0\r\n\r\n", 5) <= -1) goto oops;
|
||||
|
||||
cgi_state_mark_over (cgi_state, CGI_STATE_OVER_READ_FROM_PEER);
|
||||
}
|
||||
else
|
||||
{
|
||||
mio_oow_t rem;
|
||||
printf ( "QQQQQQQQQQQQQQQQQQ>>>>>>>>>>>>>>>>>> feeding to peer htrd.... dlen => %d\n", (int)dlen);
|
||||
|
||||
if (mio_htrd_feed(cgi_state->peer_htrd, data, dlen, &rem) <= -1)
|
||||
{
|
||||
printf ( "FEEDING FAILURE TO PEER HTDDRD.. dlen => %d\n", (int)dlen);
|
||||
cgi_state_send_final_status_to_client (cgi_state, 500); /* don't care about error */
|
||||
goto oops;
|
||||
}
|
||||
|
||||
if (rem > 0)
|
||||
{
|
||||
/* If the script specifies Content-Length and produces longer data, it will come here */
|
||||
printf ("AAAAAAAAAAAAAAAAAa EEEEEXcessive DATA..................\n");
|
||||
cgi_state->peer_eof = 1; /* EOF or use another bit-field? */
|
||||
printf ("AAAAAAAAAAAAAAAAAa EEEEEXcessive DATA..................\n");
|
||||
/* TODO: or drop this request?? */
|
||||
cgi_state_mark_over (cgi_state, CGI_STATE_OVER_READ_FROM_PEER);
|
||||
}
|
||||
}
|
||||
|
||||
@ -873,11 +936,12 @@ static int cgi_peer_capture_header (mio_htre_t* req, const mio_bch_t* key, const
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cgi_peer_htrd_peek (mio_htrd_t* htrd, mio_htre_t* req)
|
||||
{
|
||||
cgi_peer_xtn_t* cgi_peer = mio_htrd_getxtn(htrd);
|
||||
cgi_state_t* cgi_state = cgi_peer->state;
|
||||
mio_svc_htts_cli_t* cli = cgi_state->cli;
|
||||
mio_svc_htts_cli_t* cli = cgi_state->client;
|
||||
mio_bch_t dtbuf[64];
|
||||
int status_code;
|
||||
|
||||
@ -942,7 +1006,7 @@ static int cgi_peer_htrd_push_content (mio_htrd_t* htrd, mio_htre_t* req, const
|
||||
cgi_peer_xtn_t* cgi_peer = mio_htrd_getxtn(htrd);
|
||||
cgi_state_t* cgi_state = cgi_peer->state;
|
||||
|
||||
MIO_ASSERT (cgi_state->cli->htts->mio, htrd == cgi_state->peer_htrd);
|
||||
MIO_ASSERT (cgi_state->client->htts->mio, htrd == cgi_state->peer_htrd);
|
||||
|
||||
switch (cgi_state->res_mode_to_cli)
|
||||
{
|
||||
@ -958,7 +1022,7 @@ static int cgi_peer_htrd_push_content (mio_htrd_t* htrd, mio_htre_t* req, const
|
||||
|
||||
iov[0].iov_ptr = lbuf;
|
||||
iov[0].iov_len = llen;
|
||||
iov[1].iov_ptr = data;
|
||||
iov[1].iov_ptr = (void*)data;
|
||||
iov[1].iov_len = dlen;
|
||||
iov[2].iov_ptr = "\r\n";
|
||||
iov[2].iov_len = 2;
|
||||
@ -991,15 +1055,33 @@ static mio_htrd_recbs_t cgi_peer_htrd_recbs =
|
||||
cgi_peer_htrd_push_content
|
||||
};
|
||||
|
||||
static int walk_client_req_trailer (mio_htre_t* req, const mio_bch_t* key, const mio_htre_hdrval_t* val, void* ctx)
|
||||
{
|
||||
printf ("\t%s=");
|
||||
while (val)
|
||||
{
|
||||
printf ("%s ", val->ptr);
|
||||
val = val->next;
|
||||
}
|
||||
printf ("\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cgi_client_htrd_poke (mio_htrd_t* htrd, mio_htre_t* req)
|
||||
{
|
||||
/* client request got completed */
|
||||
htrd_xtn_t* htrdxtn = mio_htrd_getxtn(htrd);
|
||||
mio_dev_sck_t* sck = htrdxtn->sck;
|
||||
mio_svc_htts_cli_t* cli = mio_dev_sck_getxtn(sck);
|
||||
cgi_state_t* cgi_state = cli->rsrc;
|
||||
cgi_state_t* cgi_state = (cgi_state_t*)cli->rsrc;
|
||||
|
||||
|
||||
printf (">> CLIENT REQUEST COMPLETED\n");
|
||||
//mio_htre_walkheaders (req, walk_client_req_trailer, MIO_NULL);
|
||||
mio_htre_walktrailers (req, walk_client_req_trailer, MIO_NULL); // MIO_HTRD_TRAILERS must be set for this to work
|
||||
|
||||
/* indicate EOF to the client peer */
|
||||
cgi_state_mark_over (cgi_state, CGI_STATE_OVER_READ_FROM_CLIENT);
|
||||
return cgi_state_write_to_peer(cgi_state, MIO_NULL, 0);
|
||||
}
|
||||
|
||||
@ -1008,7 +1090,7 @@ static int cgi_client_htrd_push_content (mio_htrd_t* htrd, mio_htre_t* req, cons
|
||||
htrd_xtn_t* htrdxtn = mio_htrd_getxtn(htrd);
|
||||
mio_dev_sck_t* sck = htrdxtn->sck;
|
||||
mio_svc_htts_cli_t* cli = mio_dev_sck_getxtn(sck);
|
||||
cgi_state_t* cgi_state = cli->rsrc;
|
||||
cgi_state_t* cgi_state = (cgi_state_t*)cli->rsrc;
|
||||
|
||||
MIO_ASSERT (sck->mio, cli->sck == sck);
|
||||
return cgi_state_write_to_peer(cgi_state, data, dlen);
|
||||
@ -1024,18 +1106,20 @@ static int cgi_peer_on_write (mio_dev_pro_t* pro, mio_iolen_t wrlen, void* wrctx
|
||||
|
||||
if (wrlen <= -1)
|
||||
{
|
||||
MIO_DEBUG3 (mio, "HTTS(%p) - unable to write to peer %p(pid=%u)\n", cgi_state->cli->htts, pro, (int)pro->child_pid);
|
||||
MIO_DEBUG3 (mio, "HTTS(%p) - unable to write to peer %p(pid=%u)\n", cgi_state->client->htts, pro, (int)pro->child_pid);
|
||||
goto oops;
|
||||
}
|
||||
else if (wrlen == 0)
|
||||
{
|
||||
/* indicated EOF */
|
||||
/* do nothing here as i didn't incremented num_pending_writes_to_peer when making the write request */
|
||||
|
||||
cgi_state->num_pending_writes_to_peer--;
|
||||
MIO_ASSERT (mio, cgi_state->num_pending_writes_to_peer == 0);
|
||||
MIO_DEBUG3 (mio, "HTTS(%p) - indicated EOF to peer %p(pid=%u)\n", cgi_state->cli->htts, pro, (int)pro->child_pid);
|
||||
MIO_DEBUG3 (mio, "HTTS(%p) - indicated EOF to peer %p(pid=%u)\n", cgi_state->client->htts, pro, (int)pro->child_pid);
|
||||
/* indicated EOF to the peer side. i need no more data from the client side.
|
||||
* i don't need to enable input watching in the client side either */
|
||||
cgi_state_mark_over (cgi_state, CGI_STATE_OVER_WRITE_TO_PEER);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -1044,8 +1128,13 @@ static int cgi_peer_on_write (mio_dev_pro_t* pro, mio_iolen_t wrlen, void* wrctx
|
||||
cgi_state->num_pending_writes_to_peer--;
|
||||
if (cgi_state->num_pending_writes_to_peer == CGI_STATE_PENDING_IO_THRESHOLD)
|
||||
{
|
||||
// TODO: check if (cli has anything to read...) if so ...
|
||||
if (mio_dev_sck_read(cgi_state->cli->sck, 1) <= -1) goto oops;
|
||||
if (!(cgi_state->over & CGI_STATE_OVER_READ_FROM_CLIENT) &&
|
||||
mio_dev_sck_read(cgi_state->client->sck, 1) <= -1) goto oops;
|
||||
}
|
||||
|
||||
if ((cgi_state->over & CGI_STATE_OVER_READ_FROM_CLIENT) && cgi_state->num_pending_writes_to_peer <= 0)
|
||||
{
|
||||
cgi_state_mark_over (cgi_state, CGI_STATE_OVER_WRITE_TO_PEER);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1056,12 +1145,11 @@ oops:
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int cgi_client_on_read (mio_dev_sck_t* sck, const void* buf, mio_iolen_t len, const mio_skad_t* srcaddr)
|
||||
{
|
||||
mio_t* mio = sck->mio;
|
||||
mio_svc_htts_cli_t* cli = mio_dev_sck_getxtn(sck);
|
||||
cgi_state_t* cgi_state = cli->rsrc;
|
||||
cgi_state_t* cgi_state = (cgi_state_t*)cli->rsrc;
|
||||
|
||||
MIO_ASSERT (mio, sck == cli->sck);
|
||||
|
||||
@ -1083,24 +1171,16 @@ printf ("** HTTS - cgi client read %p %d -> htts:%p\n", sck, (int)len, cli->h
|
||||
if (len == 0)
|
||||
{
|
||||
/* EOF on the client side. arrange to close */
|
||||
printf ("asking pro to close...\n");
|
||||
/* HAVE I ALREADY CLOSED IT??? Check conflict is the poke handler */
|
||||
return cgi_state_write_to_peer(cgi_state, MIO_NULL, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
mio_oow_t rem;
|
||||
/* EOF if it got content as long as cgi_state->req_content_length??? */
|
||||
if (mio_htrd_feed(cli->htrd, buf, len, &rem) <= -1)
|
||||
{
|
||||
printf ("FAILED TO FEED TH CLIENT HTRD......\n");
|
||||
goto oops;
|
||||
}
|
||||
if (mio_htrd_feed(cli->htrd, buf, len, &rem) <= -1) goto oops;
|
||||
|
||||
if (rem > 0)
|
||||
{
|
||||
/* the cgi script is not behaving properly */
|
||||
/* giving excessive data... */
|
||||
printf ("UUUUUUUUUUUUUUUUUUUUUUUUUUGGGGGHHHHHHHHHHHH .......... CGI CLIENT GIVING EXCESSIVE DATA AFTER CONTENTS...\n");
|
||||
}
|
||||
}
|
||||
|
||||
@ -1116,7 +1196,7 @@ static int cgi_client_on_write (mio_dev_sck_t* sck, mio_iolen_t wrlen, void* wrc
|
||||
{
|
||||
mio_t* mio = sck->mio;
|
||||
mio_svc_htts_cli_t* cli = mio_dev_sck_getxtn(sck);
|
||||
cgi_state_t* cgi_state = cli->rsrc;
|
||||
cgi_state_t* cgi_state = (cgi_state_t*)cli->rsrc;
|
||||
|
||||
if (wrlen <= -1)
|
||||
{
|
||||
@ -1129,29 +1209,26 @@ static int cgi_client_on_write (mio_dev_sck_t* sck, mio_iolen_t wrlen, void* wrc
|
||||
/* if the connect is keep-alive, this part may not be called */
|
||||
cgi_state->num_pending_writes_to_client--;
|
||||
MIO_ASSERT (mio, cgi_state->num_pending_writes_to_client == 0);
|
||||
MIO_DEBUG3 (mio, "HTTS(%p) - indicated EOF to client %p(%d)\n", cgi_state->cli->htts, sck, (int)sck->hnd);
|
||||
MIO_DEBUG3 (mio, "HTTS(%p) - indicated EOF to client %p(%d)\n", cgi_state->client->htts, sck, (int)sck->hnd);
|
||||
/* since EOF has been indicated to the client, it must not write to the client any further.
|
||||
* this also means that i don't need any data from the peer side either.
|
||||
* i don't need to enable input watching on the peer side */
|
||||
cgi_state_mark_over (cgi_state, CGI_STATE_OVER_WRITE_TO_CLIENT);
|
||||
}
|
||||
else
|
||||
{
|
||||
MIO_ASSERT (mio, cgi_state->num_pending_writes_to_client > 0);
|
||||
|
||||
printf ("MANAGED TO WRITE TO CLIENT>... %d\n", (int)wrlen);
|
||||
cgi_state->num_pending_writes_to_client--;
|
||||
if (cgi_state->peer && cgi_state->num_pending_writes_to_client == CGI_STATE_PENDING_IO_THRESHOLD)
|
||||
{
|
||||
// TODO: check if there is anything to read... */
|
||||
if (mio_dev_pro_read(cgi_state->peer, MIO_DEV_PRO_OUT, 1) <= -1) goto oops;
|
||||
if (!(cgi_state->over & CGI_STATE_OVER_READ_FROM_PEER) &&
|
||||
mio_dev_pro_read(cgi_state->peer, MIO_DEV_PRO_OUT, 1) <= -1) goto oops;
|
||||
}
|
||||
|
||||
/* in case the peer died before peer read handler reads EOF */
|
||||
if (cgi_state->peer_eof && cgi_state->num_pending_writes_to_client <= 0)
|
||||
if ((cgi_state->over & CGI_STATE_OVER_READ_FROM_PEER) && cgi_state->num_pending_writes_to_client <= 0)
|
||||
{
|
||||
/*if (no_more_input is to be read from the client)*/
|
||||
cgi_state_halt_participating_devices (cgi_state); // must not use this... must kill the state ...
|
||||
/* finished writing all */
|
||||
cgi_state_mark_over (cgi_state, CGI_STATE_OVER_WRITE_TO_CLIENT);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1194,7 +1271,6 @@ int mio_svc_htts_docgi (mio_svc_htts_t* htts, mio_dev_sck_t* csck, mio_htre_t* r
|
||||
cgi_state_t* cgi_state = MIO_NULL;
|
||||
cgi_peer_xtn_t* cgi_peer;
|
||||
mio_dev_pro_make_t mi;
|
||||
int enable_input;
|
||||
|
||||
/* ensure that you call this function before any contents is received */
|
||||
MIO_ASSERT (mio, mio_htre_getcontentlen(req) == 0);
|
||||
@ -1209,14 +1285,14 @@ int mio_svc_htts_docgi (mio_svc_htts_t* htts, mio_dev_sck_t* csck, mio_htre_t* r
|
||||
cgi_state = (cgi_state_t*)mio_svc_htts_rsrc_make(htts, MIO_SIZEOF(*cgi_state), cgi_state_on_kill);
|
||||
if (MIO_UNLIKELY(!cgi_state)) goto oops;
|
||||
|
||||
cgi_state->cli = cli;
|
||||
cgi_state->client = cli;
|
||||
/*cgi_state->num_pending_writes_to_client = 0;
|
||||
cgi_state->num_pending_writes_to_peer = 0;*/
|
||||
cgi_state->req_version = *mio_htre_getversion(req);
|
||||
cgi_state->req_content_length_unlimited = get_request_content_length(req, &cgi_state->req_content_length);
|
||||
|
||||
cgi_state->cli_org_on_read = csck->on_read;
|
||||
cgi_state->cli_org_on_write = csck->on_write;
|
||||
cgi_state->client_org_on_read = csck->on_read;
|
||||
cgi_state->client_org_on_write = csck->on_write;
|
||||
csck->on_read = cgi_client_on_read;
|
||||
csck->on_write = cgi_client_on_write;
|
||||
|
||||
@ -1287,7 +1363,6 @@ int mio_svc_htts_docgi (mio_svc_htts_t* htts, mio_dev_sck_t* csck, mio_htre_t* r
|
||||
goto oops;
|
||||
}
|
||||
|
||||
enable_input = 1;
|
||||
#if defined(CGI_ALLOW_UNLIMITED_REQ_CONTENT_LENGTH)
|
||||
if (cgi_state->req_content_length_unlimited)
|
||||
{
|
||||
@ -1299,8 +1374,8 @@ int mio_svc_htts_docgi (mio_svc_htts_t* htts, mio_dev_sck_t* csck, mio_htre_t* r
|
||||
|
||||
/* TODO: must set CONTENT-LENGTH to -1 before start the process */
|
||||
/* change the callbacks to subscribe to contents to be uploaded */
|
||||
cgi_state->cli->htrd->recbs.poke = cgi_client_htrd_poke;
|
||||
cgi_state->cli->htrd->recbs.push_content = cgi_client_htrd_push_content;
|
||||
cgi_state->client->htrd->recbs.poke = cgi_client_htrd_poke;
|
||||
cgi_state->client->htrd->recbs.push_content = cgi_client_htrd_push_content;
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -1309,26 +1384,36 @@ int mio_svc_htts_docgi (mio_svc_htts_t* htts, mio_dev_sck_t* csck, mio_htre_t* r
|
||||
{
|
||||
|
||||
/* change the callbacks to subscribe to contents to be uploaded */
|
||||
cgi_state->cli->htrd->recbs.poke = cgi_client_htrd_poke;
|
||||
cgi_state->cli->htrd->recbs.push_content = cgi_client_htrd_push_content;
|
||||
cgi_state->client->htrd->recbs.poke = cgi_client_htrd_poke;
|
||||
cgi_state->client->htrd->recbs.push_content = cgi_client_htrd_push_content;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* no content to be uploaded from the client */
|
||||
/* indicate EOF to the peer and disable input wathching from the client */
|
||||
if (cgi_state_write_to_peer(cgi_state, MIO_NULL, 0) <= -1) goto oops;
|
||||
enable_input = 0;
|
||||
cgi_state_mark_over (cgi_state, CGI_STATE_OVER_READ_FROM_CLIENT | CGI_STATE_OVER_WRITE_TO_PEER);
|
||||
}
|
||||
#if defined(CGI_ALLOW_UNLIMITED_REQ_CONTENT_LENGTH)
|
||||
}
|
||||
#endif
|
||||
|
||||
/* TODO: store current input watching state and use it when destroying the cgi_state data */
|
||||
if (mio_dev_sck_read(csck, enable_input) <= -1) goto oops;
|
||||
|
||||
|
||||
/* this may change later if Content-Length is included in the cgi output */
|
||||
cgi_state->res_mode_to_cli = (req->flags & MIO_HTRE_ATTR_KEEPALIVE)? CGI_STATE_RES_MODE_CHUNKED: CGI_STATE_RES_MODE_CLOSE;
|
||||
if (req->flags & MIO_HTRE_ATTR_KEEPALIVE)
|
||||
{
|
||||
cgi_state->keep_alive = 1;
|
||||
cgi_state->res_mode_to_cli = CGI_STATE_RES_MODE_CHUNKED;
|
||||
/* the mode still can get switched to CGI_STATE_RES_MODE_LENGTH if the cgi script emits Content-Length */
|
||||
}
|
||||
else
|
||||
{
|
||||
cgi_state->keep_alive = 0;
|
||||
cgi_state->res_mode_to_cli = CGI_STATE_RES_MODE_CLOSE;
|
||||
}
|
||||
|
||||
/* TODO: store current input watching state and use it when destroying the cgi_state data */
|
||||
if (mio_dev_sck_read(csck, !(cgi_state->over & CGI_STATE_OVER_READ_FROM_CLIENT)) <= -1) goto oops;
|
||||
|
||||
return 0;
|
||||
|
||||
oops:
|
||||
|
@ -409,6 +409,13 @@ struct mio_dev_sck_t
|
||||
|
||||
};
|
||||
|
||||
enum mio_dev_sck_shutdown_how_t
|
||||
{
|
||||
MIO_DEV_SCK_SHUTDOWN_READ = (1 << 0),
|
||||
MIO_DEV_SCK_SHUTDOWN_WRITE = (1 << 1)
|
||||
};
|
||||
typedef enum mio_dev_sck_shutdown_how_t mio_dev_sck_shutdown_how_t;
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
@ -520,7 +527,6 @@ static MIO_INLINE int mio_dev_sck_timedread (mio_dev_sck_t* sck, int enabled, mi
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
MIO_EXPORT int mio_dev_sck_setsockopt (
|
||||
mio_dev_sck_t* dev,
|
||||
int level,
|
||||
@ -537,7 +543,12 @@ MIO_EXPORT int mio_dev_sck_getsockopt (
|
||||
mio_scklen_t* optlen
|
||||
);
|
||||
|
||||
MIO_EXPORT mio_uint16_t mio_checksumip (
|
||||
MIO_EXPORT int mio_dev_sck_shutdown (
|
||||
mio_dev_sck_t* dev,
|
||||
int how /* bitwise-ORed of mio_dev_sck_shutdown_how_t enumerators */
|
||||
);
|
||||
|
||||
MIO_EXPORT mio_uint16_t mio_checksum_ip (
|
||||
const void* hdr,
|
||||
mio_oow_t len
|
||||
);
|
||||
|
@ -696,7 +696,9 @@ int mio_exec (mio_t* mio)
|
||||
|
||||
if (mio_gettmrtmout(mio, MIO_NULL, &tmout) <= -1)
|
||||
{
|
||||
/* defaults to 1 second if timeout can't be acquired */
|
||||
/* defaults to 1 second if timeout can't be acquired.
|
||||
* if this timeout affects how fast the halted device will get
|
||||
* killed when there are no events or timer jobs */
|
||||
tmout.sec = 1; /* TODO: make the default timeout configurable */
|
||||
tmout.nsec = 0;
|
||||
}
|
||||
|
@ -546,6 +546,12 @@ static int dev_pro_read_slave (mio_dev_t* dev, void* buf, mio_iolen_t* len, mio_
|
||||
mio_dev_pro_slave_t* pro = (mio_dev_pro_slave_t*)dev;
|
||||
ssize_t x;
|
||||
|
||||
if (MIO_UNLIKELY(pro->pfd == MIO_SYSHND_INVALID))
|
||||
{
|
||||
mio_seterrnum (pro->mio, MIO_EBADHND);
|
||||
return -1;
|
||||
}
|
||||
|
||||
x = read(pro->pfd, buf, *len);
|
||||
if (x <= -1)
|
||||
{
|
||||
@ -564,11 +570,22 @@ static int dev_pro_write_slave (mio_dev_t* dev, const void* data, mio_iolen_t* l
|
||||
mio_dev_pro_slave_t* pro = (mio_dev_pro_slave_t*)dev;
|
||||
ssize_t x;
|
||||
|
||||
if (MIO_UNLIKELY(pro->pfd == MIO_SYSHND_INVALID))
|
||||
{
|
||||
mio_seterrnum (pro->mio, MIO_EBADHND);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (MIO_UNLIKELY(*len <= 0))
|
||||
{
|
||||
/* this is an EOF indicator */
|
||||
mio_dev_halt (dev); /* halt this slave device */
|
||||
return 1;
|
||||
//mio_dev_halt (dev); /* halt this slave device to indicate EOF on the lower-level handle */*
|
||||
if (MIO_LIKELY(pro->pfd != MIO_SYSHND_INVALID)) /* halt() doesn't close the pipe immediately. so close the underlying pipe */
|
||||
{
|
||||
close (pro->pfd);
|
||||
pro->pfd = MIO_SYSHND_INVALID;
|
||||
}
|
||||
return 1; /* indicate that the operation got successful. the core will execute on_write() with 0. */
|
||||
}
|
||||
|
||||
x = write(pro->pfd, data, *len);
|
||||
@ -589,11 +606,22 @@ static int dev_pro_writev_slave (mio_dev_t* dev, const mio_iovec_t* iov, mio_iol
|
||||
mio_dev_pro_slave_t* pro = (mio_dev_pro_slave_t*)dev;
|
||||
ssize_t x;
|
||||
|
||||
if (MIO_UNLIKELY(pro->pfd == MIO_SYSHND_INVALID))
|
||||
{
|
||||
mio_seterrnum (pro->mio, MIO_EBADHND);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (MIO_UNLIKELY(*iovcnt <= 0))
|
||||
{
|
||||
/* this is an EOF indicator */
|
||||
mio_dev_halt (dev); /* halt this slave device */
|
||||
return 1;
|
||||
/*mio_dev_halt (dev);*/ /* halt this slave device to indicate EOF on the lower-level handle */
|
||||
if (MIO_LIKELY(pro->pfd != MIO_SYSHND_INVALID)) /* halt() doesn't close the pipe immediately. so close the underlying pipe */
|
||||
{
|
||||
close (pro->pfd);
|
||||
pro->pfd = MIO_SYSHND_INVALID;
|
||||
}
|
||||
return 1; /* indicate that the operation got successful. the core will execute on_write() with 0. */
|
||||
}
|
||||
|
||||
x = writev(pro->pfd, iov, *iovcnt);
|
||||
|
@ -1716,14 +1716,37 @@ int mio_dev_sck_getsockopt (mio_dev_sck_t* dev, int level, int optname, void* op
|
||||
return getsockopt(dev->hnd, level, optname, optval, optlen);
|
||||
}
|
||||
|
||||
int mio_dev_sck_shutdown (mio_dev_sck_t* dev, int how)
|
||||
{
|
||||
switch (how & (MIO_DEV_SCK_SHUTDOWN_READ | MIO_DEV_SCK_SHUTDOWN_WRITE))
|
||||
{
|
||||
case (MIO_DEV_SCK_SHUTDOWN_READ | MIO_DEV_SCK_SHUTDOWN_WRITE):
|
||||
how = SHUT_RDWR;
|
||||
break;
|
||||
|
||||
case MIO_DEV_SCK_SHUTDOWN_READ:
|
||||
how = SHUT_RD;
|
||||
break;
|
||||
|
||||
case MIO_DEV_SCK_SHUTDOWN_WRITE:
|
||||
how = SHUT_WR;
|
||||
break;
|
||||
|
||||
default:
|
||||
mio_seterrnum (dev->mio, MIO_EINVAL);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return shutdown(dev->hnd, how);
|
||||
}
|
||||
|
||||
/* ========================================================================= */
|
||||
|
||||
mio_uint16_t mio_checksumip (const void* hdr, mio_oow_t len)
|
||||
mio_uint16_t mio_checksum_ip (const void* hdr, mio_oow_t len)
|
||||
{
|
||||
mio_uint32_t sum = 0;
|
||||
mio_uint16_t *ptr = (mio_uint16_t*)hdr;
|
||||
|
||||
|
||||
while (len > 1)
|
||||
{
|
||||
sum += *ptr++;
|
||||
|
13
mio/t/t1.txt
Normal file
13
mio/t/t1.txt
Normal file
@ -0,0 +1,13 @@
|
||||
POST /home/hyung-hwan/projects/mio/t/b.sh HTTP/1.1
|
||||
Host: abc.txt
|
||||
Content-Type: text/plain
|
||||
Transfer-Encoding: chunked
|
||||
|
||||
7
|
||||
Mozilla
|
||||
9
|
||||
Developer
|
||||
7
|
||||
Network
|
||||
0
|
||||
|
15
mio/t/t2.txt
Normal file
15
mio/t/t2.txt
Normal file
@ -0,0 +1,15 @@
|
||||
GET /home/hyung-hwan/projects/mio/t/b.sh HTTP/1.1
|
||||
Host: abc.txt
|
||||
Transfer-Encoding: chunked
|
||||
Connection: close
|
||||
Trailer: Content-Type
|
||||
|
||||
7
|
||||
Mozilla
|
||||
9
|
||||
Developer
|
||||
7
|
||||
Network
|
||||
0
|
||||
Content-Type: text/plain
|
||||
|
13
mio/t/t3.txt
Normal file
13
mio/t/t3.txt
Normal file
@ -0,0 +1,13 @@
|
||||
POST /home/hyung-hwan/projects/mio/t/b.sh HTTP/1.0
|
||||
Host: abc.txt
|
||||
Content-Type: text/plain
|
||||
Transfer-Encoding: chunked
|
||||
|
||||
7
|
||||
Mozilla
|
||||
9
|
||||
Developer
|
||||
7
|
||||
Network
|
||||
0
|
||||
|
Loading…
x
Reference in New Issue
Block a user