abstracted out most of muplexing code from httpd
This commit is contained in:
parent
6c8755de00
commit
c55bceb220
@ -24,6 +24,7 @@
|
|||||||
#include <qse/types.h>
|
#include <qse/types.h>
|
||||||
#include <qse/macros.h>
|
#include <qse/macros.h>
|
||||||
#include <qse/net/htre.h>
|
#include <qse/net/htre.h>
|
||||||
|
#include <qse/net/htrd.h>
|
||||||
#include <qse/cmn/nwad.h>
|
#include <qse/cmn/nwad.h>
|
||||||
#include <qse/cmn/time.h>
|
#include <qse/cmn/time.h>
|
||||||
|
|
||||||
@ -73,6 +74,7 @@ typedef struct qse_httpd_server_t qse_httpd_server_t;
|
|||||||
struct qse_httpd_server_t
|
struct qse_httpd_server_t
|
||||||
{
|
{
|
||||||
qse_httpd_server_t* next;
|
qse_httpd_server_t* next;
|
||||||
|
int active;
|
||||||
|
|
||||||
qse_nwad_t nwad;
|
qse_nwad_t nwad;
|
||||||
int secure;
|
int secure;
|
||||||
@ -81,6 +83,20 @@ struct qse_httpd_server_t
|
|||||||
qse_ubi_t handle;
|
qse_ubi_t handle;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum qse_httpd_mux_mask_t
|
||||||
|
{
|
||||||
|
QSE_HTTPD_MUX_READ = (1 << 0),
|
||||||
|
QSE_HTTPD_MUX_WRITE = (1 << 1)
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef int (*qse_httpd_muxcb_t) (
|
||||||
|
qse_httpd_t* httpd,
|
||||||
|
void* mux,
|
||||||
|
qse_ubi_t handle,
|
||||||
|
int mask, /* ORed of qse_httpd_mux_mask_t */
|
||||||
|
void* cbarg
|
||||||
|
);
|
||||||
|
|
||||||
typedef struct qse_httpd_cbs_t qse_httpd_cbs_t;
|
typedef struct qse_httpd_cbs_t qse_httpd_cbs_t;
|
||||||
struct qse_httpd_cbs_t
|
struct qse_httpd_cbs_t
|
||||||
{
|
{
|
||||||
@ -93,6 +109,14 @@ struct qse_httpd_cbs_t
|
|||||||
|
|
||||||
struct
|
struct
|
||||||
{
|
{
|
||||||
|
void* (*open) (qse_httpd_t* httpd);
|
||||||
|
void (*close) (qse_httpd_t* httpd, void* mux);
|
||||||
|
int (*addhnd) (
|
||||||
|
qse_httpd_t* httpd, void* mux, qse_ubi_t handle,
|
||||||
|
int mask, qse_httpd_muxcb_t cbfun, void* cbarg);
|
||||||
|
int (*delhnd) (qse_httpd_t* httpd, void* mux, qse_ubi_t handle);
|
||||||
|
int (*poll) (qse_httpd_t* httpd, void* mux, qse_ntime_t timeout);
|
||||||
|
|
||||||
int (*readable) (
|
int (*readable) (
|
||||||
qse_httpd_t* httpd, qse_ubi_t handle, qse_ntoff_t timeout);
|
qse_httpd_t* httpd, qse_ubi_t handle, qse_ntoff_t timeout);
|
||||||
int (*writable) (
|
int (*writable) (
|
||||||
@ -200,6 +224,8 @@ enum qse_httpd_task_trigger_mask_t
|
|||||||
|
|
||||||
struct qse_httpd_task_t
|
struct qse_httpd_task_t
|
||||||
{
|
{
|
||||||
|
/* == PUBLIC == */
|
||||||
|
|
||||||
/* you must not call another entask functions from within
|
/* you must not call another entask functions from within
|
||||||
* an initailizer. you can call entask functions from within
|
* an initailizer. you can call entask functions from within
|
||||||
* a finalizer and a main function. */
|
* a finalizer and a main function. */
|
||||||
@ -210,7 +236,50 @@ struct qse_httpd_task_t
|
|||||||
int trigger_mask;
|
int trigger_mask;
|
||||||
qse_ubi_t trigger[3];
|
qse_ubi_t trigger[3];
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
int mask; /* QSE_HTTPD_TASK_TRIGGER_READ | QSE_HTTPD_TASK_TRIGGER_WRITE */
|
||||||
|
qse_ubi_t handle;
|
||||||
|
} trigger[3];
|
||||||
|
#endif
|
||||||
|
|
||||||
void* ctx;
|
void* ctx;
|
||||||
|
|
||||||
|
/* == PRIVATE == */
|
||||||
|
qse_httpd_task_t* prev;
|
||||||
|
qse_httpd_task_t* next;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
struct qse_httpd_client_t
|
||||||
|
{
|
||||||
|
/* == PUBLIC == */
|
||||||
|
|
||||||
|
qse_ubi_t handle;
|
||||||
|
qse_ubi_t handle2;
|
||||||
|
qse_nwad_t local_addr;
|
||||||
|
qse_nwad_t remote_addr;
|
||||||
|
|
||||||
|
/* == PRIVATE == */
|
||||||
|
qse_htrd_t* htrd;
|
||||||
|
int secure;
|
||||||
|
int status;
|
||||||
|
|
||||||
|
qse_httpd_client_t* prev;
|
||||||
|
qse_httpd_client_t* next;
|
||||||
|
|
||||||
|
qse_httpd_client_t* bad_next;
|
||||||
|
|
||||||
|
qse_httpd_client_t* prev_tasked;
|
||||||
|
qse_httpd_client_t* next_tasked;
|
||||||
|
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
int count;
|
||||||
|
qse_httpd_task_t* head;
|
||||||
|
qse_httpd_task_t* tail;
|
||||||
|
} task;
|
||||||
};
|
};
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
@ -257,7 +326,8 @@ void qse_httpd_setoption (
|
|||||||
*/
|
*/
|
||||||
int qse_httpd_loop (
|
int qse_httpd_loop (
|
||||||
qse_httpd_t* httpd,
|
qse_httpd_t* httpd,
|
||||||
qse_httpd_cbs_t* cbs
|
qse_httpd_cbs_t* cbs,
|
||||||
|
qse_ntime_t timeout
|
||||||
);
|
);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -288,7 +358,7 @@ void qse_httpd_completecontent (
|
|||||||
qse_httpd_task_t* qse_httpd_entask (
|
qse_httpd_task_t* qse_httpd_entask (
|
||||||
qse_httpd_t* httpd,
|
qse_httpd_t* httpd,
|
||||||
qse_httpd_client_t* client,
|
qse_httpd_client_t* client,
|
||||||
const qse_httpd_task_t* pred,
|
qse_httpd_task_t* pred,
|
||||||
const qse_httpd_task_t* task,
|
const qse_httpd_task_t* task,
|
||||||
qse_size_t xtnsize
|
qse_size_t xtnsize
|
||||||
);
|
);
|
||||||
@ -298,58 +368,37 @@ qse_httpd_task_t* qse_httpd_entask (
|
|||||||
qse_httpd_task_t* qse_httpd_entaskdisconnect (
|
qse_httpd_task_t* qse_httpd_entaskdisconnect (
|
||||||
qse_httpd_t* httpd,
|
qse_httpd_t* httpd,
|
||||||
qse_httpd_client_t* client,
|
qse_httpd_client_t* client,
|
||||||
const qse_httpd_task_t* pred
|
qse_httpd_task_t* pred
|
||||||
);
|
);
|
||||||
|
|
||||||
qse_httpd_task_t* qse_httpd_entasktext (
|
qse_httpd_task_t* qse_httpd_entasktext (
|
||||||
qse_httpd_t* httpd,
|
qse_httpd_t* httpd,
|
||||||
qse_httpd_client_t* client,
|
qse_httpd_client_t* client,
|
||||||
const qse_httpd_task_t* pred,
|
qse_httpd_task_t* pred,
|
||||||
const qse_mchar_t* text
|
const qse_mchar_t* text
|
||||||
);
|
);
|
||||||
|
|
||||||
qse_httpd_task_t* qse_httpd_entaskstatictext (
|
qse_httpd_task_t* qse_httpd_entaskstatictext (
|
||||||
qse_httpd_t* httpd,
|
qse_httpd_t* httpd,
|
||||||
qse_httpd_client_t* client,
|
qse_httpd_client_t* client,
|
||||||
const qse_httpd_task_t* pred,
|
qse_httpd_task_t* pred,
|
||||||
const qse_mchar_t* text
|
const qse_mchar_t* text
|
||||||
);
|
);
|
||||||
|
|
||||||
qse_httpd_task_t* qse_httpd_entaskformat (
|
qse_httpd_task_t* qse_httpd_entaskformat (
|
||||||
qse_httpd_t* httpd,
|
qse_httpd_t* httpd,
|
||||||
qse_httpd_client_t* client,
|
qse_httpd_client_t* client,
|
||||||
const qse_httpd_task_t* pred,
|
qse_httpd_task_t* pred,
|
||||||
const qse_mchar_t* fmt,
|
const qse_mchar_t* fmt,
|
||||||
...
|
...
|
||||||
);
|
);
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
|
|
||||||
#if 0
|
|
||||||
qse_httpd_task_t* qse_httpd_entaskfile (
|
|
||||||
qse_httpd_t* httpd,
|
|
||||||
qse_httpd_client_t* client,
|
|
||||||
const qse_httpd_task_t* pred,
|
|
||||||
qse_ubi_t handle,
|
|
||||||
qse_foff_t offset,
|
|
||||||
qse_foff_t size
|
|
||||||
);
|
|
||||||
|
|
||||||
qse_httpd_task_t* qse_httpd_entaskdir (
|
|
||||||
qse_httpd_t* httpd,
|
|
||||||
qse_httpd_client_t* client,
|
|
||||||
const qse_httpd_task_t* pred,
|
|
||||||
qse_ubi_t handle,
|
|
||||||
int chunked
|
|
||||||
);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
|
||||||
|
|
||||||
qse_httpd_task_t* qse_httpd_entaskerror (
|
qse_httpd_task_t* qse_httpd_entaskerror (
|
||||||
qse_httpd_t* httpd,
|
qse_httpd_t* httpd,
|
||||||
qse_httpd_client_t* client,
|
qse_httpd_client_t* client,
|
||||||
const qse_httpd_task_t* task,
|
qse_httpd_task_t* pred,
|
||||||
int code,
|
int code,
|
||||||
qse_htre_t* req
|
qse_htre_t* req
|
||||||
);
|
);
|
||||||
@ -357,7 +406,7 @@ qse_httpd_task_t* qse_httpd_entaskerror (
|
|||||||
qse_httpd_task_t* qse_httpd_entaskcontinue (
|
qse_httpd_task_t* qse_httpd_entaskcontinue (
|
||||||
qse_httpd_t* httpd,
|
qse_httpd_t* httpd,
|
||||||
qse_httpd_client_t* client,
|
qse_httpd_client_t* client,
|
||||||
const qse_httpd_task_t* task,
|
qse_httpd_task_t* pred,
|
||||||
qse_htre_t* req
|
qse_htre_t* req
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -367,7 +416,7 @@ qse_httpd_task_t* qse_httpd_entaskcontinue (
|
|||||||
qse_httpd_task_t* qse_httpd_entaskauth (
|
qse_httpd_task_t* qse_httpd_entaskauth (
|
||||||
qse_httpd_t* httpd,
|
qse_httpd_t* httpd,
|
||||||
qse_httpd_client_t* client,
|
qse_httpd_client_t* client,
|
||||||
const qse_httpd_task_t* task,
|
qse_httpd_task_t* pred,
|
||||||
const qse_mchar_t* realm,
|
const qse_mchar_t* realm,
|
||||||
qse_htre_t* req
|
qse_htre_t* req
|
||||||
);
|
);
|
||||||
@ -375,7 +424,7 @@ qse_httpd_task_t* qse_httpd_entaskauth (
|
|||||||
qse_httpd_task_t* qse_httpd_entaskdir (
|
qse_httpd_task_t* qse_httpd_entaskdir (
|
||||||
qse_httpd_t* httpd,
|
qse_httpd_t* httpd,
|
||||||
qse_httpd_client_t* client,
|
qse_httpd_client_t* client,
|
||||||
const qse_httpd_task_t* pred,
|
qse_httpd_task_t* pred,
|
||||||
const qse_mchar_t* name,
|
const qse_mchar_t* name,
|
||||||
qse_htre_t* req
|
qse_htre_t* req
|
||||||
);
|
);
|
||||||
@ -383,7 +432,7 @@ qse_httpd_task_t* qse_httpd_entaskdir (
|
|||||||
qse_httpd_task_t* qse_httpd_entaskfile (
|
qse_httpd_task_t* qse_httpd_entaskfile (
|
||||||
qse_httpd_t* httpd,
|
qse_httpd_t* httpd,
|
||||||
qse_httpd_client_t* client,
|
qse_httpd_client_t* client,
|
||||||
const qse_httpd_task_t* pred,
|
qse_httpd_task_t* pred,
|
||||||
const qse_mchar_t* name,
|
const qse_mchar_t* name,
|
||||||
qse_htre_t* req
|
qse_htre_t* req
|
||||||
);
|
);
|
||||||
@ -391,7 +440,7 @@ qse_httpd_task_t* qse_httpd_entaskfile (
|
|||||||
qse_httpd_task_t* qse_httpd_entaskcgi (
|
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,
|
||||||
const qse_httpd_task_t* pred,
|
qse_httpd_task_t* pred,
|
||||||
const qse_mchar_t* path,
|
const qse_mchar_t* path,
|
||||||
qse_htre_t* req
|
qse_htre_t* req
|
||||||
);
|
);
|
||||||
@ -399,7 +448,7 @@ qse_httpd_task_t* qse_httpd_entaskcgi (
|
|||||||
qse_httpd_task_t* qse_httpd_entasknph (
|
qse_httpd_task_t* qse_httpd_entasknph (
|
||||||
qse_httpd_t* httpd,
|
qse_httpd_t* httpd,
|
||||||
qse_httpd_client_t* client,
|
qse_httpd_client_t* client,
|
||||||
const qse_httpd_task_t* pred,
|
qse_httpd_task_t* pred,
|
||||||
const qse_mchar_t* path,
|
const qse_mchar_t* path,
|
||||||
qse_htre_t* req
|
qse_htre_t* req
|
||||||
);
|
);
|
||||||
|
@ -48,7 +48,7 @@ static int task_main_disconnect (
|
|||||||
qse_httpd_task_t* qse_httpd_entaskdisconnect (
|
qse_httpd_task_t* qse_httpd_entaskdisconnect (
|
||||||
qse_httpd_t* httpd,
|
qse_httpd_t* httpd,
|
||||||
qse_httpd_client_t* client,
|
qse_httpd_client_t* client,
|
||||||
const qse_httpd_task_t* pred)
|
qse_httpd_task_t* pred)
|
||||||
{
|
{
|
||||||
qse_httpd_task_t task;
|
qse_httpd_task_t task;
|
||||||
|
|
||||||
@ -86,7 +86,7 @@ static int task_main_statictext (
|
|||||||
qse_httpd_task_t* qse_httpd_entaskstatictext (
|
qse_httpd_task_t* qse_httpd_entaskstatictext (
|
||||||
qse_httpd_t* httpd,
|
qse_httpd_t* httpd,
|
||||||
qse_httpd_client_t* client,
|
qse_httpd_client_t* client,
|
||||||
const qse_httpd_task_t* pred,
|
qse_httpd_task_t* pred,
|
||||||
const qse_mchar_t* text)
|
const qse_mchar_t* text)
|
||||||
{
|
{
|
||||||
qse_httpd_task_t task;
|
qse_httpd_task_t task;
|
||||||
@ -144,7 +144,7 @@ static int task_main_text (
|
|||||||
qse_httpd_task_t* qse_httpd_entasktext (
|
qse_httpd_task_t* qse_httpd_entasktext (
|
||||||
qse_httpd_t* httpd,
|
qse_httpd_t* httpd,
|
||||||
qse_httpd_client_t* client,
|
qse_httpd_client_t* client,
|
||||||
const qse_httpd_task_t* pred,
|
qse_httpd_task_t* pred,
|
||||||
const qse_mchar_t* text)
|
const qse_mchar_t* text)
|
||||||
{
|
{
|
||||||
qse_httpd_task_t task;
|
qse_httpd_task_t task;
|
||||||
@ -217,7 +217,7 @@ static int task_main_format (
|
|||||||
qse_httpd_task_t* qse_httpd_entaskformat (
|
qse_httpd_task_t* qse_httpd_entaskformat (
|
||||||
qse_httpd_t* httpd,
|
qse_httpd_t* httpd,
|
||||||
qse_httpd_client_t* client,
|
qse_httpd_client_t* client,
|
||||||
const qse_httpd_task_t* pred,
|
qse_httpd_task_t* pred,
|
||||||
const qse_mchar_t* fmt, ...)
|
const qse_mchar_t* fmt, ...)
|
||||||
{
|
{
|
||||||
qse_httpd_task_t task;
|
qse_httpd_task_t task;
|
||||||
@ -315,7 +315,7 @@ qse_printf (QSE_T("SEND: [%.*hs]\n"), (int)l, buf);
|
|||||||
|
|
||||||
static qse_httpd_task_t* entask_error (
|
static qse_httpd_task_t* entask_error (
|
||||||
qse_httpd_t* httpd, qse_httpd_client_t* client,
|
qse_httpd_t* httpd, qse_httpd_client_t* client,
|
||||||
const qse_httpd_task_t* task, int code,
|
qse_httpd_task_t* pred, int code,
|
||||||
const qse_http_version_t* version, int keepalive)
|
const qse_http_version_t* version, int keepalive)
|
||||||
{
|
{
|
||||||
const qse_mchar_t* smsg;
|
const qse_mchar_t* smsg;
|
||||||
@ -380,7 +380,7 @@ static qse_httpd_task_t* entask_error (
|
|||||||
}
|
}
|
||||||
|
|
||||||
return qse_httpd_entaskformat (
|
return qse_httpd_entaskformat (
|
||||||
httpd, client, task,
|
httpd, client, pred,
|
||||||
QSE_MT("HTTP/%d.%d %d %s\r\nConnection: %s\r\nContent-Type: text/html\r\nContent-Length: %lu\r\n\r\n%s\r\n\r\n"),
|
QSE_MT("HTTP/%d.%d %d %s\r\nConnection: %s\r\nContent-Type: text/html\r\nContent-Length: %lu\r\n\r\n%s\r\n\r\n"),
|
||||||
version->major, version->minor, code, smsg,
|
version->major, version->minor, code, smsg,
|
||||||
(keepalive? QSE_MT("keep-alive"): QSE_MT("close")),
|
(keepalive? QSE_MT("keep-alive"): QSE_MT("close")),
|
||||||
@ -390,21 +390,21 @@ static qse_httpd_task_t* entask_error (
|
|||||||
|
|
||||||
qse_httpd_task_t* qse_httpd_entaskerror (
|
qse_httpd_task_t* qse_httpd_entaskerror (
|
||||||
qse_httpd_t* httpd, qse_httpd_client_t* client,
|
qse_httpd_t* httpd, qse_httpd_client_t* client,
|
||||||
const qse_httpd_task_t* task, int code, qse_htre_t* req)
|
qse_httpd_task_t* pred, int code, qse_htre_t* req)
|
||||||
{
|
{
|
||||||
return entask_error (
|
return entask_error (
|
||||||
httpd, client, task, code,
|
httpd, client, pred, code,
|
||||||
qse_htre_getversion(req), req->attr.keepalive);
|
qse_htre_getversion(req), req->attr.keepalive);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*------------------------------------------------------------------------*/
|
/*------------------------------------------------------------------------*/
|
||||||
qse_httpd_task_t* qse_httpd_entaskcontinue (
|
qse_httpd_task_t* qse_httpd_entaskcontinue (
|
||||||
qse_httpd_t* httpd, qse_httpd_client_t* client,
|
qse_httpd_t* httpd, qse_httpd_client_t* client,
|
||||||
const qse_httpd_task_t* task, qse_htre_t* req)
|
qse_httpd_task_t* pred, qse_htre_t* req)
|
||||||
{
|
{
|
||||||
const qse_http_version_t* version = qse_htre_getversion(req);
|
const qse_http_version_t* version = qse_htre_getversion(req);
|
||||||
return qse_httpd_entaskformat (
|
return qse_httpd_entaskformat (
|
||||||
httpd, client, task,
|
httpd, client, pred,
|
||||||
QSE_MT("HTTP/%d.%d 100 Continue\r\n\r\n"),
|
QSE_MT("HTTP/%d.%d 100 Continue\r\n\r\n"),
|
||||||
version->major, version->minor);
|
version->major, version->minor);
|
||||||
}
|
}
|
||||||
@ -413,7 +413,7 @@ qse_httpd_task_t* qse_httpd_entaskcontinue (
|
|||||||
|
|
||||||
qse_httpd_task_t* qse_httpd_entaskauth (
|
qse_httpd_task_t* qse_httpd_entaskauth (
|
||||||
qse_httpd_t* httpd, qse_httpd_client_t* client,
|
qse_httpd_t* httpd, qse_httpd_client_t* client,
|
||||||
const qse_httpd_task_t* task, const qse_mchar_t* realm, qse_htre_t* req)
|
qse_httpd_task_t* pred, const qse_mchar_t* realm, qse_htre_t* req)
|
||||||
{
|
{
|
||||||
const qse_http_version_t* version;
|
const qse_http_version_t* version;
|
||||||
const qse_mchar_t* lmsg;
|
const qse_mchar_t* lmsg;
|
||||||
@ -422,7 +422,7 @@ qse_httpd_task_t* qse_httpd_entaskauth (
|
|||||||
lmsg = QSE_MT("<html><head><title>Unauthorized</title></head><body><b>UNAUTHORIZED<b></body></html>");
|
lmsg = QSE_MT("<html><head><title>Unauthorized</title></head><body><b>UNAUTHORIZED<b></body></html>");
|
||||||
|
|
||||||
return qse_httpd_entaskformat (
|
return qse_httpd_entaskformat (
|
||||||
httpd, client, task,
|
httpd, client, pred,
|
||||||
QSE_MT("HTTP/%d.%d 401 Unauthorized\r\nConnection: %s\r\nWWW-Authenticate: Basic realm=\"%s\"\r\nContent-Type: text/html\r\nContent-Length: %lu\r\n\r\n%s\r\n\r\n"),
|
QSE_MT("HTTP/%d.%d 401 Unauthorized\r\nConnection: %s\r\nWWW-Authenticate: Basic realm=\"%s\"\r\nContent-Type: text/html\r\nContent-Length: %lu\r\n\r\n%s\r\n\r\n"),
|
||||||
version->major, version->minor,
|
version->major, version->minor,
|
||||||
(req->attr.keepalive? QSE_MT("keep-alive"): QSE_MT("close")),
|
(req->attr.keepalive? QSE_MT("keep-alive"): QSE_MT("close")),
|
||||||
@ -764,7 +764,7 @@ send_dirlist:
|
|||||||
qse_httpd_task_t* qse_httpd_entaskdir (
|
qse_httpd_task_t* qse_httpd_entaskdir (
|
||||||
qse_httpd_t* httpd,
|
qse_httpd_t* httpd,
|
||||||
qse_httpd_client_t* client,
|
qse_httpd_client_t* client,
|
||||||
const qse_httpd_task_t* pred,
|
qse_httpd_task_t* pred,
|
||||||
qse_ubi_t handle, int chunked)
|
qse_ubi_t handle, int chunked)
|
||||||
{
|
{
|
||||||
qse_httpd_task_t task;
|
qse_httpd_task_t task;
|
||||||
@ -888,7 +888,7 @@ static int task_main_path (
|
|||||||
qse_httpd_task_t* qse_httpd_entaskpath (
|
qse_httpd_task_t* qse_httpd_entaskpath (
|
||||||
qse_httpd_t* httpd,
|
qse_httpd_t* httpd,
|
||||||
qse_httpd_client_t* client,
|
qse_httpd_client_t* client,
|
||||||
const qse_httpd_task_t* pred,
|
qse_httpd_task_t* pred,
|
||||||
const qse_mchar_t* name,
|
const qse_mchar_t* name,
|
||||||
qse_htre_t* req)
|
qse_htre_t* req)
|
||||||
{
|
{
|
||||||
@ -996,7 +996,7 @@ static int task_main_fseg (
|
|||||||
|
|
||||||
static qse_httpd_task_t* entask_file_segment (
|
static qse_httpd_task_t* entask_file_segment (
|
||||||
qse_httpd_t* httpd, qse_httpd_client_t* client,
|
qse_httpd_t* httpd, qse_httpd_client_t* client,
|
||||||
const qse_httpd_task_t* pred,
|
qse_httpd_task_t* pred,
|
||||||
qse_ubi_t handle, qse_foff_t offset, qse_foff_t size)
|
qse_ubi_t handle, qse_foff_t offset, qse_foff_t size)
|
||||||
{
|
{
|
||||||
qse_httpd_task_t task;
|
qse_httpd_task_t task;
|
||||||
@ -1179,7 +1179,7 @@ no_file_send:
|
|||||||
qse_httpd_task_t* qse_httpd_entaskfile (
|
qse_httpd_task_t* qse_httpd_entaskfile (
|
||||||
qse_httpd_t* httpd,
|
qse_httpd_t* httpd,
|
||||||
qse_httpd_client_t* client,
|
qse_httpd_client_t* client,
|
||||||
const qse_httpd_task_t* pred,
|
qse_httpd_task_t* pred,
|
||||||
const qse_mchar_t* path,
|
const qse_mchar_t* path,
|
||||||
qse_htre_t* req)
|
qse_htre_t* req)
|
||||||
{
|
{
|
||||||
@ -1896,6 +1896,7 @@ static int task_main_cgi_4 (
|
|||||||
|
|
||||||
QSE_ASSERT (cgi->pio_inited);
|
QSE_ASSERT (cgi->pio_inited);
|
||||||
|
|
||||||
|
qse_printf (QSE_T("task_main_cgi_4 trigger_mask = %d\n"), task->trigger_mask);
|
||||||
if (task->trigger_mask & QSE_HTTPD_TASK_TRIGGER_RELAYABLE)
|
if (task->trigger_mask & QSE_HTTPD_TASK_TRIGGER_RELAYABLE)
|
||||||
{
|
{
|
||||||
cgi_forward_content (httpd, task, 0);
|
cgi_forward_content (httpd, task, 0);
|
||||||
@ -2069,6 +2070,7 @@ qse_printf (QSE_T("[cgi-3 send failure....\n"));
|
|||||||
cgi->res_left -= n;
|
cgi->res_left -= n;
|
||||||
if (cgi->res_left <= 0)
|
if (cgi->res_left <= 0)
|
||||||
{
|
{
|
||||||
|
qse_printf (QSE_T("[switching to cgi-4....\n"));
|
||||||
task->main = task_main_cgi_4;
|
task->main = task_main_cgi_4;
|
||||||
/* don't chain-call task_main_cgi_4 since it has another send
|
/* don't chain-call task_main_cgi_4 since it has another send
|
||||||
* and it has already been sent here. so the writability must
|
* and it has already been sent here. so the writability must
|
||||||
@ -2317,7 +2319,7 @@ oops:
|
|||||||
|
|
||||||
static QSE_INLINE qse_httpd_task_t* entask_cgi (
|
static QSE_INLINE qse_httpd_task_t* entask_cgi (
|
||||||
qse_httpd_t* httpd, qse_httpd_client_t* client,
|
qse_httpd_t* httpd, qse_httpd_client_t* client,
|
||||||
const qse_httpd_task_t* pred, const qse_mchar_t* path,
|
qse_httpd_task_t* pred, const qse_mchar_t* path,
|
||||||
qse_htre_t* req, int nph)
|
qse_htre_t* req, int nph)
|
||||||
{
|
{
|
||||||
qse_httpd_task_t task;
|
qse_httpd_task_t task;
|
||||||
@ -2341,14 +2343,14 @@ static QSE_INLINE qse_httpd_task_t* entask_cgi (
|
|||||||
|
|
||||||
qse_httpd_task_t* qse_httpd_entaskcgi (
|
qse_httpd_task_t* qse_httpd_entaskcgi (
|
||||||
qse_httpd_t* httpd, qse_httpd_client_t* client,
|
qse_httpd_t* httpd, qse_httpd_client_t* client,
|
||||||
const qse_httpd_task_t* pred, const qse_mchar_t* path, qse_htre_t* req)
|
qse_httpd_task_t* pred, const qse_mchar_t* path, qse_htre_t* req)
|
||||||
{
|
{
|
||||||
return entask_cgi (httpd, client, pred, path, req, 0);
|
return entask_cgi (httpd, client, pred, path, req, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
qse_httpd_task_t* qse_httpd_entasknph (
|
qse_httpd_task_t* qse_httpd_entasknph (
|
||||||
qse_httpd_t* httpd, qse_httpd_client_t* client,
|
qse_httpd_t* httpd, qse_httpd_client_t* client,
|
||||||
const qse_httpd_task_t* pred, const qse_mchar_t* path, qse_htre_t* req)
|
qse_httpd_task_t* pred, const qse_mchar_t* path, qse_htre_t* req)
|
||||||
{
|
{
|
||||||
return entask_cgi (httpd, client, pred, path, req, 1);
|
return entask_cgi (httpd, client, pred, path, req, 1);
|
||||||
}
|
}
|
||||||
|
1070
qse/lib/net/httpd.c
1070
qse/lib/net/httpd.c
File diff suppressed because it is too large
Load Diff
@ -24,56 +24,6 @@
|
|||||||
/* private header file for httpd */
|
/* private header file for httpd */
|
||||||
|
|
||||||
#include <qse/net/httpd.h>
|
#include <qse/net/httpd.h>
|
||||||
#include <qse/net/htrd.h>
|
|
||||||
#include <qse/cmn/nwad.h>
|
|
||||||
|
|
||||||
/* REMOVE THESE headers after abstracting away select()/fd_set */
|
|
||||||
#include <sys/time.h>
|
|
||||||
#include <sys/types.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
|
|
||||||
|
|
||||||
typedef struct client_array_t client_array_t;
|
|
||||||
|
|
||||||
typedef struct task_queue_node_t task_queue_node_t;
|
|
||||||
struct task_queue_node_t
|
|
||||||
{
|
|
||||||
task_queue_node_t* next;
|
|
||||||
task_queue_node_t* prev;
|
|
||||||
qse_httpd_task_t task;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct qse_httpd_client_t
|
|
||||||
{
|
|
||||||
qse_ubi_t handle;
|
|
||||||
qse_ubi_t handle2;
|
|
||||||
qse_nwad_t local_addr;
|
|
||||||
qse_nwad_t remote_addr;
|
|
||||||
|
|
||||||
/* ------------------------------ */
|
|
||||||
|
|
||||||
int ready;
|
|
||||||
int secure;
|
|
||||||
int bad;
|
|
||||||
qse_htrd_t* htrd;
|
|
||||||
|
|
||||||
struct
|
|
||||||
{
|
|
||||||
struct
|
|
||||||
{
|
|
||||||
int count;
|
|
||||||
task_queue_node_t* head;
|
|
||||||
task_queue_node_t* tail;
|
|
||||||
} queue;
|
|
||||||
} task;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct client_array_t
|
|
||||||
{
|
|
||||||
int capa;
|
|
||||||
int size;
|
|
||||||
qse_httpd_client_t* data;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct qse_httpd_t
|
struct qse_httpd_t
|
||||||
{
|
{
|
||||||
@ -86,15 +36,29 @@ struct qse_httpd_t
|
|||||||
|
|
||||||
struct
|
struct
|
||||||
{
|
{
|
||||||
client_array_t array;
|
struct
|
||||||
|
{
|
||||||
|
qse_httpd_client_t* head;
|
||||||
|
qse_httpd_client_t* tail;
|
||||||
|
} list;
|
||||||
|
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
qse_httpd_client_t* head;
|
||||||
|
qse_httpd_client_t* tail;
|
||||||
|
} tasked;
|
||||||
|
|
||||||
|
qse_httpd_client_t* bad;
|
||||||
} client;
|
} client;
|
||||||
|
|
||||||
struct
|
struct
|
||||||
{
|
{
|
||||||
qse_httpd_server_t* list;
|
qse_httpd_server_t* list;
|
||||||
fd_set set;
|
qse_size_t navail;
|
||||||
int max;
|
qse_size_t nactive;
|
||||||
} server;
|
} server;
|
||||||
|
|
||||||
|
void* mux;
|
||||||
};
|
};
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
|
@ -19,16 +19,13 @@
|
|||||||
# include <sys/stat.h>
|
# include <sys/stat.h>
|
||||||
# include <sys/socket.h>
|
# include <sys/socket.h>
|
||||||
# include <netinet/in.h>
|
# include <netinet/in.h>
|
||||||
|
# include <sys/epoll.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <openssl/ssl.h>
|
#include <openssl/ssl.h>
|
||||||
#include <openssl/err.h>
|
#include <openssl/err.h>
|
||||||
#include <openssl/engine.h>
|
#include <openssl/engine.h>
|
||||||
|
|
||||||
|
|
||||||
// TODO: remove this and export structured needed like qse_httpd_client_t
|
|
||||||
#include "../../lib/net/httpd.h"
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------------- */
|
/* ------------------------------------------------------------------- */
|
||||||
|
|
||||||
#define MAX_SEND_SIZE 4096
|
#define MAX_SEND_SIZE 4096
|
||||||
@ -373,6 +370,7 @@ static int server_accept (
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
if (fd >= FD_SETSIZE)
|
if (fd >= FD_SETSIZE)
|
||||||
{
|
{
|
||||||
qse_fprintf (QSE_STDERR, QSE_T("Error: too many client?\n"));
|
qse_fprintf (QSE_STDERR, QSE_T("Error: too many client?\n"));
|
||||||
@ -380,6 +378,7 @@ qse_fprintf (QSE_STDERR, QSE_T("Error: too many client?\n"));
|
|||||||
close (fd);
|
close (fd);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
flag = fcntl (fd, F_GETFL);
|
flag = fcntl (fd, F_GETFL);
|
||||||
if (flag >= 0) fcntl (fd, F_SETFL, flag | O_NONBLOCK);
|
if (flag >= 0) fcntl (fd, F_SETFL, flag | O_NONBLOCK);
|
||||||
@ -407,6 +406,161 @@ qse_fprintf (QSE_STDERR, QSE_T("Error: too many client?\n"));
|
|||||||
|
|
||||||
/* ------------------------------------------------------------------- */
|
/* ------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
struct mux_ev_t
|
||||||
|
{
|
||||||
|
qse_ubi_t handle;
|
||||||
|
int reqmask;
|
||||||
|
qse_httpd_muxcb_t cbfun;
|
||||||
|
void* cbarg;
|
||||||
|
struct mux_ee_t* next;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct mux_t
|
||||||
|
{
|
||||||
|
int fd;
|
||||||
|
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
struct epoll_event* ptr;
|
||||||
|
qse_size_t len;
|
||||||
|
qse_size_t capa;
|
||||||
|
} ee;
|
||||||
|
};
|
||||||
|
|
||||||
|
static void* mux_open (qse_httpd_t* httpd)
|
||||||
|
{
|
||||||
|
struct mux_t* mux;
|
||||||
|
|
||||||
|
mux = qse_httpd_allocmem (httpd, QSE_SIZEOF(*mux));
|
||||||
|
if (mux == QSE_NULL) return QSE_NULL;
|
||||||
|
|
||||||
|
memset (mux, 0, QSE_SIZEOF(*mux));
|
||||||
|
|
||||||
|
mux->fd = epoll_create (100);
|
||||||
|
if (mux->fd <= -1)
|
||||||
|
{
|
||||||
|
qse_httpd_freemem (httpd, mux);
|
||||||
|
qse_httpd_seterrnum (httpd, syserr_to_errnum(errno));
|
||||||
|
return QSE_NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return mux;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void mux_close (qse_httpd_t* httpd, void* vmux)
|
||||||
|
{
|
||||||
|
struct mux_t* mux = (struct mux_t*)vmux;
|
||||||
|
if (mux->ee.ptr) qse_httpd_freemem (httpd, mux->ee.ptr);
|
||||||
|
close (mux->fd);
|
||||||
|
qse_httpd_freemem (httpd, mux);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int mux_addhnd (
|
||||||
|
qse_httpd_t* httpd, void* vmux, qse_ubi_t handle,
|
||||||
|
int mask, qse_httpd_muxcb_t cbfun, void* cbarg)
|
||||||
|
{
|
||||||
|
struct mux_t* mux = (struct mux_t*)vmux;
|
||||||
|
struct epoll_event ev;
|
||||||
|
struct mux_ev_t* mev;
|
||||||
|
|
||||||
|
ev.events = 0;
|
||||||
|
if (mask & QSE_HTTPD_MUX_READ) ev.events |= EPOLLIN;
|
||||||
|
if (mask & QSE_HTTPD_MUX_WRITE) ev.events |= EPOLLOUT;
|
||||||
|
|
||||||
|
if (ev.events == 0)
|
||||||
|
{
|
||||||
|
qse_httpd_seterrnum (httpd, QSE_HTTPD_EINVAL);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
mev = qse_httpd_allocmem (httpd, QSE_SIZEOF(*mev));
|
||||||
|
if (mev == QSE_NULL) return -1;
|
||||||
|
|
||||||
|
if (mux->ee.len >= mux->ee.capa)
|
||||||
|
{
|
||||||
|
struct epoll_event* tmp;
|
||||||
|
|
||||||
|
tmp = qse_httpd_reallocmem (
|
||||||
|
httpd, mux->ee.ptr,
|
||||||
|
QSE_SIZEOF(*mux->ee.ptr) * (mux->ee.capa + 1) * 2);
|
||||||
|
if (tmp == QSE_NULL)
|
||||||
|
{
|
||||||
|
qse_httpd_freemem (httpd, mev);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
mux->ee.ptr = tmp;
|
||||||
|
mux->ee.capa = (mux->ee.capa + 1) * 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
mev->handle = handle;
|
||||||
|
mev->reqmask = mask;
|
||||||
|
mev->cbfun = cbfun;
|
||||||
|
mev->cbarg = cbarg;
|
||||||
|
|
||||||
|
ev.data.ptr = mev;
|
||||||
|
|
||||||
|
if (epoll_ctl (mux->fd, EPOLL_CTL_ADD, handle.i, &ev) <= -1)
|
||||||
|
{
|
||||||
|
/* don't rollback ee.ptr */
|
||||||
|
qse_httpd_seterrnum (httpd, syserr_to_errnum(errno));
|
||||||
|
qse_httpd_freemem (httpd, mev);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
mux->ee.len++;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int mux_delhnd (qse_httpd_t* httpd, void* vmux, qse_ubi_t handle)
|
||||||
|
{
|
||||||
|
struct mux_t* mux = (struct mux_t*)vmux;
|
||||||
|
|
||||||
|
if (epoll_ctl (mux->fd, EPOLL_CTL_DEL, handle.i, QSE_NULL) <= -1)
|
||||||
|
{
|
||||||
|
qse_httpd_seterrnum (httpd, syserr_to_errnum(errno));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
mux->ee.len--;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int mux_poll (qse_httpd_t* httpd, void* vmux, qse_ntime_t timeout)
|
||||||
|
{
|
||||||
|
struct mux_t* mux = (struct mux_t*)vmux;
|
||||||
|
struct mux_ev_t* mev;
|
||||||
|
int mask, nfds, i;
|
||||||
|
|
||||||
|
nfds = epoll_wait (mux->fd, mux->ee.ptr, mux->ee.len, timeout);
|
||||||
|
if (nfds <= -1)
|
||||||
|
{
|
||||||
|
qse_httpd_seterrnum (httpd, syserr_to_errnum(errno));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < nfds; i++)
|
||||||
|
{
|
||||||
|
mev = mux->ee.ptr[i].data.ptr;
|
||||||
|
|
||||||
|
mask = 0;
|
||||||
|
|
||||||
|
if (mux->ee.ptr[i].events & EPOLLIN) mask |= QSE_HTTPD_MUX_READ;
|
||||||
|
if (mux->ee.ptr[i].events & EPOLLOUT) mask |= QSE_HTTPD_MUX_WRITE;
|
||||||
|
|
||||||
|
if (mux->ee.ptr[i].events & EPOLLHUP)
|
||||||
|
{
|
||||||
|
if (mev->reqmask & QSE_HTTPD_MUX_READ) mask |= QSE_HTTPD_MUX_READ;
|
||||||
|
if (mev->reqmask & QSE_HTTPD_MUX_WRITE) mask |= QSE_HTTPD_MUX_WRITE;
|
||||||
|
}
|
||||||
|
|
||||||
|
mev->cbfun (httpd, mux, mev->handle, mask, mev->cbarg);
|
||||||
|
|
||||||
|
//if (cbfun fails and the client is deleted???) other pending events should also be dropped???
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static int mux_readable (qse_httpd_t* httpd, qse_ubi_t handle, qse_ntoff_t msec)
|
static int mux_readable (qse_httpd_t* httpd, qse_ubi_t handle, qse_ntoff_t msec)
|
||||||
{
|
{
|
||||||
fd_set r;
|
fd_set r;
|
||||||
@ -574,7 +728,11 @@ static void client_close (
|
|||||||
static void client_shutdown (
|
static void client_shutdown (
|
||||||
qse_httpd_t* httpd, qse_httpd_client_t* client)
|
qse_httpd_t* httpd, qse_httpd_client_t* client)
|
||||||
{
|
{
|
||||||
|
#if defined(SHUT_RDWR)
|
||||||
shutdown (client->handle.i, SHUT_RDWR);
|
shutdown (client->handle.i, SHUT_RDWR);
|
||||||
|
#else
|
||||||
|
shutdown (client->handle.i, 2);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
static qse_ssize_t client_recv (
|
static qse_ssize_t client_recv (
|
||||||
@ -912,7 +1070,15 @@ static qse_httpd_cbs_t httpd_cbs =
|
|||||||
{ server_open, server_close, server_accept },
|
{ server_open, server_close, server_accept },
|
||||||
|
|
||||||
/* multiplexer */
|
/* multiplexer */
|
||||||
{ mux_readable, mux_writable },
|
{ mux_open,
|
||||||
|
mux_close,
|
||||||
|
mux_addhnd,
|
||||||
|
mux_delhnd,
|
||||||
|
mux_poll,
|
||||||
|
|
||||||
|
mux_readable,
|
||||||
|
mux_writable
|
||||||
|
},
|
||||||
|
|
||||||
/* file operation */
|
/* file operation */
|
||||||
{ file_executable,
|
{ file_executable,
|
||||||
@ -991,7 +1157,7 @@ int httpd_main (int argc, qse_char_t* argv[])
|
|||||||
signal (SIGPIPE, SIG_IGN);
|
signal (SIGPIPE, SIG_IGN);
|
||||||
|
|
||||||
qse_httpd_setoption (httpd, QSE_HTTPD_CGIERRTONUL);
|
qse_httpd_setoption (httpd, QSE_HTTPD_CGIERRTONUL);
|
||||||
ret = qse_httpd_loop (httpd, &httpd_cbs);
|
ret = qse_httpd_loop (httpd, &httpd_cbs, 10000);
|
||||||
|
|
||||||
signal (SIGINT, SIG_DFL);
|
signal (SIGINT, SIG_DFL);
|
||||||
signal (SIGPIPE, SIG_DFL);
|
signal (SIGPIPE, SIG_DFL);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user