added the shebang field to cgi.

changed qse_httpd_getoption()/qse_httpd_setoption() to qse_httpd_getopt()/qse_httpd_setopt() with QSE_HTTPD_TRAIT
fixed a bug of not passing the pred argument in qse_httpd_entaskrsrc().
This commit is contained in:
hyung-hwan 2013-01-30 14:08:38 +00:00
parent 543376b7d9
commit 1dd8de1566
9 changed files with 133 additions and 82 deletions

View File

@ -185,6 +185,7 @@ static int httpd_main (int argc, qse_char_t* argv[])
qse_httpd_t* httpd = QSE_NULL; qse_httpd_t* httpd = QSE_NULL;
qse_ntime_t tmout; qse_ntime_t tmout;
int ret = -1, i; int ret = -1, i;
int trait;
static qse_httpd_server_cbstd_t cbstd = { makersrc, freersrc }; static qse_httpd_server_cbstd_t cbstd = { makersrc, freersrc };
if (argc <= 1) if (argc <= 1)
@ -218,7 +219,8 @@ static int httpd_main (int argc, qse_char_t* argv[])
qse_httpd_setname (httpd, QSE_MT("qsehttpd 1.0")); qse_httpd_setname (httpd, QSE_MT("qsehttpd 1.0"));
qse_httpd_setoption (httpd, QSE_HTTPD_CGIERRTONUL); trait = QSE_HTTPD_CGIERRTONUL;
qse_httpd_setopt (httpd, QSE_HTTPD_TRAIT, &trait);
tmout.sec = 10; tmout.sec = 10;
tmout.nsec = 0; tmout.nsec = 0;
@ -259,7 +261,6 @@ int qse_main (int argc, qse_achar_t* argv[])
qse_setdflcmgrbyid (QSE_CMGR_SLMB); qse_setdflcmgrbyid (QSE_CMGR_SLMB);
} }
if (WSAStartup (MAKEWORD(2,0), &wsadata) != 0) if (WSAStartup (MAKEWORD(2,0), &wsadata) != 0)
{ {
qse_fprintf (QSE_STDERR, QSE_T("Failed to start up winsock\n")); qse_fprintf (QSE_STDERR, QSE_T("Failed to start up winsock\n"));

View File

@ -58,13 +58,20 @@ enum qse_httpd_errnum_t
}; };
typedef enum qse_httpd_errnum_t qse_httpd_errnum_t; typedef enum qse_httpd_errnum_t qse_httpd_errnum_t;
enum qse_httpd_option_t enum qse_httpd_opt_t
{
QSE_HTTPD_TRAIT
};
typedef enum qse_httpd_opt_t qse_httpd_opt_t;
enum qse_httpd_trait_t
{ {
QSE_HTTPD_MUTECLIENT = (1 << 0), QSE_HTTPD_MUTECLIENT = (1 << 0),
QSE_HTTPD_CGIERRTONUL = (1 << 1), QSE_HTTPD_CGIERRTONUL = (1 << 1),
QSE_HTTPD_CGINOCLOEXEC = (1 << 2), QSE_HTTPD_CGINOCLOEXEC = (1 << 2),
QSE_HTTPD_CGINOCHUNKED = (1 << 3) QSE_HTTPD_CGINOCHUNKED = (1 << 3)
}; };
typedef enum qse_httpd_trait_t qse_httpd_trait_t;
typedef struct qse_httpd_stat_t qse_httpd_stat_t; typedef struct qse_httpd_stat_t qse_httpd_stat_t;
struct qse_httpd_stat_t struct qse_httpd_stat_t
@ -383,8 +390,18 @@ enum qse_httpd_rsrc_type_t
}; };
typedef enum qse_httpd_rsrc_type_t qse_httpd_rsrc_type_t; typedef enum qse_httpd_rsrc_type_t qse_httpd_rsrc_type_t;
typedef struct qse_httpd_rsrc_t qse_httpd_rsrc_t; typedef struct qse_httpd_rsrc_cgi_t qse_httpd_rsrc_cgi_t;
struct qse_httpd_rsrc_cgi_t
{
const qse_mchar_t* path;
const qse_mchar_t* script;
const qse_mchar_t* suffix;
const qse_mchar_t* docroot;
const qse_mchar_t* shebang;
int nph;
};
typedef struct qse_httpd_rsrc_t qse_httpd_rsrc_t;
struct qse_httpd_rsrc_t struct qse_httpd_rsrc_t
{ {
qse_httpd_rsrc_type_t type; qse_httpd_rsrc_type_t type;
@ -394,14 +411,9 @@ struct qse_httpd_rsrc_t
{ {
const qse_mchar_t* realm; const qse_mchar_t* realm;
} auth; } auth;
struct
{ qse_httpd_rsrc_cgi_t cgi;
const qse_mchar_t* path;
const qse_mchar_t* script;
const qse_mchar_t* suffix;
const qse_mchar_t* docroot;
int nph;
} cgi;
struct struct
{ {
const qse_mchar_t* path; const qse_mchar_t* path;
@ -478,9 +490,10 @@ struct qse_httpd_server_cbstd_t
typedef struct qse_httpd_server_cgistd_t qse_httpd_server_cgistd_t; typedef struct qse_httpd_server_cgistd_t qse_httpd_server_cgistd_t;
struct qse_httpd_server_cgistd_t struct qse_httpd_server_cgistd_t
{ {
const qse_mchar_t* ext; const qse_mchar_t* ext;
qse_size_t len; qse_size_t len;
int nph; int nph;
const qse_mchar_t* shebang; /* optional, can be #QSE_NULL */
}; };
typedef struct qse_httpd_server_mimestd_t qse_httpd_server_mimestd_t; typedef struct qse_httpd_server_mimestd_t qse_httpd_server_mimestd_t;
@ -551,13 +564,16 @@ QSE_EXPORT void qse_httpd_seterrnum (
qse_httpd_errnum_t errnum qse_httpd_errnum_t errnum
); );
QSE_EXPORT int qse_httpd_getoption ( QSE_EXPORT int qse_httpd_getopt (
qse_httpd_t* httpd qse_httpd_t* httpd,
qse_httpd_opt_t id,
void* value
); );
QSE_EXPORT void qse_httpd_setoption ( QSE_EXPORT int qse_httpd_setopt (
qse_httpd_t* httpd, qse_httpd_t* httpd,
int option qse_httpd_opt_t id,
const void* value
); );
/** /**
@ -758,11 +774,7 @@ QSE_EXPORT qse_httpd_task_t* qse_httpd_entaskcgi (
qse_httpd_t* httpd, qse_httpd_t* httpd,
qse_httpd_client_t* client, qse_httpd_client_t* client,
qse_httpd_task_t* pred, qse_httpd_task_t* pred,
const qse_mchar_t* path, qse_httpd_rsrc_cgi_t* cgi,
const qse_mchar_t* script,
const qse_mchar_t* suffix,
const qse_mchar_t* docroot,
int nph,
qse_htre_t* req qse_htre_t* req
); );

View File

@ -504,7 +504,7 @@ int qse_awk_setopt (qse_awk_t* awk, qse_awk_opt_t id, const void* value)
return -1; return -1;
} }
int qse_awk_getopt (qse_awk_t* awk, qse_awk_opt_t id, void* value) int qse_awk_getopt (qse_awk_t* awk, qse_awk_opt_t id, void* value)
{ {
switch (id) switch (id)
{ {

View File

@ -33,6 +33,7 @@ struct task_cgi_arg_t
qse_mcstr_t script; qse_mcstr_t script;
qse_mcstr_t suffix; qse_mcstr_t suffix;
qse_mcstr_t docroot; qse_mcstr_t docroot;
qse_mcstr_t shebang;
int nph; int nph;
qse_htre_t* req; qse_htre_t* req;
}; };
@ -47,6 +48,7 @@ struct task_cgi_t
const qse_mchar_t* script; const qse_mchar_t* script;
const qse_mchar_t* suffix; const qse_mchar_t* suffix;
const qse_mchar_t* docroot; const qse_mchar_t* docroot;
const qse_mchar_t* shebang;
qse_http_version_t version; qse_http_version_t version;
int keepalive; /* taken from the request */ int keepalive; /* taken from the request */
int nph; int nph;
@ -706,10 +708,12 @@ static int task_init_cgi (
cgi->script = cgi->path + arg->path.len + 1; cgi->script = cgi->path + arg->path.len + 1;
cgi->suffix = cgi->script + arg->script.len + 1; cgi->suffix = cgi->script + arg->script.len + 1;
cgi->docroot = cgi->suffix + arg->suffix.len + 1; cgi->docroot = cgi->suffix + arg->suffix.len + 1;
cgi->shebang = cgi->docroot + arg->docroot.len + 1;
qse_mbscpy ((qse_mchar_t*)cgi->path, arg->path.ptr); qse_mbscpy ((qse_mchar_t*)cgi->path, arg->path.ptr);
qse_mbscpy ((qse_mchar_t*)cgi->script, arg->script.ptr); qse_mbscpy ((qse_mchar_t*)cgi->script, arg->script.ptr);
qse_mbscpy ((qse_mchar_t*)cgi->suffix, arg->suffix.ptr); qse_mbscpy ((qse_mchar_t*)cgi->suffix, arg->suffix.ptr);
qse_mbscpy ((qse_mchar_t*)cgi->docroot, arg->docroot.ptr); qse_mbscpy ((qse_mchar_t*)cgi->docroot, arg->docroot.ptr);
qse_mbscpy ((qse_mchar_t*)cgi->shebang, arg->shebang.ptr);
cgi->version = *qse_htre_getversion(arg->req); cgi->version = *qse_htre_getversion(arg->req);
cgi->keepalive = (arg->req->attr.flags & QSE_HTRE_ATTR_KEEPALIVE); cgi->keepalive = (arg->req->attr.flags & QSE_HTRE_ATTR_KEEPALIVE);
@ -737,7 +741,7 @@ static int task_init_cgi (
* such a request to entask a cgi script dropping the * such a request to entask a cgi script dropping the
* content */ * content */
if (httpd->option & QSE_HTTPD_CGINOCHUNKED) if (httpd->opt.trait & QSE_HTTPD_CGINOCHUNKED)
{ {
qse_htre_discardcontent (arg->req); qse_htre_discardcontent (arg->req);
cgi->reqflags |= CGI_REQ_GOTALL; cgi->reqflags |= CGI_REQ_GOTALL;
@ -844,8 +848,8 @@ done:
} }
/* get the content type header value */ /* get the content type header value */
tmp = qse_htre_getheaderval(arg->req, QSE_MT("Content-Type")); tmp = qse_htre_getheaderval(arg->req, QSE_MT("Content-Type"));
if (tmp) while (tmp->next) tmp = tmp->next; /* get the last value */ if (tmp) while (tmp->next) tmp = tmp->next; /* get the last value */
if (cgi_add_env ( if (cgi_add_env (
httpd, client, cgi->env, arg->req, httpd, client, cgi->env, arg->req,
@ -1332,8 +1336,9 @@ static int task_main_cgi (
qse_httpd_t* httpd, qse_httpd_client_t* client, qse_httpd_task_t* task) qse_httpd_t* httpd, qse_httpd_client_t* client, qse_httpd_task_t* task)
{ {
task_cgi_t* cgi = (task_cgi_t*)task->ctx; task_cgi_t* cgi = (task_cgi_t*)task->ctx;
int pio_options; int pio_options, x;
int http_errnum = 500; int http_errnum = 500;
qse_mchar_t* xpath;
if (cgi->init_failed) goto oops; if (cgi->init_failed) goto oops;
@ -1368,16 +1373,31 @@ static int task_main_cgi (
} }
pio_options = QSE_PIO_READOUT | QSE_PIO_WRITEIN | QSE_PIO_MBSCMD; pio_options = QSE_PIO_READOUT | QSE_PIO_WRITEIN | QSE_PIO_MBSCMD;
if (httpd->option & QSE_HTTPD_CGIERRTONUL) if (httpd->opt.trait & QSE_HTTPD_CGIERRTONUL)
pio_options |= QSE_PIO_ERRTONUL; pio_options |= QSE_PIO_ERRTONUL;
else else
pio_options |= QSE_PIO_ERRTOOUT; pio_options |= QSE_PIO_ERRTOOUT;
if (httpd->option & QSE_HTTPD_CGINOCLOEXEC) if (httpd->opt.trait & QSE_HTTPD_CGINOCLOEXEC)
pio_options |= QSE_PIO_NOCLOEXEC; pio_options |= QSE_PIO_NOCLOEXEC;
if (qse_pio_init ( if (cgi->shebang[0] != QSE_MT('\0'))
&cgi->pio, httpd->mmgr, (const qse_char_t*)cgi->path, {
cgi->env, pio_options) <= -1) const qse_mchar_t* tmp[4];
tmp[0] = cgi->shebang;
tmp[1] = QSE_MT(" ");
tmp[2] = cgi->path;
tmp[3] = QSE_NULL;
xpath = qse_mbsadup (tmp, QSE_NULL, httpd->mmgr);
if (xpath == QSE_NULL) goto oops;
}
else xpath = cgi->path;
x = qse_pio_init (
&cgi->pio, httpd->mmgr, (const qse_char_t*)xpath,
cgi->env, pio_options);
if (xpath != cgi->path) QSE_MMGR_FREE (httpd->mmgr, xpath);
if (x <= -1)
{ {
qse_pio_errnum_t errnum; qse_pio_errnum_t errnum;
@ -1468,30 +1488,31 @@ qse_httpd_task_t* qse_httpd_entaskcgi (
qse_httpd_t* httpd, qse_httpd_t* httpd,
qse_httpd_client_t* client, qse_httpd_client_t* client,
qse_httpd_task_t* pred, qse_httpd_task_t* pred,
const qse_mchar_t* path, qse_httpd_rsrc_cgi_t* cgi,
const qse_mchar_t* script,
const qse_mchar_t* suffix,
const qse_mchar_t* docroot,
int nph,
qse_htre_t* req) qse_htre_t* req)
{ {
qse_httpd_task_t task; qse_httpd_task_t task;
task_cgi_arg_t arg; task_cgi_arg_t arg;
qse_httpd_rsrc_cgi_t rsrc;
if (script == QSE_NULL) script = qse_htre_getqpath(req); rsrc = *cgi;
if (suffix == QSE_NULL) suffix = QSE_MT(""); if (rsrc.script == QSE_NULL) rsrc.script = qse_htre_getqpath(req);
if (docroot == QSE_NULL) docroot = QSE_MT(""); if (rsrc.suffix == QSE_NULL) rsrc.suffix = QSE_MT("");
if (rsrc.docroot == QSE_NULL) rsrc.docroot = QSE_MT("");
if (rsrc.shebang == QSE_NULL) rsrc.shebang = QSE_MT("");
arg.path.ptr = path; arg.path.ptr = rsrc.path;
arg.path.len = qse_mbslen(path); arg.path.len = qse_mbslen(rsrc.path);
arg.script.ptr = script; arg.script.ptr = rsrc.script;
arg.script.len = qse_mbslen(script); arg.script.len = qse_mbslen(rsrc.script);
arg.suffix.ptr = suffix; arg.suffix.ptr = rsrc.suffix;
arg.suffix.len = qse_mbslen(suffix); arg.suffix.len = qse_mbslen(rsrc.suffix);
arg.docroot.ptr = docroot; arg.docroot.ptr = rsrc.docroot;
arg.docroot.len = qse_mbslen(docroot); arg.docroot.len = qse_mbslen(rsrc.docroot);
arg.nph = rsrc.nph;
arg.shebang.ptr = rsrc.shebang;
arg.shebang.len = qse_mbslen(rsrc.shebang);
arg.req = req; arg.req = req;
arg.nph = nph;
QSE_MEMSET (&task, 0, QSE_SIZEOF(task)); QSE_MEMSET (&task, 0, QSE_SIZEOF(task));
task.init = task_init_cgi; task.init = task_init_cgi;
@ -1502,10 +1523,11 @@ qse_httpd_task_t* qse_httpd_entaskcgi (
return qse_httpd_entask ( return qse_httpd_entask (
httpd, client, pred, &task, httpd, client, pred, &task,
QSE_SIZEOF(task_cgi_t) + QSE_SIZEOF(task_cgi_t) +
((arg.path.len + 1) * QSE_SIZEOF(*path)) + ((arg.path.len + 1) * QSE_SIZEOF(*arg.path.ptr)) +
((arg.script.len + 1) * QSE_SIZEOF(*script)) + ((arg.script.len + 1) * QSE_SIZEOF(*arg.script.ptr)) +
((arg.suffix.len + 1) * QSE_SIZEOF(*suffix)) + ((arg.suffix.len + 1) * QSE_SIZEOF(*arg.suffix.ptr)) +
((arg.docroot.len + 1) * QSE_SIZEOF(*docroot)) ((arg.docroot.len + 1) * QSE_SIZEOF(*arg.docroot.ptr)) +
((arg.shebang.len + 1) * QSE_SIZEOF(*arg.shebang.ptr))
); );
} }

View File

@ -885,7 +885,6 @@ static int task_main_proxy_5 (
task_proxy_t* proxy = (task_proxy_t*)task->ctx; task_proxy_t* proxy = (task_proxy_t*)task->ctx;
qse_ssize_t n; qse_ssize_t n;
//QSE_ASSERT (proxy->pio_inited);
qse_printf (QSE_T("task_main_proxy_5 trigger[0].mask=%d trigger[1].mask=%d trigger[2].mask=%d\n"), qse_printf (QSE_T("task_main_proxy_5 trigger[0].mask=%d trigger[1].mask=%d trigger[2].mask=%d\n"),
task->trigger[0].mask, task->trigger[1].mask, task->trigger[2].mask); task->trigger[0].mask, task->trigger[1].mask, task->trigger[2].mask);
@ -932,8 +931,6 @@ static int task_main_proxy_4 (
{ {
task_proxy_t* proxy = (task_proxy_t*)task->ctx; task_proxy_t* proxy = (task_proxy_t*)task->ctx;
//QSE_ASSERT (proxy->pio_inited);
qse_printf (QSE_T("task_main_proxy_4 trigger[0].mask=%d trigger[1].mask=%d trigger[2].mask=%d\n"), qse_printf (QSE_T("task_main_proxy_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); task->trigger[0].mask, task->trigger[1].mask, task->trigger[2].mask);

View File

@ -2049,6 +2049,7 @@ static int attempt_cgi (
target->u.cgi.script = script; target->u.cgi.script = script;
target->u.cgi.suffix = QSE_NULL; target->u.cgi.suffix = QSE_NULL;
target->u.cgi.docroot = docroot; target->u.cgi.docroot = docroot;
target->u.cgi.shebang = cgistd[i].shebang;
return 1; return 1;
} }
} }
@ -2095,6 +2096,7 @@ static int attempt_cgi (
target->u.cgi.script = script; target->u.cgi.script = script;
target->u.cgi.suffix = suffix; target->u.cgi.suffix = suffix;
target->u.cgi.docroot = docroot; target->u.cgi.docroot = docroot;
target->u.cgi.shebang = cgistd[i].shebang;
return 1; return 1;
} }
} }
@ -2154,7 +2156,7 @@ auth_ok:
if (stx <= -1) if (stx <= -1)
{ {
/* this OS may fail in stat_file() if the path contains the trailing /* this OS may fail in stat_file() if the path contains the trailing
* separator. it 's beause of the way FindFirstFile() or DosQueryPathInfo() * separator. it's beause of the way FindFirstFile() or DosQueryPathInfo()
* is ussed in stat_file(). let me work around it here. */ * is ussed in stat_file(). let me work around it here. */
qse_size_t pl = qse_mbslen(xpath); qse_size_t pl = qse_mbslen(xpath);
if (pl > 1 && xpath[pl - 1] == QSE_MT('/')) if (pl > 1 && xpath[pl - 1] == QSE_MT('/'))
@ -2271,11 +2273,12 @@ qse_httpd_server_t* qse_httpd_attachserverstd (
qse_uint16_t default_port; qse_uint16_t default_port;
qse_uri_t xuri; qse_uri_t xuri;
static qse_httpd_server_cgistd_t server_cgistd[] = static qse_httpd_server_cgistd_t server_cgistd[] =
{ {
{ QSE_MT(".cgi"), 4, 0 }, { QSE_MT(".cgi"), 4, 0, QSE_NULL },
{ QSE_MT(".nph"), 4, 1 }, { QSE_MT(".nph"), 4, 1, QSE_NULL },
{ QSE_NULL, 0, 0 } { QSE_NULL, 0, 0, QSE_NULL }
}; };
static qse_httpd_server_mimestd_t server_mimestd[] = static qse_httpd_server_mimestd_t server_mimestd[] =
@ -2458,7 +2461,7 @@ int qse_httpd_getserveroptstd (
case QSE_HTTPD_SERVER_CGISTD: case QSE_HTTPD_SERVER_CGISTD:
case QSE_HTTPD_SERVER_MIMESTD: case QSE_HTTPD_SERVER_MIMESTD:
case QSE_HTTPD_SERVER_IDXSTD: case QSE_HTTPD_SERVER_IDXSTD:
*(qse_mchar_t**)value = (void*)server_xtn->cfg2.a[id - QSE_HTTPD_SERVER_CBSTD]; *(void**)value = (void*)server_xtn->cfg2.a[id - QSE_HTTPD_SERVER_CBSTD];
return 0; return 0;
} }

View File

@ -405,45 +405,42 @@ qse_httpd_task_t* qse_httpd_entaskrsrc (
switch (rsrc->type) switch (rsrc->type)
{ {
case QSE_HTTPD_RSRC_AUTH: case QSE_HTTPD_RSRC_AUTH:
task = qse_httpd_entaskauth (httpd, client, QSE_NULL, rsrc->u.auth.realm, req); task = qse_httpd_entaskauth (httpd, client, pred, rsrc->u.auth.realm, req);
break; break;
case QSE_HTTPD_RSRC_CGI: case QSE_HTTPD_RSRC_CGI:
task = qse_httpd_entaskcgi ( task = qse_httpd_entaskcgi (httpd, client, pred, &rsrc->u.cgi, req);
httpd, client, QSE_NULL, rsrc->u.cgi.path,
rsrc->u.cgi.script, rsrc->u.cgi.suffix,
rsrc->u.cgi.docroot, rsrc->u.cgi.nph, req);
break; break;
case QSE_HTTPD_RSRC_DIR: case QSE_HTTPD_RSRC_DIR:
qse_httpd_discardcontent (httpd, req); qse_httpd_discardcontent (httpd, req);
task = qse_httpd_entaskdir (httpd, client, QSE_NULL, rsrc->u.dir.path, req); task = qse_httpd_entaskdir (httpd, client, pred, rsrc->u.dir.path, req);
break; break;
case QSE_HTTPD_RSRC_ERR: case QSE_HTTPD_RSRC_ERR:
qse_httpd_discardcontent (httpd, req); qse_httpd_discardcontent (httpd, req);
task = qse_httpd_entaskerr (httpd, client, QSE_NULL, rsrc->u.err.code, req); task = qse_httpd_entaskerr (httpd, client, pred, rsrc->u.err.code, req);
break; break;
case QSE_HTTPD_RSRC_FILE: case QSE_HTTPD_RSRC_FILE:
qse_httpd_discardcontent (httpd, req); qse_httpd_discardcontent (httpd, req);
task = qse_httpd_entaskfile (httpd, client, QSE_NULL, rsrc->u.file.path, rsrc->u.file.mime, req); task = qse_httpd_entaskfile (httpd, client, pred, rsrc->u.file.path, rsrc->u.file.mime, req);
break; break;
case QSE_HTTPD_RSRC_PROXY: case QSE_HTTPD_RSRC_PROXY:
task = qse_httpd_entaskproxy (httpd, client, QSE_NULL, &rsrc->u.proxy.dst, &rsrc->u.proxy.src, req); task = qse_httpd_entaskproxy (httpd, client, pred, &rsrc->u.proxy.dst, &rsrc->u.proxy.src, req);
break; break;
case QSE_HTTPD_RSRC_RELOC: case QSE_HTTPD_RSRC_RELOC:
task = qse_httpd_entaskreloc (httpd, client, QSE_NULL, rsrc->u.reloc.dst, req); task = qse_httpd_entaskreloc (httpd, client, pred, rsrc->u.reloc.dst, req);
break; break;
case QSE_HTTPD_RSRC_REDIR: case QSE_HTTPD_RSRC_REDIR:
task = qse_httpd_entaskredir (httpd, client, QSE_NULL, rsrc->u.redir.dst, req); task = qse_httpd_entaskredir (httpd, client, pred, rsrc->u.redir.dst, req);
break; break;
case QSE_HTTPD_RSRC_TEXT: case QSE_HTTPD_RSRC_TEXT:
task = qse_httpd_entasktext (httpd, client, QSE_NULL, rsrc->u.text.ptr, rsrc->u.text.mime, req); task = qse_httpd_entasktext (httpd, client, pred, rsrc->u.text.ptr, rsrc->u.text.mime, req);
break; break;
default: default:

View File

@ -109,14 +109,30 @@ void* qse_httpd_getxtn (qse_httpd_t* httpd)
return QSE_XTN (httpd); return QSE_XTN (httpd);
} }
int qse_httpd_getoption (qse_httpd_t* httpd) int qse_httpd_getopt (qse_httpd_t* httpd, qse_httpd_opt_t id, void* value)
{ {
return httpd->option; switch (id)
{
case QSE_HTTPD_TRAIT:
*(int*)value = httpd->opt.trait;
return 0;
}
httpd->errnum = QSE_HTTPD_EINVAL;
return -1;
} }
void qse_httpd_setoption (qse_httpd_t* httpd, int option) int qse_httpd_setopt (qse_httpd_t* httpd, qse_httpd_opt_t id, const void* value)
{ {
httpd->option = option; switch (id)
{
case QSE_HTTPD_TRAIT:
httpd->opt.trait = *(const int*)value;
return 0;
}
httpd->errnum = QSE_HTTPD_EINVAL;
return -1;
} }
/* --------------------------------------------------- */ /* --------------------------------------------------- */
@ -640,7 +656,7 @@ qse_printf (QSE_T("Debug: connection closed %d\n"), client->handle.i);
* if QSE_HTTPD_MUTECLIENT is on, attempt to handle * if QSE_HTTPD_MUTECLIENT is on, attempt to handle
* it as a half-close under a certain condition. */ * it as a half-close under a certain condition. */
if (httpd->option & QSE_HTTPD_MUTECLIENT && if (httpd->opt.trait & QSE_HTTPD_MUTECLIENT &&
client->task.head && client->htrd->clean) client->task.head && client->htrd->clean)
{ {
/* there is still more tasks to finish and /* there is still more tasks to finish and

View File

@ -35,7 +35,10 @@ struct qse_httpd_t
qse_httpd_scb_t* scb; /* system callbacks */ qse_httpd_scb_t* scb; /* system callbacks */
qse_httpd_rcb_t* rcb; /* request callbacks */ qse_httpd_rcb_t* rcb; /* request callbacks */
int option; struct
{
int trait;
} opt;
int stopreq; int stopreq;
qse_mchar_t sname[128]; /* server name for the server header */ qse_mchar_t sname[128]; /* server name for the server header */