renamed qse_httpd_reconf() to qse_httpd_impede().

added more enhancements to httpd
This commit is contained in:
hyung-hwan 2013-02-20 08:47:22 +00:00
parent ddae5542d2
commit b677b4a892
14 changed files with 377 additions and 221 deletions

View File

@ -35,8 +35,6 @@
# include <openssl/engine.h> # include <openssl/engine.h>
#endif #endif
static void reconf_server (qse_httpd_t* httpd, qse_httpd_server_t* server);
/* --------------------------------------------------------------------- */ /* --------------------------------------------------------------------- */
static qse_httpd_t* g_httpd = QSE_NULL; static qse_httpd_t* g_httpd = QSE_NULL;
@ -48,7 +46,11 @@ static void sigint (int sig)
static void sighup (int sig) static void sighup (int sig)
{ {
if (g_httpd) qse_httpd_reconf (g_httpd); if (g_httpd)
{
/* arrange to intefere with httpd to perform reconfiguration */
qse_httpd_impede (g_httpd);
}
} }
static void setup_signal_handlers () static void setup_signal_handlers ()
@ -181,7 +183,7 @@ struct httpd_xtn_t
{ {
const qse_char_t* cfgfile; const qse_char_t* cfgfile;
qse_xli_t* xli; qse_xli_t* xli;
qse_httpd_ecb_t ecb; qse_httpd_impede_t orgimpede;
}; };
static int make_resource ( static int make_resource (
@ -222,8 +224,7 @@ static int make_resource (
if (server_xtn->nodir && rsrc->type == QSE_HTTPD_RSRC_DIR) if (server_xtn->nodir && rsrc->type == QSE_HTTPD_RSRC_DIR)
{ {
/* prohibit no directory listing */ /* prohibit no directory listing */
if (server_xtn->orgfreersrc) server_xtn->orgfreersrc (httpd, client, req, rsrc);
server_xtn->orgfreersrc (httpd, client, req, rsrc);
rsrc->type = QSE_HTTPD_RSRC_ERR; rsrc->type = QSE_HTTPD_RSRC_ERR;
rsrc->u.err.code = 403; rsrc->u.err.code = 403;
} }
@ -245,8 +246,7 @@ static void free_resource (
} }
else else
{ {
if (server_xtn->orgfreersrc) server_xtn->orgfreersrc (httpd, client, req, rsrc);
server_xtn->orgfreersrc (httpd, client, req, rsrc);
} }
} }
/* --------------------------------------------------------------------- */ /* --------------------------------------------------------------------- */
@ -653,7 +653,6 @@ static qse_httpd_server_t* attach_server (qse_httpd_t* httpd, int num, qse_xli_l
} }
dope.detach = detach_server; dope.detach = detach_server;
dope.reconf = reconf_server;
xserver = qse_httpd_attachserverstd (httpd, &dope, QSE_SIZEOF(server_xtn_t)); xserver = qse_httpd_attachserverstd (httpd, &dope, QSE_SIZEOF(server_xtn_t));
if (xserver == QSE_NULL) if (xserver == QSE_NULL)
{ {
@ -701,7 +700,6 @@ static int open_config_file (qse_httpd_t* httpd)
trait |= QSE_XLI_KEYNAME; trait |= QSE_XLI_KEYNAME;
qse_xli_setopt (httpd_xtn->xli, QSE_XLI_TRAIT, &trait); qse_xli_setopt (httpd_xtn->xli, QSE_XLI_TRAIT, &trait);
xli_in.type = QSE_XLI_IOSTD_FILE; xli_in.type = QSE_XLI_IOSTD_FILE;
xli_in.u.file.path = httpd_xtn->cfgfile; xli_in.u.file.path = httpd_xtn->cfgfile;
xli_in.u.file.cmgr = QSE_NULL; xli_in.u.file.cmgr = QSE_NULL;
@ -795,19 +793,6 @@ oops:
return -1; return -1;
} }
static void reconf_httpd (qse_httpd_t* httpd, qse_httpd_ecb_reconf_type_t type)
{
switch (type)
{
case QSE_HTTPD_ECB_RECONF_PRE:
open_config_file (httpd);
break;
case QSE_HTTPD_ECB_RECONF_POST:
close_config_file (httpd);
break;
}
}
static void reconf_server (qse_httpd_t* httpd, qse_httpd_server_t* server) static void reconf_server (qse_httpd_t* httpd, qse_httpd_server_t* server)
{ {
@ -815,6 +800,8 @@ static void reconf_server (qse_httpd_t* httpd, qse_httpd_server_t* server)
server_xtn_t* server_xtn; server_xtn_t* server_xtn;
qse_xli_pair_t* pair; qse_xli_pair_t* pair;
/* reconfigure the server when the server is impeded. */
httpd_xtn = qse_httpd_getxtnstd (httpd); httpd_xtn = qse_httpd_getxtnstd (httpd);
server_xtn = qse_httpd_getserverstdxtn (httpd, server); server_xtn = qse_httpd_getserverstdxtn (httpd, server);
@ -832,6 +819,50 @@ static void reconf_server (qse_httpd_t* httpd, qse_httpd_server_t* server)
} }
} }
static void impede_httpd (qse_httpd_t* httpd)
{
httpd_xtn_t* httpd_xtn;
httpd_xtn = qse_httpd_getxtnstd (httpd);
if (open_config_file (httpd) >= 0)
{
qse_httpd_server_t* server;
server = qse_httpd_getfirstserver (httpd);
while (server)
{
if (server->dope.flags & QSE_HTTPD_SERVER_ACTIVE)
reconf_server (httpd, server);
server = qse_httpd_getnextserver (httpd, server);
}
close_config_file (httpd);
}
/* chain-call the orignal impedence function */
if (httpd_xtn->orgimpede) httpd_xtn->orgimpede (httpd);
}
static void logact_httpd (qse_httpd_t* httpd, qse_httpd_act_t* act)
{
httpd_xtn_t* httpd_xtn;
qse_char_t tmp[256];
httpd_xtn = qse_httpd_getxtnstd (httpd);
switch (act->code)
{
case QSE_HTTPD_ACCEPT_CLIENT:
break;
case QSE_HTTPD_PURGE_CLIENT:
qse_nwadtostr (&act->u.client->remote_addr, tmp, QSE_COUNTOF(tmp), QSE_NWADTOSTR_ALL);
qse_printf (QSE_T("purged client from %s\n"), tmp);
break;
}
}
/* --------------------------------------------------------------------- */ /* --------------------------------------------------------------------- */
static int httpd_main (int argc, qse_char_t* argv[]) static int httpd_main (int argc, qse_char_t* argv[])
{ {
@ -839,6 +870,7 @@ static int httpd_main (int argc, qse_char_t* argv[])
httpd_xtn_t* httpd_xtn; httpd_xtn_t* httpd_xtn;
qse_ntime_t tmout; qse_ntime_t tmout;
int trait, ret = -1; int trait, ret = -1;
qse_httpd_rcb_t rcb;
if (argc != 2) if (argc != 2)
{ {
@ -857,21 +889,30 @@ static int httpd_main (int argc, qse_char_t* argv[])
httpd_xtn = qse_httpd_getxtnstd (httpd); httpd_xtn = qse_httpd_getxtnstd (httpd);
httpd_xtn->cfgfile = argv[1]; httpd_xtn->cfgfile = argv[1];
httpd_xtn->ecb.reconf = reconf_httpd;
qse_httpd_pushecb (httpd, &httpd_xtn->ecb);
if (load_config (httpd) <= -1) goto oops; if (load_config (httpd) <= -1) goto oops;
g_httpd = httpd; g_httpd = httpd;
setup_signal_handlers (); setup_signal_handlers ();
qse_httpd_getopt (httpd, QSE_HTTPD_TRAIT, &trait); qse_httpd_getopt (httpd, QSE_HTTPD_TRAIT, &trait);
trait |= QSE_HTTPD_CGIERRTONUL; trait |= QSE_HTTPD_CGIERRTONUL | QSE_HTTPD_ENABLELOG;
qse_httpd_setopt (httpd, QSE_HTTPD_TRAIT, &trait); qse_httpd_setopt (httpd, QSE_HTTPD_TRAIT, &trait);
tmout.sec = 10; tmout.sec = 10;
tmout.nsec = 0; tmout.nsec = 0;
ret = qse_httpd_loopstd (httpd, &tmout); qse_httpd_setopt (httpd, QSE_HTTPD_TMOUT, &tmout);
tmout.sec = 30;
tmout.nsec = 0;
qse_httpd_setopt (httpd, QSE_HTTPD_IDLELIMIT, &tmout);
qse_httpd_getopt (httpd, QSE_HTTPD_RCB, &rcb);
httpd_xtn->orgimpede = rcb.impede;
rcb.impede = impede_httpd; /* executed when qse_httpd_impede() is called */
rcb.logact = logact_httpd; /* i don't remember this */
qse_httpd_setopt (httpd, QSE_HTTPD_RCB, &rcb);
ret = qse_httpd_loopstd (httpd);
restore_signal_handlers (); restore_signal_handlers ();
g_httpd = QSE_NULL; g_httpd = QSE_NULL;

View File

@ -65,8 +65,8 @@ typedef struct qse_htrd_recbs_t qse_htrd_recbs_t;
struct qse_htrd_recbs_t struct qse_htrd_recbs_t
{ {
int (*peek) (qse_htrd_t* htrd, qse_htre_t* re); int (*peek) (qse_htrd_t* htrd, qse_htre_t* re);
int (*handle) (qse_htrd_t* htrd, qse_htre_t* re); int (*poke) (qse_htrd_t* htrd, qse_htre_t* re);
}; };
struct qse_htrd_t struct qse_htrd_t

View File

@ -61,7 +61,11 @@ typedef enum qse_httpd_errnum_t qse_httpd_errnum_t;
enum qse_httpd_opt_t enum qse_httpd_opt_t
{ {
QSE_HTTPD_TRAIT QSE_HTTPD_TRAIT,
QSE_HTTPD_SCB,
QSE_HTTPD_RCB,
QSE_HTTPD_TMOUT,
QSE_HTTPD_IDLELIMIT
}; };
typedef enum qse_httpd_opt_t qse_httpd_opt_t; typedef enum qse_httpd_opt_t qse_httpd_opt_t;
@ -70,7 +74,8 @@ 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),
QSE_HTTPD_ENABLELOG = (1 << 4)
}; };
typedef enum qse_httpd_trait_t qse_httpd_trait_t; typedef enum qse_httpd_trait_t qse_httpd_trait_t;
@ -222,26 +227,74 @@ struct qse_httpd_scb_t
qse_httpd_t* httpd, qse_httpd_t* httpd,
qse_httpd_client_t* client); /* optional */ qse_httpd_client_t* client); /* optional */
} client; } client;
}; };
/* -------------------------------------------------------------------------- */
typedef int (*qse_httpd_peekreq_t) (
qse_httpd_t* httpd,
qse_httpd_client_t* client,
qse_htre_t* req
);
typedef int (*qse_httpd_pokereq_t) (
qse_httpd_t* httpd,
qse_httpd_client_t* client,
qse_htre_t* req
);
typedef int (*qse_httpd_fmterr_t) (
qse_httpd_t* httpd,
qse_httpd_client_t* client,
int code,
qse_mchar_t* buf,
int bufsz
);
typedef int (*qse_httpd_fmtdir_t) (
qse_httpd_t* httpd,
qse_httpd_client_t* client,
const qse_mchar_t* qpath,
const qse_httpd_dirent_t* dirent,
qse_mchar_t* buf,
int bufsz
);
typedef void (*qse_httpd_impede_t) (
qse_httpd_t* httpd
);
enum qse_httpd_act_code_t
{
QSE_HTTPD_ACCEPT_CLIENT,
QSE_HTTPD_PURGE_CLIENT,
};
typedef enum qse_httpd_act_code_t qse_httpd_act_code_t;
struct qse_httpd_act_t
{
qse_httpd_act_code_t code;
union
{
qse_httpd_client_t* client;
} u;
};
typedef struct qse_httpd_act_t qse_httpd_act_t;
typedef void (*qse_httpd_logact_t) (
qse_httpd_t* httpd,
const qse_httpd_act_t* act
);
typedef struct qse_httpd_rcb_t qse_httpd_rcb_t; typedef struct qse_httpd_rcb_t qse_httpd_rcb_t;
struct qse_httpd_rcb_t struct qse_httpd_rcb_t
{ {
int (*peek_request) ( qse_httpd_peekreq_t peekreq;
qse_httpd_t* httpd, qse_httpd_client_t* client, qse_htre_t* req); qse_httpd_pokereq_t pokereq;
int (*handle_request) ( qse_httpd_fmterr_t fmterr;
qse_httpd_t* httpd, qse_httpd_client_t* client, qse_htre_t* req); qse_httpd_fmtdir_t fmtdir;
qse_httpd_impede_t impede;
int (*format_err) ( qse_httpd_logact_t logact;
qse_httpd_t* httpd, qse_httpd_client_t* client,
int code, qse_mchar_t* buf, int bufsz);
int (*format_dir) (
qse_httpd_t* httpd, qse_httpd_client_t* client,
const qse_mchar_t* qpath, const qse_httpd_dirent_t* dirent,
qse_mchar_t* buf, int bufsz);
int (*log) (qse_httpd_t* httpd, int level, const qse_char_t* message);
}; };
/* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */
@ -364,11 +417,6 @@ typedef void (*qse_httpd_server_detach_t) (
qse_httpd_server_t* server qse_httpd_server_t* server
); );
typedef void (*qse_httpd_server_reconf_t) (
qse_httpd_t* httpd,
qse_httpd_server_t* server
);
typedef struct qse_httpd_server_dope_t qse_httpd_server_dope_t; typedef struct qse_httpd_server_dope_t qse_httpd_server_dope_t;
struct qse_httpd_server_dope_t struct qse_httpd_server_dope_t
@ -377,7 +425,6 @@ struct qse_httpd_server_dope_t
qse_nwad_t nwad; /* binding address */ qse_nwad_t nwad; /* binding address */
unsigned int nwif; /* interface number to bind to */ unsigned int nwif; /* interface number to bind to */
qse_httpd_server_detach_t detach; /* executed when the server is detached */ qse_httpd_server_detach_t detach; /* executed when the server is detached */
qse_httpd_server_reconf_t reconf; /* executed when reconfuration is requested */
}; };
struct qse_httpd_server_t struct qse_httpd_server_t
@ -488,18 +535,6 @@ typedef void (*qse_httpd_ecb_close_t) (
qse_httpd_t* httpd /**< httpd */ qse_httpd_t* httpd /**< httpd */
); );
enum qse_httpd_ecb_reconf_type_t
{
QSE_HTTPD_ECB_RECONF_PRE,
QSE_HTTPD_ECB_RECONF_POST
};
typedef enum qse_httpd_ecb_reconf_type_t qse_httpd_ecb_reconf_type_t;
typedef void (*qse_httpd_ecb_reconf_t) (
qse_httpd_t* httpd, /**< httpd */
qse_httpd_ecb_reconf_type_t type
);
/** /**
* The qse_httpd_ecb_t type defines an event callback set. * The qse_httpd_ecb_t type defines an event callback set.
* You can register a callback function set with * You can register a callback function set with
@ -513,7 +548,6 @@ struct qse_httpd_ecb_t
* called by qse_httpd_close(). * called by qse_httpd_close().
*/ */
qse_httpd_ecb_close_t close; qse_httpd_ecb_close_t close;
qse_httpd_ecb_reconf_t reconf;
/* internal use only. don't touch this field */ /* internal use only. don't touch this field */
qse_httpd_ecb_t* next; qse_httpd_ecb_t* next;
@ -588,10 +622,7 @@ QSE_EXPORT void qse_httpd_pushecb (
* The qse_httpd_loop() function starts a httpd server loop. * The qse_httpd_loop() function starts a httpd server loop.
*/ */
QSE_EXPORT int qse_httpd_loop ( QSE_EXPORT int qse_httpd_loop (
qse_httpd_t* httpd, qse_httpd_t* httpd
qse_httpd_scb_t* scb,
qse_httpd_rcb_t* rcb,
const qse_ntime_t* tmout
); );
/** /**
@ -601,7 +632,7 @@ QSE_EXPORT void qse_httpd_stop (
qse_httpd_t* httpd qse_httpd_t* httpd
); );
QSE_EXPORT void qse_httpd_reconf ( QSE_EXPORT void qse_httpd_impede (
qse_httpd_t* httpd qse_httpd_t* httpd
); );
@ -618,6 +649,24 @@ QSE_EXPORT void qse_httpd_detachserver (
qse_httpd_server_t* server qse_httpd_server_t* server
); );
QSE_EXPORT qse_httpd_server_t* qse_httpd_getfirstserver (
qse_httpd_t* httpd
);
QSE_EXPORT qse_httpd_server_t* qse_httpd_getlastserver (
qse_httpd_t* httpd
);
QSE_EXPORT qse_httpd_server_t* qse_httpd_getnextserver (
qse_httpd_t* httpd,
qse_httpd_server_t* server
);
QSE_EXPORT qse_httpd_server_t* qse_httpd_getprevserver (
qse_httpd_t* httpd,
qse_httpd_server_t* server
);
QSE_EXPORT void qse_httpd_discardcontent ( QSE_EXPORT void qse_httpd_discardcontent (
qse_httpd_t* httpd, qse_httpd_t* httpd,
qse_htre_t* req qse_htre_t* req

View File

@ -282,9 +282,9 @@
* a field ID for initialzing a structure in both C9X and C89 * a field ID for initialzing a structure in both C9X and C89
*/ */
#if (defined(__STDC_VERSION__) && (__STDC_VERSION__>=199901L)) || defined(__GNUC__) #if (defined(__STDC_VERSION__) && (__STDC_VERSION__>=199901L)) || defined(__GNUC__)
# define QSE_STRUCT_FIELD(id) .id = # define QSE_STRUCT_FIELD(id,value) .id = value
#else #else
# define QSE_STRUCT_FIELD(id) # define QSE_STRUCT_FIELD(id,value) value
#endif #endif
#ifdef NDEBUG #ifdef NDEBUG

View File

@ -1390,11 +1390,11 @@ int qse_htrd_feed (qse_htrd_t* htrd, const qse_mchar_t* req, qse_size_t len)
header_completed_during_this_feed = 0; header_completed_during_this_feed = 0;
} }
if (htrd->recbs->handle) if (htrd->recbs->poke)
{ {
int n; int n;
htrd->errnum = QSE_HTRD_ENOERR; htrd->errnum = QSE_HTRD_ENOERR;
n = htrd->recbs->handle (htrd, &htrd->re); n = htrd->recbs->poke (htrd, &htrd->re);
if (n <= -1) if (n <= -1)
{ {
if (htrd->errnum == QSE_HTRD_ENOERR) if (htrd->errnum == QSE_HTRD_ENOERR)
@ -1473,11 +1473,11 @@ int qse_htrd_halt (qse_htrd_t* htrd)
{ {
qse_htre_completecontent (&htrd->re); qse_htre_completecontent (&htrd->re);
if (htrd->recbs->handle) if (htrd->recbs->poke)
{ {
int n; int n;
htrd->errnum = QSE_HTRD_ENOERR; htrd->errnum = QSE_HTRD_ENOERR;
n = htrd->recbs->handle (htrd, &htrd->re); n = htrd->recbs->poke (htrd, &htrd->re);
if (n <= -1) if (n <= -1)
{ {
if (htrd->errnum == QSE_HTRD_ENOERR) if (htrd->errnum == QSE_HTRD_ENOERR)

View File

@ -618,7 +618,7 @@ qse_printf (QSE_T("FORWARD: CLEARING REQCON FOR ERROR\n"));
if (writable) goto forward; if (writable) goto forward;
n = httpd->scb->mux.writable ( n = httpd->opt.scb.mux.writable (
httpd, qse_pio_gethandleasubi (&cgi->pio, QSE_PIO_IN), 0); httpd, qse_pio_gethandleasubi (&cgi->pio, QSE_PIO_IN), 0);
if (n >= 1) if (n >= 1)
{ {
@ -943,7 +943,7 @@ static QSE_INLINE qse_ssize_t cgi_write_script_output_to_client (
qse_ssize_t n; qse_ssize_t n;
httpd->errnum = QSE_HTTPD_ENOERR; httpd->errnum = QSE_HTTPD_ENOERR;
n = httpd->scb->client.send (httpd, client, cgi->buf, cgi->buflen); n = httpd->opt.scb.client.send (httpd, client, cgi->buf, cgi->buflen);
if (n > 0) if (n > 0)
{ {
QSE_MEMCPY (&cgi->buf[0], &cgi->buf[n], cgi->buflen - n); QSE_MEMCPY (&cgi->buf[0], &cgi->buf[n], cgi->buflen - n);
@ -1204,7 +1204,7 @@ qse_printf (QSE_T("[cgi_3 sending %d bytes]\n"), (int)count);
if (count > 0) if (count > 0)
{ {
httpd->errnum = QSE_HTTPD_ENOERR; httpd->errnum = QSE_HTTPD_ENOERR;
n = httpd->scb->client.send (httpd, client, cgi->res_ptr, count); n = httpd->opt.scb.client.send (httpd, client, cgi->res_ptr, count);
if (n <= -1) if (n <= -1)
{ {

View File

@ -83,7 +83,7 @@ static void task_fini_dseg (
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_dseg_t* ctx = (task_dseg_t*)task->ctx; task_dseg_t* ctx = (task_dseg_t*)task->ctx;
httpd->scb->dir.close (httpd, ctx->handle); httpd->opt.scb.dir.close (httpd, ctx->handle);
} }
#define SIZE_CHLEN 4 /* the space size to hold the hexadecimal chunk length */ #define SIZE_CHLEN 4 /* the space size to hold the hexadecimal chunk length */
@ -136,7 +136,7 @@ static int add_footer (qse_httpd_t* httpd, qse_httpd_client_t* client, task_dseg
return -1; return -1;
} }
x = httpd->rcb->format_dir ( x = httpd->opt.rcb.fmtdir (
httpd, client, QSE_NULL, QSE_NULL, httpd, client, QSE_NULL, QSE_NULL,
&ctx->buf[ctx->buflen], rem); &ctx->buf[ctx->buflen], rem);
if (x <= -1) return -1; if (x <= -1) return -1;
@ -234,7 +234,7 @@ static int task_main_dseg (
if (!(ctx->state & HEADER_ADDED)) if (!(ctx->state & HEADER_ADDED))
{ {
/* compose the header since this is the first time. */ /* compose the header since this is the first time. */
x = httpd->rcb->format_dir ( x = httpd->opt.rcb.fmtdir (
httpd, client, ctx->qpath.ptr, QSE_NULL, httpd, client, ctx->qpath.ptr, QSE_NULL,
&ctx->buf[ctx->buflen], ctx->bufrem); &ctx->buf[ctx->buflen], ctx->bufrem);
if (x <= -1) if (x <= -1)
@ -261,7 +261,7 @@ static int task_main_dseg (
} }
else else
{ {
if (httpd->scb->dir.read (httpd, ctx->handle, &ctx->dent) <= 0) if (httpd->opt.scb.dir.read (httpd, ctx->handle, &ctx->dent) <= 0)
ctx->state |= DIRENT_NOMORE; ctx->state |= DIRENT_NOMORE;
} }
@ -289,7 +289,7 @@ static int task_main_dseg (
if (qse_mbscmp (ctx->dent.name, QSE_MT(".")) != 0 && if (qse_mbscmp (ctx->dent.name, QSE_MT(".")) != 0 &&
qse_mbscmp (ctx->dent.name, QSE_MT("..")) != 0) qse_mbscmp (ctx->dent.name, QSE_MT("..")) != 0)
{ {
x = httpd->rcb->format_dir ( x = httpd->opt.rcb.fmtdir (
httpd, client, ctx->qpath.ptr, &ctx->dent, httpd, client, ctx->qpath.ptr, &ctx->dent,
&ctx->buf[ctx->buflen], ctx->bufrem); &ctx->buf[ctx->buflen], ctx->bufrem);
if (x <= -1) if (x <= -1)
@ -325,7 +325,7 @@ static int task_main_dseg (
} }
} }
if (httpd->scb->dir.read (httpd, ctx->handle, &ctx->dent) <= 0) if (httpd->opt.scb.dir.read (httpd, ctx->handle, &ctx->dent) <= 0)
ctx->state |= DIRENT_NOMORE; ctx->state |= DIRENT_NOMORE;
} }
while (1); while (1);
@ -333,7 +333,7 @@ static int task_main_dseg (
send_dirlist: send_dirlist:
httpd->errnum = QSE_HTTPD_ENOERR; httpd->errnum = QSE_HTTPD_ENOERR;
n = httpd->scb->client.send ( n = httpd->opt.scb.client.send (
httpd, client, &ctx->buf[ctx->bufpos], ctx->buflen - ctx->bufpos); httpd, client, &ctx->buf[ctx->bufpos], ctx->buflen - ctx->bufpos);
if (n <= -1) return -1; if (n <= -1) return -1;
@ -401,7 +401,7 @@ static QSE_INLINE int task_main_dir (
if (qse_mbsend (dir->path.ptr, QSE_MT("/"))) if (qse_mbsend (dir->path.ptr, QSE_MT("/")))
{ {
if (httpd->scb->dir.open (httpd, dir->path.ptr, &handle) <= -1) if (httpd->opt.scb.dir.open (httpd, dir->path.ptr, &handle) <= -1)
{ {
int http_errnum; int http_errnum;
http_errnum = (httpd->errnum == QSE_HTTPD_ENOENT)? 404: http_errnum = (httpd->errnum == QSE_HTTPD_ENOENT)? 404:
@ -426,7 +426,7 @@ static QSE_INLINE int task_main_dir (
if (x) x = entask_directory_segment (httpd, client, x, handle, dir); if (x) x = entask_directory_segment (httpd, client, x, handle, dir);
if (x) return 0; if (x) return 0;
httpd->scb->dir.close (httpd, handle); httpd->opt.scb.dir.close (httpd, handle);
return -1; return -1;
} }
} }

View File

@ -59,7 +59,7 @@ static void task_fini_fseg (
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_fseg_t* ctx = (task_fseg_t*)task->ctx; task_fseg_t* ctx = (task_fseg_t*)task->ctx;
httpd->scb->file.close (httpd, ctx->handle); httpd->opt.scb.file.close (httpd, ctx->handle);
} }
static int task_main_fseg ( static int task_main_fseg (
@ -73,7 +73,7 @@ static int task_main_fseg (
if (count >= ctx->left) count = ctx->left; if (count >= ctx->left) count = ctx->left;
/* TODO: more adjustment needed for OS with different sendfile semantics... */ /* TODO: more adjustment needed for OS with different sendfile semantics... */
n = httpd->scb->client.sendfile ( n = httpd->opt.scb.client.sendfile (
httpd, client, ctx->handle, &ctx->offset, count); httpd, client, ctx->handle, &ctx->offset, count);
if (n <= -1) if (n <= -1)
{ {
@ -158,7 +158,7 @@ static QSE_INLINE int task_main_file (
setting a trigger or non-blocking I/O are needed. */ setting a trigger or non-blocking I/O are needed. */
httpd->errnum = QSE_HTTPD_ENOERR; httpd->errnum = QSE_HTTPD_ENOERR;
if (httpd->scb->file.stat (httpd, file->path.ptr, &st) <= -1) if (httpd->opt.scb.file.stat (httpd, file->path.ptr, &st) <= -1)
{ {
int http_errnum; int http_errnum;
http_errnum = (httpd->errnum == QSE_HTTPD_ENOENT)? 404: http_errnum = (httpd->errnum == QSE_HTTPD_ENOENT)? 404:
@ -170,7 +170,7 @@ static QSE_INLINE int task_main_file (
} }
httpd->errnum = QSE_HTTPD_ENOERR; httpd->errnum = QSE_HTTPD_ENOERR;
if (httpd->scb->file.ropen (httpd, file->path.ptr, &handle) <= -1) if (httpd->opt.scb.file.ropen (httpd, file->path.ptr, &handle) <= -1)
{ {
int http_errnum; int http_errnum;
http_errnum = (httpd->errnum == QSE_HTTPD_ENOENT)? 404: http_errnum = (httpd->errnum == QSE_HTTPD_ENOENT)? 404:
@ -292,11 +292,11 @@ static QSE_INLINE int task_main_file (
} }
if (x) return 0; if (x) return 0;
httpd->scb->file.close (httpd, handle); httpd->opt.scb.file.close (httpd, handle);
return -1; return -1;
no_file_send: no_file_send:
if (fileopen) httpd->scb->file.close (httpd, handle); if (fileopen) httpd->opt.scb.file.close (httpd, handle);
return (x == QSE_NULL)? -1: 0; return (x == QSE_NULL)? -1: 0;
} }

View File

@ -609,7 +609,7 @@ qse_printf (QSE_T("FORWARD: CLEARING REQCON FOR ERROR\n"));
if (writable) goto forward; if (writable) goto forward;
n = httpd->scb->mux.writable (httpd, proxy->peer.handle, 0); n = httpd->opt.scb.mux.writable (httpd, proxy->peer.handle, 0);
if (n == 0) qse_printf (QSE_T("PROXY FORWARD: @@@@@@@@@NOT WRITABLE\n")); if (n == 0) qse_printf (QSE_T("PROXY FORWARD: @@@@@@@@@NOT WRITABLE\n"));
if (n >= 1) if (n >= 1)
{ {
@ -618,7 +618,7 @@ if (n == 0) qse_printf (QSE_T("PROXY FORWARD: @@@@@@@@@NOT WRITABLE\n"));
qse_printf (QSE_T("PROXY FORWARD: @@@@@@@@@@WRITING[%.*hs]\n"), qse_printf (QSE_T("PROXY FORWARD: @@@@@@@@@@WRITING[%.*hs]\n"),
(int)QSE_MBS_LEN(proxy->reqfwdbuf), (int)QSE_MBS_LEN(proxy->reqfwdbuf),
QSE_MBS_PTR(proxy->reqfwdbuf)); QSE_MBS_PTR(proxy->reqfwdbuf));
n = httpd->scb->peer.send ( n = httpd->opt.scb.peer.send (
httpd, &proxy->peer, httpd, &proxy->peer,
QSE_MBS_PTR(proxy->reqfwdbuf), QSE_MBS_PTR(proxy->reqfwdbuf),
QSE_MBS_LEN(proxy->reqfwdbuf) QSE_MBS_LEN(proxy->reqfwdbuf)
@ -871,7 +871,7 @@ static void task_fini_proxy (
task_proxy_t* proxy = (task_proxy_t*)task->ctx; task_proxy_t* proxy = (task_proxy_t*)task->ctx;
if (proxy->peer_status & PROXY_PEER_OPEN) if (proxy->peer_status & PROXY_PEER_OPEN)
httpd->scb->peer.close (httpd, &proxy->peer); httpd->opt.scb.peer.close (httpd, &proxy->peer);
if (proxy->res) qse_mbs_close (proxy->res); if (proxy->res) qse_mbs_close (proxy->res);
if (proxy->peer_htrd) qse_htrd_close (proxy->peer_htrd); if (proxy->peer_htrd) qse_htrd_close (proxy->peer_htrd);
@ -906,7 +906,7 @@ qse_printf (QSE_T("task_main_proxy_5 trigger[0].mask=%d trigger[1].mask=%d trigg
{ {
/* TODO: check if proxy outputs more than content-length if it is set... */ /* TODO: check if proxy outputs more than content-length if it is set... */
httpd->errnum = QSE_HTTPD_ENOERR; httpd->errnum = QSE_HTTPD_ENOERR;
n = httpd->scb->client.send (httpd, client, proxy->buf, proxy->buflen); n = httpd->opt.scb.client.send (httpd, client, proxy->buf, proxy->buflen);
if (n <= -1) if (n <= -1)
{ {
/* can't return internal server error any more... */ /* can't return internal server error any more... */
@ -952,7 +952,7 @@ qse_printf (QSE_T("task_main_proxy_4 about to read from PEER...\n"));
{ {
qse_printf (QSE_T("task_main_proxy_4 reading from PEER... %d %d\n"), (int)proxy->peer_output_length, (int)proxy->peer_output_received); qse_printf (QSE_T("task_main_proxy_4 reading from PEER... %d %d\n"), (int)proxy->peer_output_length, (int)proxy->peer_output_received);
httpd->errnum = QSE_HTTPD_ENOERR; httpd->errnum = QSE_HTTPD_ENOERR;
n = httpd->scb->peer.recv ( n = httpd->opt.scb.peer.recv (
httpd, &proxy->peer, httpd, &proxy->peer,
&proxy->buf[proxy->buflen], &proxy->buf[proxy->buflen],
QSE_SIZEOF(proxy->buf) - proxy->buflen QSE_SIZEOF(proxy->buf) - proxy->buflen
@ -1007,7 +1007,7 @@ qse_printf (QSE_T("task_main_proxy_4 read from PEER...%d\n"), (int)n);
* side is writable. it should be safe to write whenever * side is writable. it should be safe to write whenever
* this task function is called. */ * this task function is called. */
httpd->errnum = QSE_HTTPD_ENOERR; httpd->errnum = QSE_HTTPD_ENOERR;
n = httpd->scb->client.send (httpd, client, proxy->buf, proxy->buflen); n = httpd->opt.scb.client.send (httpd, client, proxy->buf, proxy->buflen);
if (n <= -1) if (n <= -1)
{ {
/* can't return internal server error any more... */ /* can't return internal server error any more... */
@ -1059,7 +1059,7 @@ qse_printf (QSE_T("[PROXY-----3 SENDING XXXXX]\n"));
{ {
qse_printf (QSE_T("[proxy_3 sending %d bytes]\n"), (int)count); qse_printf (QSE_T("[proxy_3 sending %d bytes]\n"), (int)count);
httpd->errnum = QSE_HTTPD_ENOERR; httpd->errnum = QSE_HTTPD_ENOERR;
n = httpd->scb->client.send ( n = httpd->opt.scb.client.send (
httpd, client, httpd, client,
&QSE_MBS_CHAR(proxy->res,proxy->res_consumed), &QSE_MBS_CHAR(proxy->res,proxy->res_consumed),
count count
@ -1152,7 +1152,7 @@ for (i = 0; i < count; i++) qse_printf (QSE_T("%hc"), QSE_MBS_CHAR(proxy->res,pr
qse_printf (QSE_T("]\n")); qse_printf (QSE_T("]\n"));
httpd->errnum = QSE_HTTPD_ENOERR; httpd->errnum = QSE_HTTPD_ENOERR;
n = httpd->scb->client.send ( n = httpd->opt.scb.client.send (
httpd, client, httpd, client,
QSE_MBS_CPTR(proxy->res,proxy->res_consumed), QSE_MBS_CPTR(proxy->res,proxy->res_consumed),
count count
@ -1183,7 +1183,7 @@ qse_printf (QSE_T("[proxy-2 send failure....\n"));
/* there is something to read from peer */ /* there is something to read from peer */
httpd->errnum = QSE_HTTPD_ENOERR; httpd->errnum = QSE_HTTPD_ENOERR;
n = httpd->scb->peer.recv ( n = httpd->opt.scb.peer.recv (
httpd, &proxy->peer, httpd, &proxy->peer,
&proxy->buf[proxy->buflen], &proxy->buf[proxy->buflen],
QSE_SIZEOF(proxy->buf) - proxy->buflen QSE_SIZEOF(proxy->buf) - proxy->buflen
@ -1309,7 +1309,7 @@ qse_printf (QSE_T("task_main_proxy_1....\n"));
int n; int n;
httpd->errnum = QSE_HTTPD_ENOERR; httpd->errnum = QSE_HTTPD_ENOERR;
n = httpd->scb->peer.connected (httpd, &proxy->peer); n = httpd->opt.scb.peer.connected (httpd, &proxy->peer);
if (n <= -1) if (n <= -1)
{ {
/* improve error conversion */ /* improve error conversion */
@ -1381,7 +1381,7 @@ qse_printf (QSE_T("task_main_proxy....\n"));
proxy->res_pending = 0; proxy->res_pending = 0;
httpd->errnum = QSE_HTTPD_ENOERR; httpd->errnum = QSE_HTTPD_ENOERR;
n = httpd->scb->peer.open (httpd, &proxy->peer); n = httpd->opt.scb.peer.open (httpd, &proxy->peer);
if (n <= -1) if (n <= -1)
{ {
/* TODO: translate error code to http error... */ /* TODO: translate error code to http error... */

View File

@ -95,7 +95,6 @@ typedef struct server_xtn_t server_xtn_t;
struct server_xtn_t struct server_xtn_t
{ {
qse_httpd_server_detach_t detach; qse_httpd_server_detach_t detach;
qse_httpd_server_reconf_t reconf;
qse_httpd_serverstd_query_t query; qse_httpd_serverstd_query_t query;
qse_httpd_serverstd_makersrc_t makersrc; qse_httpd_serverstd_makersrc_t makersrc;
@ -105,6 +104,8 @@ struct server_xtn_t
qse_mxstr_t auth; qse_mxstr_t auth;
}; };
static void set_httpd_callbacks (qse_httpd_t* httpd);
/* ------------------------------------------------------------------- */ /* ------------------------------------------------------------------- */
#include "../cmn/syserr.h" #include "../cmn/syserr.h"
@ -602,8 +603,11 @@ qse_httpd_t* qse_httpd_openstdwithmmgr (qse_mmgr_t* mmgr, qse_size_t xtnsize)
/*init_xtn_ssl (xtn, "http01.pem", "http01.key");*/ /*init_xtn_ssl (xtn, "http01.pem", "http01.key");*/
#endif #endif
set_httpd_callbacks (httpd);
xtn->ecb.close = cleanup_standard_httpd; xtn->ecb.close = cleanup_standard_httpd;
qse_httpd_pushecb (httpd, &xtn->ecb); qse_httpd_pushecb (httpd, &xtn->ecb);
return httpd; return httpd;
} }
@ -1862,8 +1866,7 @@ if (qse_htre_getcontentlen(req) > 0)
else else
{ {
task = qse_httpd_entaskrsrc (httpd, client, QSE_NULL, &rsrc, req); task = qse_httpd_entaskrsrc (httpd, client, QSE_NULL, &rsrc, req);
if (server_xtn->freersrc) server_xtn->freersrc (httpd, client, req, &rsrc);
server_xtn->freersrc (httpd, client, req, &rsrc);
} }
if (task == QSE_NULL) goto oops; if (task == QSE_NULL) goto oops;
} }
@ -1903,13 +1906,13 @@ static int peek_request (
return process_request (httpd, client, req, 1); return process_request (httpd, client, req, 1);
} }
static int handle_request ( static int poke_request (
qse_httpd_t* httpd, qse_httpd_client_t* client, qse_htre_t* req) qse_httpd_t* httpd, qse_httpd_client_t* client, qse_htre_t* req)
{ {
return process_request (httpd, client, req, 0); return process_request (httpd, client, req, 0);
} }
static int format_err ( static int format_error (
qse_httpd_t* httpd, qse_httpd_client_t* client, int code, qse_mchar_t* buf, int bufsz) qse_httpd_t* httpd, qse_httpd_client_t* client, int code, qse_mchar_t* buf, int bufsz)
{ {
int n; int n;
@ -2036,6 +2039,16 @@ static int format_dir (
return n; return n;
} }
static void impede_httpd (qse_httpd_t* httpd)
{
/* do nothing */
}
static void logact_httpd (qse_httpd_t* httpd, qse_httpd_act_t* act)
{
/* do nothing */
}
static qse_httpd_scb_t httpd_system_callbacks = static qse_httpd_scb_t httpd_system_callbacks =
{ {
/* server */ /* server */
@ -2088,12 +2101,19 @@ static qse_httpd_scb_t httpd_system_callbacks =
static qse_httpd_rcb_t httpd_request_callbacks = static qse_httpd_rcb_t httpd_request_callbacks =
{ {
peek_request, QSE_STRUCT_FIELD(peekreq, peek_request),
handle_request, QSE_STRUCT_FIELD(pokereq, poke_request),
format_err, QSE_STRUCT_FIELD(fmterr, format_error),
format_dir QSE_STRUCT_FIELD(fmtdir, format_dir),
QSE_STRUCT_FIELD(impede, impede_httpd),
QSE_STRUCT_FIELD(logact, logact_httpd)
}; };
static void set_httpd_callbacks (qse_httpd_t* httpd)
{
qse_httpd_setopt (httpd, QSE_HTTPD_SCB, &httpd_system_callbacks);
qse_httpd_setopt (httpd, QSE_HTTPD_RCB, &httpd_request_callbacks);
}
/* ------------------------------------------------------------------- */ /* ------------------------------------------------------------------- */
static void free_resource ( static void free_resource (
@ -2163,7 +2183,10 @@ static void merge_paths_to_buf (
qse_size_t len = 0; qse_size_t len = 0;
len += qse_mbscpy (&xpath[len], base); len += qse_mbscpy (&xpath[len], base);
len += qse_mbscpy (&xpath[len], QSE_MT("/")); len += qse_mbscpy (&xpath[len], QSE_MT("/"));
len += qse_mbsncpy (&xpath[len], path, plen); if (plen == (qse_size_t)-1)
len += qse_mbscpy (&xpath[len], path);
else
len += qse_mbsncpy (&xpath[len], path, plen);
qse_canonmbspath (xpath, xpath, 0); qse_canonmbspath (xpath, xpath, 0);
} }
@ -2219,6 +2242,7 @@ static int attempt_cgi (
/* inspect each segment from the head. */ /* inspect each segment from the head. */
const qse_mchar_t* ptr; const qse_mchar_t* ptr;
const qse_mchar_t* slash; const qse_mchar_t* slash;
int xpath_changed = 0;
QSE_ASSERT (tmp->qpath[0] == QSE_T('/')); QSE_ASSERT (tmp->qpath[0] == QSE_T('/'));
@ -2238,10 +2262,18 @@ static int attempt_cgi (
* tmp->xpath should be large enough to hold the merge path made of * tmp->xpath should be large enough to hold the merge path made of
* the subsegments of the original query path and docroot. */ * the subsegments of the original query path and docroot. */
merge_paths_to_buf (httpd, tmp->docroot, tmp->qpath, slash - tmp->qpath, tmp->xpath); merge_paths_to_buf (httpd, tmp->docroot, tmp->qpath, slash - tmp->qpath, tmp->xpath);
xpath_changed = 1;
/* attempt this */
stx = stat_file (httpd, tmp->xpath, &st, 0); stx = stat_file (httpd, tmp->xpath, &st, 0);
if (stx >= 0 && !st.isdir) if (stx <= -1)
{
/* stop at the current segment if stating fails.
* if the current semgment can't be stat-ed, it's not likely that
* the next segment can be successfully stat-ed */
break;
}
if (!st.isdir)
{ {
if (server_xtn->query (httpd, client->server, req, tmp->xpath, QSE_HTTPD_SERVERSTD_CGI, &cgi) >= 0 && cgi.cgi) if (server_xtn->query (httpd, client->server, req, tmp->xpath, QSE_HTTPD_SERVERSTD_CGI, &cgi) >= 0 && cgi.cgi)
{ {
@ -2269,6 +2301,9 @@ static int attempt_cgi (
break; break;
} }
} }
/* restore the xpath because it has changed... */
if (xpath_changed) merge_paths_to_buf (httpd, tmp->docroot, tmp->qpath, (qse_size_t)-1, tmp->xpath);
} }
return 0; /* not a cgi */ return 0; /* not a cgi */
@ -2407,7 +2442,7 @@ auth_ok:
return -1; return -1;
} }
if (httpd->scb->file.stat (httpd, tpath, &st) >= 0 && !st.isdir) if (httpd->opt.scb.file.stat (httpd, tpath, &st) >= 0 && !st.isdir)
{ {
/* the index file is found */ /* the index file is found */
QSE_MMGR_FREE (httpd->mmgr, tmp.xpath); QSE_MMGR_FREE (httpd->mmgr, tmp.xpath);
@ -2468,16 +2503,6 @@ static void detach_server (qse_httpd_t* httpd, qse_httpd_server_t* server)
if (server_xtn->auth.ptr) QSE_MMGR_FREE (httpd->mmgr, server_xtn->auth.ptr); if (server_xtn->auth.ptr) QSE_MMGR_FREE (httpd->mmgr, server_xtn->auth.ptr);
} }
static void reconf_server (qse_httpd_t* httpd, qse_httpd_server_t* server)
{
server_xtn_t* server_xtn;
server_xtn = (server_xtn_t*) qse_httpd_getserverxtn (httpd, server);
if (server_xtn->reconf) server_xtn->reconf (httpd, server);
/* nothing more to do here ... */
}
struct mime_tab_t struct mime_tab_t
{ {
const qse_mchar_t* suffix; const qse_mchar_t* suffix;
@ -2571,7 +2596,6 @@ qse_httpd_server_t* qse_httpd_attachserverstd (
xdope = *dope; xdope = *dope;
xdope.detach = detach_server; xdope.detach = detach_server;
xdope.reconf = reconf_server;
xserver = qse_httpd_attachserver (httpd, &xdope, QSE_SIZEOF(*server_xtn) + xtnsize); xserver = qse_httpd_attachserver (httpd, &xdope, QSE_SIZEOF(*server_xtn) + xtnsize);
if (xserver == QSE_NULL) return QSE_NULL; if (xserver == QSE_NULL) return QSE_NULL;
@ -2579,7 +2603,6 @@ qse_httpd_server_t* qse_httpd_attachserverstd (
server_xtn = qse_httpd_getserverxtn (httpd, xserver); server_xtn = qse_httpd_getserverxtn (httpd, xserver);
server_xtn->detach = dope->detach; server_xtn->detach = dope->detach;
server_xtn->reconf = dope->reconf;
server_xtn->query = query_server; server_xtn->query = query_server;
server_xtn->makersrc = make_resource; server_xtn->makersrc = make_resource;
@ -2592,7 +2615,6 @@ qse_httpd_server_t* qse_httpd_attachserverstd (
qse_httpd_server_t* qse_httpd_attachserverstdwithuri ( qse_httpd_server_t* qse_httpd_attachserverstdwithuri (
qse_httpd_t* httpd, const qse_char_t* uri, qse_httpd_t* httpd, const qse_char_t* uri,
qse_httpd_server_detach_t detach, qse_httpd_server_detach_t detach,
qse_httpd_server_reconf_t reconf,
qse_httpd_serverstd_query_t query, qse_httpd_serverstd_query_t query,
qse_size_t xtnsize) qse_size_t xtnsize)
{ {
@ -2632,7 +2654,6 @@ qse_httpd_server_t* qse_httpd_attachserverstdwithuri (
} }
server.detach = detach; server.detach = detach;
server.reconf = reconf;
#if 0 #if 0
server.docroot = xuri.path; server.docroot = xuri.path;
if (server.docroot.ptr && qse_ismbsdriveabspath((const qse_mchar_t*)server.docroot.ptr + 1)) if (server.docroot.ptr && qse_ismbsdriveabspath((const qse_mchar_t*)server.docroot.ptr + 1))
@ -2717,9 +2738,7 @@ void* qse_httpd_getserverstdxtn (qse_httpd_t* httpd, qse_httpd_server_t* server)
/* ------------------------------------------------------------------- */ /* ------------------------------------------------------------------- */
int qse_httpd_loopstd (qse_httpd_t* httpd, const qse_ntime_t* tmout) int qse_httpd_loopstd (qse_httpd_t* httpd)
{ {
return qse_httpd_loop ( return qse_httpd_loop (httpd);
httpd, &httpd_system_callbacks,
&httpd_request_callbacks, tmout);
} }

View File

@ -37,7 +37,7 @@
static int task_main_disconnect ( static int task_main_disconnect (
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)
{ {
httpd->scb->client.shutdown (httpd, client); httpd->opt.scb.client.shutdown (httpd, client);
return 0; return 0;
} }
@ -95,7 +95,7 @@ static int task_main_format (
count = MAX_SEND_SIZE; count = MAX_SEND_SIZE;
if (count >= ctx->left) count = ctx->left; if (count >= ctx->left) count = ctx->left;
n = httpd->scb->client.send (httpd, client, ctx->ptr, count); n = httpd->opt.scb.client.send (httpd, client, ctx->ptr, count);
if (n <= -1) return -1; if (n <= -1) return -1;
ctx->left -= n; ctx->left -= n;
@ -230,8 +230,7 @@ static qse_httpd_task_t* entask_status (
} }
else else
{ {
if (httpd->rcb->format_err (httpd, client, code, text, QSE_COUNTOF(text)) <= -1) if (httpd->opt.rcb.fmterr (httpd, client, code, text, QSE_COUNTOF(text)) <= -1) return QSE_NULL;
return QSE_NULL;
if (code == 401) if (code == 401)
{ {

View File

@ -53,7 +53,7 @@ static int task_main_text (
if (count >= ctx->left) count = ctx->left; if (count >= ctx->left) count = ctx->left;
/* TODO: do i need to add code to skip this send if count is 0? */ /* TODO: do i need to add code to skip this send if count is 0? */
n = httpd->scb->client.send (httpd, client, ctx->ptr, count); n = httpd->opt.scb.client.send (httpd, client, ctx->ptr, count);
if (n <= -1) return -1; if (n <= -1) return -1;
ctx->left -= n; ctx->left -= n;

View File

@ -73,9 +73,14 @@ void qse_httpd_close (qse_httpd_t* httpd)
int qse_httpd_init (qse_httpd_t* httpd, qse_mmgr_t* mmgr) int qse_httpd_init (qse_httpd_t* httpd, qse_mmgr_t* mmgr)
{ {
QSE_MEMSET (httpd, 0, QSE_SIZEOF(*httpd)); QSE_MEMSET (httpd, 0, QSE_SIZEOF(*httpd));
httpd->mmgr = mmgr; httpd->mmgr = mmgr;
qse_mbscpy (httpd->sname, QSE_MT("QSE-HTTPD " QSE_PACKAGE_VERSION)); qse_mbscpy (httpd->sname, QSE_MT("QSE-HTTPD " QSE_PACKAGE_VERSION));
httpd->opt.tmout.sec = 3;
httpd->opt.idle_limit.sec = 30;
return 0; return 0;
} }
@ -89,9 +94,9 @@ void qse_httpd_stop (qse_httpd_t* httpd)
httpd->stopreq = 1; httpd->stopreq = 1;
} }
void qse_httpd_reconf (qse_httpd_t* httpd) void qse_httpd_impede (qse_httpd_t* httpd)
{ {
httpd->reconfreq = 1; httpd->impedereq = 1;
} }
qse_httpd_errnum_t qse_httpd_geterrnum (qse_httpd_t* httpd) qse_httpd_errnum_t qse_httpd_geterrnum (qse_httpd_t* httpd)
@ -121,6 +126,22 @@ int qse_httpd_getopt (qse_httpd_t* httpd, qse_httpd_opt_t id, void* value)
case QSE_HTTPD_TRAIT: case QSE_HTTPD_TRAIT:
*(int*)value = httpd->opt.trait; *(int*)value = httpd->opt.trait;
return 0; return 0;
case QSE_HTTPD_SCB:
*(qse_httpd_scb_t*)value = httpd->opt.scb;
return 0;
case QSE_HTTPD_RCB:
*(qse_httpd_rcb_t*)value = httpd->opt.rcb;
return 0;
case QSE_HTTPD_TMOUT:
*(qse_ntime_t*)value = httpd->opt.tmout;
return 0;
case QSE_HTTPD_IDLELIMIT:
*(qse_ntime_t*)value = httpd->opt.idle_limit;
return 0;
} }
httpd->errnum = QSE_HTTPD_EINVAL; httpd->errnum = QSE_HTTPD_EINVAL;
@ -134,6 +155,22 @@ int qse_httpd_setopt (qse_httpd_t* httpd, qse_httpd_opt_t id, const void* value)
case QSE_HTTPD_TRAIT: case QSE_HTTPD_TRAIT:
httpd->opt.trait = *(const int*)value; httpd->opt.trait = *(const int*)value;
return 0; return 0;
case QSE_HTTPD_SCB:
httpd->opt.scb = *(qse_httpd_scb_t*)value;
return 0;
case QSE_HTTPD_RCB:
httpd->opt.rcb = *(qse_httpd_rcb_t*)value;
return 0;
case QSE_HTTPD_TMOUT:
httpd->opt.tmout = *(qse_ntime_t*)value;
return 0;
case QSE_HTTPD_IDLELIMIT:
httpd->opt.idle_limit = *(qse_ntime_t*)value;
return 0;
} }
httpd->errnum = QSE_HTTPD_EINVAL; httpd->errnum = QSE_HTTPD_EINVAL;
@ -288,7 +325,7 @@ static QSE_INLINE int dequeue_task (
{ {
if (client->status & CLIENT_TASK_TRIGGER_IN_MUX(i)) if (client->status & CLIENT_TASK_TRIGGER_IN_MUX(i))
{ {
httpd->scb->mux.delhnd (httpd, httpd->mux, task->trigger[i].handle); httpd->opt.scb.mux.delhnd (httpd, httpd->mux, task->trigger[i].handle);
client->status &= ~CLIENT_TASK_TRIGGER_IN_MUX(i); client->status &= ~CLIENT_TASK_TRIGGER_IN_MUX(i);
} }
} }
@ -324,19 +361,19 @@ static QSE_INLINE void purge_tasks (
static int htrd_peek_request (qse_htrd_t* htrd, qse_htre_t* req) static int htrd_peek_request (qse_htrd_t* htrd, qse_htre_t* req)
{ {
htrd_xtn_t* xtn = (htrd_xtn_t*) qse_htrd_getxtn (htrd); htrd_xtn_t* xtn = (htrd_xtn_t*) qse_htrd_getxtn (htrd);
return xtn->httpd->rcb->peek_request (xtn->httpd, xtn->client, req); return xtn->httpd->opt.rcb.peekreq (xtn->httpd, xtn->client, req);
} }
static int htrd_handle_request (qse_htrd_t* htrd, qse_htre_t* req) static int htrd_poke_request (qse_htrd_t* htrd, qse_htre_t* req)
{ {
htrd_xtn_t* xtn = (htrd_xtn_t*) qse_htrd_getxtn (htrd); htrd_xtn_t* xtn = (htrd_xtn_t*) qse_htrd_getxtn (htrd);
return xtn->httpd->rcb->handle_request (xtn->httpd, xtn->client, req); return xtn->httpd->opt.rcb.pokereq (xtn->httpd, xtn->client, req);
} }
static qse_htrd_recbs_t htrd_recbs = static qse_htrd_recbs_t htrd_recbs =
{ {
htrd_peek_request, QSE_STRUCT_FIELD (peek, htrd_peek_request),
htrd_handle_request QSE_STRUCT_FIELD (poke, htrd_poke_request)
}; };
/* --------------------------------------------------- */ /* --------------------------------------------------- */
@ -366,7 +403,7 @@ static qse_httpd_client_t* new_client (
/* copy the public fields, /* copy the public fields,
* keep the private fields initialized at 0 */ * keep the private fields initialized at 0 */
client->status = tmpl->status; client->status = tmpl->status;
if (httpd->scb->client.accepted == QSE_NULL) if (httpd->opt.scb.client.accepted == QSE_NULL)
client->status |= CLIENT_READY; client->status |= CLIENT_READY;
client->handle = tmpl->handle; client->handle = tmpl->handle;
client->handle2 = tmpl->handle2; client->handle2 = tmpl->handle2;
@ -398,16 +435,16 @@ qse_printf (QSE_T("Debug: CLOSING SOCKET %d\n"), client->handle.i);
if (client->status & CLIENT_HANDLE_IN_MUX) if (client->status & CLIENT_HANDLE_IN_MUX)
{ {
httpd->scb->mux.delhnd (httpd, httpd->mux, client->handle); httpd->opt.scb.mux.delhnd (httpd, httpd->mux, client->handle);
client->status &= ~CLIENT_HANDLE_IN_MUX; client->status &= ~CLIENT_HANDLE_IN_MUX;
} }
/* note that client.closed is not a counterpart to client.accepted. /* note that client.closed is not a counterpart to client.accepted.
* so it is called even if client.close() failed. */ * so it is called even if client.close() failed. */
if (httpd->scb->client.closed) if (httpd->opt.scb.client.closed)
httpd->scb->client.closed (httpd, client); httpd->opt.scb.client.closed (httpd, client);
httpd->scb->client.close (httpd, client); httpd->opt.scb.client.close (httpd, client);
qse_httpd_freemem (httpd, client); qse_httpd_freemem (httpd, client);
} }
@ -420,6 +457,14 @@ static void purge_client (qse_httpd_t* httpd, qse_httpd_client_t* client)
prev = client->prev; prev = client->prev;
next = client->next; next = client->next;
if (httpd->opt.trait & QSE_HTTPD_ENABLELOG)
{
qse_httpd_act_t msg;
msg.code = QSE_HTTPD_PURGE_CLIENT;
msg.u.client = client;
httpd->opt.rcb.logact (httpd, &msg);
}
free_client (httpd, client); free_client (httpd, client);
if (prev) prev->next = next; if (prev) prev->next = next;
@ -471,7 +516,7 @@ static int accept_client (
QSE_MEMSET (&clibuf, 0, QSE_SIZEOF(clibuf)); QSE_MEMSET (&clibuf, 0, QSE_SIZEOF(clibuf));
if (httpd->scb->server.accept (httpd, server, &clibuf) <= -1) if (httpd->opt.scb.server.accept (httpd, server, &clibuf) <= -1)
{ {
/* TODO: proper logging */ /* TODO: proper logging */
qse_char_t tmp[128]; qse_char_t tmp[128];
@ -489,12 +534,12 @@ qse_printf (QSE_T("failed to accept from server [%s] [%d]\n"), tmp, server->hand
client = new_client (httpd, &clibuf); client = new_client (httpd, &clibuf);
if (client == QSE_NULL) if (client == QSE_NULL)
{ {
httpd->scb->client.close (httpd, &clibuf); httpd->opt.scb.client.close (httpd, &clibuf);
return -1; return -1;
} }
qse_printf (QSE_T("MUX ADDHND CLIENT READ %d\n"), client->handle.i); qse_printf (QSE_T("MUX ADDHND CLIENT READ %d\n"), client->handle.i);
if (httpd->scb->mux.addhnd ( if (httpd->opt.scb.mux.addhnd (
httpd, mux, client->handle, QSE_HTTPD_MUX_READ, client) <= -1) httpd, mux, client->handle, QSE_HTTPD_MUX_READ, client) <= -1)
{ {
free_client (httpd, client); free_client (httpd, client);
@ -539,8 +584,8 @@ static void deactivate_servers (qse_httpd_t* httpd)
{ {
if (server->dope.flags & QSE_HTTPD_SERVER_ACTIVE) if (server->dope.flags & QSE_HTTPD_SERVER_ACTIVE)
{ {
httpd->scb->mux.delhnd (httpd, httpd->mux, server->handle); httpd->opt.scb.mux.delhnd (httpd, httpd->mux, server->handle);
httpd->scb->server.close (httpd, server); httpd->opt.scb.server.close (httpd, server);
server->dope.flags &= ~QSE_HTTPD_SERVER_ACTIVE; server->dope.flags &= ~QSE_HTTPD_SERVER_ACTIVE;
httpd->server.nactive--; httpd->server.nactive--;
} }
@ -553,29 +598,29 @@ static int activate_servers (qse_httpd_t* httpd)
for (server = httpd->server.list.head; server; server = server->next) for (server = httpd->server.list.head; server; server = server->next)
{ {
if (httpd->scb->server.open (httpd, server) <= -1) if (httpd->opt.scb.server.open (httpd, server) <= -1)
{ {
qse_char_t buf[64]; qse_char_t buf[64];
qse_nwadtostr (&server->dope.nwad, buf, QSE_COUNTOF(buf), QSE_NWADTOSTR_ALL); qse_nwadtostr (&server->dope.nwad, buf, QSE_COUNTOF(buf), QSE_NWADTOSTR_ALL);
/* /*
httpd->rcb->log (httpd, 0, QSE_T("cannot activate %s"), buf); httpd->opt.rcb.log (httpd, 0, QSE_T("cannot activate %s"), buf);
*/ */
qse_printf(QSE_T("cannot activate [%s]\n"), buf); qse_printf(QSE_T("cannot activate [%s]\n"), buf);
continue; continue;
} }
if (httpd->scb->mux.addhnd ( if (httpd->opt.scb.mux.addhnd (
httpd, httpd->mux, server->handle, QSE_HTTPD_MUX_READ, server) <= -1) httpd, httpd->mux, server->handle, QSE_HTTPD_MUX_READ, server) <= -1)
{ {
qse_char_t buf[64]; qse_char_t buf[64];
qse_nwadtostr (&server->dope.nwad, buf, QSE_COUNTOF(buf), QSE_NWADTOSTR_ALL); qse_nwadtostr (&server->dope.nwad, buf, QSE_COUNTOF(buf), QSE_NWADTOSTR_ALL);
/* /*
httpd->rcb->log (httpd, 0, QSE_T("cannot activate %s - "), buf); httpd->opt.rcb.log (httpd, 0, QSE_T("cannot activate %s - "), buf);
*/ */
qse_printf(QSE_T("cannot add handle [%s]\n"), buf); qse_printf(QSE_T("cannot add handle [%s]\n"), buf);
httpd->scb->server.close (httpd, server); httpd->opt.scb.server.close (httpd, server);
continue; continue;
} }
@ -651,6 +696,26 @@ void qse_httpd_detachserver (qse_httpd_t* httpd, qse_httpd_server_t* server)
else httpd->server.list.tail = prev; else httpd->server.list.tail = prev;
} }
qse_httpd_server_t* qse_httpd_getfirstserver (qse_httpd_t* httpd)
{
return httpd->server.list.head;
}
qse_httpd_server_t* qse_httpd_getlastserver (qse_httpd_t* httpd)
{
return httpd->server.list.tail;
}
qse_httpd_server_t* qse_httpd_getnextserver (qse_httpd_t* httpd, qse_httpd_server_t* server)
{
return server->next;
}
qse_httpd_server_t* qse_httpd_getprevserver (qse_httpd_t* httpd, qse_httpd_server_t* server)
{
return server->prev;
}
/* --------------------------------------------------- */ /* --------------------------------------------------- */
static int read_from_client (qse_httpd_t* httpd, qse_httpd_client_t* client) static int read_from_client (qse_httpd_t* httpd, qse_httpd_client_t* client)
@ -658,11 +723,11 @@ static int read_from_client (qse_httpd_t* httpd, qse_httpd_client_t* client)
qse_mchar_t buf[4096]; /* TODO: adjust this buffer size */ qse_mchar_t buf[4096]; /* TODO: adjust this buffer size */
qse_ssize_t m; qse_ssize_t m;
QSE_ASSERT (httpd->scb->client.recv != QSE_NULL); QSE_ASSERT (httpd->opt.scb.client.recv != QSE_NULL);
reread: reread:
httpd->errnum = QSE_HTTPD_ENOERR; httpd->errnum = QSE_HTTPD_ENOERR;
m = httpd->scb->client.recv (httpd, client, buf, QSE_SIZEOF(buf)); m = httpd->opt.scb.client.recv (httpd, client, buf, QSE_SIZEOF(buf));
if (m <= -1) if (m <= -1)
{ {
if (httpd->errnum == QSE_HTTPD_EAGAIN) if (httpd->errnum == QSE_HTTPD_EAGAIN)
@ -834,7 +899,7 @@ qse_printf (QSE_T("ERROR: mute client got no more task [%d] failed...\n"), (int)
qse_ntime_t tmout; qse_ntime_t tmout;
tmout.sec = 0; tmout.sec = 0;
tmout.nsec = 0; tmout.nsec = 0;
if (httpd->scb->mux.writable (httpd, client->handle, &tmout) <= 0) if (httpd->opt.scb.mux.writable (httpd, client->handle, &tmout) <= 0)
{ {
/* it is not writable yet. so just skip /* it is not writable yet. so just skip
* performing the actual task */ * performing the actual task */
@ -883,12 +948,12 @@ qse_printf (QSE_T("task returend %d\n"), n);
if ((client->status & CLIENT_HANDLE_IN_MUX) != if ((client->status & CLIENT_HANDLE_IN_MUX) !=
(mux_status & CLIENT_HANDLE_IN_MUX)) (mux_status & CLIENT_HANDLE_IN_MUX))
{ {
httpd->scb->mux.delhnd (httpd, httpd->mux, client->handle); httpd->opt.scb.mux.delhnd (httpd, httpd->mux, client->handle);
client->status &= ~CLIENT_HANDLE_IN_MUX; client->status &= ~CLIENT_HANDLE_IN_MUX;
if (mux_status) if (mux_status)
{ {
if (httpd->scb->mux.addhnd ( if (httpd->opt.scb.mux.addhnd (
httpd, httpd->mux, client->handle, mux_mask, client) <= -1) httpd, httpd->mux, client->handle, mux_mask, client) <= -1)
{ {
return -1; return -1;
@ -928,7 +993,7 @@ qse_printf (QSE_T("task returend %d\n"), n);
{ {
if (client->status & CLIENT_TASK_TRIGGER_IN_MUX(i)) if (client->status & CLIENT_TASK_TRIGGER_IN_MUX(i))
{ {
httpd->scb->mux.delhnd (httpd, httpd->mux, client->trigger[i].handle); httpd->opt.scb.mux.delhnd (httpd, httpd->mux, client->trigger[i].handle);
client->status &= ~CLIENT_TASK_TRIGGER_IN_MUX(i); client->status &= ~CLIENT_TASK_TRIGGER_IN_MUX(i);
} }
} }
@ -974,7 +1039,7 @@ qse_printf (QSE_T("task returend %d\n"), n);
} }
else else
{ {
if (httpd->scb->mux.addhnd ( if (httpd->opt.scb.mux.addhnd (
httpd, httpd->mux, task->trigger[i].handle, httpd, httpd->mux, task->trigger[i].handle,
trigger_mux_mask, client) <= -1) trigger_mux_mask, client) <= -1)
{ {
@ -1003,12 +1068,12 @@ qse_printf (QSE_T("task returend %d\n"), n);
if ((client->status & CLIENT_HANDLE_IN_MUX) != if ((client->status & CLIENT_HANDLE_IN_MUX) !=
(client_handle_mux_status & CLIENT_HANDLE_IN_MUX)) (client_handle_mux_status & CLIENT_HANDLE_IN_MUX))
{ {
httpd->scb->mux.delhnd (httpd, httpd->mux, client->handle); httpd->opt.scb.mux.delhnd (httpd, httpd->mux, client->handle);
client->status &= ~CLIENT_HANDLE_IN_MUX; client->status &= ~CLIENT_HANDLE_IN_MUX;
if (client_handle_mux_mask) if (client_handle_mux_mask)
{ {
if (httpd->scb->mux.addhnd ( if (httpd->opt.scb.mux.addhnd (
httpd, httpd->mux, client->handle, httpd, httpd->mux, client->handle,
client_handle_mux_mask, client) <= -1) client_handle_mux_mask, client) <= -1)
{ {
@ -1036,7 +1101,7 @@ static int perform_client_task (
if (!(client->status & CLIENT_READY)) if (!(client->status & CLIENT_READY))
{ {
int x; int x;
x = httpd->scb->client.accepted (httpd, client); x = httpd->opt.scb.client.accepted (httpd, client);
if (x <= -1) goto oops; if (x <= -1) goto oops;
if (x >= 1) if (x >= 1)
{ {
@ -1079,7 +1144,6 @@ static void purge_bad_clients (qse_httpd_t* httpd)
{ {
client = httpd->client.bad; client = httpd->client.bad;
httpd->client.bad = client->bad_next; httpd->client.bad = client->bad_next;
qse_printf (QSE_T("PURGING BAD CLIENT XXXXXXXXXXXXXX\n"));
purge_client (httpd, client); purge_client (httpd, client);
} }
} }
@ -1096,10 +1160,11 @@ static void purge_idle_clients (qse_httpd_t* httpd)
while (client) while (client)
{ {
next_client = client->next; next_client = client->next;
if (now.sec <= client->last_active.sec) break;
if (now.sec - client->last_active.sec < 30) break; /* TODO: make this time configurable... */
qse_printf (QSE_T("PURGING IDLE CLIENT XXXXXXXXXXXXXX %d\n"), (int)(now.sec - client->last_active.sec)); /* TODO: check the nsec part */
if (now.sec <= client->last_active.sec) break;
if (now.sec - client->last_active.sec < httpd->opt.idle_limit.sec) break;
purge_client (httpd, client); purge_client (httpd, client);
client = next_client; client = next_client;
} }
@ -1127,11 +1192,11 @@ qse_httpd_task_t* qse_httpd_entask (
/* arrange to invokde this task so long as /* arrange to invokde this task so long as
* the client-side handle is writable. */ * the client-side handle is writable. */
QSE_ASSERT (client->status & CLIENT_HANDLE_IN_MUX); QSE_ASSERT (client->status & CLIENT_HANDLE_IN_MUX);
httpd->scb->mux.delhnd (httpd, httpd->mux, client->handle); httpd->opt.scb.mux.delhnd (httpd, httpd->mux, client->handle);
client->status &= ~CLIENT_HANDLE_IN_MUX; client->status &= ~CLIENT_HANDLE_IN_MUX;
qse_printf (QSE_T("MUX ADDHND CLIENT RW(ENTASK) %d\n"), client->handle.i); qse_printf (QSE_T("MUX ADDHND CLIENT RW(ENTASK) %d\n"), client->handle.i);
if (httpd->scb->mux.addhnd ( if (httpd->opt.scb.mux.addhnd (
httpd, httpd->mux, client->handle, httpd, httpd->mux, client->handle,
QSE_HTTPD_MUX_READ | QSE_HTTPD_MUX_WRITE, QSE_HTTPD_MUX_READ | QSE_HTTPD_MUX_WRITE,
client) <= -1) client) <= -1)
@ -1154,22 +1219,7 @@ static int dispatch_mux (
perform_client_task (httpd, mux, handle, mask, cbarg); perform_client_task (httpd, mux, handle, mask, cbarg);
} }
static void reconf_servers (qse_httpd_t* httpd) int qse_httpd_loop (qse_httpd_t* httpd)
{
qse_httpd_server_t* server;
for (server = httpd->server.list.head; server; server = server->next)
{
if (server->dope.flags & QSE_HTTPD_SERVER_ACTIVE)
{
if (server->dope.reconf) server->dope.reconf (httpd, server);
}
}
}
int qse_httpd_loop (
qse_httpd_t* httpd, qse_httpd_scb_t* scb,
qse_httpd_rcb_t* rcb, const qse_ntime_t* tmout)
{ {
int xret; int xret;
@ -1179,31 +1229,34 @@ int qse_httpd_loop (
QSE_ASSERTX (httpd->client.list.head == QSE_NULL, QSE_ASSERTX (httpd->client.list.head == QSE_NULL,
"No client should exist when this loop is started"); "No client should exist when this loop is started");
if (scb == QSE_NULL || rcb == QSE_NULL || if (httpd->server.list.head == QSE_NULL)
httpd->server.list.head == QSE_NULL)
{ {
httpd->errnum = QSE_HTTPD_EINVAL; httpd->errnum = QSE_HTTPD_EINVAL;
return -1; return -1;
} }
httpd->stopreq = 0; httpd->stopreq = 0;
httpd->scb = scb; httpd->impedereq = 0;
httpd->rcb = rcb;
/* system callbacks and request callbacks must be set before the call to this function */
QSE_ASSERT (httpd->opt.scb.mux.open && httpd->opt.scb.mux.close && httpd->opt.scb.mux.poll);
QSE_ASSERT (httpd->opt.rcb.peekreq && httpd->opt.rcb.pokereq);
/* a server must be attached before the call to this function */
QSE_ASSERT (httpd->server.navail > 0); QSE_ASSERT (httpd->server.navail > 0);
httpd->mux = httpd->scb->mux.open (httpd, dispatch_mux); httpd->mux = httpd->opt.scb.mux.open (httpd, dispatch_mux);
if (httpd->mux == QSE_NULL) return -1; if (httpd->mux == QSE_NULL) return -1;
if (activate_servers (httpd) <= -1) if (activate_servers (httpd) <= -1)
{ {
httpd->scb->mux.close (httpd, httpd->mux); httpd->opt.scb.mux.close (httpd, httpd->mux);
return -1; return -1;
} }
if (httpd->server.nactive <= 0) if (httpd->server.nactive <= 0)
{ {
httpd->errnum = QSE_HTTPD_ENOSVR; httpd->errnum = QSE_HTTPD_ENOSVR;
httpd->scb->mux.close (httpd, httpd->mux); httpd->opt.scb.mux.close (httpd, httpd->mux);
return -1; return -1;
} }
@ -1213,7 +1266,7 @@ int qse_httpd_loop (
{ {
int count; int count;
count = httpd->scb->mux.poll (httpd, httpd->mux, tmout); count = httpd->opt.scb.mux.poll (httpd, httpd->mux, &httpd->opt.tmout);
if (count <= -1) if (count <= -1)
{ {
if (httpd->errnum != QSE_HTTPD_EINTR) if (httpd->errnum != QSE_HTTPD_EINTR)
@ -1226,25 +1279,16 @@ int qse_httpd_loop (
purge_bad_clients (httpd); purge_bad_clients (httpd);
purge_idle_clients (httpd); purge_idle_clients (httpd);
if (httpd->reconfreq) if (httpd->impedereq)
{ {
qse_httpd_ecb_t* ecb; httpd->impedereq = 0;
httpd->opt.rcb.impede (httpd);
for (ecb = httpd->ecb; ecb; ecb = ecb->next)
if (ecb->reconf) ecb->reconf (httpd, QSE_HTTPD_ECB_RECONF_PRE);
reconf_servers (httpd);
for (ecb = httpd->ecb; ecb; ecb = ecb->next)
if (ecb->reconf) ecb->reconf (httpd, QSE_HTTPD_ECB_RECONF_POST);
httpd->reconfreq = 0;
} }
} }
purge_client_list (httpd); purge_client_list (httpd);
deactivate_servers (httpd); deactivate_servers (httpd);
httpd->scb->mux.close (httpd, httpd->mux); httpd->opt.scb.mux.close (httpd, httpd->mux);
return xret; return xret;
} }

View File

@ -32,15 +32,19 @@ struct qse_httpd_t
qse_mmgr_t* mmgr; qse_mmgr_t* mmgr;
qse_httpd_errnum_t errnum; qse_httpd_errnum_t errnum;
qse_httpd_ecb_t* ecb; /* event callbacks */ qse_httpd_ecb_t* ecb; /* event callbacks */
qse_httpd_scb_t* scb; /* system callbacks */
qse_httpd_rcb_t* rcb; /* request callbacks */
struct struct
{ {
int trait; int trait;
qse_httpd_scb_t scb; /* system callbacks */
qse_httpd_rcb_t rcb; /* request callbacks */
qse_ntime_t tmout; /* poll timeout */
qse_ntime_t idle_limit;
} opt; } opt;
int stopreq: 1; int stopreq: 1;
int reconfreq: 1; int impedereq: 1;
qse_mchar_t sname[128]; /* server name for the server header */ qse_mchar_t sname[128]; /* server name for the server header */
qse_mchar_t gtbuf[10][64]; /* GMT time buffers */ qse_mchar_t gtbuf[10][64]; /* GMT time buffers */