touched up httpd

This commit is contained in:
hyung-hwan 2014-07-22 17:58:11 +00:00
parent ad0d80fff5
commit 5703aaa8a5
9 changed files with 391 additions and 308 deletions

View File

@ -105,6 +105,12 @@ QSE_EXPORT void qse_clearnwad (
qse_nwad_type_t type
);
QSE_EXPORT void qse_setnwadport (
qse_nwad_t* nwad,
qse_uint16_t port
);
QSE_EXPORT int qse_mbstonwad (
const qse_mchar_t* mbs,
qse_nwad_t* nwad

View File

@ -360,6 +360,8 @@ struct qse_httpd_task_trigger_t
{
int flags; /**< [IN] bitwise-ORed of #qse_httpd_task_trigger_flag_t enumerators*/
int cmask; /* client mask - QSE_HTTPD_TASK_TRIGGER_READ | QSE_HTTPD_TASK_TRIGGER_WRITE */
struct
{
int mask; /* QSE_HTTPD_TASK_TRIGGER_READ | QSE_HTTPD_TASK_TRIGGER_WRITE */

View File

@ -52,6 +52,20 @@ void qse_clearnwad (qse_nwad_t* nwad, qse_nwad_type_t type)
nwad->type = type;
}
void qse_setnwadport (qse_nwad_t* nwad, qse_uint16_t port)
{
switch (nwad->type)
{
case QSE_NWAD_IN4:
nwad->u.in4.port = port;
break;
case QSE_NWAD_IN6:
nwad->u.in4.port = port;
break;
}
}
int qse_mbstonwad (const qse_mchar_t* str, qse_nwad_t* nwad)
{
return qse_mbsntonwad (str, qse_mbslen(str), nwad);

View File

@ -233,7 +233,7 @@ static int cgi_htrd_peek_script_output (qse_htrd_t* htrd, qse_htre_t* req)
/* TODO: check the syntax of status value??? if not numeric??? */
QSE_MBSTONUM (nstatus, req->attr.status, &endptr, 10);
snprintf (buf, QSE_COUNTOF(buf),
snprintf (buf, QSE_COUNTOF(buf),
QSE_MT("HTTP/%d.%d %d "),
cgi->version.major,
cgi->version.minor,
@ -561,7 +561,7 @@ else qse_printf (QSE_T("!!!CGI SNATCHING DONE\n"));
/* since there is no more to read from the client side.
* the relay trigger is not needed any more. */
task->trigger.v[2].mask = 0;
task->trigger.cmask &= ~QSE_HTTPD_TASK_TRIGGER_READ;
if (QSE_MBS_LEN(cgi->reqfwdbuf) > 0 && cgi->pio_inited &&
!(task->trigger.v[1].mask & QSE_HTTPD_TASK_TRIGGER_WRITE))
@ -630,9 +630,6 @@ static void cgi_forward_client_input_to_script (
{
/* a forwarding error has occurred previously.
* clear the forwarding buffer */
#if 0
qse_printf (QSE_T("FORWARD: CLEARING REQCON FOR ERROR\n"));
#endif
qse_mbs_clear (cgi->reqfwdbuf);
}
else
@ -648,11 +645,6 @@ qse_printf (QSE_T("FORWARD: CLEARING REQCON FOR ERROR\n"));
{
forward:
/* writable */
#if 0
qse_printf (QSE_T("FORWARD: @@@@@@@@@@WRITING[%.*hs]\n"),
(int)QSE_MBS_LEN(cgi->reqfwdbuf),
QSE_MBS_PTR(cgi->reqfwdbuf));
#endif
n = qse_pio_write (
&cgi->pio, QSE_PIO_IN,
QSE_MBS_PTR(cgi->reqfwdbuf),
@ -703,19 +695,19 @@ to the head all the time.. grow the buffer to a certain limit. */
{
done:
/* there is nothing to read from the client side and
* there is nothing more to forward in the forwarding buffer.
* clear the relay and write triggers for the time being.
*/
#if 0
qse_printf (QSE_T("FORWARD: @@@@@@@@NOTHING MORE TO WRITE TO CGI\n"));
#endif
* there is nothing more to forward from the client-side to the peer
* in the forwarding buffer. */
QSE_ASSERT (cgi->req == QSE_NULL);
/* mark the end of input to the child explicitly. */
qse_pio_end (&cgi->pio, QSE_PIO_IN);
task->trigger.v[1].mask = 0; /* pipe output to child */
task->trigger.v[2].mask = 0; /* client-side */
/* nothing more to write to the cgi script. so exclude
* the input pipe to the script from the mux */
task->trigger.v[1].mask &= ~QSE_HTTPD_TASK_TRIGGER_WRITE;
/* nothing to read from the client side. */
task->trigger.cmask &= ~QSE_HTTPD_TASK_TRIGGER_READ;
}
}
@ -994,17 +986,20 @@ static int task_main_cgi_5 (
QSE_ASSERT (cgi->pio_inited);
if (task->trigger.v[2].mask & QSE_HTTPD_TASK_TRIGGER_READABLE)
if (cgi->reqfwdbuf)
{
cgi_forward_client_input_to_script (httpd, task, 0);
}
else if (task->trigger.v[1].mask & QSE_HTTPD_TASK_TRIGGER_WRITABLE)
{
cgi_forward_client_input_to_script (httpd, task, 1);
if (task->trigger.cmask & QSE_HTTPD_TASK_TRIGGER_READABLE)
{
cgi_forward_client_input_to_script (httpd, task, 0);
}
else if (task->trigger.v[1].mask & QSE_HTTPD_TASK_TRIGGER_WRITABLE)
{
cgi_forward_client_input_to_script (httpd, task, 1);
}
}
if (!(task->trigger.v[2].mask & QSE_HTTPD_TASK_TRIGGER_WRITE) ||
(task->trigger.v[2].mask & QSE_HTTPD_TASK_TRIGGER_WRITABLE))
if (/*!(task->trigger.cmask & QSE_HTTPD_TASK_TRIGGER_WRITE) ||*/
(task->trigger.cmask & QSE_HTTPD_TASK_TRIGGER_WRITABLE))
{
if (cgi->buflen > 0)
{
@ -1031,13 +1026,16 @@ static int task_main_cgi_4_nph (
QSE_ASSERT (cgi->nph);
if (task->trigger.v[2].mask & QSE_HTTPD_TASK_TRIGGER_READABLE)
if (cgi->reqfwdbuf)
{
cgi_forward_client_input_to_script (httpd, task, 0);
}
else if (task->trigger.v[1].mask & QSE_HTTPD_TASK_TRIGGER_WRITABLE)
{
cgi_forward_client_input_to_script (httpd, task, 1);
if (task->trigger.cmask & QSE_HTTPD_TASK_TRIGGER_READABLE)
{
cgi_forward_client_input_to_script (httpd, task, 0);
}
else if (task->trigger.v[1].mask & QSE_HTTPD_TASK_TRIGGER_WRITABLE)
{
cgi_forward_client_input_to_script (httpd, task, 1);
}
}
if (task->trigger.v[0].mask & QSE_HTTPD_TASK_TRIGGER_READABLE)
@ -1051,7 +1049,7 @@ static int task_main_cgi_4_nph (
/* switch to the next phase */
task->main = task_main_cgi_5;
task->trigger.v[0].mask = 0;
task->trigger.v[2].mask |= QSE_HTTPD_TASK_TRIGGER_WRITE;
task->trigger.cmask |= QSE_HTTPD_TASK_TRIGGER_WRITE;
return 1;
}
}
@ -1073,17 +1071,20 @@ static int task_main_cgi_4 (
QSE_ASSERT (cgi->pio_inited);
#if 0
qse_printf (QSE_T("task_main_cgi_4 trigger[0].mask=%d trigger[1].mask=%d trigger[2].mask=%d\n"),
task->trigger.v[0].mask, task->trigger.v[1].mask, task->trigger.v[2].mask);
printf ("task_main_cgi_4 trigger[0].mask=%d trigger[1].mask=%d cmask=%d\n",
task->trigger.v[0].mask, task->trigger.v[1].mask, task->trigger.cmask);
#endif
if (task->trigger.v[2].mask & QSE_HTTPD_TASK_TRIGGER_READABLE)
if (cgi->reqfwdbuf)
{
cgi_forward_client_input_to_script (httpd, task, 0);
}
else if (task->trigger.v[1].mask & QSE_HTTPD_TASK_TRIGGER_WRITABLE)
{
cgi_forward_client_input_to_script (httpd, task, 1);
if (task->trigger.cmask & QSE_HTTPD_TASK_TRIGGER_READABLE)
{
cgi_forward_client_input_to_script (httpd, task, 0);
}
else if (task->trigger.v[1].mask & QSE_HTTPD_TASK_TRIGGER_WRITABLE)
{
cgi_forward_client_input_to_script (httpd, task, 1);
}
}
if (task->trigger.v[0].mask & QSE_HTTPD_TASK_TRIGGER_READABLE)
@ -1121,10 +1122,10 @@ qse_printf (QSE_T("task_main_cgi_4 trigger[0].mask=%d trigger[1].mask=%d trigger
cgi->buf[cgi->buflen++] = QSE_MT('\n');
cgi->buf[cgi->buflen++] = QSE_MT('\r');
cgi->buf[cgi->buflen++] = QSE_MT('\n');
task->main = task_main_cgi_5;
task->trigger.v[0].mask = 0;
task->trigger.v[2].mask |= QSE_HTTPD_TASK_TRIGGER_WRITE;
task->trigger.cmask |= QSE_HTTPD_TASK_TRIGGER_WRITE;
return 1;
}
@ -1169,7 +1170,7 @@ qse_printf (QSE_T("task_main_cgi_4 trigger[0].mask=%d trigger[1].mask=%d trigger
/* switch to the next phase */
task->main = task_main_cgi_5;
task->trigger.v[0].mask = 0;
task->trigger.v[2].mask |= QSE_HTTPD_TASK_TRIGGER_WRITE;
task->trigger.cmask |= QSE_HTTPD_TASK_TRIGGER_WRITE;
return 1;
}
@ -1207,23 +1208,26 @@ static int task_main_cgi_3 (
QSE_ASSERT (!cgi->nph);
#if 0
qse_printf (QSE_T("task_main_cgi_3 trigger[0].mask=%d trigger[1].mask=%d trigger[2].mask=%d\n"),
task->trigger.v[0].mask, task->trigger.v[1].mask, task->trigger.v[2].mask);
#if 0
printf ("task_main_cgi_3 trigger[0].mask=%d trigger[1].mask=%d cmask=%d\n",
task->trigger.v[0].mask, task->trigger.v[1].mask, task->trigger.cmask);
#endif
if (task->trigger.v[2].mask & QSE_HTTPD_TASK_TRIGGER_READABLE)
if (cgi->reqfwdbuf)
{
cgi_forward_client_input_to_script (httpd, task, 0);
}
else if (task->trigger.v[1].mask & QSE_HTTPD_TASK_TRIGGER_WRITABLE)
{
cgi_forward_client_input_to_script (httpd, task, 1);
if (task->trigger.cmask & QSE_HTTPD_TASK_TRIGGER_READABLE)
{
cgi_forward_client_input_to_script (httpd, task, 0);
}
else if (task->trigger.v[1].mask & QSE_HTTPD_TASK_TRIGGER_WRITABLE)
{
cgi_forward_client_input_to_script (httpd, task, 1);
}
}
/* send the partial reponse received with the initial line and headers
* so long as the client-side handle is writable... */
if (!(task->trigger.v[2].mask & QSE_HTTPD_TASK_TRIGGER_WRITE) ||
(task->trigger.v[2].mask & QSE_HTTPD_TASK_TRIGGER_WRITABLE))
if (/*!(task->trigger.cmask & QSE_HTTPD_TASK_TRIGGER_WRITE) ||*/
(task->trigger.cmask & QSE_HTTPD_TASK_TRIGGER_WRITABLE))
{
count = MAX_SEND_SIZE;
if (count >= cgi->res_left) count = cgi->res_left;
@ -1248,7 +1252,7 @@ qse_printf (QSE_T("task_main_cgi_3 trigger[0].mask=%d trigger[1].mask=%d trigger
if ((cgi->resflags & CGI_RES_SCRIPT_LENGTH) &&
cgi->script_output_received >= cgi->script_output_length)
{
{
/* if a cgi script specified the content length
* and it has emitted as much as the length,
* i don't wait for the script to finish.
@ -1257,12 +1261,12 @@ qse_printf (QSE_T("task_main_cgi_3 trigger[0].mask=%d trigger[1].mask=%d trigger
* something extra after having done so.
* however, a CGI script shouln't do that... */
task->main = task_main_cgi_5;
task->trigger.v[2].mask |= QSE_HTTPD_TASK_TRIGGER_WRITE;
task->trigger.cmask |= QSE_HTTPD_TASK_TRIGGER_WRITE;
}
else
{
task->main = task_main_cgi_4;
task->trigger.v[2].mask &= ~QSE_HTTPD_TASK_TRIGGER_WRITE;
task->trigger.cmask &= ~QSE_HTTPD_TASK_TRIGGER_WRITE;
}
return 1;
}
@ -1287,21 +1291,28 @@ static int task_main_cgi_2 (
QSE_ASSERT (cgi->pio_inited);
#if 0
qse_printf (QSE_T("task_main_cgi_2 trigger[0].mask=%d trigger[1].mask=%d trigger[2].mask=%d\n"),
task->trigger.v[0].mask, task->trigger.v[1].mask, task->trigger.v[2].mask);
printf ("task_main_cgi_2 trigger[0].mask=%d trigger[1].mask=%d cmask=%d\n",
task->trigger.v[0].mask, task->trigger.v[1].mask, task->trigger.cmask);
#endif
if (task->trigger.v[2].mask & QSE_HTTPD_TASK_TRIGGER_READABLE)
if (cgi->reqfwdbuf)
{
cgi_forward_client_input_to_script (httpd, task, 0);
}
else if (task->trigger.v[1].mask & QSE_HTTPD_TASK_TRIGGER_WRITABLE)
{
cgi_forward_client_input_to_script (httpd, task, 1);
if (task->trigger.cmask & QSE_HTTPD_TASK_TRIGGER_READABLE)
{
/* client side is readable */
cgi_forward_client_input_to_script (httpd, task, 0);
}
else if (task->trigger.v[1].mask & QSE_HTTPD_TASK_TRIGGER_WRITABLE)
{
/* can write to the input pipe to the cgi script */
cgi_forward_client_input_to_script (httpd, task, 1);
}
}
if (task->trigger.v[0].mask & QSE_HTTPD_TASK_TRIGGER_READABLE)
{
/* can read from cgi's output pipe */
n = qse_pio_read (
&cgi->pio, QSE_PIO_OUT,
&cgi->buf[cgi->buflen],
@ -1347,14 +1358,10 @@ qse_printf (QSE_T("task_main_cgi_2 trigger[0].mask=%d trigger[1].mask=%d trigger
cgi->res_ptr = QSE_MBS_PTR(cgi->res);
cgi->res_left = QSE_MBS_LEN(cgi->res);
#if 0
qse_printf (QSE_T("TRAILING DATA=[%.*hs]\n"), (int)QSE_MBS_LEN(cgi->res), QSE_MBS_PTR(cgi->res));
#endif
task->main = task_main_cgi_3;
task->trigger.v[2].mask |= QSE_HTTPD_TASK_TRIGGER_WRITE;
task->trigger.cmask |= QSE_HTTPD_TASK_TRIGGER_WRITE;
return 1;
}
}
/* complete headers not seen yet. i need to be called again */
@ -1380,8 +1387,7 @@ static int task_main_cgi (
* since i don't parse the header. so i have to close
* the connection regardless of content-length or transfer-encoding
* in the actual header. */
if (qse_httpd_entaskdisconnect (
httpd, client, task) == QSE_NULL) goto oops;
if (qse_httpd_entaskdisconnect (httpd, client, task) == QSE_NULL) goto oops;
}
else
{
@ -1445,13 +1451,13 @@ static int task_main_cgi (
/* set the trigger that the main loop can use this
* handle for multiplexing
*
* it the output from the child is available, this task
* if the output from the child is available, this task
* writes it back to the client. so add a trigger for
* checking the data availability from the child process */
task->trigger.v[0].mask = QSE_HTTPD_TASK_TRIGGER_READ;
task->trigger.v[0].handle = qse_pio_gethandleasubi (&cgi->pio, QSE_PIO_OUT);
task->trigger.v[1].handle = qse_pio_gethandleasubi (&cgi->pio, QSE_PIO_IN);
task->trigger.v[2].handle = client->handle;
task->trigger.cmask = 0;
if (cgi->reqfwdbuf)
{
@ -1462,7 +1468,7 @@ static int task_main_cgi (
{
/* there are still things to forward from the client-side.
* i can rely on this relay trigger for task invocation. */
task->trigger.v[2].mask = QSE_HTTPD_TASK_TRIGGER_READ;
task->trigger.cmask = QSE_HTTPD_TASK_TRIGGER_READ;
}
if (QSE_MBS_LEN(cgi->reqfwdbuf) > 0)

View File

@ -476,8 +476,9 @@ static int task_main_putfile_2 (
* QSE_NULL when snatching is over in putfile_snatch_client_input().
* i set a trigger so that the task is executed
* while there is input from the client side */
task->trigger.v[0].mask = QSE_HTTPD_TASK_TRIGGER_READ;
task->trigger.v[0].handle = client->handle;
/*task->trigger.v[0].mask = QSE_HTTPD_TASK_TRIGGER_READ;
task->trigger.v[0].handle = client->handle;*/
task->trigger.cmask = QSE_HTTPD_TASK_TRIGGER_READ;
return 1; /* trigger me when a client sends data */
}

View File

@ -23,6 +23,7 @@
#include "../cmn/mem.h"
#include <qse/cmn/str.h>
#include <qse/cmn/fmt.h>
#include <qse/cmn/hton.h>
typedef struct task_proxy_arg_t task_proxy_arg_t;
struct task_proxy_arg_t
@ -49,7 +50,9 @@ struct task_proxy_t
qse_htrd_t* peer_htrd;
const qse_mchar_t* peer_name;
qse_mchar_t* peer_name;
qse_uint16_t peer_port;
qse_httpd_peer_t peer;
#define PROXY_PEER_OPEN (1 << 0)
#define PROXY_PEER_CONNECTED (1 << 1)
@ -268,7 +271,7 @@ else qse_printf (QSE_T("!!!PROXY SNATCHING DONE\n"));
/* since there is no more to read from the client side.
* the relay trigger is not needed any more. */
task->trigger.v[2].mask = 0;
task->trigger.cmask &= ~QSE_HTTPD_TASK_TRIGGER_READ;
if (QSE_MBS_LEN(proxy->reqfwdbuf) > 0 &&
(proxy->peer_status & PROXY_PEER_CONNECTED) &&
@ -738,7 +741,7 @@ to the head all the time.. grow the buffer to a certain limit. */
* clear the read and write triggers.
*/
task->trigger.v[0].mask &= ~QSE_HTTPD_TASK_TRIGGER_WRITE; /* peer */
task->trigger.v[2].mask = 0; /* client-side */
task->trigger.cmask &= ~QSE_HTTPD_TASK_TRIGGER_READ; /* client-side */
}
}
@ -767,9 +770,29 @@ static int task_init_proxy (
proxy->peer.local = arg->rsrc->src.nwad;
if (arg->rsrc->flags & QSE_HTTPD_RSRC_PROXY_DST_STR)
{
qse_mchar_t* colon;
proxy->flags |= PROXY_RESOL_PEER_NAME;
proxy->peer_name = (const qse_mchar_t*)(proxy + 1);
qse_mbscpy ((qse_mchar_t*)proxy->peer_name, arg->rsrc->dst.str);
proxy->peer_name = (qse_mchar_t*)(proxy + 1);
qse_mbscpy (proxy->peer_name, arg->rsrc->dst.str);
colon = qse_mbschr (proxy->peer_name, QSE_MT(':'));
if (colon)
{
qse_mchar_t* endptr;
/* handle a port number after the colon sign */
*colon = QSE_MT('\0');
QSE_MBSTONUM (proxy->peer_port, colon + 1, &endptr, 10);
/* TODO: check if *endptr is QSE_T('\0')? */
}
else
{
/*proxy->peer_port = 443;*/
qse_httpd_seterrnum (httpd, QSE_HTTPD_EINVAL);
goto oops;
}
}
else
{
@ -1014,10 +1037,10 @@ static int task_main_proxy_5 (
#if 0
printf ("task_main_proxy_5 trigger[0].mask=%d trigger[1].mask=%d trigger[2].mask=%d\n",
task->trigger.v[0].mask, task->trigger.v[1].mask, task->trigger.v[2].mask);
task->trigger.v[0].mask, task->trigger.v[1].mask, task->trigger.cmask);
#endif
if (task->trigger.v[2].mask & QSE_HTTPD_TASK_TRIGGER_READABLE)
if (task->trigger.cmask & QSE_HTTPD_TASK_TRIGGER_READABLE)
{
/* if the client side is readable */
proxy_forward_client_input_to_peer (httpd, task, 0);
@ -1028,8 +1051,8 @@ printf ("task_main_proxy_5 trigger[0].mask=%d trigger[1].mask=%d trigger[2].mask
proxy_forward_client_input_to_peer (httpd, task, 1);
}
if (!(task->trigger.v[2].mask & QSE_HTTPD_TASK_TRIGGER_WRITE) ||
(task->trigger.v[2].mask & QSE_HTTPD_TASK_TRIGGER_WRITABLE))
if (/*!(task->trigger.cmask & QSE_HTTPD_TASK_TRIGGER_WRITE) ||*/
(task->trigger.cmask & QSE_HTTPD_TASK_TRIGGER_WRITABLE))
{
if (proxy->buflen > 0)
{
@ -1063,10 +1086,10 @@ static int task_main_proxy_4 (
#if 1
printf ("task_main_proxy_4 trigger[0].mask=%d trigger[1].mask=%d trigger[2].mask=%d\n",
task->trigger.v[0].mask, task->trigger.v[1].mask, task->trigger.v[2].mask);
task->trigger.v[0].mask, task->trigger.v[1].mask, task->trigger.cmask);
#endif
if (task->trigger.v[2].mask & QSE_HTTPD_TASK_TRIGGER_READABLE)
if (task->trigger.cmask & QSE_HTTPD_TASK_TRIGGER_READABLE)
{
proxy_forward_client_input_to_peer (httpd, task, 0);
}
@ -1117,7 +1140,7 @@ printf ("task_main_proxy_4 trigger[0].mask=%d trigger[1].mask=%d trigger[2].mask
task->trigger.v[0].mask = 0;
/* arrange to be called if the client side is writable */
task->trigger.v[2].mask |= QSE_HTTPD_TASK_TRIGGER_WRITE;
task->trigger.cmask |= QSE_HTTPD_TASK_TRIGGER_WRITE;
if (proxy->flags & PROXY_RAW)
{
@ -1151,7 +1174,7 @@ printf ("task_main_proxy_4 trigger[0].mask=%d trigger[1].mask=%d trigger[2].mask
/* proxy has finished reading all */
task->main = task_main_proxy_5;
task->trigger.v[0].mask = 0;
task->trigger.v[2].mask |= QSE_HTTPD_TASK_TRIGGER_WRITE;
task->trigger.cmask |= QSE_HTTPD_TASK_TRIGGER_WRITE;
return 1;
}
}
@ -1188,10 +1211,10 @@ static int task_main_proxy_3 (
#if 0
qse_printf (QSE_T("task_main_proxy_3 trigger[0].mask=%d trigger[1].mask=%d trigger[2].mask=%d\n"),
task->trigger.v[0].mask, task->trigger.v[1].mask, task->trigger.v[2].mask);
task->trigger.v[0].mask, task->trigger.v[1].mask, task->trigger.cmask);
#endif
if (task->trigger.v[2].mask & QSE_HTTPD_TASK_TRIGGER_READABLE)
if (task->trigger.cmask & QSE_HTTPD_TASK_TRIGGER_READABLE)
{
proxy_forward_client_input_to_peer (httpd, task, 0);
}
@ -1200,8 +1223,8 @@ qse_printf (QSE_T("task_main_proxy_3 trigger[0].mask=%d trigger[1].mask=%d trigg
proxy_forward_client_input_to_peer (httpd, task, 1);
}
if (!(task->trigger.v[2].mask & QSE_HTTPD_TASK_TRIGGER_WRITE) ||
(task->trigger.v[2].mask & QSE_HTTPD_TASK_TRIGGER_WRITABLE))
if (/*!(task->trigger.cmask & QSE_HTTPD_TASK_TRIGGER_WRITE) ||*/
(task->trigger.cmask & QSE_HTTPD_TASK_TRIGGER_WRITABLE))
{
qse_ssize_t n;
qse_size_t count;
@ -1230,20 +1253,27 @@ qse_printf (QSE_T("task_main_proxy_3 trigger[0].mask=%d trigger[1].mask=%d trigg
if (proxy->res_pending <= 0)
{
/* all data received from the peer so far(including those injected)
* have been sent back to the client-side */
qse_mbs_clear (proxy->res);
proxy->res_consumed = 0;
if ((proxy->resflags & PROXY_RES_CLIENT_CHUNK) ||
((proxy->resflags & PROXY_RES_PEER_LENGTH) && proxy->peer_output_received >= proxy->peer_output_length))
{
/* received all contents */
task->main = task_main_proxy_5;
task->trigger.v[2].mask |= QSE_HTTPD_TASK_TRIGGER_WRITE;
task->trigger.cmask |= QSE_HTTPD_TASK_TRIGGER_WRITE;
}
else
{
/* arrange to read the remaining contents from the peer */
/* there are still more to read from the peer.
* arrange to read the remaining contents from the peer */
task->main = task_main_proxy_4;
task->trigger.v[2].mask &= ~QSE_HTTPD_TASK_TRIGGER_WRITE;
/* nothing to write in proxy->res. so clear WRITE from the
* client side */
task->trigger.cmask &= ~QSE_HTTPD_TASK_TRIGGER_WRITE;
}
return 1;
}
@ -1259,11 +1289,11 @@ static int task_main_proxy_2 (
int http_errnum = 500;
#if 0
printf ("task_main_proxy_2 trigger[0].mask=%d trigger[1].mask=%d trigger[2].mask=%d\n",
task->trigger.v[0].mask, task->trigger.v[1].mask, task->trigger.v[2].mask);
printf ("task_main_proxy_2 trigger[0].mask=%d trigger[1].mask=%d cmask=%d\n",
task->trigger.v[0].mask, task->trigger.v[1].mask, task->trigger.cmask);
#endif
if (task->trigger.v[2].mask & QSE_HTTPD_TASK_TRIGGER_READABLE)
if (task->trigger.cmask & QSE_HTTPD_TASK_TRIGGER_READABLE)
{
/* client is readable */
proxy_forward_client_input_to_peer (httpd, task, 0);
@ -1274,8 +1304,8 @@ printf ("task_main_proxy_2 trigger[0].mask=%d trigger[1].mask=%d trigger[2].mask
proxy_forward_client_input_to_peer (httpd, task, 1);
}
if (!(task->trigger.v[2].mask & QSE_HTTPD_TASK_TRIGGER_WRITE) ||
(task->trigger.v[2].mask & QSE_HTTPD_TASK_TRIGGER_WRITABLE))
if (/*!(task->trigger.cmask & QSE_HTTPD_TASK_TRIGGER_WRITE) ||*/
(task->trigger.cmask & QSE_HTTPD_TASK_TRIGGER_WRITABLE))
{
if (proxy->res_pending > 0)
{
@ -1296,16 +1326,6 @@ printf ("task_main_proxy_2 trigger[0].mask=%d trigger[1].mask=%d trigger[2].mask
count = proxy->res_pending;
if (count > MAX_SEND_SIZE) count = MAX_SEND_SIZE;
#if 0
qse_printf (QSE_T("[proxy_2 sending %d bytes (index %d)] ["),
(int)count, (int)proxy->res_consumed);
{
int i;
for (i = 0; i < count; i++) qse_printf (QSE_T("%hc"), QSE_MBS_CHAR(proxy->res,proxy->res_consumed+i));
}
qse_printf (QSE_T("]\n"));
#endif
n = httpd->opt.scb.client.send (
httpd, client,
QSE_MBS_CPTR(proxy->res,proxy->res_consumed),
@ -1326,8 +1346,12 @@ qse_printf (QSE_T("]\n"));
{
/* '100 Continue' and payload received together
* has all been relayed back. no need for writability
* check of the client side */
task->trigger.v[2].mask &= ~QSE_HTTPD_TASK_TRIGGER_WRITE;
* check of the client side as there's nothing to write.
* when something is read from the peer and proxy->res
* becomes loaded, this cmask is added with WRITE
* in the 'if' block below that takes care of reading
* from the peer. */
task->trigger.cmask &= ~QSE_HTTPD_TASK_TRIGGER_WRITE;
}
}
}
@ -1373,7 +1397,7 @@ qse_printf (QSE_T("]\n"));
* case. call qse_htrd_halt() for this. */
qse_htrd_halt (proxy->peer_htrd);
task->main = task_main_proxy_3;
task->trigger.v[2].mask |= QSE_HTTPD_TASK_TRIGGER_WRITE;
task->trigger.cmask |= QSE_HTTPD_TASK_TRIGGER_WRITE;
return 1;
}
@ -1408,24 +1432,27 @@ qse_printf (QSE_T("]\n"));
{
if (proxy->resflags & PROXY_RES_RECEIVED_RESCON)
{
/* received the contents in full */
QSE_ASSERT (proxy->resflags & PROXY_RES_CLIENT_CHUNK);
task->main = task_main_proxy_3;
task->trigger.v[2].mask |= QSE_HTTPD_TASK_TRIGGER_WRITE;
task->trigger.cmask |= QSE_HTTPD_TASK_TRIGGER_WRITE;
}
else if (proxy->resflags & PROXY_RES_AWAIT_RESCON)
{
/* waiting for contents */
QSE_ASSERT (proxy->resflags & PROXY_RES_CLIENT_CHUNK);
task->trigger.v[2].mask |= QSE_HTTPD_TASK_TRIGGER_WRITE;
task->trigger.cmask |= QSE_HTTPD_TASK_TRIGGER_WRITE;
}
else if (proxy->resflags & PROXY_RES_RECEIVED_RESHDR)
{
/* the actual response header has been received
* with or without '100 continue'. you can
* check it with proxy->resflags & PROXY_RES_RECEIVED_100 */
if (proxy->resflags & PROXY_RES_CLIENT_CHUNK)
{
proxy->resflags |= PROXY_RES_AWAIT_RESCON;
task->trigger.v[2].mask |= QSE_HTTPD_TASK_TRIGGER_WRITE;
task->trigger.cmask |= QSE_HTTPD_TASK_TRIGGER_WRITE;
}
else
{
@ -1434,14 +1461,14 @@ qse_printf (QSE_T("TRAILING DATA=%d, [%hs]\n"), (int)QSE_MBS_LEN(proxy->res), QS
#endif
/* switch to the next phase */
task->main = task_main_proxy_3;
task->trigger.v[2].mask |= QSE_HTTPD_TASK_TRIGGER_WRITE;
task->trigger.cmask |= QSE_HTTPD_TASK_TRIGGER_WRITE;
}
}
else if (proxy->resflags & PROXY_RES_RECEIVED_100)
{
/* 100 continue has been received but
* the actual response has not. */
task->trigger.v[2].mask |= QSE_HTTPD_TASK_TRIGGER_WRITE;
task->trigger.cmask |= QSE_HTTPD_TASK_TRIGGER_WRITE;
}
else
{
@ -1461,6 +1488,10 @@ oops:
static int task_main_proxy_1 (
qse_httpd_t* httpd, qse_httpd_client_t* client, qse_httpd_task_t* task)
{
/* scheduling of this function is made in task_main_proxy() if
* the connection to the peer isn't established. this function should
* check the connection state to the peer. */
task_proxy_t* proxy = (task_proxy_t*)task->ctx;
int http_errnum = 500;
@ -1490,10 +1521,11 @@ static int task_main_proxy_1 (
{
/* connected to the peer now */
proxy->peer_status |= PROXY_PEER_CONNECTED;
if (proxy->req)
{
task->trigger.v[2].mask = QSE_HTTPD_TASK_TRIGGER_READ;
/* need to read from the client-side as
* the content has not been received in full. */
task->trigger.cmask |= QSE_HTTPD_TASK_TRIGGER_READ;
}
task->trigger.v[0].mask &= ~QSE_HTTPD_TASK_TRIGGER_WRITE;
@ -1523,7 +1555,7 @@ static int task_main_proxy_1 (
/* arrange to be called if the client side is writable.
* it must write the injected response. */
task->trigger.v[2].mask |= QSE_HTTPD_TASK_TRIGGER_WRITE;
task->trigger.cmask |= QSE_HTTPD_TASK_TRIGGER_WRITE;
task->main = task_main_proxy_3;
}
else
@ -1546,16 +1578,13 @@ static void on_peer_name_resolved (qse_httpd_t* httpd, const qse_mchar_t* name,
QSE_ASSERT (proxy->flags & PROXY_RESOL_PEER_NAME);
task->trigger.flags &= ~QSE_HTTPD_TASK_TRIGGER_INACTIVE;
if (nwad)
{
/* resolved successfully */
proxy->flags &= ~PROXY_RESOL_PEER_NAME;
proxy->peer.nwad = *nwad;
/*TODO: set port number .... */
proxy->peer.nwad.u.in4.port = qse_hton16(80);
qse_setnwadport (&proxy->peer.nwad, qse_hton16(proxy->peer_port));
if (proxy->peer.local.type == QSE_NWAD_NX)
proxy->peer.local.type = proxy->peer.nwad.type;
@ -1566,9 +1595,6 @@ proxy->peer.nwad.u.in4.port = qse_hton16(80);
proxy->flags |= PROXY_INIT_FAILED | PROXY_UNKNOWN_PEER_NWAD;
}
/* TODO: do something about this... */
task->trigger.v[2].handle = proxy->client->handle;
task->trigger.v[2].mask |= QSE_HTTPD_TASK_TRIGGER_WRITE;
if (qse_httpd_activatetasktrigger (httpd, proxy->client, task) <= -1)
{
proxy->flags |= PROXY_INIT_FAILED;
@ -1600,11 +1626,6 @@ static int task_main_proxy (
return 1;
}
/* TODO: do something abotu this */
printf ("XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXx\n");
task->trigger.v[2].mask = 0;
if (!(proxy->flags & PROXY_RAW))
{
/* set up a http reader to read a response from the peer */
@ -1641,23 +1662,25 @@ task->trigger.v[2].mask = 0;
proxy->peer_status |= PROXY_PEER_OPEN;
task->trigger.v[0].mask = QSE_HTTPD_TASK_TRIGGER_READ;
task->trigger.v[0].handle = proxy->peer.handle;
task->trigger.v[2].handle = client->handle;
/*task->trigger.cmask = QSE_HTTPD_TASK_TRIGGER_READ;*/
task->trigger.cmask = 0;
if (n == 0)
{
printf ("PEER 00000000000000000000\n");
/* peer not connected yet */
/*task->trigger.cmask &= ~QSE_HTTPD_TASK_TRIGGER_READ;*/
task->trigger.v[0].mask |= QSE_HTTPD_TASK_TRIGGER_WRITE;
task->main = task_main_proxy_1;
}
else
{
/* peer connected already */
printf ("PEER 111111111111111111111\n");
proxy->peer_status |= PROXY_PEER_CONNECTED;
if (proxy->req)
{
task->trigger.v[2].mask = QSE_HTTPD_TASK_TRIGGER_READ;
/* need to read from the client-side as
* the content has not been received in full. */
task->trigger.cmask = QSE_HTTPD_TASK_TRIGGER_READ;
}
if (QSE_MBS_LEN(proxy->reqfwdbuf) > 0)
@ -1682,7 +1705,7 @@ printf ("PEER 111111111111111111111\n");
/* arrange to be called if the client side is writable.
* it must write the injected response. */
task->trigger.v[2].mask |= QSE_HTTPD_TASK_TRIGGER_WRITE;
task->trigger.cmask |= QSE_HTTPD_TASK_TRIGGER_WRITE;
task->main = task_main_proxy_3;
}
else

View File

@ -1979,7 +1979,10 @@ struct dns_ctx_t
struct dns_req_t
{
qse_uint16_t seq;
#define DNS_REQ_A_ERROR (1 << 0)
#define DNS_REQ_AAAA_ERROR (1 << 1)
int flags;
qse_uint16_t seqa, seqaaaa;
qse_mchar_t* name;
qse_uint8_t* dn;
@ -2274,20 +2277,22 @@ printf ("RECV....\n");
if (len >= QSE_SIZEOF(*hdr))
{
qse_uint16_t id, qdcount, ancount;
qse_uint16_t id, qdcount, ancount, xid;
hdr = (dns_hdr_t*)buf;
id = qse_ntoh16(hdr->id);
qdcount = qse_ntoh16(hdr->qdcount);
ancount = qse_ntoh16(hdr->ancount);
xid = (id >= QSE_COUNTOF(dc->reqs))? (id - QSE_COUNTOF(dc->reqs)): id;
printf ("%d qdcount %d ancount %d\n", id, qdcount, ancount);
if (id >= 0 && id < QSE_COUNTOF(dc->reqs) && hdr->qr && hdr->opcode == DNS_OPCODE_QUERY && qdcount >= 1)
if (id >= 0 && id < QSE_COUNTOF(dc->reqs) * 2 && hdr->qr && hdr->opcode == DNS_OPCODE_QUERY && qdcount >= 1)
{
qse_uint8_t* plptr = (qse_uint8_t*)(hdr + 1);
qse_size_t pllen = len - QSE_SIZEOF(*hdr);
qse_uint8_t i, dnlen;
dns_req_t* req = QSE_NULL;
dns_req_t* req = QSE_NULL, * preq = QSE_NULL;
qse_size_t reclen;
printf ("finding match req...\n");
@ -2302,7 +2307,7 @@ printf ("1111111111111111111111\n");
if (!req)
{
dns_qdtrail_t* qdtrail = (dns_qdtrail_t*)(plptr + dnlen);
for (req = dc->reqs[id]; req; req = req->next)
for (preq = QSE_NULL, req = dc->reqs[xid]; req; preq = req, req = req->next)
{
printf ("checking req... %d %d\n",(int)req->dnlen, (int)dnlen);
if (req->dnlen == dnlen &&
@ -2322,13 +2327,13 @@ printf ("found matching req...\n");
}
if (!req) goto done;
if (hdr->rcode == DNS_RCODE_NOERROR && ancount > 0)
{
dns_antrail_t* antrail;
qse_uint16_t qtype, anlen;
printf ("checking answers.... pllen => %d\n", pllen);
printf ("checking answers.... pllen => %d\n", (int)pllen);
for (i = 0; i < ancount; i++)
{
if (pllen < 1) goto done;
@ -2340,7 +2345,6 @@ printf ("........... %d\n", dnlen);
if (dnlen <= 0) goto done; /* invalid dn name */
}
printf ("111111111111111111111111111\n");
reclen = dnlen + QSE_SIZEOF(dns_antrail_t);
if (pllen < reclen) goto done;
@ -2351,7 +2355,6 @@ printf ("111111111111111111111111111\n");
qtype = qse_ntoh16(antrail->qtype);
anlen = qse_ntoh16(antrail->dlen);
printf ("XXXXXXXXXXXXXXXXXxx\n");
if (antrail->qclass == qse_hton16(DNS_QCLASS_IN))
{
if (qtype == DNS_QTYPE_A && anlen == 4)
@ -2363,7 +2366,12 @@ printf ("XXXXXXXXXXXXXXXXXxx\n");
QSE_MEMCPY (&nwad.u.in4.addr, antrail + 1, 4);
printf ("invoking resoll with ipv4 \n");
req->resol (httpd, req->name, &nwad, req->ctx);
/* TODO: delete req from dc ... */
/* delete the request from dc */
if (preq) preq->next = req->next;
else dc->reqs[xid] = req->next;
qse_httpd_freemem (httpd, req);
goto done;
}
else if (qtype == DNS_QTYPE_AAAA || anlen == 16)
@ -2375,7 +2383,12 @@ printf ("invoking resoll with ipv4 \n");
QSE_MEMCPY (&nwad.u.in6.addr, antrail + 1, 16);
printf ("invoking resoll with ipv6 \n");
req->resol (httpd, req->name, &nwad, req->ctx);
/* TODO:delete req from dc*/
/* delete the request from dc */
if (preq) preq->next = req->next;
else dc->reqs[xid] = req->next;
qse_httpd_freemem (httpd, req);
goto done;
}
}
@ -2384,6 +2397,21 @@ printf ("invoking resoll with ipv6 \n");
pllen -= reclen;
}
}
else
{
if (id == req->seqa) req->flags |= DNS_REQ_A_ERROR;
else if (id == req->seqaaaa) req->flags |= DNS_REQ_AAAA_ERROR;
if ((req->flags & (DNS_REQ_A_ERROR | DNS_REQ_AAAA_ERROR)) == (DNS_REQ_A_ERROR | DNS_REQ_AAAA_ERROR))
{
req->resol (httpd, req->name, QSE_NULL, req->ctx);
/* delete the request from dc */
if (preq) preq->next = req->next;
else dc->reqs[xid] = req->next;
qse_httpd_freemem (httpd, req);
}
}
/*req->resol (httpd, req->name, QSE_NULL, req->ctx);*//* TODO: handle this better */
}
@ -2413,7 +2441,8 @@ static int dns_send (qse_httpd_t* httpd, qse_httpd_dns_t* dns, const qse_mchar_t
req = qse_httpd_callocmem (httpd, QSE_SIZEOF(*req) + (name_len + 1) + (name_len + 2));
if (req == QSE_NULL) return -1;
req->seq = seq;
req->seqa = seq;
req->seqaaaa = seq + QSE_COUNTOF(dc->reqs); /* this must not go beyond the qse_uint16_t max */
req->name = (qse_mchar_t*)(req + 1);
req->dn = (qse_uint8_t*)(req->name + name_len + 1);
@ -2427,9 +2456,9 @@ static int dns_send (qse_httpd_t* httpd, qse_httpd_dns_t* dns, const qse_mchar_t
}
req->resol = resol;
req->ctx = ctx;
req->qalen = init_dns_query (req->qa, QSE_SIZEOF(req->qa), name, DNS_QTYPE_A, seq);
req->qaaaalen = init_dns_query (req->qaaaa, QSE_SIZEOF(req->qaaaa), name, DNS_QTYPE_AAAA, seq);
req->qalen = init_dns_query (req->qa, QSE_SIZEOF(req->qa), name, DNS_QTYPE_A, req->seqa);
req->qaaaalen = init_dns_query (req->qaaaa, QSE_SIZEOF(req->qaaaa), name, DNS_QTYPE_AAAA, req->seqaaaa);
if (req->qalen <= -1 || req->qaaaalen <= -1)
{
qse_httpd_seterrnum (httpd, QSE_HTTPD_EINVAL);

View File

@ -727,34 +727,6 @@ qse_httpd_server_t* qse_httpd_getprevserver (qse_httpd_t* httpd, qse_httpd_serve
/* ----------------------------------------------------------------------- */
#if 0
qse_httpd_dns_t* qse_httpd_attachdns (qse_httpd_t* httpd, qse_httpd_dns_dope_t* dns, qse_size_t xtnsize)
{
qse_httpd_dns_t* dns;
dns = qse_httpd_callocmem (httpd, QSE_SIZEOF(*dns) + xtnsize);
if (dns == QSE_NULL) return QSE_NULL;
dns->type = QSE_HTTPD_SERVER;
/* copy the dns dope */
dns->dope = *dope;
/* and correct some fields in case the dope contains invalid stuffs */
dns->dope.flags &= ~QSE_HTTPD_SERVER_ACTIVE;
/* chain the dns to the tail of the list */
dns->prev = httpd->dns.list.tail;
dns->next = QSE_NULL;
if (httpd->dns.list.tail)
httpd->dns.list.tail->next = dns;
else
httpd->dns.list.head = dns;
httpd->dns.list.tail = dns;
httpd->dns.navail++;
return dns;
}
#endif
static int activate_dns (qse_httpd_t* httpd)
{
if (httpd->opt.scb.dns.open (httpd, &httpd->dns) <= -1) return -1;
@ -767,7 +739,6 @@ static int activate_dns (qse_httpd_t* httpd)
return -1;
}
//httpd->dns = dns;
return 0;
}
@ -909,6 +880,19 @@ qse_printf (QSE_T("!!!!!FEEDING OK OK OK OK %d from %d\n"), (int)m, (int)client-
return 0;
}
static void clear_trigger_mask_result (qse_httpd_task_t* task)
{
qse_size_t i;
task->trigger.cmask &= ~(QSE_HTTPD_TASK_TRIGGER_READABLE |
QSE_HTTPD_TASK_TRIGGER_WRITABLE);
for (i = 0; i < QSE_COUNTOF(task->trigger.v); i++)
{
task->trigger.v[i].mask &= ~(QSE_HTTPD_TASK_TRIGGER_READABLE |
QSE_HTTPD_TASK_TRIGGER_WRITABLE);
}
}
static int update_mux_for_current_task (qse_httpd_t* httpd, qse_httpd_client_t* client, qse_httpd_task_t* task)
{
qse_size_t i;
@ -917,11 +901,8 @@ static int update_mux_for_current_task (qse_httpd_t* httpd, qse_httpd_client_t*
* that something can go wrong if the task handler plays
* with the trigger field in an unexpected manner.
*/
for (i = 0; i < QSE_COUNTOF(task->trigger.v); i++)
{
task->trigger.v[i].mask &= ~(QSE_HTTPD_TASK_TRIGGER_READABLE |
QSE_HTTPD_TASK_TRIGGER_WRITABLE);
}
clear_trigger_mask_result (task);
printf ("update_mux_for_current_task..............\n");
if (QSE_MEMCMP (&client->trigger, &task->trigger, QSE_SIZEOF(client->trigger)) != 0 ||
@ -930,7 +911,6 @@ printf ("update_mux_for_current_task..............\n");
/* manipulate muxtiplexer settings if there are trigger changes */
int has_trigger = 0;
int expected_client_handle_mux_mask_from_trigger = 0;
int expected_client_handle_mux_mask;
int expected_client_handle_mux_status;
@ -996,15 +976,13 @@ printf ("ACTIVE TO ACTIVE....\n");
int expected_trigger_mux_mask = 0;
int expected_trigger_mux_status = 0;
if (task->trigger.v[i].handle.i == client->handle.i) continue; /* TODO: no direct comparision */
if (task->trigger.v[i].mask & QSE_HTTPD_TASK_TRIGGER_READ)
{
if (task->trigger.v[i].handle.i != client->handle.i || !(client->status & CLIENT_MUTE))
{
expected_trigger_mux_mask |= QSE_HTTPD_MUX_READ;
expected_trigger_mux_status |= CLIENT_TASK_TRIGGER_READ_IN_MUX(i);
}
expected_trigger_mux_mask |= QSE_HTTPD_MUX_READ;
expected_trigger_mux_status |= CLIENT_TASK_TRIGGER_READ_IN_MUX(i);
}
if (task->trigger.v[i].mask & QSE_HTTPD_TASK_TRIGGER_WRITE)
{
expected_trigger_mux_mask |= QSE_HTTPD_MUX_WRITE;
@ -1014,52 +992,52 @@ printf ("ACTIVE TO ACTIVE....\n");
if (expected_trigger_mux_mask)
{
has_trigger = 1;
if (task->trigger.v[i].handle.i == client->handle.i) /* TODO: no direct comparsion */
{
/* if the client handle is included in the trigger,
* delay its manipulation until the loop is over.
* instead, just remember what mask is requested */
expected_client_handle_mux_mask_from_trigger |= expected_trigger_mux_mask;
}
else
{
if (httpd->opt.scb.mux.addhnd (httpd, httpd->mux, task->trigger.v[i].handle, expected_trigger_mux_mask, client) <= -1)
{
return -1;
}
client->status |= expected_trigger_mux_status;
}
if (httpd->opt.scb.mux.addhnd (httpd, httpd->mux, task->trigger.v[i].handle, expected_trigger_mux_mask, client) <= -1) return -1;
client->status |= expected_trigger_mux_status;
}
}
expected_client_handle_mux_mask = QSE_HTTPD_MUX_READ;
expected_client_handle_mux_status = CLIENT_HANDLE_READ_IN_MUX;
/* client-side handle is registered for both reading and
* writing when the task is executed for the first time.
* see update_mux_for_next_task() for this.
*
* starting from the second call, the client-side handle
* is registered for writing if it's explicitly requested.
* it's always registered for reading if not for CLIENT_MUTE.
*
* this means that QSE_HTTP_TASK_TRIGGER_READ set or clear
* in task->trigger.cmask is not honored.
*/
if (expected_client_handle_mux_mask_from_trigger)
expected_client_handle_mux_mask = 0;
expected_client_handle_mux_status = 0;
if (task->trigger.cmask & QSE_HTTPD_TASK_TRIGGER_WRITE)
{
expected_client_handle_mux_mask |= expected_client_handle_mux_mask_from_trigger;
if (expected_client_handle_mux_mask_from_trigger & QSE_HTTPD_MUX_WRITE)
expected_client_handle_mux_status |= CLIENT_HANDLE_READ_IN_MUX;
if (expected_client_handle_mux_mask_from_trigger & QSE_HTTPD_MUX_WRITE)
expected_client_handle_mux_status |= CLIENT_HANDLE_WRITE_IN_MUX;
}
if (!expected_client_handle_mux_status && !has_trigger)
{
/* if there is no trigger and the client handle is to be excluded
* from reading and writing, writing should be enabled. */
expected_client_handle_mux_status |= CLIENT_HANDLE_WRITE_IN_MUX;
expected_client_handle_mux_mask |= QSE_HTTPD_MUX_WRITE;
expected_client_handle_mux_status |= CLIENT_HANDLE_WRITE_IN_MUX;
}
if (client->status & CLIENT_MUTE)
{
/* readking should be excluded from mux if the client-side has
/* reading should be excluded from mux if the client-side has
* been closed */
client->status |= CLIENT_MUTE_DELETED;
expected_client_handle_mux_mask &= ~QSE_HTTPD_MUX_READ;
expected_client_handle_mux_status &= ~CLIENT_HANDLE_READ_IN_MUX;
}
else
{
if (task->trigger.cmask & QSE_HTTPD_TASK_TRIGGER_READ)
{
expected_client_handle_mux_mask |= QSE_HTTPD_MUX_READ;
expected_client_handle_mux_status |= CLIENT_HANDLE_READ_IN_MUX;
}
}
if (!expected_client_handle_mux_mask && !has_trigger)
{
/* if there is no trigger and the client handle is to be excluded
* from reading and writing, writing should be enabled. */
expected_client_handle_mux_mask |= QSE_HTTPD_MUX_WRITE;
expected_client_handle_mux_status |= CLIENT_HANDLE_WRITE_IN_MUX;
}
if ((client->status & CLIENT_HANDLE_RW_IN_MUX) != expected_client_handle_mux_status)
@ -1067,9 +1045,11 @@ printf ("ACTIVE TO ACTIVE....\n");
httpd->opt.scb.mux.delhnd (httpd, httpd->mux, client->handle);
client->status &= ~CLIENT_HANDLE_RW_IN_MUX;
QSE_ASSERT (expected_client_handle_mux_status & CLIENT_HANDLE_RW_IN_MUX);
if (httpd->opt.scb.mux.addhnd (httpd, httpd->mux, client->handle, expected_client_handle_mux_mask, client) <= -1) return -1;
client->status |= expected_client_handle_mux_status;
if (expected_client_handle_mux_mask)
{
if (httpd->opt.scb.mux.addhnd (httpd, httpd->mux, client->handle, expected_client_handle_mux_mask, client) <= -1) return -1;
client->status |= expected_client_handle_mux_status;
}
}
/* save the task trigger information */
@ -1079,59 +1059,30 @@ printf ("ACTIVE TO ACTIVE....\n");
return 0;
}
static int update_mux_for_new_task (qse_httpd_t* httpd, qse_httpd_client_t* client)
{
/* this task is the first task to activate.
*
* the client handle should be in mux for reading at this phase.
* a new task should be invoked at least once regardless of the
* data availablility(read) on the client side. arrange to invoke
* this task so long as the client-side handle is writable as well
* as when data is available for reading. */
int expected_mux_mask;
int expected_mux_status;
QSE_ASSERT (client->status & CLIENT_HANDLE_RW_IN_MUX);
expected_mux_mask = QSE_HTTPD_MUX_READ | QSE_HTTPD_MUX_WRITE;
expected_mux_status = CLIENT_HANDLE_RW_IN_MUX;
if ((client->status & CLIENT_HANDLE_RW_IN_MUX) != expected_mux_status)
{
/* no updating is needed if the client handle is in mux for
* both reading and writing. if not, the handle must be
* re-registered for both reading and writing. */
httpd->opt.scb.mux.delhnd (httpd, httpd->mux, client->handle);
client->status &= ~CLIENT_HANDLE_RW_IN_MUX;
#if 0
printf ("MUX ADDHND CLIENT RW(ENTASK) %d\n", client->handle.i);
#endif
QSE_ASSERT (expected_mux_status & CLIENT_HANDLE_RW_IN_MUX);
if (httpd->opt.scb.mux.addhnd (httpd, httpd->mux, client->handle, expected_mux_mask, client) <= -1) return -1;
client->status |= expected_mux_status;
}
return 0;
}
static int update_mux_for_next_task (qse_httpd_t* httpd, qse_httpd_client_t* client)
{
/* A new task should be invoked at least once regardless of the
* data availablility(read) on the client side. Arrange to invoke
* this task so long as the client-side handle is readable or writable. */
qse_httpd_task_t* task;
int expected_mux_mask;
int expected_mux_status;
int expected_trigger_cmask;
printf ("update_mux_for_next_task\n");
expected_mux_mask = QSE_HTTPD_MUX_READ;
expected_mux_status = CLIENT_HANDLE_READ_IN_MUX;
expected_trigger_cmask = QSE_HTTPD_TASK_TRIGGER_READ;
if (client->task.head)
task = client->task.head;
if (task)
{
/* there is a pending task. arrange to trigger it as if it is
* just entasked. */
expected_mux_mask |= QSE_HTTPD_MUX_WRITE;
expected_mux_status |= CLIENT_HANDLE_WRITE_IN_MUX;
expected_trigger_cmask |= QSE_HTTPD_TASK_TRIGGER_WRITE;
if (client->status & CLIENT_MUTE)
{
@ -1139,11 +1090,13 @@ static int update_mux_for_next_task (qse_httpd_t* httpd, qse_httpd_client_t* cli
* from the side any more. so exclude reading */
expected_mux_mask &= ~QSE_HTTPD_MUX_READ;
expected_mux_status &= ~CLIENT_HANDLE_READ_IN_MUX;
expected_trigger_cmask &= ~QSE_HTTPD_TASK_TRIGGER_READ;
}
}
else
{
/* there is no pending task to invoke */
/* there is no pending task to invoke. */
if (client->status & CLIENT_MUTE)
{
/* and this client has closed connection previously.
@ -1164,6 +1117,7 @@ static int update_mux_for_next_task (qse_httpd_t* httpd, qse_httpd_client_t* cli
client->status |= expected_mux_status;
}
if (task) task->trigger.cmask = expected_trigger_cmask;
return 0;
}
@ -1173,11 +1127,13 @@ static int invoke_client_task (
{
qse_httpd_task_t* task;
qse_size_t i;
int n, trigger_fired, client_handle_writable;
int n, trigger_fired;
/* TODO: handle comparison callback ... */
if (handle.i == client->handle.i && (mask & QSE_HTTPD_MUX_READ)) /* TODO: no direct comparision */
{
/* keep reading from the client-side as long as
* it's readable. */
if (!(client->status & CLIENT_MUTE) &&
read_from_client (httpd, client) <= -1)
{
@ -1189,45 +1145,59 @@ static int invoke_client_task (
}
}
/* this client doesn't have any task */
task = client->task.head;
if (task == QSE_NULL)
{
/* this client doesn't have any task */
if (client->status & CLIENT_MUTE)
{
/* handle this delayed client disconnection */
/* handle the delayed client disconnection */
return -1;
}
return 0;
}
trigger_fired = 0;
client_handle_writable = 0;
for (i = 0; i < QSE_COUNTOF(task->trigger.v); i++)
clear_trigger_mask_result (task);
if (handle.i == client->handle.i) /* TODO: no direct comparison */
{
task->trigger.v[i].mask &= ~(QSE_HTTPD_TASK_TRIGGER_READABLE |
QSE_HTTPD_TASK_TRIGGER_WRITABLE);
if (task->trigger.v[i].handle.i == handle.i) /* TODO: no direct comparision */
if (mask & QSE_HTTPD_MUX_READ)
{
if (mask & QSE_HTTPD_MUX_READ)
/*QSE_ASSERT (task->trigger.cmask & QSE_HTTPD_TASK_TRIGGER_READ);*/
task->trigger.cmask |= QSE_HTTPD_TASK_TRIGGER_READABLE;
trigger_fired = 1;
}
if (mask & QSE_HTTPD_MUX_WRITE)
{
/*QSE_ASSERT (task->trigger.cmask & QSE_HTTPD_TASK_TRIGGER_WRITE);*/
task->trigger.cmask |= QSE_HTTPD_TASK_TRIGGER_WRITABLE;
trigger_fired = 1;
}
}
else
{
for (i = 0; i < QSE_COUNTOF(task->trigger.v); i++)
{
if (task->trigger.v[i].handle.i == handle.i) /* TODO: no direct comparision */
{
QSE_ASSERT (task->trigger.v[i].mask & QSE_HTTPD_TASK_TRIGGER_READ);
trigger_fired = 1;
task->trigger.v[i].mask |= QSE_HTTPD_TASK_TRIGGER_READABLE;
}
if (mask & QSE_HTTPD_MUX_WRITE)
{
QSE_ASSERT (task->trigger.v[i].mask & QSE_HTTPD_TASK_TRIGGER_WRITE);
trigger_fired = 1;
task->trigger.v[i].mask |= QSE_HTTPD_TASK_TRIGGER_WRITABLE;
if (handle.i == client->handle.i) client_handle_writable = 1; /* TODO: no direct comparison */
if (mask & QSE_HTTPD_MUX_READ)
{
QSE_ASSERT (task->trigger.v[i].mask & QSE_HTTPD_TASK_TRIGGER_READ);
task->trigger.v[i].mask |= QSE_HTTPD_TASK_TRIGGER_READABLE;
trigger_fired = 1;
}
if (mask & QSE_HTTPD_MUX_WRITE)
{
QSE_ASSERT (task->trigger.v[i].mask & QSE_HTTPD_TASK_TRIGGER_WRITE);
task->trigger.v[i].mask |= QSE_HTTPD_TASK_TRIGGER_WRITABLE;
trigger_fired = 1;
}
}
}
}
if (trigger_fired && !client_handle_writable)
if (trigger_fired && !(task->trigger.cmask & QSE_HTTPD_TASK_TRIGGER_WRITABLE))
{
/* the task is invoked for triggers.
* check if the client handle is writable */
@ -1240,6 +1210,10 @@ static int invoke_client_task (
* performing the actual task */
return 0;
}
/* WRITABLE can be set without WRITE as this is the result of
* the additional writability check. */
task->trigger.cmask |= QSE_HTTPD_TASK_TRIGGER_WRITABLE;
}
n = task->main (httpd, client, task);
@ -1253,7 +1227,7 @@ static int invoke_client_task (
/* update the multiplexer settings */
n = update_mux_for_next_task (httpd, client);
/* reset the task trigger */
/* reset the task trigger remembered */
QSE_MEMSET (&client->trigger, 0, QSE_SIZEOF(client->trigger));
}
else if (n > 0)
@ -1375,16 +1349,9 @@ qse_httpd_task_t* qse_httpd_entask (
}
else if (new_task->prev == QSE_NULL)
{
/* this task is the first task to activate.
*
* the client handle should be in mux for reading at this phase.
* a new task should be invoked at least once regardless of the
* data availablility(read) on the client side. arrange to invoke
* this task so long as the client-side handle is writable as well
* as when data is available for reading. */
/* this task is the first task to activate. */
if (update_mux_for_new_task (httpd, client) <= -1)
if (update_mux_for_next_task (httpd, client) <= -1)
{
/*purge_client (httpd, client);*/
client->status |= CLIENT_BAD;
@ -1641,12 +1608,35 @@ printf ("dns_send.........................\n");
int qse_httpd_activatetasktrigger (qse_httpd_t* httpd, qse_httpd_client_t* client, qse_httpd_task_t* task)
{
int x, org_cmask;
printf ("activate ..$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$..\n");
/* don't do anything if it's active */
if (!(task->trigger.flags & QSE_HTTPD_TASK_TRIGGER_INACTIVE)) return 0;
printf ("activate reakly....\n");
/* when task trigger is inactive, no handle are registered
* into mux. update_mux_for_current_task adds the client handle
* to mux for reading only if writing is not requested explicitly.
* if no data is available for reading, the task can never be
* called after activation. so let's request writing here.
*/
QSE_ASSERT (!(client->status & CLIENT_HANDLE_RW_IN_MUX));
org_cmask = task->trigger.cmask;
task->trigger.cmask |= QSE_HTTPD_TASK_TRIGGER_WRITE;
task->trigger.flags &= ~QSE_HTTPD_TASK_TRIGGER_INACTIVE;
return update_mux_for_current_task (httpd, client, task);
x = update_mux_for_current_task (httpd, client, task);
task->trigger.cmask = org_cmask;
return x;
}
int qse_httpd_inactivatetasktrigger (qse_httpd_t* httpd, qse_httpd_client_t* client, qse_httpd_task_t* task)
{
if (task->trigger.flags & QSE_HTTPD_TASK_TRIGGER_INACTIVE) return 0;
task->trigger.flags |= QSE_HTTPD_TASK_TRIGGER_INACTIVE;
return update_mux_for_current_task (httpd, client, task);
}

View File

@ -143,6 +143,18 @@ qse_httpd_task_t* qse_httpd_entask_nomod (
int keepalive
);
int qse_httpd_activatetasktrigger (
qse_httpd_t* httpd,
qse_httpd_client_t* client,
qse_httpd_task_t* task
);
int qse_httpd_inactivatetasktrigger (
qse_httpd_t* httpd,
qse_httpd_client_t* client,
qse_httpd_task_t* task
);
#ifdef __cplusplus
}
#endif