added file-access and dir-access to cmd/http/httpd.c
This commit is contained in:
@ -23,6 +23,7 @@
|
||||
#include <qse/cmn/str.h>
|
||||
#include <qse/cmn/pio.h>
|
||||
#include <qse/cmn/fmt.h>
|
||||
#include <qse/cmn/path.h>
|
||||
|
||||
#include <stdio.h> /* TODO: remove this */
|
||||
|
||||
@ -196,6 +197,17 @@ static int cgi_capture_script_header (qse_htre_t* req, const qse_mchar_t* key, c
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void log_cgi_script_error (task_cgi_t* cgi, const qse_mchar_t* shortmsg)
|
||||
{
|
||||
qse_httpd_act_t msg;
|
||||
qse_size_t pos = 0;
|
||||
|
||||
msg.code = QSE_HTTPD_CATCH_MERRMSG;
|
||||
pos += qse_mbsxcpy (&msg.u.merrmsg[pos], QSE_COUNTOF(msg.u.merrmsg) - pos, shortmsg);
|
||||
pos += qse_mbsxcpy (&msg.u.merrmsg[pos], QSE_COUNTOF(msg.u.merrmsg) - pos, cgi->script);
|
||||
cgi->httpd->opt.rcb.logact (cgi->httpd, &msg);
|
||||
}
|
||||
|
||||
static int cgi_htrd_peek_script_output (qse_htrd_t* htrd, qse_htre_t* req)
|
||||
{
|
||||
cgi_script_htrd_xtn_t* xtn;
|
||||
@ -355,8 +367,9 @@ static int cgi_htrd_peek_script_output (qse_htrd_t* htrd, qse_htre_t* req)
|
||||
if ((cgi->resflags & CGI_RES_SCRIPT_LENGTH) &&
|
||||
cgi->script_output_received > cgi->script_output_length)
|
||||
{
|
||||
/* TODO: cgi returning too much data... something is wrong in CGI */
|
||||
qse_printf (QSE_T("CGI SCRIPT FUCKED - RETURNING TOO MUCH...\n"));
|
||||
/* 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 - "));
|
||||
cgi->httpd->errnum = QSE_HTTPD_EINVAL; /* TODO: change it to a better error code */
|
||||
return -1;
|
||||
}
|
||||
@ -501,8 +514,10 @@ static int cgi_snatch_client_input (
|
||||
task = (qse_httpd_task_t*)ctx;
|
||||
cgi = (task_cgi_t*)task->ctx;
|
||||
|
||||
#if 0
|
||||
if (ptr) qse_printf (QSE_T("!!!CGI SNATCHING [%.*hs]\n"), len, ptr);
|
||||
else qse_printf (QSE_T("!!!CGI SNATCHING DONE\n"));
|
||||
#endif
|
||||
|
||||
QSE_ASSERT (cgi->req);
|
||||
QSE_ASSERT (!(cgi->reqflags & CGI_REQ_GOTALL));
|
||||
@ -587,7 +602,9 @@ else qse_printf (QSE_T("!!!CGI SNATCHING DONE\n"));
|
||||
|
||||
/* output pipe to child */
|
||||
task->trigger[1].mask = QSE_HTTPD_TASK_TRIGGER_WRITE;
|
||||
#if 0
|
||||
qse_printf (QSE_T("!!!CGI SNATCHED [%.*hs]\n"), len, ptr);
|
||||
#endif
|
||||
}
|
||||
|
||||
return 0;
|
||||
@ -608,7 +625,9 @@ 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
|
||||
@ -624,9 +643,11 @@ 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),
|
||||
@ -647,8 +668,9 @@ to the head all the time.. grow the buffer to a certain limit. */
|
||||
|
||||
if (n <= -1)
|
||||
{
|
||||
qse_printf (QSE_T("FORWARD: @@@@@@@@WRITE TO CGI FAILED\n"));
|
||||
/* TODO: logging ... */
|
||||
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);
|
||||
|
||||
@ -679,7 +701,9 @@ qse_printf (QSE_T("FORWARD: @@@@@@@@WRITE TO CGI FAILED\n"));
|
||||
* 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
|
||||
QSE_ASSERT (cgi->req == QSE_NULL);
|
||||
|
||||
/* mark the end of input to the child explicitly. */
|
||||
@ -919,8 +943,6 @@ static void task_fini_cgi (
|
||||
QSE_ASSERT (!(cgi->reqflags & CGI_REQ_GOTALL));
|
||||
qse_htre_unsetconcb (cgi->req);
|
||||
}
|
||||
|
||||
qse_printf (QSE_T("task_fini_cgi\n"));
|
||||
}
|
||||
|
||||
static QSE_INLINE qse_ssize_t cgi_read_script_output_to_buffer (
|
||||
@ -934,6 +956,10 @@ static QSE_INLINE qse_ssize_t cgi_read_script_output_to_buffer (
|
||||
QSE_SIZEOF(cgi->buf) - cgi->buflen
|
||||
);
|
||||
if (n > 0) cgi->buflen += n;
|
||||
|
||||
if (n <= -1 && cgi->httpd->opt.trait & QSE_HTTPD_LOGACT)
|
||||
log_cgi_script_error (cgi, QSE_MT("cgi pio read error - "));
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
@ -942,13 +968,16 @@ static QSE_INLINE qse_ssize_t cgi_write_script_output_to_client (
|
||||
{
|
||||
qse_ssize_t n;
|
||||
|
||||
httpd->errnum = QSE_HTTPD_ENOERR;
|
||||
n = httpd->opt.scb.client.send (httpd, client, cgi->buf, cgi->buflen);
|
||||
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;
|
||||
}
|
||||
|
||||
@ -971,13 +1000,11 @@ static int task_main_cgi_5 (
|
||||
if (!(task->trigger[2].mask & QSE_HTTPD_TASK_TRIGGER_WRITE) ||
|
||||
(task->trigger[2].mask & QSE_HTTPD_TASK_TRIGGER_WRITABLE))
|
||||
{
|
||||
qse_printf (QSE_T("task_main_cgi_5 about to write %d bytes\n"), (int)cgi->buflen);
|
||||
if (cgi->buflen > 0)
|
||||
{
|
||||
if (cgi_write_script_output_to_client (httpd, client, cgi) <= -1)
|
||||
{
|
||||
/* can't return internal server error any more... */
|
||||
/* TODO: logging ... */
|
||||
/* can't return internal server error any more... */
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
@ -1024,11 +1051,7 @@ static int task_main_cgi_4_nph (
|
||||
}
|
||||
|
||||
QSE_ASSERT (cgi->buflen > 0);
|
||||
if (cgi_write_script_output_to_client (httpd, client, cgi) <= -1)
|
||||
{
|
||||
/* TODO: logging ... */
|
||||
return -1;
|
||||
}
|
||||
if (cgi_write_script_output_to_client (httpd, client, cgi) <= -1) return -1;
|
||||
}
|
||||
|
||||
return 1;
|
||||
@ -1043,8 +1066,10 @@ static int task_main_cgi_4 (
|
||||
QSE_ASSERT (!cgi->nph);
|
||||
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[0].mask, task->trigger[1].mask, task->trigger[2].mask);
|
||||
#endif
|
||||
|
||||
if (task->trigger[2].mask & QSE_HTTPD_TASK_TRIGGER_READABLE)
|
||||
{
|
||||
@ -1057,7 +1082,6 @@ qse_printf (QSE_T("task_main_cgi_4 trigger[0].mask=%d trigger[1].mask=%d trigger
|
||||
|
||||
if (task->trigger[0].mask & QSE_HTTPD_TASK_TRIGGER_READABLE)
|
||||
{
|
||||
qse_printf (QSE_T("TASK_MAIN_CGI_4\n"));
|
||||
if (cgi->resflags & CGI_RES_CLIENT_CHUNK)
|
||||
{
|
||||
qse_size_t count, extra;
|
||||
@ -1068,7 +1092,6 @@ qse_printf (QSE_T("TASK_MAIN_CGI_4\n"));
|
||||
|
||||
#define CHLEN_RESERVE 6
|
||||
|
||||
qse_printf (QSE_T("READING CHUNKED MODE...\n"));
|
||||
extra = CHLEN_RESERVE + 2;
|
||||
count = QSE_SIZEOF(cgi->buf) - cgi->buflen;
|
||||
if (count > extra)
|
||||
@ -1080,7 +1103,8 @@ qse_printf (QSE_T("TASK_MAIN_CGI_4\n"));
|
||||
);
|
||||
if (n <= -1)
|
||||
{
|
||||
/* TODO: logging ... */
|
||||
if (cgi->httpd->opt.trait & QSE_HTTPD_LOGACT)
|
||||
log_cgi_script_error (cgi, QSE_MT("cgi pio read error - "));
|
||||
return -1;
|
||||
}
|
||||
if (n == 0)
|
||||
@ -1121,15 +1145,15 @@ qse_printf (QSE_T("TASK_MAIN_CGI_4\n"));
|
||||
if ((cgi->resflags & CGI_RES_SCRIPT_LENGTH) &&
|
||||
cgi->script_output_received > cgi->script_output_length)
|
||||
{
|
||||
/* TODO: cgi returning too much data... something is wrong in CGI */
|
||||
qse_printf (QSE_T("CGI FUCKED UP...RETURNING TOO MUCH DATA\n"));
|
||||
/* 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
qse_printf (QSE_T("READING IN NON-CHUNKED MODE...\n"));
|
||||
if (cgi->buflen < QSE_SIZEOF(cgi->buf))
|
||||
{
|
||||
n = cgi_read_script_output_to_buffer (httpd, client, cgi);
|
||||
@ -1147,9 +1171,9 @@ qse_printf (QSE_T("TASK_MAIN_CGI_4\n"));
|
||||
if ((cgi->resflags & CGI_RES_SCRIPT_LENGTH) &&
|
||||
cgi->script_output_received > cgi->script_output_length)
|
||||
{
|
||||
/* TODO: logging */
|
||||
/* TODO: cgi returning too much data... something is wrong in CGI */
|
||||
qse_printf (QSE_T("CGI FUCKED UP...RETURNING TOO MUCH DATA\n"));
|
||||
/* 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;
|
||||
}
|
||||
}
|
||||
@ -1159,11 +1183,7 @@ qse_printf (QSE_T("TASK_MAIN_CGI_4\n"));
|
||||
* 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)
|
||||
{
|
||||
/* TODO: logging ... */
|
||||
return -1;
|
||||
}
|
||||
if (cgi_write_script_output_to_client (httpd, client, cgi) <= -1) return -1;
|
||||
}
|
||||
|
||||
return 1;
|
||||
@ -1181,8 +1201,10 @@ 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[0].mask, task->trigger[1].mask, task->trigger[2].mask);
|
||||
#endif
|
||||
if (task->trigger[2].mask & QSE_HTTPD_TASK_TRIGGER_READABLE)
|
||||
{
|
||||
cgi_forward_client_input_to_script (httpd, task, 0);
|
||||
@ -1200,15 +1222,13 @@ qse_printf (QSE_T("task_main_cgi_3 trigger[0].mask=%d trigger[1].mask=%d trigger
|
||||
count = MAX_SEND_SIZE;
|
||||
if (count >= cgi->res_left) count = cgi->res_left;
|
||||
|
||||
qse_printf (QSE_T("[cgi_3 sending %d bytes]\n"), (int)count);
|
||||
if (count > 0)
|
||||
{
|
||||
httpd->errnum = QSE_HTTPD_ENOERR;
|
||||
n = httpd->opt.scb.client.send (httpd, client, cgi->res_ptr, count);
|
||||
|
||||
if (n <= -1)
|
||||
{
|
||||
qse_printf (QSE_T("[cgi-3 send failure....\n"));
|
||||
if (cgi->httpd->opt.trait & QSE_HTTPD_LOGACT)
|
||||
log_cgi_script_error (cgi, QSE_MT("cgi initial write error to client - "));
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -1223,7 +1243,6 @@ qse_printf (QSE_T("[cgi-3 send failure....\n"));
|
||||
if ((cgi->resflags & CGI_RES_SCRIPT_LENGTH) &&
|
||||
cgi->script_output_received >= cgi->script_output_length)
|
||||
{
|
||||
qse_printf (QSE_T("[switching to cgi-5....\n"));
|
||||
/* 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.
|
||||
@ -1236,7 +1255,6 @@ qse_printf (QSE_T("[switching to cgi-5....\n"));
|
||||
}
|
||||
else
|
||||
{
|
||||
qse_printf (QSE_T("[switching to cgi-4....\n"));
|
||||
task->main = task_main_cgi_4;
|
||||
task->trigger[2].mask &= ~QSE_HTTPD_TASK_TRIGGER_WRITE;
|
||||
}
|
||||
@ -1262,12 +1280,13 @@ static int task_main_cgi_2 (
|
||||
QSE_ASSERT (!cgi->nph);
|
||||
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[0].mask, task->trigger[1].mask, task->trigger[2].mask);
|
||||
#endif
|
||||
|
||||
if (task->trigger[2].mask & QSE_HTTPD_TASK_TRIGGER_READABLE)
|
||||
{
|
||||
qse_printf (QSE_T("[cgi_2 write]\n"));
|
||||
cgi_forward_client_input_to_script (httpd, task, 0);
|
||||
}
|
||||
else if (task->trigger[1].mask & QSE_HTTPD_TASK_TRIGGER_WRITABLE)
|
||||
@ -1277,7 +1296,6 @@ qse_printf (QSE_T("[cgi_2 write]\n"));
|
||||
|
||||
if (task->trigger[0].mask & QSE_HTTPD_TASK_TRIGGER_READABLE)
|
||||
{
|
||||
qse_printf (QSE_T("[cgi_2 read]\n"));
|
||||
n = qse_pio_read (
|
||||
&cgi->pio, QSE_PIO_OUT,
|
||||
&cgi->buf[cgi->buflen],
|
||||
@ -1286,25 +1304,24 @@ qse_printf (QSE_T("[cgi_2 read]\n"));
|
||||
if (n <= -1)
|
||||
{
|
||||
/* can't return internal server error any more... */
|
||||
/* TODO: logging ... */
|
||||
if (cgi->httpd->opt.trait & QSE_HTTPD_LOGACT)
|
||||
log_cgi_script_error (cgi, QSE_MT("cgi pio read error - "));
|
||||
goto oops;
|
||||
}
|
||||
if (n == 0)
|
||||
{
|
||||
/* end of output from cgi before it has seen a header.
|
||||
* the cgi script must be crooked. */
|
||||
/* TODO: logging */
|
||||
qse_printf (QSE_T("#####PREMATURE EOF FROM CHILD\n"));
|
||||
if (cgi->httpd->opt.trait & QSE_HTTPD_LOGACT)
|
||||
log_cgi_script_error (cgi, QSE_MT("cgi premature eof - "));
|
||||
goto oops;
|
||||
}
|
||||
|
||||
cgi->buflen += n;
|
||||
|
||||
qse_printf (QSE_T("#####CGI FEED [%.*hs]\n"), (int)cgi->buflen, cgi->buf);
|
||||
if (qse_htrd_feed (cgi->script_htrd, cgi->buf, cgi->buflen) <= -1)
|
||||
{
|
||||
/* TODO: logging */
|
||||
qse_printf (QSE_T("#####INVALID HEADER FROM FROM CHILD [%.*hs]\n"), (int)cgi->buflen, cgi->buf);
|
||||
if (cgi->httpd->opt.trait & QSE_HTTPD_LOGACT)
|
||||
log_cgi_script_error (cgi, QSE_MT("cgi feed error - "));
|
||||
goto oops;
|
||||
}
|
||||
|
||||
@ -1324,7 +1341,9 @@ qse_printf (QSE_T("#####INVALID HEADER FROM FROM CHILD [%.*hs]\n"), (int)cgi->bu
|
||||
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[2].mask |= QSE_HTTPD_TASK_TRIGGER_WRITE;
|
||||
return 1;
|
||||
@ -1447,7 +1466,6 @@ static int task_main_cgi (
|
||||
* this is possible because the main loop can still read
|
||||
* between the initializer function (task_init_cgi()) and
|
||||
* this function. so let's forward it initially. */
|
||||
qse_printf (QSE_T("FORWARDING INITIAL PART OF CONTENT...\n"));
|
||||
cgi_forward_client_input_to_script (httpd, task, 0);
|
||||
|
||||
/* if the initial forwarding clears the forwarding
|
||||
|
@ -29,8 +29,8 @@
|
||||
typedef struct task_proxy_arg_t task_proxy_arg_t;
|
||||
struct task_proxy_arg_t
|
||||
{
|
||||
qse_nwad_t* peer_nwad;
|
||||
qse_nwad_t* peer_local;
|
||||
const qse_nwad_t* peer_nwad;
|
||||
const qse_nwad_t* peer_local;
|
||||
qse_htre_t* req;
|
||||
};
|
||||
|
||||
|
@ -531,12 +531,15 @@ struct httpd_xtn_t
|
||||
|
||||
#if defined(HAVE_SSL)
|
||||
static int init_xtn_ssl (
|
||||
httpd_xtn_t* xtn,
|
||||
qse_httpd_t* httpd,
|
||||
const qse_mchar_t* pemfile,
|
||||
const qse_mchar_t* keyfile/*,
|
||||
const qse_mchar_t* chainfile*/)
|
||||
{
|
||||
SSL_CTX* ctx;
|
||||
httpd_xtn_t* xtn;
|
||||
|
||||
xtn = (httpd_xtn_t*)qse_httpd_getxtn (httpd);
|
||||
|
||||
ctx = SSL_CTX_new (SSLv23_server_method());
|
||||
if (ctx == QSE_NULL) return -1;
|
||||
@ -548,10 +551,14 @@ static int init_xtn_ssl (
|
||||
SSL_CTX_check_private_key (ctx) == 0 /*||
|
||||
SSL_CTX_use_certificate_chain_file (ctx, chainfile) == 0*/)
|
||||
{
|
||||
qse_mchar_t buf[128];
|
||||
ERR_error_string_n(ERR_get_error(), buf, QSE_COUNTOF(buf));
|
||||
/* TODO: logging */
|
||||
qse_fprintf (QSE_STDERR, QSE_T("Error: %hs\n"), buf);
|
||||
if (httpd->opt.trait & QSE_HTTPD_LOGACT)
|
||||
{
|
||||
qse_httpd_act_t msg;
|
||||
msg.code = QSE_HTTPD_CATCH_MERRMSG;
|
||||
ERR_error_string_n (ERR_get_error(), msg.u.merrmsg, QSE_COUNTOF(msg.u.merrmsg));
|
||||
httpd->opt.rcb.logact (httpd, &msg);
|
||||
}
|
||||
|
||||
SSL_CTX_free (ctx);
|
||||
return -1;
|
||||
}
|
||||
@ -600,7 +607,7 @@ qse_httpd_t* qse_httpd_openstdwithmmgr (qse_mmgr_t* mmgr, qse_size_t xtnsize)
|
||||
xtn = (httpd_xtn_t*)qse_httpd_getxtn (httpd);
|
||||
|
||||
#if defined(HAVE_SSL)
|
||||
/*init_xtn_ssl (xtn, "http01.pem", "http01.key");*/
|
||||
/*init_xtn_ssl (httpd, "http01.pem", "http01.key");*/
|
||||
#endif
|
||||
|
||||
set_httpd_callbacks (httpd);
|
||||
@ -1409,7 +1416,16 @@ static int file_ropen (
|
||||
}
|
||||
|
||||
handle->ptr = fio;
|
||||
qse_printf (QSE_T("opened rfile [%hs][%p][%p]\n"), path, handle->ptr, fio->handle);
|
||||
|
||||
if (httpd->opt.trait & QSE_HTTPD_LOGACT)
|
||||
{
|
||||
qse_httpd_act_t msg;
|
||||
qse_size_t pos;
|
||||
msg.code = QSE_HTTPD_CATCH_MDBGMSG;
|
||||
pos = qse_mbscpy (msg.u.mdbgmsg, QSE_MT("ropened file "));
|
||||
qse_mbsxcpy (&msg.u.mdbgmsg[pos], QSE_COUNTOF(msg.u.mdbgmsg) - pos, path);
|
||||
httpd->opt.rcb.logact (httpd, &msg);
|
||||
}
|
||||
return 0;
|
||||
|
||||
}
|
||||
@ -1438,13 +1454,22 @@ static int file_wopen (
|
||||
}
|
||||
|
||||
handle->ptr = fio;
|
||||
qse_printf (QSE_T("opened wfile [%hs][%p][%p]\n"), path, handle->ptr, fio->handle);
|
||||
|
||||
if (httpd->opt.trait & QSE_HTTPD_LOGACT)
|
||||
{
|
||||
qse_httpd_act_t msg;
|
||||
qse_size_t pos;
|
||||
msg.code = QSE_HTTPD_CATCH_MDBGMSG;
|
||||
pos = qse_mbscpy (msg.u.mdbgmsg, QSE_MT("wopened file "));
|
||||
qse_mbsxcpy (&msg.u.mdbgmsg[pos], QSE_COUNTOF(msg.u.mdbgmsg) - pos, path);
|
||||
httpd->opt.rcb.logact (httpd, &msg);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void file_close (qse_httpd_t* httpd, qse_ubi_t handle)
|
||||
{
|
||||
qse_printf (QSE_T("closed file....%p\n"), handle.ptr);
|
||||
qse_fio_fini (handle.ptr);
|
||||
QSE_MMGR_FREE (httpd->mmgr, handle.ptr);
|
||||
}
|
||||
@ -1512,7 +1537,16 @@ static int dir_open (qse_httpd_t* httpd, const qse_mchar_t* path, qse_ubi_t* han
|
||||
return -1;
|
||||
}
|
||||
|
||||
qse_printf (QSE_T("OPENED DIRECTORY [%hs]\n"), path);
|
||||
if (httpd->opt.trait & QSE_HTTPD_LOGACT)
|
||||
{
|
||||
qse_httpd_act_t msg;
|
||||
qse_size_t pos;
|
||||
msg.code = QSE_HTTPD_CATCH_MDBGMSG;
|
||||
pos = qse_mbscpy (msg.u.mdbgmsg, QSE_MT("opened dir "));
|
||||
qse_mbsxcpy (&msg.u.mdbgmsg[pos], QSE_COUNTOF(msg.u.mdbgmsg) - pos, path);
|
||||
httpd->opt.rcb.logact (httpd, &msg);
|
||||
}
|
||||
|
||||
handle->ptr = d;
|
||||
return 0;
|
||||
}
|
||||
@ -1693,7 +1727,7 @@ static int client_accepted (qse_httpd_t* httpd, qse_httpd_client_t* client)
|
||||
{
|
||||
/* delayed initialization of ssl */
|
||||
/* TODO: certificate from options */
|
||||
if (init_xtn_ssl (xtn, "http01.pem", "http01.key") <= -1)
|
||||
if (init_xtn_ssl (httpd, "http01.pem", "http01.key") <= -1)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
@ -1711,9 +1745,6 @@ static int client_accepted (qse_httpd_t* httpd, qse_httpd_client_t* client)
|
||||
if (ssl == QSE_NULL) return -1;
|
||||
|
||||
client->handle2.ptr = ssl;
|
||||
|
||||
qse_printf (QSE_T("SSL ACCEPTING %d\n"), client->handle.i);
|
||||
qse_fflush (QSE_STDOUT);
|
||||
if (SSL_set_fd (ssl, client->handle.i) == 0)
|
||||
{
|
||||
/* don't free ssl here since client_closed()
|
||||
@ -1727,18 +1758,25 @@ qse_fflush (QSE_STDOUT);
|
||||
ret = SSL_accept (ssl);
|
||||
if (ret <= 0)
|
||||
{
|
||||
if (SSL_get_error(ssl,ret) == SSL_ERROR_WANT_READ)
|
||||
int err;
|
||||
if ((err = SSL_get_error(ssl,ret)) == SSL_ERROR_WANT_READ)
|
||||
{
|
||||
/* handshaking isn't complete. */
|
||||
return 0;
|
||||
}
|
||||
|
||||
qse_fprintf (QSE_STDERR, QSE_T("Error: SSL ACCEPT ERROR\n"));
|
||||
if (httpd->opt.trait & QSE_HTTPD_LOGACT)
|
||||
{
|
||||
qse_httpd_act_t msg;
|
||||
msg.code = QSE_HTTPD_CATCH_MERRMSG;
|
||||
ERR_error_string_n (err, msg.u.merrmsg, QSE_COUNTOF(msg.u.merrmsg));
|
||||
httpd->opt.rcb.logact (httpd, &msg);
|
||||
}
|
||||
|
||||
/* SSL_free (ssl); */
|
||||
return -1;
|
||||
}
|
||||
qse_printf (QSE_T("SSL ACCEPTED %d\n"), client->handle.i);
|
||||
qse_fflush (QSE_STDOUT);
|
||||
|
||||
#else
|
||||
qse_httpd_seterrnum (httpd, QSE_HTTPD_ENOIMPL);
|
||||
return -1;
|
||||
@ -1763,6 +1801,7 @@ static void client_closed (qse_httpd_t* httpd, qse_httpd_client_t* client)
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------- */
|
||||
#if 0
|
||||
static qse_htb_walk_t walk (qse_htb_t* htb, qse_htb_pair_t* pair, void* ctx)
|
||||
{
|
||||
qse_htre_hdrval_t* val;
|
||||
@ -1775,6 +1814,7 @@ qse_printf (QSE_T("HEADER OK %d[%hs] %d[%hs]\n"), (int)QSE_HTB_KLEN(pair), QSE_
|
||||
}
|
||||
return QSE_HTB_WALK_FORWARD;
|
||||
}
|
||||
#endif
|
||||
|
||||
static int process_request (
|
||||
qse_httpd_t* httpd, qse_httpd_client_t* client, qse_htre_t* req, int peek)
|
||||
@ -1796,6 +1836,7 @@ static int process_request (
|
||||
* non-peek mode as well */
|
||||
if (peek) qse_perdechttpstr (qse_htre_getqpath(req), qse_htre_getqpath(req));
|
||||
|
||||
#if 0
|
||||
qse_printf (QSE_T("================================\n"));
|
||||
qse_printf (QSE_T("[%lu] %hs REQUEST ==> [%hs] version[%d.%d %hs] method[%hs]\n"),
|
||||
(unsigned long)time(NULL),
|
||||
@ -1814,6 +1855,7 @@ if (qse_htre_getcontentlen(req) > 0)
|
||||
{
|
||||
qse_printf (QSE_T("CONTENT [%.*S]\n"), (int)qse_htre_getcontentlen(req), qse_htre_getcontentptr(req));
|
||||
}
|
||||
#endif
|
||||
|
||||
if (peek)
|
||||
{
|
||||
@ -2044,11 +2086,12 @@ static void impede_httpd (qse_httpd_t* httpd)
|
||||
/* do nothing */
|
||||
}
|
||||
|
||||
static void logact_httpd (qse_httpd_t* httpd, qse_httpd_act_t* act)
|
||||
static void logact_httpd (qse_httpd_t* httpd, const qse_httpd_act_t* act)
|
||||
{
|
||||
/* do nothing */
|
||||
}
|
||||
|
||||
|
||||
static qse_httpd_scb_t httpd_system_callbacks =
|
||||
{
|
||||
/* server */
|
||||
@ -2341,11 +2384,11 @@ static int make_resource (
|
||||
|
||||
QSE_MEMSET (target, 0, QSE_SIZEOF(*target));
|
||||
|
||||
qse_printf (QSE_T(">>> MAKING RESOURCE [%hs]\n"), tmp.qpath);
|
||||
server_xtn = qse_httpd_getserverxtn (httpd, client->server);
|
||||
|
||||
if (server_xtn->query (httpd, client->server, req, tmp.xpath, QSE_HTTPD_SERVERSTD_DOCROOT, &tmp.docroot) <= -1 ||
|
||||
server_xtn->query (httpd, client->server, req, tmp.xpath, QSE_HTTPD_SERVERSTD_REALM, &tmp.realm) <= -1 ||
|
||||
if (server_xtn->query (httpd, client->server, req, tmp.xpath, QSE_HTTPD_SERVERSTD_DOCROOT, &tmp.docroot) <= -1) return -1;
|
||||
|
||||
if (server_xtn->query (httpd, client->server, req, tmp.xpath, QSE_HTTPD_SERVERSTD_REALM, &tmp.realm) <= -1 ||
|
||||
server_xtn->query (httpd, client->server, req, tmp.xpath, QSE_HTTPD_SERVERSTD_AUTH, &tmp.auth) <= -1 ||
|
||||
server_xtn->query (httpd, client->server, req, tmp.xpath, QSE_HTTPD_SERVERSTD_INDEX, &tmp.index) <= -1)
|
||||
{
|
||||
@ -2455,8 +2498,19 @@ auth_ok:
|
||||
}
|
||||
}
|
||||
|
||||
target->type = QSE_HTTPD_RSRC_DIR;
|
||||
target->u.dir.path = tmp.xpath;
|
||||
/* it is a directory - should i allow it? */
|
||||
if (server_xtn->query (httpd, client->server, req, tmp.xpath, QSE_HTTPD_SERVERSTD_DIRACC, &target->u.err.code) <= -1) target->u.err.code = 500;
|
||||
if (target->u.err.code != 200)
|
||||
{
|
||||
target->type = QSE_HTTPD_RSRC_ERR;
|
||||
/* free xpath since it won't be used */
|
||||
QSE_MMGR_FREE (httpd->mmgr, tmp.xpath);
|
||||
}
|
||||
else
|
||||
{
|
||||
target->type = QSE_HTTPD_RSRC_DIR;
|
||||
target->u.dir.path = tmp.xpath;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -2478,14 +2532,25 @@ auth_ok:
|
||||
}
|
||||
if (n >= 1) return 0;
|
||||
|
||||
/* fall back to a normal file. */
|
||||
target->type = QSE_HTTPD_RSRC_FILE;
|
||||
target->u.file.path = tmp.xpath;
|
||||
|
||||
if (server_xtn->query (httpd, client->server, req, tmp.xpath, QSE_HTTPD_SERVERSTD_MIME, &target->u.file.mime) <= -1)
|
||||
/* check file's access permission */
|
||||
if (server_xtn->query (httpd, client->server, req, tmp.xpath, QSE_HTTPD_SERVERSTD_FILEACC, &target->u.err.code) <= -1) target->u.err.code = 500;
|
||||
if (target->u.err.code != 200)
|
||||
{
|
||||
/* don't care about failure */
|
||||
target->u.file.mime = QSE_NULL;
|
||||
target->type = QSE_HTTPD_RSRC_ERR;
|
||||
/* free xpath since it won't be used */
|
||||
QSE_MMGR_FREE (httpd->mmgr, tmp.xpath);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* fall back to a normal file. */
|
||||
target->type = QSE_HTTPD_RSRC_FILE;
|
||||
target->u.file.path = tmp.xpath;
|
||||
|
||||
if (server_xtn->query (httpd, client->server, req, tmp.xpath, QSE_HTTPD_SERVERSTD_MIME, &target->u.file.mime) <= -1)
|
||||
{
|
||||
/* don't care about failure */
|
||||
target->u.file.mime = QSE_NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -2581,6 +2646,12 @@ static int query_server (
|
||||
|
||||
*(const qse_mchar_t**)result = QSE_NULL;
|
||||
return 0;
|
||||
|
||||
case QSE_HTTPD_SERVERSTD_DIRACC:
|
||||
case QSE_HTTPD_SERVERSTD_FILEACC:
|
||||
*(int*)result = 200;
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
qse_httpd_seterrnum (httpd, QSE_HTTPD_EINVAL);
|
||||
|
@ -457,7 +457,7 @@ static void purge_client (qse_httpd_t* httpd, qse_httpd_client_t* client)
|
||||
prev = client->prev;
|
||||
next = client->next;
|
||||
|
||||
if (httpd->opt.trait & QSE_HTTPD_ENABLELOG)
|
||||
if (httpd->opt.trait & QSE_HTTPD_LOGACT)
|
||||
{
|
||||
qse_httpd_act_t msg;
|
||||
msg.code = QSE_HTTPD_PURGE_CLIENT;
|
||||
@ -562,14 +562,13 @@ qse_printf (QSE_T("MUX ADDHND CLIENT READ %d\n"), client->handle.i);
|
||||
httpd->client.list.tail = client;
|
||||
}
|
||||
|
||||
{
|
||||
/* TODO: proper logging */
|
||||
qse_char_t tmp[128], tmp2[128], tmp3[128];
|
||||
qse_nwadtostr (&client->local_addr, tmp, QSE_COUNTOF(tmp), QSE_NWADTOSTR_ALL);
|
||||
qse_nwadtostr (&client->orgdst_addr, tmp2, QSE_COUNTOF(tmp2), QSE_NWADTOSTR_ALL);
|
||||
qse_nwadtostr (&client->remote_addr, tmp3, QSE_COUNTOF(tmp3), QSE_NWADTOSTR_ALL);
|
||||
qse_printf (QSE_T("connection %d accepted %s(%s from %s\n"), client->handle.i, tmp, tmp2, tmp3);
|
||||
}
|
||||
if (httpd->opt.trait & QSE_HTTPD_LOGACT)
|
||||
{
|
||||
qse_httpd_act_t msg;
|
||||
msg.code = QSE_HTTPD_ACCEPT_CLIENT;
|
||||
msg.u.client = client;
|
||||
httpd->opt.rcb.logact (httpd, &msg);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@ -733,7 +732,6 @@ reread:
|
||||
if (httpd->errnum == QSE_HTTPD_EAGAIN)
|
||||
{
|
||||
/* nothing to read yet. */
|
||||
qse_printf (QSE_T("Warning: Nothing to read from a client %d\n"), client->handle.i);
|
||||
return 0; /* return ok */
|
||||
}
|
||||
else if (httpd->errnum == QSE_HTTPD_EINTR)
|
||||
@ -743,14 +741,22 @@ qse_printf (QSE_T("Warning: Nothing to read from a client %d\n"), client->handle
|
||||
else
|
||||
{
|
||||
/* TOOD: if (httpd->errnum == QSE_HTTPD_ENOERR) httpd->errnum = QSE_HTTPD_ECALLBACK; */
|
||||
qse_printf (QSE_T("Error: failed to read from a client %d\n"), client->handle.i);
|
||||
/* TODO: find a way to disconnect */
|
||||
if (httpd->opt.trait & QSE_HTTPD_LOGACT)
|
||||
{
|
||||
qse_httpd_act_t msg;
|
||||
msg.code = QSE_HTTPD_READERR_CLIENT;
|
||||
msg.u.client = client;
|
||||
httpd->opt.rcb.logact (httpd, &msg);
|
||||
}
|
||||
/* TODO: find a way to disconnect */
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
else if (m == 0)
|
||||
{
|
||||
#if 0
|
||||
qse_printf (QSE_T("Debug: connection closed %d\n"), client->handle.i);
|
||||
#endif
|
||||
/* reading from the client returned 0. this typically
|
||||
* happens when the client closes the connection or
|
||||
* shutdown the writing half of the socket. it's
|
||||
@ -764,17 +770,22 @@ qse_printf (QSE_T("Debug: connection closed %d\n"), client->handle.i);
|
||||
/* there is still more tasks to finish and
|
||||
* http reader is not waiting for any more feeds. */
|
||||
client->status |= CLIENT_MUTE;
|
||||
#if 0
|
||||
qse_printf (QSE_T(">>>>> Marking client %d as MUTE\n"), client->handle.i);
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
#if 0
|
||||
qse_printf (QSE_T(">>>>> Returning failure for client %d\n"), client->handle.i);
|
||||
#endif
|
||||
httpd->errnum = QSE_HTTPD_EDISCON;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
#if 0
|
||||
qse_printf (QSE_T("!!!!!FEEDING %d from %d ["), (int)m, (int)client->handle.i);
|
||||
#if !defined(__WATCOMC__)
|
||||
{
|
||||
@ -783,6 +794,7 @@ for (i = 0; i < m; i++) qse_printf (QSE_T("%hc"), buf[i]);
|
||||
}
|
||||
#endif
|
||||
qse_printf (QSE_T("]\n"));
|
||||
#endif
|
||||
|
||||
/* qse_htrd_feed() may call the request callback
|
||||
* multiple times. that's because we don't know
|
||||
@ -798,17 +810,21 @@ qse_printf (QSE_T("]\n"));
|
||||
else httpd->errnum = QSE_HTTPD_ENOMEM; /* TODO: better translate error code */
|
||||
}
|
||||
|
||||
#if 0
|
||||
qse_printf (QSE_T("Error: http error while processing %d ["), (int)client->handle.i);
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < m; i++) qse_printf (QSE_T("%hc"), buf[i]);
|
||||
}
|
||||
qse_printf (QSE_T("]\n"));
|
||||
#endif
|
||||
|
||||
|
||||
return -1;
|
||||
}
|
||||
#if 0
|
||||
qse_printf (QSE_T("!!!!!FEEDING OK OK OK OK %d from %d\n"), (int)m, (int)client->handle.i);
|
||||
#endif
|
||||
|
||||
if (client->status & CLIENT_PENDING)
|
||||
{
|
||||
@ -840,7 +856,6 @@ static int invoke_client_task (
|
||||
int n, trigger_fired, client_handle_writable;
|
||||
|
||||
/* TODO: handle comparison callback ... */
|
||||
qse_printf (QSE_T("INVOKE CLIENT TASK..........\n"));
|
||||
if (handle.i == client->handle.i && (mask & QSE_HTTPD_MUX_READ)) /* TODO: no direct comparision */
|
||||
{
|
||||
if (!(client->status & CLIENT_MUTE) &&
|
||||
@ -850,7 +865,6 @@ qse_printf (QSE_T("INVOKE CLIENT TASK..........\n"));
|
||||
* purge the client in perform_client_task().
|
||||
* thus the following line isn't necessary.
|
||||
*if (httpd->errnum == QSE_HTTPD_EDISCON) return 0;*/
|
||||
qse_printf (QSE_T("ERROR: read from client [%d] failed...\n"), (int)handle.i);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
@ -862,7 +876,6 @@ qse_printf (QSE_T("ERROR: read from client [%d] failed...\n"), (int)handle.i);
|
||||
if (client->status & CLIENT_MUTE)
|
||||
{
|
||||
/* handle this delayed client disconnection */
|
||||
qse_printf (QSE_T("ERROR: mute client got no more task [%d] failed...\n"), (int)client->handle.i);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -908,7 +921,6 @@ qse_printf (QSE_T("ERROR: mute client got no more task [%d] failed...\n"), (int)
|
||||
}
|
||||
|
||||
n = task->main (httpd, client, task);
|
||||
qse_printf (QSE_T("task returend %d\n"), n);
|
||||
if (n <= -1) return -1;
|
||||
else if (n == 0)
|
||||
{
|
||||
@ -1118,17 +1130,12 @@ static int perform_client_task (
|
||||
qse_gettime (&client->last_active); /* TODO: error check??? */
|
||||
move_client_to_tail (httpd, client);
|
||||
|
||||
if (invoke_client_task (httpd, client, handle, mask) <= -1)
|
||||
{
|
||||
qse_printf (QSE_T("OOPS AFTER CLIENT TASK BAD XXXXXXXXXXXXXX [%d]\n"), (int)handle.i);
|
||||
goto oops;
|
||||
}
|
||||
if (invoke_client_task (httpd, client, handle, mask) <= -1) goto oops;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
oops:
|
||||
qse_printf (QSE_T("MARKING BAD XXXXXXXXXXXXXX [%d]\n"), (int)handle.i);
|
||||
/*purge_client (httpd, client);*/
|
||||
client->status |= CLIENT_BAD;
|
||||
client->bad_next = httpd->client.bad;
|
||||
@ -1336,3 +1343,8 @@ const qse_mchar_t* qse_httpd_fmtgmtimetobb (
|
||||
qse_fmthttptime (nt, httpd->gtbuf[idx], QSE_COUNTOF(httpd->gtbuf[idx]));
|
||||
return httpd->gtbuf[idx];
|
||||
}
|
||||
|
||||
|
||||
/* --------------------------------------------------- */
|
||||
|
||||
|
||||
|
Reference in New Issue
Block a user