added QSE_HTTPD_MUTECLIENT
This commit is contained in:
parent
05e0476f97
commit
8ccc2698d6
@ -58,9 +58,10 @@ typedef enum qse_httpd_errnum_t qse_httpd_errnum_t;
|
|||||||
|
|
||||||
enum qse_httpd_option_t
|
enum qse_httpd_option_t
|
||||||
{
|
{
|
||||||
QSE_HTTPD_CGIERRTONUL = (1 << 0),
|
QSE_HTTPD_MUTECLIENT = (1 << 0),
|
||||||
QSE_HTTPD_CGINOCLOEXEC = (1 << 1),
|
QSE_HTTPD_CGIERRTONUL = (1 << 1),
|
||||||
QSE_HTTPD_CGINOCHUNKED = (1 << 2)
|
QSE_HTTPD_CGINOCLOEXEC = (1 << 2),
|
||||||
|
QSE_HTTPD_CGINOCHUNKED = (1 << 3)
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef struct qse_httpd_stat_t qse_httpd_stat_t;
|
typedef struct qse_httpd_stat_t qse_httpd_stat_t;
|
||||||
@ -240,12 +241,9 @@ typedef int (*qse_httpd_task_main_t) (
|
|||||||
enum qse_httpd_task_trigger_mask_t
|
enum qse_httpd_task_trigger_mask_t
|
||||||
{
|
{
|
||||||
QSE_HTTPD_TASK_TRIGGER_READ = (1 << 0),
|
QSE_HTTPD_TASK_TRIGGER_READ = (1 << 0),
|
||||||
QSE_HTTPD_TASK_TRIGGER_RELAY = (1 << 1),
|
QSE_HTTPD_TASK_TRIGGER_WRITE = (1 << 1),
|
||||||
QSE_HTTPD_TASK_TRIGGER_WRITE = (1 << 2),
|
QSE_HTTPD_TASK_TRIGGER_READABLE = (1 << 2),
|
||||||
QSE_HTTPD_TASK_TRIGGER_READABLE = (1 << 3),
|
QSE_HTTPD_TASK_TRIGGER_WRITABLE = (1 << 3)
|
||||||
QSE_HTTPD_TASK_TRIGGER_RELAYABLE = (1 << 4),
|
|
||||||
QSE_HTTPD_TASK_TRIGGER_WRITABLE = (1 << 5)
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef struct qse_httpd_task_trigger_t qse_httpd_task_trigger_t;
|
typedef struct qse_httpd_task_trigger_t qse_httpd_task_trigger_t;
|
||||||
|
@ -1419,7 +1419,7 @@ feedme_more:
|
|||||||
|
|
||||||
int qse_htrd_halt (qse_htrd_t* htrd)
|
int qse_htrd_halt (qse_htrd_t* htrd)
|
||||||
{
|
{
|
||||||
if (htrd->fed.s.flags & CONSUME_UNTIL_CLOSE)
|
if (htrd->fed.s.flags & CONSUME_UNTIL_CLOSE || !htrd->clean)
|
||||||
{
|
{
|
||||||
qse_htre_completecontent (&htrd->re);
|
qse_htre_completecontent (&htrd->re);
|
||||||
|
|
||||||
|
@ -2701,6 +2701,7 @@ struct task_proxy_t
|
|||||||
#define PROXY_RES_PEER_LENGTH (1 << 5) /* peer's output is set with
|
#define PROXY_RES_PEER_LENGTH (1 << 5) /* peer's output is set with
|
||||||
* the content-length */
|
* the content-length */
|
||||||
#define PROXY_RES_PEER_LENGTH_FAKE (1 << 6) /* peer_output_length is fake */
|
#define PROXY_RES_PEER_LENGTH_FAKE (1 << 6) /* peer_output_length is fake */
|
||||||
|
#define PROXY_RES_EVER_SENTBACK (1 << 7) /* any single byte sent back to a client */
|
||||||
#define PROXY_RES_AWAIT_100 (1 << 10) /* waiting for 100 continue */
|
#define PROXY_RES_AWAIT_100 (1 << 10) /* waiting for 100 continue */
|
||||||
#define PROXY_RES_AWAIT_RESHDR (1 << 11) /* waiting for response header */
|
#define PROXY_RES_AWAIT_RESHDR (1 << 11) /* waiting for response header */
|
||||||
#define PROXY_RES_AWAIT_RESCON (1 << 12) /* waiting for response content.
|
#define PROXY_RES_AWAIT_RESCON (1 << 12) /* waiting for response content.
|
||||||
@ -3652,11 +3653,16 @@ qse_printf (QSE_T("task_main_proxy_4 read from PEER...%d\n"), (int)n);
|
|||||||
static int task_main_proxy_3 (
|
static int task_main_proxy_3 (
|
||||||
qse_httpd_t* httpd, qse_httpd_client_t* client, qse_httpd_task_t* task)
|
qse_httpd_t* httpd, qse_httpd_client_t* client, qse_httpd_task_t* task)
|
||||||
{
|
{
|
||||||
/* send the http initial line and headers built using the headers
|
/* let's send up the http initial line and headers before
|
||||||
* returned by peer. it may include some contents as well */
|
* attempting to read the reset of content. it may already
|
||||||
|
* include some contents as well received together with
|
||||||
|
* the header. */
|
||||||
|
|
||||||
task_proxy_t* proxy = (task_proxy_t*)task->ctx;
|
task_proxy_t* proxy = (task_proxy_t*)task->ctx;
|
||||||
|
|
||||||
|
qse_printf (QSE_T("task_main_proxy_3 trigger[0].mask=%d trigger[1].mask=%d trigger[2].mask=%d\n"),
|
||||||
|
task->trigger[0].mask, task->trigger[1].mask, task->trigger[2].mask);
|
||||||
|
|
||||||
if (task->trigger[2].mask & QSE_HTTPD_TASK_TRIGGER_READABLE)
|
if (task->trigger[2].mask & QSE_HTTPD_TASK_TRIGGER_READABLE)
|
||||||
{
|
{
|
||||||
proxy_forward_client_input_to_peer (httpd, task, 0);
|
proxy_forward_client_input_to_peer (httpd, task, 0);
|
||||||
@ -3666,7 +3672,6 @@ static int task_main_proxy_3 (
|
|||||||
proxy_forward_client_input_to_peer (httpd, task, 1);
|
proxy_forward_client_input_to_peer (httpd, task, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
qse_printf (QSE_T("[PROXY-----3]\n"));
|
|
||||||
if (!(task->trigger[2].mask & QSE_HTTPD_TASK_TRIGGER_WRITE) ||
|
if (!(task->trigger[2].mask & QSE_HTTPD_TASK_TRIGGER_WRITE) ||
|
||||||
(task->trigger[2].mask & QSE_HTTPD_TASK_TRIGGER_WRITABLE))
|
(task->trigger[2].mask & QSE_HTTPD_TASK_TRIGGER_WRITABLE))
|
||||||
{
|
{
|
||||||
@ -3693,6 +3698,7 @@ qse_printf (QSE_T("[proxy-3 send failure....\n"));
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
proxy->resflags |= PROXY_RES_EVER_SENTBACK;
|
||||||
proxy->res_consumed += n;
|
proxy->res_consumed += n;
|
||||||
proxy->res_pending -= n;
|
proxy->res_pending -= n;
|
||||||
}
|
}
|
||||||
@ -3713,7 +3719,7 @@ qse_printf (QSE_T("SWITINCG TO 55555555555555555555555555 %d %d %d %d\n"),
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
qse_printf (QSE_T("SWITINCG TO 4444444444444444444444444444\n"));
|
qse_printf (QSE_T("SWITICHING TO 4444444444444444444444444444\n"));
|
||||||
task->main = task_main_proxy_4;
|
task->main = task_main_proxy_4;
|
||||||
task->trigger[2].mask &= ~QSE_HTTPD_TASK_TRIGGER_WRITE;
|
task->trigger[2].mask &= ~QSE_HTTPD_TASK_TRIGGER_WRITE;
|
||||||
}
|
}
|
||||||
@ -3729,7 +3735,7 @@ static int task_main_proxy_2 (
|
|||||||
qse_httpd_t* httpd, qse_httpd_client_t* client, qse_httpd_task_t* task)
|
qse_httpd_t* httpd, qse_httpd_client_t* client, qse_httpd_task_t* task)
|
||||||
{
|
{
|
||||||
task_proxy_t* proxy = (task_proxy_t*)task->ctx;
|
task_proxy_t* proxy = (task_proxy_t*)task->ctx;
|
||||||
int http_errnum = 0;
|
int http_errnum = 500;
|
||||||
|
|
||||||
qse_printf (QSE_T("task_main_proxy_2 trigger[0].mask=%d trigger[1].mask=%d trigger[2].mask=%d\n"),
|
qse_printf (QSE_T("task_main_proxy_2 trigger[0].mask=%d trigger[1].mask=%d trigger[2].mask=%d\n"),
|
||||||
task->trigger[0].mask, task->trigger[1].mask, task->trigger[2].mask);
|
task->trigger[0].mask, task->trigger[1].mask, task->trigger[2].mask);
|
||||||
@ -3782,9 +3788,10 @@ qse_printf (QSE_T("]\n"));
|
|||||||
if (n <= -1)
|
if (n <= -1)
|
||||||
{
|
{
|
||||||
qse_printf (QSE_T("[proxy-2 send failure....\n"));
|
qse_printf (QSE_T("[proxy-2 send failure....\n"));
|
||||||
return -1;
|
goto oops;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
proxy->resflags |= PROXY_RES_EVER_SENTBACK;
|
||||||
proxy->res_consumed += n;
|
proxy->res_consumed += n;
|
||||||
proxy->res_pending -= n;
|
proxy->res_pending -= n;
|
||||||
|
|
||||||
@ -3822,14 +3829,9 @@ qse_printf (QSE_T("[proxy-2 send failure....\n"));
|
|||||||
* the proxy script must be crooked. */
|
* the proxy script must be crooked. */
|
||||||
/* TODO: logging */
|
/* TODO: logging */
|
||||||
qse_printf (QSE_T("#####PREMATURE EOF FROM PEER\n"));
|
qse_printf (QSE_T("#####PREMATURE EOF FROM PEER\n"));
|
||||||
if (!(proxy->resflags & PROXY_RES_RECEIVED_100))
|
if (!(proxy->resflags & PROXY_RES_RECEIVED_100)) http_errnum = 502;
|
||||||
{
|
|
||||||
http_errnum = 502;
|
|
||||||
goto oops;
|
goto oops;
|
||||||
}
|
}
|
||||||
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
QSE_ASSERT (proxy->resflags & PROXY_RES_CLIENT_CHUNK);
|
QSE_ASSERT (proxy->resflags & PROXY_RES_CLIENT_CHUNK);
|
||||||
@ -3846,7 +3848,7 @@ qse_printf (QSE_T("#####PREMATURE EOF FROM PEER\n"));
|
|||||||
}
|
}
|
||||||
|
|
||||||
qse_printf (QSE_T("#####PREMATURE EOF FROM PEER CLIENT CHUNK\n"));
|
qse_printf (QSE_T("#####PREMATURE EOF FROM PEER CLIENT CHUNK\n"));
|
||||||
return -1;
|
goto oops;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3893,7 +3895,7 @@ qse_printf (QSE_T("#####INVALID HEADER FROM PEER [%.*hs]\n"), (int)proxy->buflen
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
qse_printf (QSE_T("TRAILING DATA=[%hs]\n"), QSE_MBS_CPTR(proxy->res,proxy->res_consumed));
|
qse_printf (QSE_T("TRAILING DATA=%d, [%hs]\n"), (int)QSE_MBS_LEN(proxy->res), QSE_MBS_CPTR(proxy->res,proxy->res_consumed));
|
||||||
/* switch to the next phase */
|
/* switch to the next phase */
|
||||||
task->main = task_main_proxy_3;
|
task->main = task_main_proxy_3;
|
||||||
task->trigger[2].mask |= QSE_HTTPD_TASK_TRIGGER_WRITE;
|
task->trigger[2].mask |= QSE_HTTPD_TASK_TRIGGER_WRITE;
|
||||||
@ -3916,6 +3918,7 @@ qse_printf (QSE_T("TRAILING DATA=[%hs]\n"), QSE_MBS_CPTR(proxy->res,proxy->res_c
|
|||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
oops:
|
oops:
|
||||||
|
if (proxy->resflags & PROXY_RES_EVER_SENTBACK) return -1;
|
||||||
return (entask_error (httpd, client, task, http_errnum, &proxy->version, proxy->keepalive) == QSE_NULL)? -1: 0;
|
return (entask_error (httpd, client, task, http_errnum, &proxy->version, proxy->keepalive) == QSE_NULL)? -1: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -693,15 +693,25 @@ qse_printf (QSE_T("Error: failed to read from a client %d\n"), client->handle.i)
|
|||||||
else if (m == 0)
|
else if (m == 0)
|
||||||
{
|
{
|
||||||
qse_printf (QSE_T("Debug: connection closed %d - errno %d\n"), client->handle.i, errno);
|
qse_printf (QSE_T("Debug: connection closed %d - errno %d\n"), client->handle.i, errno);
|
||||||
if (client->task.head && client->htrd->clean)
|
/* reading from the client returned 0. this typically
|
||||||
|
* happens when the client closes the connection or
|
||||||
|
* shutdown the writing half of the socket. it's
|
||||||
|
* not really easy to determine one from the other.
|
||||||
|
* if QSE_HTTPD_MUTECLIENT is on, attempt to handle
|
||||||
|
* it as a half-close under a certain condition. */
|
||||||
|
|
||||||
|
if (httpd->option & QSE_HTTPD_MUTECLIENT &&
|
||||||
|
client->task.head && client->htrd->clean)
|
||||||
{
|
{
|
||||||
/* there is still more tasks to finish and
|
/* there is still more tasks to finish and
|
||||||
* http reader is not waiting for any more feeds. */
|
* http reader is not waiting for any more feeds. */
|
||||||
client->status |= CLIENT_MUTE;
|
client->status |= CLIENT_MUTE;
|
||||||
|
qse_printf (QSE_T(">>>>> Marking client %d as MUTE\n"), client->handle.i);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
qse_printf (QSE_T(">>>>> Returning failure for client %d\n"), client->handle.i);
|
||||||
httpd->errnum = QSE_HTTPD_EDISCON;
|
httpd->errnum = QSE_HTTPD_EDISCON;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@ -820,7 +830,7 @@ qse_printf (QSE_T("task returend %d\n"), n);
|
|||||||
int mux_mask;
|
int mux_mask;
|
||||||
int mux_status;
|
int mux_status;
|
||||||
|
|
||||||
/* the current task is over. remove remove the task
|
/* the current task is over. remove the task
|
||||||
* from the queue. dequeue_task() clears task triggers
|
* from the queue. dequeue_task() clears task triggers
|
||||||
* from the mux. so i don't clear them explicitly here */
|
* from the mux. so i don't clear them explicitly here */
|
||||||
|
|
||||||
|
@ -699,13 +699,17 @@ static int mux_poll (qse_httpd_t* httpd, void* vmux, qse_ntime_t timeout)
|
|||||||
|
|
||||||
mask = 0;
|
mask = 0;
|
||||||
|
|
||||||
if (mux->ee.ptr[i].events & EPOLLIN) mask |= QSE_HTTPD_MUX_READ;
|
if (mux->ee.ptr[i].events & EPOLLIN)
|
||||||
if (mux->ee.ptr[i].events & EPOLLOUT) mask |= QSE_HTTPD_MUX_WRITE;
|
mask |= QSE_HTTPD_MUX_READ;
|
||||||
|
if (mux->ee.ptr[i].events & EPOLLOUT)
|
||||||
|
mask |= QSE_HTTPD_MUX_WRITE;
|
||||||
|
|
||||||
if (mux->ee.ptr[i].events & EPOLLHUP)
|
if (mux->ee.ptr[i].events & EPOLLHUP)
|
||||||
{
|
{
|
||||||
if (mev->reqmask & QSE_HTTPD_MUX_READ) mask |= QSE_HTTPD_MUX_READ;
|
if (mev->reqmask & QSE_HTTPD_MUX_READ)
|
||||||
if (mev->reqmask & QSE_HTTPD_MUX_WRITE) mask |= QSE_HTTPD_MUX_WRITE;
|
mask |= QSE_HTTPD_MUX_READ;
|
||||||
|
if (mev->reqmask & QSE_HTTPD_MUX_WRITE)
|
||||||
|
mask |= QSE_HTTPD_MUX_WRITE;
|
||||||
}
|
}
|
||||||
|
|
||||||
mev->cbfun (httpd, mux, mev->handle, mask, mev->cbarg);
|
mev->cbfun (httpd, mux, mev->handle, mask, mev->cbarg);
|
||||||
|
Loading…
Reference in New Issue
Block a user