implemented primitive idle client detector in htts
This commit is contained in:
parent
e77391da1d
commit
c5598970d7
@ -342,22 +342,6 @@ struct xx_mq_t
|
||||
|
||||
static xx_mq_t xx_mq;
|
||||
|
||||
#if 0
|
||||
static int schedule_timer_job_at (mio_dev_sck_t* dev, const mio_ntime_t* fire_at, mio_tmrjob_handler_t handler, mio_tmridx_t* tmridx)
|
||||
{
|
||||
mio_tmrjob_t tmrjob;
|
||||
|
||||
memset (&tmrjob, 0, MIO_SIZEOF(tmrjob));
|
||||
tmrjob.ctx = dev;
|
||||
if (fire_at) tmrjob.when = *fire_at;
|
||||
|
||||
tmrjob.handler = handler;
|
||||
tmrjob.idxptr = tmridx;
|
||||
|
||||
return mio_instmrjob(dev->mio, &tmrjob);
|
||||
}
|
||||
#endif
|
||||
|
||||
static void enable_accept (mio_t* mio, const mio_ntime_t* now, mio_tmrjob_t* job)
|
||||
{
|
||||
mio_dev_sck_t* rdev = (mio_dev_sck_t*)job->ctx;
|
||||
@ -452,7 +436,6 @@ static void tcp_sck_on_raw_accept (mio_dev_sck_t* sck, mio_syshnd_t syshnd, mio_
|
||||
qxmsg.syshnd = syshnd;
|
||||
qxmsg.remoteaddr = *remoteaddr;
|
||||
|
||||
//printf ("A %d\n", qxmsg.syshnd);
|
||||
try_to_accept (sck, &qxmsg, 0);
|
||||
}
|
||||
|
||||
|
@ -218,7 +218,6 @@ static void file_state_mark_over (file_state_t* file_state, int over_bits)
|
||||
/* how to arrange to delete this file_state object and put the socket back to the normal waiting state??? */
|
||||
MIO_ASSERT (file_state->htts->mio, file_state->client->rsrc == (mio_svc_htts_rsrc_t*)file_state);
|
||||
|
||||
|
||||
MIO_SVC_HTTS_RSRC_DETACH (file_state->client->rsrc);
|
||||
/* file_state must not be accessed from here down as it could have been destroyed */
|
||||
}
|
||||
@ -293,7 +292,6 @@ static void file_state_on_kill (file_state_t* file_state)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void file_client_on_disconnect (mio_dev_sck_t* sck)
|
||||
{
|
||||
mio_svc_htts_cli_t* cli = mio_dev_sck_getxtn(sck);
|
||||
@ -463,8 +461,6 @@ static int file_state_send_header_to_client (file_state_t* file_state, int statu
|
||||
cli->htts->server_name, dtbuf,
|
||||
(force_close? "close": "keep-alive"), mime_type) == (mio_oow_t)-1) return -1;
|
||||
|
||||
/* TODO: content_type */
|
||||
|
||||
if (file_state->req_method == MIO_HTTP_GET && mio_becs_fcat(cli->sbuf, "ETag: %hs\r\n", file_state->peer_etag) == (mio_oow_t)-1) return -1;
|
||||
if (status_code == 206 && mio_becs_fcat(cli->sbuf, "Content-Ranges: bytes %ju-%ju/%ju\r\n", (mio_uintmax_t)file_state->start_offset, (mio_uintmax_t)file_state->end_offset, (mio_uintmax_t)file_state->total_size) == (mio_oow_t)-1) return -1;
|
||||
if (mio_becs_fcat(cli->sbuf, "Content-Length: %ju\r\n\r\n", (mio_uintmax_t)content_length) == (mio_oow_t)-1) return -1;
|
||||
@ -552,6 +548,13 @@ static MIO_INLINE int process_range_header (file_state_t* file_state, mio_htre_t
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ((st.st_mode & S_IFMT) == S_IFREG)
|
||||
{
|
||||
/* TODO: support directory listing if S_IFDIR? still disallow special files. */
|
||||
file_state_send_final_status_to_client (file_state, 403, 1); /* forbidden */
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (file_state->req_method == MIO_HTTP_GET)
|
||||
{
|
||||
etag_len = mio_fmt_uintmax_to_bcstr(&file_state->peer_etag[0], MIO_COUNTOF(file_state->peer_etag), st.st_mtim.tv_sec, 16, -1, '\0', MIO_NULL);
|
||||
@ -631,13 +634,24 @@ static int open_peer (file_state_t* file_state, const mio_bch_t* actual_file)
|
||||
{
|
||||
case MIO_HTTP_GET:
|
||||
case MIO_HTTP_HEAD:
|
||||
{
|
||||
int flags;
|
||||
|
||||
if (access(actual_file, R_OK) == -1)
|
||||
{
|
||||
file_state_send_final_status_to_client (file_state, ERRNO_TO_STATUS_CODE(errno), 1); /* 404 not found 403 Forbidden */
|
||||
return -1;
|
||||
}
|
||||
|
||||
file_state->peer = open(actual_file, O_RDONLY | O_NONBLOCK | O_CLOEXEC);
|
||||
flags = O_RDONLY | O_NONBLOCK;
|
||||
#if defined(O_CLOEXEC)
|
||||
flags |= O_CLOEXEC;
|
||||
#endif
|
||||
#if defined(O_LARGEFILE)
|
||||
flags |= O_LARGEFILE;
|
||||
#endif
|
||||
file_state->peer = open(actual_file, flags);
|
||||
|
||||
if (MIO_UNLIKELY(file_state->peer <= -1))
|
||||
{
|
||||
file_state_send_final_status_to_client (file_state, ERRNO_TO_STATUS_CODE(errno), 1);
|
||||
@ -645,6 +659,7 @@ static int open_peer (file_state_t* file_state, const mio_bch_t* actual_file)
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if 0
|
||||
case MIO_HTTP_PUT:
|
||||
@ -720,7 +735,7 @@ int mio_svc_htts_dofile (mio_svc_htts_t* htts, mio_dev_sck_t* csck, mio_htre_t*
|
||||
csck->on_write = file_client_on_write;
|
||||
csck->on_disconnect = file_client_on_disconnect;
|
||||
|
||||
MIO_ASSERT (mio, cli->rsrc == MIO_NULL);
|
||||
MIO_ASSERT (mio, cli->rsrc == MIO_NULL); /* you must not call this function while cli->rsrc is not MIO_NULL */
|
||||
MIO_SVC_HTTS_RSRC_ATTACH (file_state, cli->rsrc);
|
||||
|
||||
file_state->peer_tmridx = MIO_TMRIDX_INVALID;
|
||||
|
@ -47,6 +47,7 @@ struct mio_svc_htts_cli_t
|
||||
mio_becs_t* sbuf; /* temporary buffer for status line formatting */
|
||||
|
||||
mio_svc_htts_rsrc_t* rsrc;
|
||||
mio_ntime_t last_active;
|
||||
};
|
||||
|
||||
struct mio_svc_htts_cli_htrd_xtn_t
|
||||
@ -63,6 +64,7 @@ struct mio_svc_htts_t
|
||||
|
||||
mio_dev_sck_t* lsck;
|
||||
mio_svc_htts_cli_t cli; /* list head for client list */
|
||||
mio_tmridx_t idle_tmridx;
|
||||
|
||||
mio_bch_t* server_name;
|
||||
mio_bch_t server_name_buf[64];
|
||||
|
@ -74,7 +74,8 @@ static int init_client (mio_svc_htts_cli_t* cli, mio_dev_sck_t* sck)
|
||||
|
||||
mio_htrd_setrecbs (cli->htrd, &client_htrd_recbs);
|
||||
|
||||
MIO_DEBUG3 (sck->mio, "HTTS(%p) - initialized client %p socket %p\n", cli->htts, cli, sck);
|
||||
mio_gettime (sck->mio, &cli->last_active);
|
||||
MIO_DEBUG3 (sck->mio, "HTTS(%p) - initialized client %p socket %p\n", cli->htts, cli, sck);
|
||||
return 0;
|
||||
|
||||
oops:
|
||||
@ -152,6 +153,7 @@ static int listener_on_read (mio_dev_sck_t* sck, const void* buf, mio_iolen_t le
|
||||
goto oops;
|
||||
}
|
||||
|
||||
mio_gettime (mio, &cli->last_active);
|
||||
if ((x = mio_htrd_feed(cli->htrd, buf, len, &rem)) <= -1)
|
||||
{
|
||||
MIO_DEBUG3 (mio, "HTTS(%p) - feed error onto client htrd %p(%d)\n", cli->htts, sck, (int)sck->hnd);
|
||||
@ -275,6 +277,42 @@ printf ("listener socket disconnect..................sck %p %d\n", sck, sck->hnd
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------ */
|
||||
#define MAX_CLIENT_IDLE 10
|
||||
|
||||
|
||||
static void halt_idle_clients (mio_t* mio, const mio_ntime_t* now, mio_tmrjob_t* job)
|
||||
{
|
||||
/* TODO: this idle client detector is far away from being accurate.
|
||||
* enhance htrd to specify timeout on feed() and utilize it...
|
||||
* and remove this timer job */
|
||||
mio_svc_htts_t* htts = (mio_svc_htts_t*)job->ctx;
|
||||
mio_svc_htts_cli_t* cli;
|
||||
mio_ntime_t t;
|
||||
|
||||
static mio_ntime_t max_client_idle = { MAX_CLIENT_IDLE, 0 };
|
||||
|
||||
for (cli = MIO_SVC_HTTS_CLIL_FIRST_CLI(&htts->cli); !MIO_SVC_HTTS_CLIL_IS_NIL_CLI(&htts->cli, cli); cli = cli->cli_next)
|
||||
{
|
||||
if (!cli->rsrc)
|
||||
{
|
||||
mio_ntime_t t;
|
||||
MIO_SUB_NTIME(&t, now, &cli->last_active);
|
||||
|
||||
if (MIO_CMP_NTIME(&t, &max_client_idle) >= 0)
|
||||
{
|
||||
MIO_DEBUG3 (mio, "HTTS(%p) - Halting idle client socket %p(client=%p)\n", htts, cli->sck, cli);
|
||||
mio_dev_sck_halt (cli->sck);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
MIO_INIT_NTIME (&t, MAX_CLIENT_IDLE, 0);
|
||||
MIO_ADD_NTIME (&t, &t, now);
|
||||
if (mio_schedtmrjobat(mio, &t, halt_idle_clients, &htts->idle_tmridx, htts) <= -1)
|
||||
{
|
||||
MIO_INFO1 (mio, "HTTS(%p) - unable to reschedule idle client detector. continuting\n", htts);
|
||||
}
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------ */
|
||||
|
||||
@ -294,6 +332,7 @@ mio_svc_htts_t* mio_svc_htts_start (mio_t* mio, mio_dev_sck_bind_t* sck_bind, mi
|
||||
htts->mio = mio;
|
||||
htts->svc_stop = mio_svc_htts_stop;
|
||||
htts->proc_req = proc_req;
|
||||
htts->idle_tmridx = MIO_TMRIDX_INVALID;
|
||||
|
||||
MIO_MEMSET (&info, 0, MIO_SIZEOF(info));
|
||||
switch (mio_skad_family(&sck_bind->localaddr))
|
||||
@ -343,10 +382,23 @@ mio_svc_htts_t* mio_svc_htts_start (mio_t* mio, mio_dev_sck_bind_t* sck_bind, mi
|
||||
MIO_PACKAGE_NAME, (int)MIO_PACKAGE_VERSION_MAJOR, (int)MIO_PACKAGE_VERSION_MINOR, (int)MIO_PACKAGE_VERSION_PATCH);
|
||||
htts->server_name = htts->server_name_buf;
|
||||
|
||||
|
||||
MIO_SVCL_APPEND_SVC (&mio->actsvc, (mio_svc_t*)htts);
|
||||
MIO_SVC_HTTS_CLIL_INIT (&htts->cli);
|
||||
|
||||
MIO_DEBUG3 (mio, "HTTS - STARTED SERVICE %p - LISTENER SOCKET %p(%d)\n", htts, htts->lsck, (int)htts->lsck->hnd);
|
||||
|
||||
{
|
||||
mio_ntime_t t;
|
||||
|
||||
MIO_INIT_NTIME (&t, MAX_CLIENT_IDLE, 0);
|
||||
if (mio_schedtmrjobafter(mio, &t, halt_idle_clients, &htts->idle_tmridx, htts) <= -1)
|
||||
{
|
||||
MIO_INFO1 (mio, "HTTS(%p) - unable to schedule idle client detector. continuting\n", htts);
|
||||
/* don't care about failure */
|
||||
}
|
||||
}
|
||||
|
||||
return htts;
|
||||
|
||||
oops:
|
||||
@ -376,6 +428,9 @@ void mio_svc_htts_stop (mio_svc_htts_t* htts)
|
||||
|
||||
MIO_SVCL_UNLINK_SVC (htts);
|
||||
if (htts->server_name && htts->server_name != htts->server_name_buf) mio_freemem (mio, htts->server_name);
|
||||
|
||||
if (htts->idle_tmridx != MIO_TMRIDX_INVALID) mio_deltmrjob (mio, htts->idle_tmridx);
|
||||
|
||||
mio_freemem (mio, htts);
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user