changed sockets and pipes used in httped to work in non-blocking mode

This commit is contained in:
hyung-hwan 2014-07-25 17:28:20 +00:00
parent 6137df4e86
commit e8a241ed71
10 changed files with 767 additions and 551 deletions

View File

@ -39,7 +39,7 @@ enum qse_pio_flag_t
{
/** enable text based I/O. */
QSE_PIO_TEXT = (1 << 0),
QSE_PIO_IGNOREMBWCERR = (1 << 1),
QSE_PIO_IGNOREMBWCERR = (1 << 1),
QSE_PIO_NOAUTOFLUSH = (1 << 2),
/** execute the command via a system shell
@ -67,7 +67,7 @@ enum qse_pio_flag_t
QSE_PIO_READERR = (1 << 10),
/** redirect stderr to stdout (2>&1, require #QSE_PIO_READOUT) */
QSE_PIO_ERRTOOUT = (1 << 11),
QSE_PIO_ERRTOOUT = (1 << 11),
/** redirect stdout to stderr (1>&2, require #QSE_PIO_READERR) */
QSE_PIO_OUTTOERR = (1 << 12),
@ -92,7 +92,14 @@ enum qse_pio_flag_t
/** return immediately from qse_pio_wait() if a child has not exited */
QSE_PIO_WAITNOBLOCK = (1 << 23),
/** do not wait again if waitpid has been interrupted */
QSE_PIO_WAITNORETRY = (1 << 24)
QSE_PIO_WAITNORETRY = (1 << 24),
/** put stdin to non-blocking mode (only on supported platforms) */
QSE_PIO_INNOBLOCK = (1 << 25),
/** put stdout to non-blocking mode (only on supported platforms)*/
QSE_PIO_OUTNOBLOCK = (1 << 26),
/** put stderr to non-blocking mode (only on supported platforms) */
QSE_PIO_ERRNOBLOCK = (1 << 27)
};
/**

View File

@ -438,6 +438,26 @@ qse_mux_errnum_t qse_mux_geterrnum (qse_mux_t* mux)
int qse_mux_insert (qse_mux_t* mux, const qse_mux_evt_t* evt)
{
#if defined(USE_SELECT)
/* nothing */
#elif defined(USE_KQUEUE)
struct kevent chlist[2];
int count = 0;
#elif defined(USE_EPOLL)
struct epoll_event ev;
#elif defined(__OS2__)
/* nothing */
#else
/* nothing */
#endif
/* sanity check */
if (!(evt->mask & (QSE_MUX_IN | QSE_MUX_OUT)) || evt->hnd < 0)
{
mux->errnum = QSE_MUX_EINVAL;
return -1;
}
#if defined(USE_SELECT)
/* TODO: windows seems to return a pretty high file descriptors
@ -482,9 +502,6 @@ int qse_mux_insert (qse_mux_t* mux, const qse_mux_evt_t* evt)
return 0;
#elif defined(USE_KQUEUE)
struct kevent chlist[2];
int count = 0;
/* TODO: study if it is better to put 'evt' to the udata
* field of chlist? */
@ -502,11 +519,7 @@ int qse_mux_insert (qse_mux_t* mux, const qse_mux_evt_t* evt)
count++;
}
if (count == 0 || evt->hnd < 0)
{
mux->errnum = QSE_MUX_EINVAL;
return -1;
}
QSE_ASSERT (count > 0);
if (evt->hnd >= mux->me.ubound)
{
@ -550,17 +563,12 @@ int qse_mux_insert (qse_mux_t* mux, const qse_mux_evt_t* evt)
return 0;
#elif defined(USE_EPOLL)
struct epoll_event ev;
QSE_MEMSET (&ev, 0, QSE_SIZEOF(ev));
if (evt->mask & QSE_MUX_IN) ev.events |= EPOLLIN;
if (evt->mask & QSE_MUX_OUT) ev.events |= EPOLLOUT;
if (ev.events == 0 || evt->hnd < 0)
{
mux->errnum = QSE_MUX_EINVAL;
return -1;
}
QSE_ASSERT (ev.events != 0);
if (evt->hnd >= mux->me.ubound)
{
@ -937,13 +945,13 @@ int qse_mux_poll (qse_mux_t* mux, const qse_ntime_t* tmout)
if (mux->ee.ptr[i].events & EPOLLIN) xevt.mask |= QSE_MUX_IN;
if (mux->ee.ptr[i].events & EPOLLOUT) xevt.mask |= QSE_MUX_OUT;
if (mux->ee.ptr[i].events & EPOLLHUP)
if (mux->ee.ptr[i].events & (EPOLLHUP | EPOLLERR))
{
if (evt->mask & QSE_MUX_IN) xevt.mask |= QSE_MUX_IN;
if (evt->mask & QSE_MUX_OUT) xevt.mask |= QSE_MUX_OUT;
}
mux->evtfun (mux, &xevt);
if (xevt.mask > 0) mux->evtfun (mux, &xevt);
}
return nfds;

View File

@ -429,6 +429,22 @@ static int get_highest_fd (void)
#endif
static int set_pipe_nonblock (qse_pio_t* pio, qse_pio_hnd_t fd, int enabled)
{
#if defined(O_NONBLOCK)
int flag = QSE_FCNTL (fd, F_GETFL, 0);
if (flag >= 0) flag = QSE_FCNTL (fd, F_SETFL, (enabled? (flag | O_NONBLOCK): (flag & ~O_NONBLOCK)));
if (flag <= -1) pio->errnum = syserr_to_errnum (errno);
return flag;
#else
pio->errnum = QSE_PIO_ENOIMPL;
return -1;
#endif
}
int qse_pio_init (
qse_pio_t* pio, qse_mmgr_t* mmgr, const qse_char_t* cmd,
qse_env_t* env, int flags)
@ -1785,6 +1801,13 @@ create_process:
#endif
if (((flags & QSE_PIO_INNOBLOCK) && set_pipe_nonblock(pio, handle[1], 1) <= -1) ||
((flags & QSE_PIO_OUTNOBLOCK) && set_pipe_nonblock(pio, handle[2], 1) <= -1) ||
((flags & QSE_PIO_ERRNOBLOCK) && set_pipe_nobnlock(pio, handle[4], 1) <= -1))
{
goto oops;
}
/* store back references */
pio->pin[QSE_PIO_IN].self = pio;
pio->pin[QSE_PIO_OUT].self = pio;
@ -1795,6 +1818,7 @@ create_process:
pio->pin[QSE_PIO_OUT].handle = handle[2];
pio->pin[QSE_PIO_ERR].handle = handle[4];
if (flags & QSE_PIO_TEXT)
{
int topt = 0;
@ -1882,17 +1906,17 @@ oops:
}
for (i = minidx; i < maxidx; i++)
{
if (handle[i] != QSE_PIO_HND_NIL) QSE_CLOSE (handle[i]);
if (handle[i] != QSE_PIO_HND_NIL) QSE_CLOSE (handle[i]);
}
#elif defined(QSE_SYSCALL0) && defined(SYS_vfork)
for (i = minidx; i < maxidx; i++)
{
if (handle[i] != QSE_PIO_HND_NIL) QSE_CLOSE (handle[i]);
if (handle[i] != QSE_PIO_HND_NIL) QSE_CLOSE (handle[i]);
}
#else
for (i = minidx; i < maxidx; i++)
{
if (handle[i] != QSE_PIO_HND_NIL) QSE_CLOSE (handle[i]);
if (handle[i] != QSE_PIO_HND_NIL) QSE_CLOSE (handle[i]);
}
#endif

View File

@ -25,6 +25,16 @@
#include <qse/cmn/fmt.h>
#include <qse/cmn/path.h>
#if defined(_WIN32)
/* nothing */
#elif defined(__OS2__)
/* nothing */
#elif defined(__DOS__)
/* nothing */
#else
# include "../cmn/syscall.h"
#endif
#include <stdio.h> /* TODO: remove this */
#if defined(_MSC_VER) || defined(__BORLANDC__) || (defined(__WATCOMC__) && (__WATCOMC__ < 1200))
# define snprintf _snprintf
@ -78,7 +88,7 @@ struct task_cgi_t
int resflags;
qse_mbs_t* res;
qse_mchar_t* res_ptr;
qse_size_t res_left;
qse_size_t res_left;
/* content-length that CGI returned */
qse_size_t script_output_length; /* TODO: a script maybe be able to output more than the maximum value of qse_size_t */
@ -104,6 +114,8 @@ struct cgi_client_req_hdr_ctx_t
qse_env_t* env;
};
static int cgi_capture_client_header (
qse_htre_t* req, const qse_mchar_t* key, const qse_htre_hdrval_t* val, void* ctx)
{
@ -637,57 +649,50 @@ static void cgi_forward_client_input_to_script (
/* normal forwarding */
qse_ssize_t n;
if (writable) goto forward;
n = httpd->opt.scb.mux.writable (
httpd, qse_pio_gethandleasubi (&cgi->pio, QSE_PIO_IN), 0);
if (n >= 1)
{
forward:
/* writable */
n = qse_pio_write (
&cgi->pio, QSE_PIO_IN,
QSE_MBS_PTR(cgi->reqfwdbuf),
QSE_MBS_LEN(cgi->reqfwdbuf)
);
if (n > 0)
{
/* TODO: improve performance.. instead of copying the remaing part
to the head all the time.. grow the buffer to a certain limit. */
qse_mbs_del (cgi->reqfwdbuf, 0, n);
if (QSE_MBS_LEN(cgi->reqfwdbuf) <= 0)
{
if (cgi->reqflags & CGI_REQ_GOTALL) goto done;
else task->trigger.v[1].mask = 0; /* pipe output to child */
}
}
}
n = qse_pio_write (
&cgi->pio, QSE_PIO_IN,
QSE_MBS_PTR(cgi->reqfwdbuf),
QSE_MBS_LEN(cgi->reqfwdbuf)
);
if (n <= -1)
{
if (cgi->httpd->opt.trait & QSE_HTTPD_LOGACT)
log_cgi_script_error (cgi, QSE_MT("cgi pio write error - "));
cgi->reqflags |= CGI_REQ_FWDERR;
qse_mbs_clear (cgi->reqfwdbuf);
if (!(cgi->reqflags & CGI_REQ_GOTALL))
if (qse_pio_geterrnum(&cgi->pio) != QSE_PIO_EAGAIN)
{
QSE_ASSERT (cgi->req);
qse_htre_discardcontent (cgi->req);
if (cgi->httpd->opt.trait & QSE_HTTPD_LOGACT)
log_cgi_script_error (cgi, QSE_MT("cgi pio write error - "));
/* NOTE:
* this qse_htre_discardcontent() invokes
* cgi_snatch_client_input()
* which sets cgi->req to QSE_NULL
* and toggles on CGI_REQ_GOTALL. */
QSE_ASSERT (!cgi->req);
QSE_ASSERT (cgi->reqflags & CGI_REQ_GOTALL);
cgi->reqflags |= CGI_REQ_FWDERR;
qse_mbs_clear (cgi->reqfwdbuf);
if (!(cgi->reqflags & CGI_REQ_GOTALL))
{
QSE_ASSERT (cgi->req);
qse_htre_discardcontent (cgi->req);
/* NOTE:
* this qse_htre_discardcontent() invokes
* cgi_snatch_client_input()
* which sets cgi->req to QSE_NULL
* and toggles on CGI_REQ_GOTALL. */
QSE_ASSERT (!cgi->req);
QSE_ASSERT (cgi->reqflags & CGI_REQ_GOTALL);
}
/* 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 */
}
}
else if (n > 0)
{
/* TODO: improve performance.. instead of copying the remaing part
to the head all the time.. grow the buffer to a certain limit. */
qse_mbs_del (cgi->reqfwdbuf, 0, n);
if (QSE_MBS_LEN(cgi->reqfwdbuf) <= 0)
{
if (cgi->reqflags & CGI_REQ_GOTALL) goto done;
else task->trigger.v[1].mask = 0; /* pipe output to child */
}
/* 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 */
}
}
}
@ -953,10 +958,18 @@ static QSE_INLINE qse_ssize_t cgi_read_script_output_to_buffer (
&cgi->buf[cgi->buflen],
QSE_SIZEOF(cgi->buf) - cgi->buflen
);
if (n > 0) cgi->buflen += n;
if (n <= -1)
{
if (qse_pio_geterrnum(&cgi->pio) != QSE_PIO_EAGAIN)
{
if (cgi->httpd->opt.trait & QSE_HTTPD_LOGACT)
log_cgi_script_error (cgi, QSE_MT("cgi pio read error - "));
return -1;
}
if (n <= -1 && cgi->httpd->opt.trait & QSE_HTTPD_LOGACT)
log_cgi_script_error (cgi, QSE_MT("cgi pio read error - "));
n = -999;
}
else if (n > 0) cgi->buflen += n;
return n;
}
@ -966,16 +979,25 @@ static QSE_INLINE qse_ssize_t cgi_write_script_output_to_client (
{
qse_ssize_t n;
QSE_ASSERT (cgi->buflen > 0);
httpd->errnum = QSE_HTTPD_ENOERR;
n = httpd->opt.scb.client.send (httpd, client, cgi->buf, cgi->buflen);
if (n > 0)
if (n <= -1)
{
if (httpd->errnum != QSE_HTTPD_EAGAIN)
{
if (cgi->httpd->opt.trait & QSE_HTTPD_LOGACT)
log_cgi_script_error (cgi, QSE_MT("cgi write error to client - "));
}
else n = 0;
}
else if (n > 0)
{
QSE_MEMCPY (&cgi->buf[0], &cgi->buf[n], cgi->buflen - n);
cgi->buflen -= n;
}
if (n <= -1 && cgi->httpd->opt.trait & QSE_HTTPD_LOGACT)
log_cgi_script_error (cgi, QSE_MT("cgi write error to client - "));
return n;
}
@ -998,16 +1020,12 @@ static int task_main_cgi_5 (
}
}
if (/*!(task->trigger.cmask & QSE_HTTPD_TASK_TRIGGER_WRITE) ||*/
(task->trigger.cmask & QSE_HTTPD_TASK_TRIGGER_WRITABLE))
if (/*(task->trigger.cmask & QSE_HTTPD_TASK_TRIGGER_WRITABLE) && */ cgi->buflen > 0)
{
if (cgi->buflen > 0)
if (cgi_write_script_output_to_client (httpd, client, cgi) <= -1)
{
if (cgi_write_script_output_to_client (httpd, client, cgi) <= -1)
{
/* can't return internal server error any more... */
return -1;
}
/* can't return internal server error any more... */
return -1;
}
}
@ -1042,9 +1060,21 @@ static int task_main_cgi_4_nph (
{
if (cgi->buflen < QSE_SIZEOF(cgi->buf))
{
n = cgi_read_script_output_to_buffer (httpd, client, cgi);
if (n <= -1) return -1; /* TODO: logging */
if (n == 0)
n = qse_pio_read (
&cgi->pio, QSE_PIO_OUT,
&cgi->buf[cgi->buflen],
QSE_SIZEOF(cgi->buf) - cgi->buflen
);
if (n <= -1)
{
if (qse_pio_geterrnum(&cgi->pio) != QSE_PIO_EAGAIN)
{
if (cgi->httpd->opt.trait & QSE_HTTPD_LOGACT)
log_cgi_script_error (cgi, QSE_MT("cgi pio read error - "));
return -1;
}
}
else if (n == 0)
{
/* switch to the next phase */
task->main = task_main_cgi_5;
@ -1052,10 +1082,10 @@ static int task_main_cgi_4_nph (
task->trigger.cmask |= QSE_HTTPD_TASK_TRIGGER_WRITE;
return 1;
}
else cgi->buflen += n;
}
QSE_ASSERT (cgi->buflen > 0);
if (cgi_write_script_output_to_client (httpd, client, cgi) <= -1) return -1;
if (cgi->buflen > 0 && cgi_write_script_output_to_client (httpd, client, cgi) <= -1) return -1;
}
return 1;
@ -1110,11 +1140,14 @@ printf ("task_main_cgi_4 trigger[0].mask=%d trigger[1].mask=%d cmask=%d\n",
);
if (n <= -1)
{
if (cgi->httpd->opt.trait & QSE_HTTPD_LOGACT)
log_cgi_script_error (cgi, QSE_MT("cgi pio read error - "));
return -1;
if (qse_pio_geterrnum(&cgi->pio) != QSE_PIO_EAGAIN)
{
if (cgi->httpd->opt.trait & QSE_HTTPD_LOGACT)
log_cgi_script_error (cgi, QSE_MT("cgi pio read error - "));
return -1;
}
}
if (n == 0)
else if (n == 0)
{
/* the cgi script closed the output */
cgi->buf[cgi->buflen++] = QSE_MT('0');
@ -1128,34 +1161,36 @@ printf ("task_main_cgi_4 trigger[0].mask=%d trigger[1].mask=%d cmask=%d\n",
task->trigger.cmask |= QSE_HTTPD_TASK_TRIGGER_WRITE;
return 1;
}
/* set the chunk length. if the length string is less
* than 4 digits, the right side of the string is filled
* with space letters. for example, the chunk length line
* for the length 10 will be "A \r\n". */
cgi->buflen += qse_fmtuintmaxtombs (
&cgi->buf[cgi->buflen], CHLEN_RESERVE - 2 + 1,
n, 16 | QSE_FMTUINTMAXTOMBS_UPPERCASE | QSE_FMTUINTMAXTOMBS_FILLRIGHT,
-1, QSE_MT(' '), QSE_NULL
);
cgi->buf[cgi->buflen++] = QSE_MT('\r');
cgi->buf[cgi->buflen++] = QSE_MT('\n');
cgi->buflen += n; /* +n for the data read above */
/* set the trailing CR & LF for a chunk */
cgi->buf[cgi->buflen++] = QSE_MT('\r');
cgi->buf[cgi->buflen++] = QSE_MT('\n');
cgi->script_output_received += n;
if ((cgi->resflags & CGI_RES_SCRIPT_LENGTH) &&
cgi->script_output_received > cgi->script_output_length)
else
{
/* cgi returning too much data... something is wrong in CGI */
if (cgi->httpd->opt.trait & QSE_HTTPD_LOGACT)
log_cgi_script_error (cgi, QSE_MT("cgi redundant output - "));
return -1;
/* set the chunk length. if the length string is less
* than 4 digits, the right side of the string is filled
* with space letters. for example, the chunk length line
* for the length 10 will be "A \r\n". */
cgi->buflen += qse_fmtuintmaxtombs (
&cgi->buf[cgi->buflen], CHLEN_RESERVE - 2 + 1,
n, 16 | QSE_FMTUINTMAXTOMBS_UPPERCASE | QSE_FMTUINTMAXTOMBS_FILLRIGHT,
-1, QSE_MT(' '), QSE_NULL
);
cgi->buf[cgi->buflen++] = QSE_MT('\r');
cgi->buf[cgi->buflen++] = QSE_MT('\n');
cgi->buflen += n; /* +n for the data read above */
/* set the trailing CR & LF for a chunk */
cgi->buf[cgi->buflen++] = QSE_MT('\r');
cgi->buf[cgi->buflen++] = QSE_MT('\n');
cgi->script_output_received += n;
if ((cgi->resflags & CGI_RES_SCRIPT_LENGTH) &&
cgi->script_output_received > cgi->script_output_length)
{
/* cgi returning too much data... something is wrong in CGI */
if (cgi->httpd->opt.trait & QSE_HTTPD_LOGACT)
log_cgi_script_error (cgi, QSE_MT("cgi redundant output - "));
return -1;
}
}
}
}
@ -1163,9 +1198,21 @@ printf ("task_main_cgi_4 trigger[0].mask=%d trigger[1].mask=%d cmask=%d\n",
{
if (cgi->buflen < QSE_SIZEOF(cgi->buf))
{
n = cgi_read_script_output_to_buffer (httpd, client, cgi);
if (n <= -1) return -1; /* TODO: logging */
if (n == 0)
n = qse_pio_read (
&cgi->pio, QSE_PIO_OUT,
&cgi->buf[cgi->buflen],
QSE_SIZEOF(cgi->buf) - cgi->buflen
);
if (n <= -1)
{
if (qse_pio_geterrnum(&cgi->pio) != QSE_PIO_EAGAIN)
{
if (cgi->httpd->opt.trait & QSE_HTTPD_LOGACT)
log_cgi_script_error (cgi, QSE_MT("cgi pio read error - "));
return -1;
}
}
else if (n == 0)
{
/* switch to the next phase */
task->main = task_main_cgi_5;
@ -1173,15 +1220,17 @@ printf ("task_main_cgi_4 trigger[0].mask=%d trigger[1].mask=%d cmask=%d\n",
task->trigger.cmask |= QSE_HTTPD_TASK_TRIGGER_WRITE;
return 1;
}
cgi->script_output_received += n;
if ((cgi->resflags & CGI_RES_SCRIPT_LENGTH) &&
cgi->script_output_received > cgi->script_output_length)
else
{
/* cgi returning too much data... something is wrong in CGI */
if (cgi->httpd->opt.trait & QSE_HTTPD_LOGACT)
log_cgi_script_error (cgi, QSE_MT("cgi redundant output - "));
return -1;
cgi->script_output_received += n;
if ((cgi->resflags & CGI_RES_SCRIPT_LENGTH) &&
cgi->script_output_received > cgi->script_output_length)
{
/* cgi returning too much data... something is wrong in CGI */
if (cgi->httpd->opt.trait & QSE_HTTPD_LOGACT)
log_cgi_script_error (cgi, QSE_MT("cgi redundant output - "));
return -1;
}
}
}
}
@ -1189,8 +1238,7 @@ printf ("task_main_cgi_4 trigger[0].mask=%d trigger[1].mask=%d cmask=%d\n",
/* the main loop invokes the task function only if the client
* side is writable. it should be safe to write whenever
* this task function is called. */
QSE_ASSERT (cgi->buflen > 0);
if (cgi_write_script_output_to_client (httpd, client, cgi) <= -1) return -1;
if (cgi->buflen > 0 && cgi_write_script_output_to_client (httpd, client, cgi) <= -1) return -1;
}
return 1;
@ -1226,51 +1274,52 @@ printf ("task_main_cgi_3 trigger[0].mask=%d trigger[1].mask=%d cmask=%d\n",
/* send the partial reponse received with the initial line and headers
* so long as the client-side handle is writable... */
if (/*!(task->trigger.cmask & QSE_HTTPD_TASK_TRIGGER_WRITE) ||*/
(task->trigger.cmask & QSE_HTTPD_TASK_TRIGGER_WRITABLE))
if (/*(task->trigger.cmask & QSE_HTTPD_TASK_TRIGGER_WRITABLE) && */ cgi->res_left > 0)
{
count = MAX_SEND_SIZE;
if (count >= cgi->res_left) count = cgi->res_left;
count = cgi->res_left;
if (count >= MAX_SEND_SIZE) count = MAX_SEND_SIZE;
if (count > 0)
httpd->errnum = QSE_HTTPD_ENOERR;
n = httpd->opt.scb.client.send (httpd, client, cgi->res_ptr, count);
if (n <= -1)
{
n = httpd->opt.scb.client.send (httpd, client, cgi->res_ptr, count);
if (n <= -1)
if (httpd->errnum != QSE_HTTPD_EAGAIN)
{
if (cgi->httpd->opt.trait & QSE_HTTPD_LOGACT)
log_cgi_script_error (cgi, QSE_MT("cgi initial write error to client - "));
return -1;
}
}
else if (n > 0)
{
cgi->res_ptr += n;
cgi->res_left -= n;
}
if (cgi->res_left <= 0)
{
qse_mbs_clear (cgi->res);
if ((cgi->resflags & CGI_RES_SCRIPT_LENGTH) &&
cgi->script_output_received >= cgi->script_output_length)
if (cgi->res_left <= 0)
{
/* 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.
* one potential side-effect is that the script
* can be killed prematurely if it wants to do
* something extra after having done so.
* however, a CGI script shouln't do that... */
task->main = task_main_cgi_5;
task->trigger.cmask |= QSE_HTTPD_TASK_TRIGGER_WRITE;
}
else
{
task->main = task_main_cgi_4;
task->trigger.cmask &= ~QSE_HTTPD_TASK_TRIGGER_WRITE;
}
return 1;
}
qse_mbs_clear (cgi->res);
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.
* one potential side-effect is that the script
* can be killed prematurely if it wants to do
* something extra after having done so.
* however, a CGI script shouln't do that... */
task->main = task_main_cgi_5;
task->trigger.cmask |= QSE_HTTPD_TASK_TRIGGER_WRITE;
}
else
{
task->main = task_main_cgi_4;
task->trigger.cmask &= ~QSE_HTTPD_TASK_TRIGGER_WRITE;
}
return 1;
}
}
}
return 1; /* more work to do */
@ -1320,12 +1369,15 @@ printf ("task_main_cgi_2 trigger[0].mask=%d trigger[1].mask=%d cmask=%d\n",
);
if (n <= -1)
{
/* can't return internal server error any more... */
if (cgi->httpd->opt.trait & QSE_HTTPD_LOGACT)
log_cgi_script_error (cgi, QSE_MT("cgi pio read error - "));
goto oops;
if (qse_pio_geterrnum(&cgi->pio) != QSE_PIO_EAGAIN)
{
/* can't return internal server error any more... */
if (cgi->httpd->opt.trait & QSE_HTTPD_LOGACT)
log_cgi_script_error (cgi, QSE_MT("cgi pio read error - "));
goto oops;
}
}
if (n == 0)
else if (n == 0)
{
/* end of output from cgi before it has seen a header.
* the cgi script must be crooked. */
@ -1333,16 +1385,22 @@ printf ("task_main_cgi_2 trigger[0].mask=%d trigger[1].mask=%d cmask=%d\n",
log_cgi_script_error (cgi, QSE_MT("cgi premature eof - "));
goto oops;
}
cgi->buflen += n;
if (qse_htrd_feed (cgi->script_htrd, cgi->buf, cgi->buflen) <= -1)
else
{
if (cgi->httpd->opt.trait & QSE_HTTPD_LOGACT)
log_cgi_script_error (cgi, QSE_MT("cgi feed error - "));
goto oops;
cgi->buflen += n;
}
cgi->buflen = 0;
if (cgi->buflen > 0)
{
if (qse_htrd_feed (cgi->script_htrd, cgi->buf, cgi->buflen) <= -1)
{
if (cgi->httpd->opt.trait & QSE_HTTPD_LOGACT)
log_cgi_script_error (cgi, QSE_MT("cgi feed error - "));
goto oops;
}
cgi->buflen = 0;
}
if (QSE_MBS_LEN(cgi->res) > 0)
{
@ -1410,7 +1468,11 @@ static int task_main_cgi (
if (cgi->res == QSE_NULL) goto oops;
}
pio_options = QSE_PIO_READOUT | QSE_PIO_WRITEIN | QSE_PIO_MBSCMD;
/* <<WARNING>>
* QSE_PIO_INNOBLOCK and QSE_PIO_OUTNONBLOCK are not supported
* on non-unix/linux platforms. so the CGI task can only be
* used on unix/linux platforms */
pio_options = QSE_PIO_READOUT | QSE_PIO_WRITEIN | QSE_PIO_MBSCMD | QSE_PIO_INNOBLOCK | QSE_PIO_OUTNOBLOCK;
if (httpd->opt.trait & QSE_HTTPD_CGIERRTONUL)
pio_options |= QSE_PIO_ERRTONUL;
else
@ -1446,8 +1508,9 @@ static int task_main_cgi (
goto oops;
}
cgi->pio_inited = 1;
/* set the trigger that the main loop can use this
* handle for multiplexing
*

View File

@ -93,12 +93,19 @@ static int task_main_getfseg (
count = MAX_SEND_SIZE;
if (count >= ctx->left) count = ctx->left;
httpd->errnum = QSE_HTTPD_ENOERR;
n = httpd->opt.scb.client.sendfile (
httpd, client, ctx->handle, &ctx->offset, count);
if (n <= -1)
{
/* HANDLE EGAIN specially??? */
return -1; /* TODO: any logging */
if (httpd->errnum != QSE_HTTPD_EAGAIN)
{
/* TODO: logging */
return -1;
}
goto more_work;
}
if (n == 0 && count > 0)
@ -108,12 +115,13 @@ static int task_main_getfseg (
* So let's return an error here so that the main loop abort
* the connection. */
/* TODO: any logging....??? */
return -1;
return -1;
}
ctx->left -= n;
if (ctx->left <= 0) return 0;
more_work:
return 1; /* more work to do */
}

View File

@ -658,8 +658,7 @@ static qse_htrd_recbs_t proxy_peer_htrd_cbs =
proxy_htrd_handle_peer_output
};
static void proxy_forward_client_input_to_peer (
qse_httpd_t* httpd, qse_httpd_task_t* task, int writable)
static void proxy_forward_client_input_to_peer (qse_httpd_t* httpd, qse_httpd_task_t* task)
{
task_proxy_t* proxy = (task_proxy_t*)task->ctx;
@ -680,56 +679,48 @@ static void proxy_forward_client_input_to_peer (
/* normal forwarding */
qse_ssize_t n;
if (writable) goto forward;
n = httpd->opt.scb.mux.writable (httpd, proxy->peer.handle, 0);
#if 0
if (n == 0) qse_printf (QSE_T("PROXY FORWARD: @@@@@@@@@NOT WRITABLE\n"));
#endif
if (n >= 1)
{
forward:
/* writable */
#if 0
qse_printf (QSE_T("PROXY FORWARD: @@@@@@@@@@WRITING[%.*hs]\n"),
(int)QSE_MBS_LEN(proxy->reqfwdbuf),
QSE_MBS_PTR(proxy->reqfwdbuf));
#endif
n = httpd->opt.scb.peer.send (
httpd, &proxy->peer,
QSE_MBS_PTR(proxy->reqfwdbuf),
QSE_MBS_LEN(proxy->reqfwdbuf)
);
/* TODO: improve performance.. instead of copying the remaing part
to the head all the time.. grow the buffer to a certain limit. */
if (n > 0)
{
qse_mbs_del (proxy->reqfwdbuf, 0, n);
if (QSE_MBS_LEN(proxy->reqfwdbuf) <= 0)
{
if (proxy->req == QSE_NULL) goto done;
else task->trigger.v[0].mask &= ~QSE_HTTPD_TASK_TRIGGER_WRITE;
}
}
}
httpd->errnum = QSE_HTTPD_ENOERR;
n = httpd->opt.scb.peer.send (
httpd, &proxy->peer,
QSE_MBS_PTR(proxy->reqfwdbuf),
QSE_MBS_LEN(proxy->reqfwdbuf)
);
if (n <= -1)
{
if (httpd->opt.trait & QSE_HTTPD_LOGACT)
log_proxy_error (proxy, "proxy send-to-peer error - ");
proxy->reqflags |= PROXY_REQ_FWDERR;
qse_mbs_clear (proxy->reqfwdbuf);
if (proxy->req)
if (httpd->errnum != QSE_HTTPD_EAGAIN)
{
qse_htre_discardcontent (proxy->req);
/* NOTE: proxy->req may be set to QSE_NULL
* in proxy_snatch_client_input() triggered by
* qse_htre_discardcontent() */
}
if (httpd->opt.trait & QSE_HTTPD_LOGACT)
log_proxy_error (proxy, "proxy send-to-peer error - ");
task->trigger.v[0].mask &= ~QSE_HTTPD_TASK_TRIGGER_WRITE; /* peer */
proxy->reqflags |= PROXY_REQ_FWDERR;
qse_mbs_clear (proxy->reqfwdbuf);
if (proxy->req)
{
qse_htre_discardcontent (proxy->req);
/* NOTE: proxy->req may be set to QSE_NULL
* in proxy_snatch_client_input() triggered by
* qse_htre_discardcontent() */
}
task->trigger.v[0].mask &= ~QSE_HTTPD_TASK_TRIGGER_WRITE; /* peer */
}
}
else if (n > 0)
{
/* TODO: improve performance.. instead of copying the remaing part
to the head all the time.. grow the buffer to a certain limit. */
qse_mbs_del (proxy->reqfwdbuf, 0, n);
if (QSE_MBS_LEN(proxy->reqfwdbuf) <= 0)
{
if (proxy->req == QSE_NULL) goto done;
else task->trigger.v[0].mask &= ~QSE_HTTPD_TASK_TRIGGER_WRITE;
}
}
}
}
@ -1038,6 +1029,7 @@ printf ("task_main_proxy_5 trigger[0].mask=%d trigger[1].mask=%d trigger[2].mask
task->trigger.v[0].mask, task->trigger.v[1].mask, task->trigger.cmask);
#endif
#if 0
if (task->trigger.cmask & QSE_HTTPD_TASK_TRIGGER_READABLE)
{
/* if the client side is readable */
@ -1048,23 +1040,30 @@ printf ("task_main_proxy_5 trigger[0].mask=%d trigger[1].mask=%d trigger[2].mask
/* if the peer side is writable while the client side is not readable*/
proxy_forward_client_input_to_peer (httpd, task, 1);
}
#endif
proxy_forward_client_input_to_peer (httpd, task);
if (/*!(task->trigger.cmask & QSE_HTTPD_TASK_TRIGGER_WRITE) ||*/
(task->trigger.cmask & QSE_HTTPD_TASK_TRIGGER_WRITABLE))
if (/*(task->trigger.cmask & QSE_HTTPD_TASK_TRIGGER_WRITABLE) && */ proxy->buflen > 0)
{
if (proxy->buflen > 0)
{
/* TODO: check if proxy outputs more than content-length if it is set... */
/* wrote to the client socket as long as there's something to
* write. it's safe to do so as the socket is non-blocking.
* i commented out the check in the 'if' condition above */
n = httpd->opt.scb.client.send (httpd, client, proxy->buf, proxy->buflen);
if (n <= -1)
/* TODO: check if proxy outputs more than content-length if it is set... */
httpd->errnum = QSE_HTTPD_ENOERR;
n = httpd->opt.scb.client.send (httpd, client, proxy->buf, proxy->buflen);
if (n <= -1)
{
if (httpd->errnum != QSE_HTTPD_EAGAIN)
{
/* can't return internal server error any more... */
if (httpd->opt.trait & QSE_HTTPD_LOGACT)
log_proxy_error (proxy, "proxy send-to-client error - ");
return -1;
}
}
else if (n > 0)
{
QSE_MEMCPY (&proxy->buf[0], &proxy->buf[n], proxy->buflen - n);
proxy->buflen -= n;
}
@ -1087,6 +1086,8 @@ printf ("task_main_proxy_4 trigger[0].mask=%d trigger[1].mask=%d trigger[2].mask
task->trigger.v[0].mask, task->trigger.v[1].mask, task->trigger.cmask);
#endif
proxy_forward_client_input_to_peer (httpd, task);
/*
if (task->trigger.cmask & QSE_HTTPD_TASK_TRIGGER_READABLE)
{
proxy_forward_client_input_to_peer (httpd, task, 0);
@ -1095,64 +1096,69 @@ printf ("task_main_proxy_4 trigger[0].mask=%d trigger[1].mask=%d trigger[2].mask
{
proxy_forward_client_input_to_peer (httpd, task, 1);
}
*/
if (task->trigger.v[0].mask & QSE_HTTPD_TASK_TRIGGER_READABLE)
if ((task->trigger.v[0].mask & QSE_HTTPD_TASK_TRIGGER_READABLE) &&
proxy->buflen < QSE_SIZEOF(proxy->buf))
{
qse_ssize_t n;
if (proxy->buflen < QSE_SIZEOF(proxy->buf))
/* reading from the peer */
httpd->errnum = QSE_HTTPD_ENOERR;
n = httpd->opt.scb.peer.recv (
httpd, &proxy->peer,
&proxy->buf[proxy->buflen],
QSE_SIZEOF(proxy->buf) - proxy->buflen
);
if (n <= -1)
{
/* reading from the peer */
httpd->errnum = QSE_HTTPD_ENOERR;
n = httpd->opt.scb.peer.recv (
httpd, &proxy->peer,
&proxy->buf[proxy->buflen],
QSE_SIZEOF(proxy->buf) - proxy->buflen
);
if (n <= -1)
/* can't return internal server error any more... */
if (httpd->errnum != QSE_HTTPD_EAGAIN)
{
/* can't return internal server error any more... */
if (httpd->opt.trait & QSE_HTTPD_LOGACT)
log_proxy_error (proxy, "proxy recv-from-peer error - ");
return -1;
}
if (n == 0)
/* carry on as if recv was't called at all */
}
else if (n == 0)
{
/* peer closed connection */
if (proxy->resflags & PROXY_RES_PEER_LENGTH)
{
/* peer closed connection */
if (proxy->resflags & PROXY_RES_PEER_LENGTH)
QSE_ASSERT (!(proxy->flags & PROXY_RAW));
if (proxy->peer_output_received < proxy->peer_output_length)
{
QSE_ASSERT (!(proxy->flags & PROXY_RAW));
if (proxy->peer_output_received < proxy->peer_output_length)
{
if (httpd->opt.trait & QSE_HTTPD_LOGACT)
log_proxy_error (proxy, "proxy premature eof - ");
return -1;
}
if (httpd->opt.trait & QSE_HTTPD_LOGACT)
log_proxy_error (proxy, "proxy premature eof - ");
return -1;
}
task->main = task_main_proxy_5;
/* nothing to read from peer. set the mask to 0 */
task->trigger.v[0].mask = 0;
/* arrange to be called if the client side is writable */
task->trigger.cmask |= QSE_HTTPD_TASK_TRIGGER_WRITE;
if (proxy->flags & PROXY_RAW)
{
/* peer connection has been closed.
* so no more forwarding from the client to the peer
* is possible. get rid of the content callback on the
* client side. */
qse_htre_unsetconcb (proxy->req);
proxy->req = QSE_NULL;
}
return 1;
}
task->main = task_main_proxy_5;
/* nothing to read from peer. set the mask to 0 */
task->trigger.v[0].mask = 0;
/* arrange to be called if the client side is writable */
task->trigger.cmask |= QSE_HTTPD_TASK_TRIGGER_WRITE;
if (proxy->flags & PROXY_RAW)
{
/* peer connection has been closed.
* so no more forwarding from the client to the peer
* is possible. get rid of the content callback on the
* client side. */
qse_htre_unsetconcb (proxy->req);
proxy->req = QSE_NULL;
}
return 1;
}
else
{
proxy->buflen += n;
proxy->peer_output_received += n;
@ -1177,21 +1183,33 @@ printf ("task_main_proxy_4 trigger[0].mask=%d trigger[1].mask=%d trigger[2].mask
}
}
}
}
if (proxy->buflen)
{
/* the main loop invokes the task function only if the client
* side is writable. it should be safe to write whenever
* this task function is called. */
* this task function is called. even if it's not writable,
* it should still be ok as the client socket is non-blocking. */
qse_ssize_t n;
httpd->errnum = QSE_HTTPD_ENOERR;
n = httpd->opt.scb.client.send (httpd, client, proxy->buf, proxy->buflen);
if (n <= -1)
{
/* can't return internal server error any more... */
if (httpd->opt.trait & QSE_HTTPD_LOGACT)
log_proxy_error (proxy, "proxy send-to-client error - ");
return -1;
if (httpd->errnum != QSE_HTTPD_EAGAIN)
{
/* can't return internal server error any more... */
if (httpd->opt.trait & QSE_HTTPD_LOGACT)
log_proxy_error (proxy, "proxy send-to-client error - ");
return -1;
}
}
else if (n > 0)
{
QSE_MEMCPY (&proxy->buf[0], &proxy->buf[n], proxy->buflen - n);
proxy->buflen -= n;
}
QSE_MEMCPY (&proxy->buf[0], &proxy->buf[n], proxy->buflen - n);
proxy->buflen -= n;
}
return 1;
@ -1212,6 +1230,8 @@ qse_printf (QSE_T("task_main_proxy_3 trigger[0].mask=%d trigger[1].mask=%d trigg
task->trigger.v[0].mask, task->trigger.v[1].mask, task->trigger.cmask);
#endif
proxy_forward_client_input_to_peer (httpd, task);
/*
if (task->trigger.cmask & QSE_HTTPD_TASK_TRIGGER_READABLE)
{
proxy_forward_client_input_to_peer (httpd, task, 0);
@ -1220,60 +1240,68 @@ 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.cmask & QSE_HTTPD_TASK_TRIGGER_WRITE) ||*/
(task->trigger.cmask & QSE_HTTPD_TASK_TRIGGER_WRITABLE))
if (/*(task->trigger.cmask & QSE_HTTPD_TASK_TRIGGER_WRITABLE) &&*/ proxy->res_pending > 0)
{
/* the client socket is non-blocking. so attempt to send
* so long as there's something to send regardless of writability
* of the client socket. see the check commented out in the 'if'
* condition above.*/
qse_ssize_t n;
qse_size_t count;
count = proxy->res_pending;
if (count > MAX_SEND_SIZE) count = MAX_SEND_SIZE;
if (count > 0)
httpd->errnum = QSE_HTTPD_ENOERR;
n = httpd->opt.scb.client.send (
httpd, client,
&QSE_MBS_CHAR(proxy->res,proxy->res_consumed),
count
);
if (n <= -1)
{
n = httpd->opt.scb.client.send (
httpd, client,
&QSE_MBS_CHAR(proxy->res,proxy->res_consumed),
count
);
if (n <= -1)
if (httpd->errnum != QSE_HTTPD_EAGAIN)
{
if (httpd->opt.trait & QSE_HTTPD_LOGACT)
log_proxy_error (proxy, "proxy send-to-client error - ");
return -1;
}
}
else if (n > 0)
{
proxy->resflags |= PROXY_RES_EVER_SENTBACK;
proxy->res_consumed += n;
proxy->res_pending -= n;
}
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))
if (proxy->res_pending <= 0)
{
/* received all contents */
task->main = task_main_proxy_5;
task->trigger.cmask |= QSE_HTTPD_TASK_TRIGGER_WRITE;
/* 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.cmask |= QSE_HTTPD_TASK_TRIGGER_WRITE;
}
else
{
/* there are still more to read from the peer.
* arrange to read the remaining contents from the peer */
task->main = task_main_proxy_4;
/* nothing to write in proxy->res. so clear WRITE from the
* client side */
task->trigger.cmask &= ~QSE_HTTPD_TASK_TRIGGER_WRITE;
}
return 1;
}
else
{
/* there are still more to read from the peer.
* arrange to read the remaining contents from the peer */
task->main = task_main_proxy_4;
/* nothing to write in proxy->res. so clear WRITE from the
* client side */
task->trigger.cmask &= ~QSE_HTTPD_TASK_TRIGGER_WRITE;
}
return 1;
}
}
@ -1291,6 +1319,8 @@ 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
proxy_forward_client_input_to_peer (httpd, task);
#if 0
if (task->trigger.cmask & QSE_HTTPD_TASK_TRIGGER_READABLE)
{
/* client is readable */
@ -1301,41 +1331,46 @@ printf ("task_main_proxy_2 trigger[0].mask=%d trigger[1].mask=%d cmask=%d\n",
/* client is not readable but peer is writable */
proxy_forward_client_input_to_peer (httpd, task, 1);
}
#endif
if (/*!(task->trigger.cmask & QSE_HTTPD_TASK_TRIGGER_WRITE) ||*/
(task->trigger.cmask & QSE_HTTPD_TASK_TRIGGER_WRITABLE))
if (/*(task->trigger.cmask & QSE_HTTPD_TASK_TRIGGER_WRITABLE) && */ proxy->res_pending > 0)
{
if (proxy->res_pending > 0)
/* the 'if' condition becomes true only if '100 Continue'
* is received without an actual reply in a previous call to
* qse_htrd_feed() far below. Since the actual reply is not
* received yet, i just want to read more while relaying
* '100 Continue' to the client.
*
* attempt to write to the client regardless of writability of
* the cleint socket as it is non-blocking. see the check commented
* in the 'if' condition above. */
qse_ssize_t n;
qse_size_t count;
QSE_ASSERT ((proxy->resflags & PROXY_RES_AWAIT_RESHDR) ||
(proxy->resflags & PROXY_RES_CLIENT_CHUNK));
count = proxy->res_pending;
if (count > MAX_SEND_SIZE) count = MAX_SEND_SIZE;
httpd->errnum = QSE_HTTPD_ENOERR;
n = httpd->opt.scb.client.send (
httpd, client,
QSE_MBS_CPTR(proxy->res,proxy->res_consumed),
count
);
if (n <= -1)
{
/* the 'if' condition becomes true only if '100 Continue'
* is received without an actual reply in a previous call to
* qse_htrd_feed() below. Since the actual reply is not
* received yet, i just want to read more while realying
* '100 Continue' to the client. this task handler is called
* only if the client side handle is writable. i can safely
* write to the client without a check. */
qse_ssize_t n;
qse_size_t count;
QSE_ASSERT ((proxy->resflags & PROXY_RES_AWAIT_RESHDR) ||
(proxy->resflags & PROXY_RES_CLIENT_CHUNK));
count = proxy->res_pending;
if (count > MAX_SEND_SIZE) count = MAX_SEND_SIZE;
n = httpd->opt.scb.client.send (
httpd, client,
QSE_MBS_CPTR(proxy->res,proxy->res_consumed),
count
);
if (n <= -1)
if (httpd->errnum != QSE_HTTPD_EAGAIN)
{
if (httpd->opt.trait & QSE_HTTPD_LOGACT)
log_proxy_error (proxy, "proxy send-to-client error - ");
goto oops;
}
}
else if (n > 0)
{
proxy->resflags |= PROXY_RES_EVER_SENTBACK;
proxy->res_consumed += n;
proxy->res_pending -= n;
@ -1367,16 +1402,19 @@ printf ("task_main_proxy_2 trigger[0].mask=%d trigger[1].mask=%d cmask=%d\n",
);
if (n <= -1)
{
if (httpd->opt.trait & QSE_HTTPD_LOGACT)
log_proxy_error (proxy, "proxy recv-from-peer error - ");
goto oops;
if (httpd->errnum != QSE_HTTPD_EAGAIN)
{
if (httpd->opt.trait & QSE_HTTPD_LOGACT)
log_proxy_error (proxy, "proxy recv-from-peer error - ");
goto oops;
}
}
if (n == 0)
else if (n == 0)
{
if (!(proxy->resflags & PROXY_RES_RECEIVED_RESHDR))
{
/* end of output from peer before it has seen a header.
* the proxy peer must be crooked. */
* the proxy peer must be bad. */
if (httpd->opt.trait & QSE_HTTPD_LOGACT)
log_proxy_error (proxy, "proxy premature eof - ");
@ -1405,8 +1443,10 @@ printf ("task_main_proxy_2 trigger[0].mask=%d trigger[1].mask=%d cmask=%d\n",
goto oops;
}
}
proxy->buflen += n;
else
{
proxy->buflen += n;
}
#if 0
qse_printf (QSE_T("#####PROXY FEEDING %d [\n"), (int)proxy->buflen);
@ -1416,15 +1456,17 @@ for (i = 0; i < proxy->buflen; i++) qse_printf (QSE_T("%hc"), proxy->buf[i]);
}
qse_printf (QSE_T("]\n"));
#endif
if (qse_htrd_feed (proxy->peer_htrd, proxy->buf, proxy->buflen) <= -1)
if (proxy->buflen > 0)
{
if (httpd->opt.trait & QSE_HTTPD_LOGACT)
log_proxy_error (proxy, "proxy feed error - ");
goto oops;
}
if (qse_htrd_feed (proxy->peer_htrd, proxy->buf, proxy->buflen) <= -1)
{
if (httpd->opt.trait & QSE_HTTPD_LOGACT)
log_proxy_error (proxy, "proxy feed error - ");
goto oops;
}
proxy->buflen = 0;
proxy->buflen = 0;
}
if (QSE_MBS_LEN(proxy->res) > 0)
{
@ -1530,7 +1572,7 @@ static int task_main_proxy_1 (
if (QSE_MBS_LEN(proxy->reqfwdbuf) > 0)
{
/* forward the initial part of the input to the peer */
proxy_forward_client_input_to_peer (httpd, task, 0);
proxy_forward_client_input_to_peer (httpd, task);
if (QSE_MBS_LEN(proxy->reqfwdbuf) > 0)
{
/* there are still more to forward in the buffer
@ -1697,7 +1739,7 @@ static int task_main_proxy (
if (QSE_MBS_LEN(proxy->reqfwdbuf) > 0)
{
proxy_forward_client_input_to_peer (httpd, task, 0);
proxy_forward_client_input_to_peer (httpd, task);
if (QSE_MBS_LEN(proxy->reqfwdbuf) > 0)
{
task->trigger.v[0].mask |= QSE_HTTPD_TASK_TRIGGER_WRITE;

View File

@ -135,6 +135,9 @@ static qse_httpd_errnum_t skerr_to_errnum (DWORD e)
case WSAEINTR:
return QSE_HTTPD_EINTR;
case WASEWOULDBLOCK:
return QSE_HTTPD_EAGAIN;
case WSAECONNREFUSED:
case WSAENETUNREACH:
case WSAEHOSTUNREACH:
@ -180,6 +183,9 @@ static qse_httpd_errnum_t skerr_to_errnum (int e)
case SOCEPIPE:
return QSE_HTTPD_EPIPE;
case SOCEAGAIN:
return QSE_HTTPD_EAGAIN;
case SOCECONNREFUSED:
case SOCENETUNREACH:
case SOCEHOSTUNREACH:
@ -229,6 +235,9 @@ static qse_httpd_errnum_t skerr_to_errnum (int e)
return QSE_HTTPD_EPIPE;
case EAGAIN:
#if defined(EWEOULDBLOCK) && defined(EAGAIN) && EWOULDBLOCK != EAGAIN
case EWOULDBLOCK:
#endif
return QSE_HTTPD_EAGAIN;
#if defined(ECONNREFUSED) || defined(ENETUNREACH) || defined(EHOSTUNREACH) || defined(EHOSTDOWN)
@ -259,68 +268,68 @@ static qse_httpd_errnum_t skerr_to_errnum (int e)
static qse_httpd_errnum_t muxerr_to_errnum (qse_mux_errnum_t e)
{
switch (e)
{
case QSE_MUX_ENOMEM:
return QSE_HTTPD_ENOMEM;
switch (e)
{
case QSE_MUX_ENOMEM:
return QSE_HTTPD_ENOMEM;
case QSE_MUX_EINVAL:
return QSE_HTTPD_EINVAL;
case QSE_MUX_EINVAL:
return QSE_HTTPD_EINVAL;
case QSE_MUX_EACCES:
return QSE_HTTPD_EACCES;
case QSE_MUX_EACCES:
return QSE_HTTPD_EACCES;
case QSE_MUX_ENOENT:
return QSE_HTTPD_ENOENT;
case QSE_MUX_ENOENT:
return QSE_HTTPD_ENOENT;
case QSE_MUX_EEXIST:
return QSE_HTTPD_EEXIST;
case QSE_MUX_EEXIST:
return QSE_HTTPD_EEXIST;
case QSE_MUX_EINTR:
return QSE_HTTPD_EINTR;
case QSE_MUX_EINTR:
return QSE_HTTPD_EINTR;
case QSE_MUX_EPIPE:
return QSE_HTTPD_EPIPE;
case QSE_MUX_EPIPE:
return QSE_HTTPD_EPIPE;
case QSE_MUX_EAGAIN:
return QSE_HTTPD_EAGAIN;
case QSE_MUX_EAGAIN:
return QSE_HTTPD_EAGAIN;
default:
return QSE_HTTPD_ESYSERR;
}
default:
return QSE_HTTPD_ESYSERR;
}
}
static qse_httpd_errnum_t fioerr_to_errnum (qse_fio_errnum_t e)
{
switch (e)
{
case QSE_FIO_ENOMEM:
return QSE_HTTPD_ENOMEM;
switch (e)
{
case QSE_FIO_ENOMEM:
return QSE_HTTPD_ENOMEM;
case QSE_FIO_EINVAL:
return QSE_HTTPD_EINVAL;
case QSE_FIO_EINVAL:
return QSE_HTTPD_EINVAL;
case QSE_FIO_EACCES:
return QSE_HTTPD_EACCES;
case QSE_FIO_EACCES:
return QSE_HTTPD_EACCES;
case QSE_FIO_ENOENT:
return QSE_HTTPD_ENOENT;
case QSE_FIO_ENOENT:
return QSE_HTTPD_ENOENT;
case QSE_FIO_EEXIST:
return QSE_HTTPD_EEXIST;
case QSE_FIO_EEXIST:
return QSE_HTTPD_EEXIST;
case QSE_FIO_EINTR:
return QSE_HTTPD_EINTR;
case QSE_FIO_EINTR:
return QSE_HTTPD_EINTR;
case QSE_FIO_EPIPE:
return QSE_HTTPD_EPIPE;
case QSE_FIO_EPIPE:
return QSE_HTTPD_EPIPE;
case QSE_FIO_EAGAIN:
return QSE_HTTPD_EAGAIN;
case QSE_FIO_EAGAIN:
return QSE_HTTPD_EAGAIN;
default:
return QSE_HTTPD_ESYSERR;
}
default:
return QSE_HTTPD_ESYSERR;
}
}
static qse_httpd_errnum_t direrr_to_errnum (qse_dir_errnum_t e)
@ -488,7 +497,7 @@ static QSE_INLINE qse_ssize_t __send_file_ssl (
if (offset && (foff = qse_fio_seek (in_fd.ptr, *offset, QSE_FIO_BEGIN)) != *offset)
{
if (foff == (qse_foff_t)-1)
qse_httpd_seterrnum (httpd, fioerr_to_errnum(qse_fio_geterrnum(in_fd.ptr)));
qse_httpd_seterrnum (httpd, fioerr_to_errnum(qse_fio_geterrnum(in_fd.ptr)));
else
qse_httpd_seterrnum (httpd, QSE_HTTPD_ESYSERR);
return (qse_ssize_t)-1;
@ -514,7 +523,7 @@ static QSE_INLINE qse_ssize_t __send_file_ssl (
}
else if (ret <= -1)
{
qse_httpd_seterrnum (httpd, fioerr_to_errnum(qse_fio_geterrnum(in_fd.ptr)));
qse_httpd_seterrnum (httpd, fioerr_to_errnum(qse_fio_geterrnum(in_fd.ptr)));
}
return ret;
@ -640,13 +649,86 @@ void* qse_httpd_getxtnstd (qse_httpd_t* httpd)
/* ------------------------------------------------------------------- */
#if defined(_WIN32)
typedef SOCKET sock_t;
# define SOCK_INIT INVALID_SOCKET
#else
typedef int sock_t;
# define SOCK_INIT -1
#endif
#if !defined(HAVE_SOCKLEN_T)
typedef int socklen_t;
#endif
static QSE_INLINE int is_valid_socket (sock_t fd)
{
#if defined(_WIN32)
return fd != INVALID_SOCKET;
#else
return fd >= 0;
#endif
}
static QSE_INLINE void close_socket (sock_t fd)
{
#if defined(_WIN32)
closesocket (fd);
#elif defined(__OS2__)
soclose (fd);
#elif defined(__DOS__)
/* TODO: */
#else
QSE_CLOSE (fd);
#endif
}
static int set_socket_nonblock (qse_httpd_t* httpd, sock_t fd, int enabled)
{
#if defined(_WIN32)
if (ioctlsocket (fd, FIONBIO, &enabled) == SOCKET_ERROR)
{
qse_httpd_seterrnum (httpd, SKERR_TO_ERRNUM());
return -1;
}
return 0;
#elif defined(__OS2__)
if (ioctl (fd, FIONBIO, (char*)&enabled, sizeof(enabled)) <= -1)
{
qse_httpd_seterrnum (httpd, SKERR_TO_ERRNUM());
return -1;
}
return 0;
#elif defined(O_NONBLOCK)
int flag = fcntl (fd, F_GETFL);
if (flag >= 0) flag = fcntl (fd, F_SETFL, (enabled? (flag | O_NONBLOCK): (flag & ~O_NONBLOCK)));
if (flag <= -1)
{
qse_httpd_seterrnum (httpd, SKERR_TO_ERRNUM());
return -1;
}
return 0;
#else
qse_httpd_seterrnum (httpd, QSE_HTTPD_ENOIMPL);
return -1;
#endif
}
/* ------------------------------------------------------------------- */
static int server_open (qse_httpd_t* httpd, qse_httpd_server_t* server)
{
#if defined(__DOS__)
qse_httpd_seterrnum (httpd, QSE_HTTPD_ENOIMPL);
return -1;
#else
int fd = -1, flag;
sock_t fd = SOCK_INIT, flag;
qse_skad_t addr;
int addrsize;
@ -658,7 +740,11 @@ static int server_open (qse_httpd_t* httpd, qse_httpd_server_t* server)
}
fd = socket (qse_skadfamily(&addr), SOCK_STREAM, IPPROTO_TCP);
if (fd <= -1) goto oops;
if (!is_valid_socket(fd))
{
qse_httpd_seterrnum (httpd, SKERR_TO_ERRNUM());
goto oops;
}
#if defined(FD_CLOEXEC)
flag = fcntl (fd, F_GETFD);
@ -720,6 +806,7 @@ static int server_open (qse_httpd_t* httpd, qse_httpd_server_t* server)
if (len <= 0 || setsockopt (fd, SOL_SOCKET, SO_BINDTODEVICE, tmp, len) <= -1)
{
/* TODO: logging ... */
qse_httpd_seterrnum (httpd, ((len <= 0)? QSE_HTTPD_EINVAL: SKERR_TO_ERRNUM()));
goto oops;
}
#endif
@ -735,50 +822,44 @@ static int server_open (qse_httpd_t* httpd, qse_httpd_server_t* server)
{
int on = 1;
setsockopt (fd, IPPROTO_IPV6, IPV6_V6ONLY, &on, sizeof(on));
if (bind (fd, (struct sockaddr*)&addr, addrsize) <= -1) goto oops;
if (bind (fd, (struct sockaddr*)&addr, addrsize) <= -1)
{
qse_httpd_seterrnum (httpd, SKERR_TO_ERRNUM());
goto oops;
}
}
else
{
qse_httpd_seterrnum (httpd, SKERR_TO_ERRNUM());
goto oops;
}
else goto oops;
#else
qse_httpd_seterrnum (httpd, SKERR_TO_ERRNUM());
goto oops;
#endif
}
if (listen (fd, 10) <= -1) goto oops;
if (listen (fd, 10) <= -1)
{
qse_httpd_seterrnum (httpd, SKERR_TO_ERRNUM());
goto oops;
}
#if defined(O_NONBLOCK)
flag = fcntl (fd, F_GETFL);
if (flag >= 0) fcntl (fd, F_SETFL, flag | O_NONBLOCK);
#endif
if (set_socket_nonblock (httpd, fd, 1) <= -1) goto oops;
server->handle.i = fd;
return 0;
oops:
qse_httpd_seterrnum (httpd, SKERR_TO_ERRNUM());
#if defined(_WIN32)
if (fd != INVALID_SOCKET) closesocket (fd);
#elif defined(__OS2__)
if (fd >= 0) soclose (fd);
#elif defined(__DOS__)
/* TODO: */
#else
if (fd >= 0) QSE_CLOSE (fd);
#endif
if (is_valid_socket(fd)) close_socket (fd);
return -1;
#endif
}
static void server_close (qse_httpd_t* httpd, qse_httpd_server_t* server)
{
#if defined(_WIN32)
closesocket (server->handle.i);
#elif defined(__OS2__)
soclose (server->handle.i);
#elif defined(__DOS__)
/* TODO: */
#else
QSE_CLOSE (server->handle.i);
#endif
close_socket (server->handle.i);
}
static int server_accept (
@ -790,29 +871,25 @@ static int server_accept (
#else
qse_skad_t addr;
#if defined(HAVE_SOCKLEN_T)
socklen_t addrlen;
#else
int addrlen;
#endif
int fd, flag;
sock_t fd = SOCK_INIT;
int flag;
addrlen = QSE_SIZEOF(addr);
fd = accept (server->handle.i, (struct sockaddr*)&addr, &addrlen);
if (fd <= -1)
if (!is_valid_socket(fd))
{
qse_httpd_seterrnum (httpd, SKERR_TO_ERRNUM());
return -1;
goto oops;
}
#if 0
/* TODO: implement maximum number of client per server??? */
if (fd >= FD_SETSIZE)
{
qse_fprintf (QSE_STDERR, QSE_T("Error: too many client?\n"));
/*TODO: qse_httpd_seterrnum (httpd, QSE_HTTPD_EXXXXX);*/
QSE_CLOSE (fd);
return -1;
goto oops;
}
#endif
@ -821,10 +898,7 @@ qse_fprintf (QSE_STDERR, QSE_T("Error: too many client?\n"));
if (flag >= 0) fcntl (fd, F_SETFD, flag | FD_CLOEXEC);
#endif
#if defined(O_NONBLOCK)
flag = fcntl (fd, F_GETFL);
if (flag >= 0) fcntl (fd, F_SETFL, flag | O_NONBLOCK);
#endif
if (set_socket_nonblock (httpd, fd, 1) <= -1) goto oops;
if (qse_skadtonwad (&addr, &client->remote_addr) <= -1)
{
@ -867,6 +941,10 @@ qse_fprintf (QSE_STDERR, QSE_T("Error: too many client?\n"));
client->handle.i = fd;
return 0;
oops:
if (is_valid_socket(fd)) close_socket (fd);
return -1;
#endif
}
@ -885,17 +963,14 @@ static int peer_open (qse_httpd_t* httpd, qse_httpd_peer_t* peer)
qse_skad_t connaddr, bindaddr;
int connaddrsize, bindaddrsize;
int connected = 1;
sock_t fd = SOCK_INIT;
#if defined(_WIN32)
SOCKET fd = -1;
unsigned long cmd;
#elif defined(__OS2__)
int fd = -1;
int cmd;
#elif defined(__DOS__)
int fd = -1;
int flag;
#else
int fd = -1;
int flag;
#endif
@ -908,7 +983,11 @@ static int peer_open (qse_httpd_t* httpd, qse_httpd_peer_t* peer)
}
fd = socket (qse_skadfamily(&connaddr), SOCK_STREAM, IPPROTO_TCP);
if (fd <= -1) goto oops;
if (!is_valid_socket(fd))
{
qse_httpd_seterrnum (httpd, SKERR_TO_ERRNUM());
goto oops;
}
#if defined(IP_TRANSPARENT)
flag = 1;
@ -921,72 +1000,58 @@ static int peer_open (qse_httpd_t* httpd, qse_httpd_peer_t* peer)
/* TODO: some logging for this failure though */
}
#if defined(_WIN32)
cmd = 1;
if (ioctlsocket(fd, FIONBIO, &cmd) == SOCKET_ERROR) goto oops;
if (connect (fd, (struct sockaddr*)&connaddr, connaddrsize) <= -1)
{
if (WSAGetLastError() != WSAEWOULDBLOCK) goto oops;
connected = 0;
}
cmd = 0;
if (ioctlsocket(fd, FIONBIO, &cmd) == SOCKET_ERROR) goto oops;
#elif defined(__OS2__)
cmd = 1;
if (ioctl(fd, FIONBIO, (char*)&cmd, QSE_SIZEOF(cmd)) == -1) goto oops;
if (connect (fd, (struct sockaddr*)&connaddr, connaddrsize) == -1)
{
if (sock_errno() != SOCEINPROGRESS) goto oops;
connected = 0;
}
cmd = 0;
if (ioctl(fd, FIONBIO, (char*)&cmd, QSE_SIZEOF(cmd)) == -1) goto oops;
#elif defined(__DOS__)
/* TODO: */
#else
#if defined(FD_CLOEXEC)
flag = fcntl (fd, F_GETFD);
if (flag >= 0) fcntl (fd, F_SETFD, flag | FD_CLOEXEC);
#endif
flag = fcntl (fd, F_GETFL);
if (flag >= 0) fcntl (fd, F_SETFL, flag | O_NONBLOCK);
if (set_socket_nonblock (httpd, fd, 1) <= -1) goto oops;
#if defined(_WIN32)
if (connect (fd, (struct sockaddr*)&connaddr, connaddrsize) <= -1)
{
if (errno != EINPROGRESS) goto oops;
if (WSAGetLastError() != WSAEWOULDBLOCK)
{
qse_httpd_seterrnum (httpd, SKERR_TO_ERRNUM());
goto oops;
}
connected = 0;
}
/* restore flags */
if (fcntl (fd, F_SETFL, flag) <= -1) goto oops;
#elif defined(__OS2__)
if (connect (fd, (struct sockaddr*)&connaddr, connaddrsize) == -1)
{
if (sock_errno() != SOCEINPROGRESS)
{
qse_httpd_seterrnum (httpd, SKERR_TO_ERRNUM());
goto oops;
}
connected = 0;
}
#elif defined(__DOS__)
/* TODO: */
#else
if (connect (fd, (struct sockaddr*)&connaddr, connaddrsize) <= -1)
{
if (errno != EINPROGRESS)
{
qse_httpd_seterrnum (httpd, SKERR_TO_ERRNUM());
goto oops;
}
connected = 0;
}
#endif
/*if (set_socket_nonblock (httpd, fd, 0) <= -1) goto oops;*/
peer->handle.i = fd;
return connected;
oops:
qse_httpd_seterrnum (httpd, SKERR_TO_ERRNUM());
#if defined(_WIN32)
if (fd != INVALID_SOCKET) closesocket (fd);
#elif defined(__OS2__)
if (fd >= 0) soclose (fd);
#elif defined(__DOS__)
/* TODO: */
#else
if (fd >= 0) QSE_CLOSE (fd);
#endif
if (is_valid_socket(fd)) close_socket (fd);
return -1;
/* -------------------------------------------------------------------- */
@ -995,15 +1060,7 @@ oops:
static void peer_close (qse_httpd_t* httpd, qse_httpd_peer_t* peer)
{
#if defined(_WIN32)
closesocket (peer->handle.i);
#elif defined(__OS2__)
soclose (peer->handle.i);
#elif defined(__DOS__)
/* TODO: */
#else
QSE_CLOSE (peer->handle.i);
#endif
close_socket (peer->handle.i);
}
static int peer_connected (qse_httpd_t* httpd, qse_httpd_peer_t* peer)
@ -1057,11 +1114,7 @@ static int peer_connected (qse_httpd_t* httpd, qse_httpd_peer_t* peer)
#else
#if defined(HAVE_SOCKLEN_T)
socklen_t len;
#else
int len;
#endif
int ret;
len = QSE_SIZEOF(ret);
@ -1747,26 +1800,22 @@ static int dir_read (qse_httpd_t* httpd, qse_ubi_t handle, qse_httpd_dirent_t* d
# define SHUT_RDWR 2
#endif
static void client_close (
qse_httpd_t* httpd, qse_httpd_client_t* client)
static void client_close (qse_httpd_t* httpd, qse_httpd_client_t* client)
{
#if defined(_WIN32)
shutdown (client->handle.i, SHUT_RDWR);
closesocket (client->handle.i);
#elif defined(__OS2__)
shutdown (client->handle.i, SHUT_RDWR);
soclose (client->handle.i);
#elif defined(__DOS__)
/* TODO: */
#else
shutdown (client->handle.i, SHUT_RDWR);
QSE_CLOSE (client->handle.i);
#endif
close_socket (client->handle.i);
}
static void client_shutdown (
qse_httpd_t* httpd, qse_httpd_client_t* client)
static void client_shutdown (qse_httpd_t* httpd, qse_httpd_client_t* client)
{
#if defined(_WIN32)
shutdown (client->handle.i, SHUT_RDWR);
@ -2201,7 +2250,8 @@ static int dns_open (qse_httpd_t* httpd, qse_httpd_dns_t* dns)
qse_httpd_seterrnum (httpd, QSE_HTTPD_ENOIMPL);
return -1;
#else
int fd = -1, flag;
sock_t fd = SOCK_INIT;
int flag;
qse_nwad_t nwad;
dns_ctx_t* dc;
httpd_xtn_t* httpd_xtn;
@ -2276,7 +2326,11 @@ static int dns_open (qse_httpd_t* httpd, qse_httpd_dns_t* dns)
}
fd = socket (qse_skadfamily(&dc->skad), SOCK_DGRAM, IPPROTO_UDP);
if (fd <= -1) goto oops;
if (!is_valid_socket(fd))
{
qse_httpd_seterrnum (httpd, SKERR_TO_ERRNUM());
goto oops;
}
#if defined(FD_CLOEXEC)
flag = fcntl (fd, F_GETFD);
@ -2293,22 +2347,14 @@ static int dns_open (qse_httpd_t* httpd, qse_httpd_dns_t* dns)
setsockopt (fd, SOL_SOCKET, SO_REUSEPORT, (void*)&flag, QSE_SIZEOF(flag));
#endif
if (set_socket_nonblock (httpd, fd, 1) <= -1) goto oops;
dns->handle.i = fd;
dns->ctx = dc;
return 0;
oops:
if (fd >= 0)
{
#if defined(_WIN32)
closesocket (fd);
#elif defined(__OS2__)
soclose (fd);
#else
QSE_CLOSE (fd);
#endif
}
if (is_valid_socket(fd)) close_socket (fd);
if (dc) qse_httpd_freemem (httpd, dc);
return -1;
@ -2447,7 +2493,7 @@ static int dns_recv (qse_httpd_t* httpd, qse_httpd_dns_t* dns)
dns_ctx_t* dc = (dns_ctx_t*)dns->ctx;
qse_skad_t fromaddr;
socklen_t fromlen; /* TODO: change type */
socklen_t fromlen;
qse_uint8_t buf[DNS_MAX_MSG_LEN];
qse_ssize_t len;
@ -2614,16 +2660,13 @@ static int dns_send (qse_httpd_t* httpd, qse_httpd_dns_t* dns, const qse_mchar_t
qse_size_t name_len;
dns_ans_t* ans;
printf ("finding answer in cache...\n");
ans = dns_get_answer_from_cache (dc, name);
if (ans)
{
printf ("found answer in cache...\n");
resol (httpd, name, ((ans->nwad.type == QSE_NWAD_NX)? QSE_NULL: &ans->nwad), ctx);
return 0;
}
printf ("found XXXXX in cache...\n");
seq = dc->seq;
seq = (seq + 1) % QSE_COUNTOF(dc->reqs);
dc->seq = seq;

View File

@ -90,13 +90,19 @@ static int task_main_format (
count = MAX_SEND_SIZE;
if (count >= ctx->left) count = ctx->left;
httpd->errnum = QSE_HTTPD_ENOERR;
n = httpd->opt.scb.client.send (httpd, client, ctx->ptr, count);
if (n <= -1) return -1;
if (n <= -1)
{
if (httpd->errnum != QSE_HTTPD_EAGAIN) return -1;
}
else if (n > 0)
{
ctx->left -= n;
if (ctx->left <= 0) return 0;
ctx->ptr += n;
}
ctx->left -= n;
if (ctx->left <= 0) return 0;
ctx->ptr += n;
return 1; /* more work to do */
}

View File

@ -53,13 +53,18 @@ static int task_main_text (
if (count >= ctx->left) count = ctx->left;
/* TODO: do i need to add code to skip this send if count is 0? */
httpd->errnum = QSE_HTTPD_ENOERR;
n = httpd->opt.scb.client.send (httpd, client, ctx->ptr, count);
if (n <= -1) return -1;
ctx->left -= n;
if (ctx->left <= 0) return 0;
ctx->ptr += n;
if (n <= -1)
{
if (httpd->errnum != QSE_HTTPD_EAGAIN) return -1;
}
else if (n > 0)
{
ctx->left -= n;
if (ctx->left <= 0) return 0;
ctx->ptr += n;
}
return 1; /* more work to do */
}

View File

@ -921,7 +921,7 @@ static int update_mux_for_current_task (qse_httpd_t* httpd, qse_httpd_client_t*
{
/* active to inactive */
printf ("ACTIVE TO INACTIVE....\n");
/*printf ("ACTIVE TO INACTIVE....\n");*/
for (i = 0; i < QSE_COUNTOF(task->trigger.v); i++)
{
if (client->status & CLIENT_TASK_TRIGGER_RW_IN_MUX(i))
@ -942,21 +942,21 @@ printf ("ACTIVE TO INACTIVE....\n");
return 0;
}
printf ("INACTIVE TO ACTIVE....\n");
/*printf ("INACTIVE TO ACTIVE....\n");*/
/* inactive to active . go on*/
}
else
{
if (task->trigger.flags & QSE_HTTPD_TASK_TRIGGER_INACTIVE)
{
printf ("INACTIVE TO INACTIVE....\n");
/*printf ("INACTIVE TO INACTIVE....\n");*/
/* inactive to inactive.
* save the trigger as the trigger handle and masks could change */
client->trigger = task->trigger;
return 0;
}
printf ("ACTIVE TO ACTIVE....\n");
/*printf ("ACTIVE TO ACTIVE....\n");*/
/* active to active. go on */
}
@ -1183,13 +1183,23 @@ static int invoke_client_task (
{
if (mask & QSE_HTTPD_MUX_READ)
{
QSE_ASSERT (task->trigger.v[i].mask & QSE_HTTPD_TASK_TRIGGER_READ);
/*QSE_ASSERT (task->trigger.v[i].mask & QSE_HTTPD_TASK_TRIGGER_READ);*/
/* the assertion above may be false if a task for the same
* trigger set was called earlier by a qse_mux_poll() call.
* and the task has changed some masks.
*
* for instance, you put handle A and B in to a trigger.
* if the task is triggered for A but the task may change
* the mask for B. the task may get executed for B by
* the same qse_mux_poll() call.
*/
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);
/*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;
}