added mio_dupbcstrs() and mio_dupucstrs()

changed mio_svc_htts_start() to access the main processor callback
This commit is contained in:
hyung-hwan 2020-05-20 16:14:36 +00:00
parent f373f367b3
commit aa5c70c3f5
10 changed files with 307 additions and 255 deletions

View File

@ -748,6 +748,102 @@ static void on_dnc_resolve_brief (mio_svc_dnc_t* dnc, mio_dns_msg_t* reqmsg, mio
} }
} }
/* ========================================================================= */
int process_http_request (mio_svc_htts_t* htts, mio_dev_sck_t* csck, mio_htre_t* req)
{
mio_t* mio = mio_svc_htts_getmio(htts);
// mio_svc_htts_cli_t* cli = mio_dev_sck_getxtn(csck);
mio_http_method_t mth;
/* percent-decode the query path to the original buffer
* since i'm not going to need it in the original form
* any more. once it's decoded in the peek mode,
* the decoded query path is made available in the
* non-peek mode as well */
MIO_DEBUG2 (mio, "[RAW-REQ] %s %s\n", mio_htre_getqmethodname(req), mio_htre_getqpath(req));
mio_htre_perdecqpath(req);
/* TODO: proper request logging */
MIO_DEBUG2 (mio, "[REQ] %s %s\n", mio_htre_getqmethodname(req), mio_htre_getqpath(req));
#if 0
mio_printf (MIO_T("================================\n"));
mio_printf (MIO_T("[%lu] %hs REQUEST ==> [%hs] version[%d.%d %hs] method[%hs]\n"),
(unsigned long)time(NULL),
(peek? MIO_MT("PEEK"): MIO_MT("HANDLE")),
mio_htre_getqpath(req),
mio_htre_getmajorversion(req),
mio_htre_getminorversion(req),
mio_htre_getverstr(req),
mio_htre_getqmethodname(req)
);
if (mio_htre_getqparam(req))
mio_printf (MIO_T("PARAMS ==> [%hs]\n"), mio_htre_getqparam(req));
mio_htb_walk (&req->hdrtab, walk, MIO_NULL);
if (mio_htre_getcontentlen(req) > 0)
{
mio_printf (MIO_T("CONTENT [%.*S]\n"), (int)mio_htre_getcontentlen(req), mio_htre_getcontentptr(req));
}
#endif
mth = mio_htre_getqmethodtype(req);
/* determine what to do once the header fields are all received.
* i don't want to delay this until the contents are received.
* if you don't like this behavior, you must implement your own
* callback function for request handling. */
#if 0
/* TODO support X-HTTP-Method-Override */
if (data.method == MIO_HTTP_POST)
{
tmp = mio_htre_getheaderval(req, MIO_MT("X-HTTP-Method-Override"));
if (tmp)
{
/*while (tmp->next) tmp = tmp->next;*/ /* get the last value */
data.method = mio_mbstohttpmethod (tmp->ptr);
}
}
#endif
#if 0
if (mth == MIO_HTTP_CONNECT)
{
/* CONNECT method must not have content set.
* however, arrange to discard it if so.
*
* NOTE: CONNECT is implemented to ignore many headers like
* 'Expect: 100-continue' and 'Connection: keep-alive'. */
mio_htre_discardcontent (req);
}
else
{
/* this part can be checked in actual mio_svc_htts_doXXX() functions.
* some doXXX handlers may not require length for POST.
* it may be able to simply accept till EOF? or treat as if CONTENT_LENGTH is 0*/
if (mth == MIO_HTTP_POST && !(req->flags & (MIO_HTRE_ATTR_LENGTH | MIO_HTRE_ATTR_CHUNKED)))
{
/* POST without Content-Length nor not chunked */
mio_htre_discardcontent (req);
/* 411 Length Required - can't keep alive. Force disconnect */
req->flags &= ~MIO_HTRE_ATTR_KEEPALIVE; /* to cause sendstatus() to close */
if (mio_svc_htts_sendstatus(htts, csck, req, 411, MIO_NULL) <= -1) goto oops;
}
else
{
#endif
/*const mio_bch_t* qpath = mio_htre_getqpath(req);*/
if (mio_svc_htts_docgi(htts, csck, req, "", mio_htre_getqpath(req)) <= -1) goto oops;
return 0;
oops:
mio_dev_sck_halt (csck);
return -1;
}
/* ========================================================================= */ /* ========================================================================= */
static mio_t* g_mio; static mio_t* g_mio;
@ -976,7 +1072,7 @@ for (i = 0; i < 5; i++)
mio_bcstrtoskad (mio, "127.0.0.1:9988", &htts_bind_addr); mio_bcstrtoskad (mio, "127.0.0.1:9988", &htts_bind_addr);
dnc = mio_svc_dnc_start(mio, &servaddr, MIO_NULL, &send_tmout, &reply_tmout, 2); /* option - send to all, send one by one */ dnc = mio_svc_dnc_start(mio, &servaddr, MIO_NULL, &send_tmout, &reply_tmout, 2); /* option - send to all, send one by one */
htts = mio_svc_htts_start(mio, &htts_bind_addr); htts = mio_svc_htts_start(mio, &htts_bind_addr, process_http_request);
mio_svc_htts_setservernamewithbcstr (htts, "MIO-HTTP"); mio_svc_htts_setservernamewithbcstr (htts, "MIO-HTTP");
#if 1 #if 1

View File

@ -1217,43 +1217,9 @@ int mio_htrd_feed (mio_htrd_t* htrd, const mio_bch_t* req, mio_oow_t len, mio_oo
/* need to clear request on error? /* need to clear request on error?
clear_feed (htrd); */ clear_feed (htrd); */
return -1; return -1;
/// TODO: PEEKONLY doens't seem to be neede. delete it...
} }
//////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////
if (htrd->option & MIO_HTRD_PEEKONLY)
{
/* when MIO_HTRD_PEEKONLY is set,
* the peek callback is invoked once
* a complete header is seen. the caller
* should not feed more data by calling
* this function again once the callback is
* invoked. the trailing data is appended
* to the content buffer.
*
* NOTE: if the current feed that completed
* the header contains the next request,
* the next request is treated as if it
* belongs to the current request.
*
* In priciple, this option was added for
* reading CGI outputs. So it comes with
* awkwardity described above.
*/
if (ptr < end && push_content(htrd, ptr, end - ptr) <= -1) return -1;
/* i don't really know if it is really completed
* with content. MIO_HTRD_PEEKONLY is not compatible
* with the completed state. anyway, let me complete
* it. */
mio_htre_completecontent (&htrd->re);
/* this jump is only to invoke the peek
* callback. this function should not be fed
* more. */
goto feedme_more;
}
/* carry on processing content body fed together with the header */ /* carry on processing content body fed together with the header */
if (htrd->re.flags & MIO_HTRE_ATTR_CHUNKED) if (htrd->re.flags & MIO_HTRE_ATTR_CHUNKED)
{ {

View File

@ -3,6 +3,7 @@
#include "mio-pro.h" /* for cgi */ #include "mio-pro.h" /* for cgi */
#include "mio-fmt.h" #include "mio-fmt.h"
#include "mio-chr.h" #include "mio-chr.h"
#include "mio-path.h"
#include "mio-prv.h" #include "mio-prv.h"
@ -35,6 +36,8 @@ struct mio_svc_htts_t
{ {
MIO_SVC_HEADER; MIO_SVC_HEADER;
mio_svc_htts_proc_req_t proc_req;
mio_dev_sck_t* lsck; mio_dev_sck_t* lsck;
mio_svc_htts_cli_t cli; /* list head for client list */ mio_svc_htts_cli_t cli; /* list head for client list */
@ -98,110 +101,11 @@ static int test_func_handler (int rfd, int wfd)
return -1; return -1;
} }
static int process_request (mio_svc_htts_t* htts, mio_dev_sck_t* csck, mio_htre_t* req)
{
//server_xtn_t* server_xtn = GET_SERVER_XTN(htts, client->server);
//mio_htts_task_t* task;
mio_svc_htts_cli_t* cli = mio_dev_sck_getxtn(csck);
mio_http_method_t mth;
//mio_htts_rsrc_t rsrc;
/* percent-decode the query path to the original buffer
* since i'm not going to need it in the original form
* any more. once it's decoded in the peek mode,
* the decoded query path is made available in the
* non-peek mode as well */
MIO_DEBUG2 (htts->mio, "[RAW-REQ] %s %s\n", mio_htre_getqmethodname(req), mio_htre_getqpath(req));
mio_htre_perdecqpath(req);
/* TODO: proper request logging */
MIO_DEBUG2 (htts->mio, "[REQ] %s %s\n", mio_htre_getqmethodname(req), mio_htre_getqpath(req));
#if 0
mio_printf (MIO_T("================================\n"));
mio_printf (MIO_T("[%lu] %hs REQUEST ==> [%hs] version[%d.%d %hs] method[%hs]\n"),
(unsigned long)time(NULL),
(peek? MIO_MT("PEEK"): MIO_MT("HANDLE")),
mio_htre_getqpath(req),
mio_htre_getmajorversion(req),
mio_htre_getminorversion(req),
mio_htre_getverstr(req),
mio_htre_getqmethodname(req)
);
if (mio_htre_getqparam(req))
mio_printf (MIO_T("PARAMS ==> [%hs]\n"), mio_htre_getqparam(req));
mio_htb_walk (&req->hdrtab, walk, MIO_NULL);
if (mio_htre_getcontentlen(req) > 0)
{
mio_printf (MIO_T("CONTENT [%.*S]\n"), (int)mio_htre_getcontentlen(req), mio_htre_getcontentptr(req));
}
#endif
mth = mio_htre_getqmethodtype(req);
/* determine what to do once the header fields are all received.
* i don't want to delay this until the contents are received.
* if you don't like this behavior, you must implement your own
* callback function for request handling. */
#if 0
/* TODO support X-HTTP-Method-Override */
if (data.method == MIO_HTTP_POST)
{
tmp = mio_htre_getheaderval(req, MIO_MT("X-HTTP-Method-Override"));
if (tmp)
{
/*while (tmp->next) tmp = tmp->next;*/ /* get the last value */
data.method = mio_mbstohttpmethod (tmp->ptr);
}
}
#endif
#if 0
if (mth == MIO_HTTP_CONNECT)
{
/* CONNECT method must not have content set.
* however, arrange to discard it if so.
*
* NOTE: CONNECT is implemented to ignore many headers like
* 'Expect: 100-continue' and 'Connection: keep-alive'. */
mio_htre_discardcontent (req);
}
else
{
/* this part can be checked in actual mio_svc_htts_doXXX() functions.
* some doXXX handlers may not require length for POST.
* it may be able to simply accept till EOF? or treat as if CONTENT_LENGTH is 0*/
if (mth == MIO_HTTP_POST && !(req->flags & (MIO_HTRE_ATTR_LENGTH | MIO_HTRE_ATTR_CHUNKED)))
{
/* POST without Content-Length nor not chunked */
mio_htre_discardcontent (req);
/* 411 Length Required - can't keep alive. Force disconnect */
req->flags &= ~MIO_HTRE_ATTR_KEEPALIVE; /* to cause sendstatus() to close */
if (mio_svc_htts_sendstatus(htts, csck, req, 411, MIO_NULL) <= -1) goto oops;
}
else
{
#endif
/*const mio_bch_t* qpath = mio_htre_getqpath(req);*/
if (mio_svc_htts_docgi(htts, csck, req, "") <= -1) goto oops;
return 0;
oops:
mio_dev_sck_halt (csck);
return -1;
}
static int client_htrd_peek_request (mio_htrd_t* htrd, mio_htre_t* req) static int client_htrd_peek_request (mio_htrd_t* htrd, mio_htre_t* req)
{ {
htrd_xtn_t* htrdxtn = (htrd_xtn_t*)mio_htrd_getxtn(htrd); htrd_xtn_t* htrdxtn = (htrd_xtn_t*)mio_htrd_getxtn(htrd);
mio_svc_htts_cli_t* sckxtn = (mio_svc_htts_cli_t*)mio_dev_sck_getxtn(htrdxtn->sck); mio_svc_htts_cli_t* sckxtn = (mio_svc_htts_cli_t*)mio_dev_sck_getxtn(htrdxtn->sck);
return process_request(sckxtn->htts, htrdxtn->sck, req); return sckxtn->htts->proc_req(sckxtn->htts, htrdxtn->sck, req);
} }
@ -439,7 +343,7 @@ static void listener_on_disconnect (mio_dev_sck_t* sck)
/* ------------------------------------------------------------------------ */ /* ------------------------------------------------------------------------ */
mio_svc_htts_t* mio_svc_htts_start (mio_t* mio, const mio_skad_t* bind_addr) mio_svc_htts_t* mio_svc_htts_start (mio_t* mio, const mio_skad_t* bind_addr, mio_svc_htts_proc_req_t proc_req)
{ {
mio_svc_htts_t* htts = MIO_NULL; mio_svc_htts_t* htts = MIO_NULL;
union union
@ -455,6 +359,7 @@ mio_svc_htts_t* mio_svc_htts_start (mio_t* mio, const mio_skad_t* bind_addr)
htts->mio = mio; htts->mio = mio;
htts->svc_stop = mio_svc_htts_stop; htts->svc_stop = mio_svc_htts_stop;
htts->proc_req = proc_req;
MIO_MEMSET (&info, 0, MIO_SIZEOF(info)); MIO_MEMSET (&info, 0, MIO_SIZEOF(info));
switch (mio_skad_family(bind_addr)) switch (mio_skad_family(bind_addr))
@ -1314,6 +1219,8 @@ struct cgi_peer_fork_ctx_t
mio_svc_htts_cli_t* cli; mio_svc_htts_cli_t* cli;
mio_htre_t* req; mio_htre_t* req;
const mio_bch_t* docroot; const mio_bch_t* docroot;
const mio_bch_t* script;
mio_bch_t* actual_script;
}; };
typedef struct cgi_peer_fork_ctx_t cgi_peer_fork_ctx_t; typedef struct cgi_peer_fork_ctx_t cgi_peer_fork_ctx_t;
@ -1362,24 +1269,27 @@ static int cgi_peer_on_fork (mio_dev_pro_t* pro, void* fork_ctx)
cgi_peer_fork_ctx_t* fc = (cgi_peer_fork_ctx_t*)fork_ctx; cgi_peer_fork_ctx_t* fc = (cgi_peer_fork_ctx_t*)fork_ctx;
mio_oow_t content_length; mio_oow_t content_length;
const mio_bch_t* qparam; const mio_bch_t* qparam;
const char* path; const char* path, * lang;
mio_bch_t tmp[256]; mio_bch_t tmp[256];
mio_becs_t dbuf; mio_becs_t dbuf;
qparam = mio_htre_getqparam(fc->req); qparam = mio_htre_getqparam(fc->req);
path = getenv("PATH"); path = getenv("PATH");
lang = getenv("LANG");
clearenv (); clearenv ();
if (path) setenv ("PATH", path, 1); if (path) setenv ("PATH", path, 1);
if (lang) setenv ("LANG", lang, 1);
setenv ("GATEWAY_INTERFACE", "CGI/1.1", 1); setenv ("GATEWAY_INTERFACE", "CGI/1.1", 1);
mio_fmttobcstr (pro->mio, tmp, MIO_COUNTOF(tmp), "HTTP/%d.%d", (int)mio_htre_getmajorversion(fc->req), (int)mio_htre_getminorversion(fc->req)); mio_fmttobcstr (pro->mio, tmp, MIO_COUNTOF(tmp), "HTTP/%d.%d", (int)mio_htre_getmajorversion(fc->req), (int)mio_htre_getminorversion(fc->req));
setenv ("SERVER_PROTOCOL", tmp, 1); setenv ("SERVER_PROTOCOL", tmp, 1);
//setenv ("SCRIPT_FILENAME",
//setenv ("SCRIPT_NAME",
setenv ("DOCUMENT_ROOT", fc->docroot, 1); setenv ("DOCUMENT_ROOT", fc->docroot, 1);
setenv ("SCRIPT_NAME", fc->script, 1);
setenv ("SCRIPT_FILENAME", fc->actual_script, 1);
/* TODO: PATH_INFO */
setenv ("REQUEST_METHOD", mio_htre_getqmethodname(fc->req), 1); setenv ("REQUEST_METHOD", mio_htre_getqmethodname(fc->req), 1);
setenv ("REQUEST_URI", mio_htre_getqpath(fc->req), 1); setenv ("REQUEST_URI", mio_htre_getqpath(fc->req), 1);
@ -1422,8 +1332,7 @@ static int cgi_peer_on_fork (mio_dev_pro_t* pro, void* fork_ctx)
return 0; return 0;
} }
int mio_svc_htts_docgi (mio_svc_htts_t* htts, mio_dev_sck_t* csck, mio_htre_t* req, const mio_bch_t* docroot, const mio_bch_t* script)
int mio_svc_htts_docgi (mio_svc_htts_t* htts, mio_dev_sck_t* csck, mio_htre_t* req, const mio_bch_t* docroot)
{ {
mio_t* mio = htts->mio; mio_t* mio = htts->mio;
mio_svc_htts_cli_t* cli = mio_dev_sck_getxtn(csck); mio_svc_htts_cli_t* cli = mio_dev_sck_getxtn(csck);
@ -1439,10 +1348,13 @@ int mio_svc_htts_docgi (mio_svc_htts_t* htts, mio_dev_sck_t* csck, mio_htre_t* r
fc.cli = cli; fc.cli = cli;
fc.req = req; fc.req = req;
fc.docroot = docroot; fc.docroot = docroot;
fc.script = script;
fc.actual_script = mio_svc_htts_dupmergepaths(htts, docroot, script);
if (!fc.actual_script) goto oops;
MIO_MEMSET (&mi, 0, MIO_SIZEOF(mi)); MIO_MEMSET (&mi, 0, MIO_SIZEOF(mi));
mi.flags = MIO_DEV_PRO_READOUT | MIO_DEV_PRO_ERRTONUL | MIO_DEV_PRO_WRITEIN /*| MIO_DEV_PRO_FORGET_CHILD*/; mi.flags = MIO_DEV_PRO_READOUT | MIO_DEV_PRO_ERRTONUL | MIO_DEV_PRO_WRITEIN /*| MIO_DEV_PRO_FORGET_CHILD*/;
mi.cmd = mio_htre_getqpath(req); /* TODO: combine it with docroot */ mi.cmd = fc.actual_script;
mi.on_read = cgi_peer_on_read; mi.on_read = cgi_peer_on_read;
mi.on_write = cgi_peer_on_write; mi.on_write = cgi_peer_on_write;
mi.on_close = cgi_peer_on_close; mi.on_close = cgi_peer_on_close;
@ -1468,10 +1380,6 @@ int mio_svc_htts_docgi (mio_svc_htts_t* htts, mio_dev_sck_t* csck, mio_htre_t* r
MIO_ASSERT (mio, cli->rsrc == MIO_NULL); MIO_ASSERT (mio, cli->rsrc == MIO_NULL);
MIO_SVC_HTTS_RSRC_ATTACH (cgi_state, cli->rsrc); MIO_SVC_HTTS_RSRC_ATTACH (cgi_state, cli->rsrc);
/* TODO: create cgi environment variables... */
/* TODO:
* never put Expect: 100-continue to environment variable
*/
if (access(mi.cmd, X_OK) == -1) if (access(mi.cmd, X_OK) == -1)
{ {
cgi_state_send_final_status_to_client (cgi_state, 403); /* 403 Forbidden */ cgi_state_send_final_status_to_client (cgi_state, 403); /* 403 Forbidden */
@ -1588,17 +1496,29 @@ int mio_svc_htts_docgi (mio_svc_htts_t* htts, mio_dev_sck_t* csck, mio_htre_t* r
/* TODO: store current input watching state and use it when destroying the cgi_state data */ /* TODO: store current input watching state and use it when destroying the cgi_state data */
if (mio_dev_sck_read(csck, !(cgi_state->over & CGI_STATE_OVER_READ_FROM_CLIENT)) <= -1) goto oops; if (mio_dev_sck_read(csck, !(cgi_state->over & CGI_STATE_OVER_READ_FROM_CLIENT)) <= -1) goto oops;
mio_freemem (mio, fc.actual_script);
return 0; return 0;
oops: oops:
MIO_DEBUG2 (mio, "HTTS(%p) - FAILURE in docgi - socket(%p)\n", htts, csck); MIO_DEBUG2 (mio, "HTTS(%p) - FAILURE in docgi - socket(%p)\n", htts, csck);
if (cgi_state) cgi_state_halt_participating_devices (cgi_state); if (cgi_state) cgi_state_halt_participating_devices (cgi_state);
if (fc.actual_script) mio_freemem (mio, fc.actual_script);
return -1; return -1;
} }
/* ----------------------------------------------------------------- */ /* ----------------------------------------------------------------- */
int mio_svc_htts_dofile (mio_svc_htts_t* htts, mio_dev_sck_t* csck, mio_htre_t* req, const mio_bch_t* docroot) #if 0
int mio_svc_htts_dothrfunc (mio_svc_htts_t* htts, mio_dev_sck_t* csck, mio_htre_t* req, mio_svc_htts_func_t func)
{
}
#endif
/* ----------------------------------------------------------------- */
int mio_svc_htts_dofile (mio_svc_htts_t* htts, mio_dev_sck_t* csck, mio_htre_t* req, const mio_bch_t* docroot, const mio_bch_t* file)
{ {
switch (mio_htre_getqmethodtype(req)) switch (mio_htre_getqmethodtype(req))
{ {
@ -1668,6 +1588,26 @@ void mio_svc_htts_fmtgmtime (mio_svc_htts_t* htts, const mio_ntime_t* nt, mio_bc
mio_fmt_http_time_to_bcstr(nt, buf, len); mio_fmt_http_time_to_bcstr(nt, buf, len);
} }
mio_bch_t* mio_svc_htts_dupmergepaths (mio_svc_htts_t* htts, const mio_bch_t* base, const mio_bch_t* path)
{
mio_bch_t* xpath;
const mio_bch_t* ta[4];
mio_oow_t idx = 0;
ta[idx++] = base;
if (path[0] != '\0')
{
ta[idx++] = "/";
ta[idx++] = path;
}
ta[idx++] = MIO_NULL;
xpath = mio_dupbcstrs(htts->mio, ta, MIO_NULL);
if (MIO_UNLIKELY(!xpath)) return MIO_NULL;
mio_canon_bcstr_path (xpath, xpath, 0);
return xpath;
}
/* ----------------------------------------------------------------- */ /* ----------------------------------------------------------------- */
#if 0 #if 0

View File

@ -387,15 +387,7 @@ typedef void (*mio_svc_dnc_on_resolve_t) (
mio_oow_t len mio_oow_t len
); );
#if defined(MIO_HAVE_INLINE)
static MIO_INLINE mio_t* mio_svc_dns_getmio(mio_svc_dns_t* svc) { return mio_svc_getmio((mio_svc_t*)svc); }
static MIO_INLINE mio_t* mio_svc_dnc_getmio(mio_svc_dnc_t* svc) { return mio_svc_getmio((mio_svc_t*)svc); }
static MIO_INLINE mio_t* mio_svc_dnr_getmio(mio_svc_dnr_t* svc) { return mio_svc_getmio((mio_svc_t*)svc); }
#else
# define mio_svc_dns_getmio(svc) mio_svc_getmio(svc)
# define mio_svc_dnc_getmio(svc) mio_svc_getmio(svc)
# define mio_svc_dnr_getmio(svc) mio_svc_getmio(svc)
#endif
enum mio_svc_dnc_send_flag_t enum mio_svc_dnc_send_flag_t
{ {
@ -476,6 +468,16 @@ MIO_EXPORT void mio_svc_dnc_stop (
mio_svc_dnc_t* dnc mio_svc_dnc_t* dnc
); );
#if defined(MIO_HAVE_INLINE)
static MIO_INLINE mio_t* mio_svc_dns_getmio(mio_svc_dns_t* svc) { return mio_svc_getmio((mio_svc_t*)svc); }
static MIO_INLINE mio_t* mio_svc_dnc_getmio(mio_svc_dnc_t* svc) { return mio_svc_getmio((mio_svc_t*)svc); }
static MIO_INLINE mio_t* mio_svc_dnr_getmio(mio_svc_dnr_t* svc) { return mio_svc_getmio((mio_svc_t*)svc); }
#else
# define mio_svc_dns_getmio(svc) mio_svc_getmio(svc)
# define mio_svc_dnc_getmio(svc) mio_svc_getmio(svc)
# define mio_svc_dnr_getmio(svc) mio_svc_getmio(svc)
#endif
MIO_EXPORT mio_dns_msg_t* mio_svc_dnc_sendmsg ( MIO_EXPORT mio_dns_msg_t* mio_svc_dnc_sendmsg (
mio_svc_dnc_t* dnc, mio_svc_dnc_t* dnc,
mio_dns_bhdr_t* bdns, mio_dns_bhdr_t* bdns,

View File

@ -55,11 +55,10 @@ enum mio_htrd_option_t
MIO_HTRD_SKIPEMPTYLINES = (1 << 0), /**< skip leading empty lines before the initial line */ MIO_HTRD_SKIPEMPTYLINES = (1 << 0), /**< skip leading empty lines before the initial line */
MIO_HTRD_SKIPINITIALLINE = (1 << 1), /**< skip processing an initial line */ MIO_HTRD_SKIPINITIALLINE = (1 << 1), /**< skip processing an initial line */
MIO_HTRD_CANONQPATH = (1 << 2), /**< canonicalize the query path */ MIO_HTRD_CANONQPATH = (1 << 2), /**< canonicalize the query path */
MIO_HTRD_PEEKONLY = (1 << 3), /**< trigger a peek callback after headers without processing contents */ MIO_HTRD_REQUEST = (1 << 3), /**< parse input as a request */
MIO_HTRD_REQUEST = (1 << 4), /**< parse input as a request */ MIO_HTRD_RESPONSE = (1 << 4), /**< parse input as a response */
MIO_HTRD_RESPONSE = (1 << 5), /**< parse input as a response */ MIO_HTRD_TRAILERS = (1 << 5), /**< store trailers in a separate table */
MIO_HTRD_TRAILERS = (1 << 6), /**< store trailers in a separate table */ MIO_HTRD_STRICT = (1 << 6) /**< be more picky */
MIO_HTRD_STRICT = (1 << 7) /**< be more picky */
}; };
typedef enum mio_htrd_option_t mio_htrd_option_t; typedef enum mio_htrd_option_t mio_htrd_option_t;

View File

@ -27,8 +27,74 @@
#ifndef _MIO_HTRE_H_ #ifndef _MIO_HTRE_H_
#define _MIO_HTRE_H_ #define _MIO_HTRE_H_
#include <mio-http.h>
#include <mio-htb.h> #include <mio-htb.h>
#include <mio-ecs.h>
/**
* The mio_http_version_t type defines http version.
*/
struct mio_http_version_t
{
short major; /**< major version */
short minor; /**< minor version */
};
typedef struct mio_http_version_t mio_http_version_t;
/**
* The mio_http_method_t type defines http methods .
*/
enum mio_http_method_t
{
MIO_HTTP_OTHER,
/* rfc 2616 */
MIO_HTTP_HEAD,
MIO_HTTP_GET,
MIO_HTTP_POST,
MIO_HTTP_PUT,
MIO_HTTP_DELETE,
MIO_HTTP_OPTIONS,
MIO_HTTP_TRACE,
MIO_HTTP_CONNECT
#if 0
/* rfc 2518 */
MIO_HTTP_PROPFIND,
MIO_HTTP_PROPPATCH,
MIO_HTTP_MKCOL,
MIO_HTTP_COPY,
MIO_HTTP_MOVE,
MIO_HTTP_LOCK,
MIO_HTTP_UNLOCK,
/* rfc 3253 */
MIO_HTTP_VERSION_CONTROL,
MIO_HTTP_REPORT,
MIO_HTTP_CHECKOUT,
MIO_HTTP_CHECKIN,
MIO_HTTP_UNCHECKOUT,
MIO_HTTP_MKWORKSPACE,
MIO_HTTP_UPDATE,
MIO_HTTP_LABEL,
MIO_HTTP_MERGE,
MIO_HTTP_BASELINE_CONTROL,
MIO_HTTP_MKACTIVITY,
/* microsoft */
MIO_HTTP_BPROPFIND,
MIO_HTTP_BPROPPATCH,
MIO_HTTP_BCOPY,
MIO_HTTP_BDELETE,
MIO_HTTP_BMOVE,
MIO_HTTP_NOTIFY,
MIO_HTTP_POLL,
MIO_HTTP_SUBSCRIBE,
MIO_HTTP_UNSUBSCRIBE,
#endif
};
typedef enum mio_http_method_t mio_http_method_t;
/* /*
* You should not manipulate an object of the #mio_htre_t * You should not manipulate an object of the #mio_htre_t
@ -37,7 +103,7 @@
*/ */
/* header and contents of request/response */ /* header and contents of request/response */
/*typedef struct mio_htre_t mio_htre_t; <--- defined in mio-http.h TODO: remove recursive definition */ typedef struct mio_htre_t mio_htre_t;
typedef struct mio_htre_hdrval_t mio_htre_hdrval_t; typedef struct mio_htre_hdrval_t mio_htre_hdrval_t;
enum mio_htre_state_t enum mio_htre_state_t

View File

@ -27,77 +27,12 @@
#include <mio-ecs.h> #include <mio-ecs.h>
#include <mio-sck.h> #include <mio-sck.h>
#include <mio-htre.h>
/** \file /** \file
* This file provides basic data types and functions for the http protocol. * This file provides basic data types and functions for the http protocol.
*/ */
/**
* The mio_http_version_t type defines http version.
*/
struct mio_http_version_t
{
short major; /**< major version */
short minor; /**< minor version */
};
typedef struct mio_http_version_t mio_http_version_t;
/**
* The mio_http_method_t type defines http methods .
*/
enum mio_http_method_t
{
MIO_HTTP_OTHER,
/* rfc 2616 */
MIO_HTTP_HEAD,
MIO_HTTP_GET,
MIO_HTTP_POST,
MIO_HTTP_PUT,
MIO_HTTP_DELETE,
MIO_HTTP_OPTIONS,
MIO_HTTP_TRACE,
MIO_HTTP_CONNECT
#if 0
/* rfc 2518 */
MIO_HTTP_PROPFIND,
MIO_HTTP_PROPPATCH,
MIO_HTTP_MKCOL,
MIO_HTTP_COPY,
MIO_HTTP_MOVE,
MIO_HTTP_LOCK,
MIO_HTTP_UNLOCK,
/* rfc 3253 */
MIO_HTTP_VERSION_CONTROL,
MIO_HTTP_REPORT,
MIO_HTTP_CHECKOUT,
MIO_HTTP_CHECKIN,
MIO_HTTP_UNCHECKOUT,
MIO_HTTP_MKWORKSPACE,
MIO_HTTP_UPDATE,
MIO_HTTP_LABEL,
MIO_HTTP_MERGE,
MIO_HTTP_BASELINE_CONTROL,
MIO_HTTP_MKACTIVITY,
/* microsoft */
MIO_HTTP_BPROPFIND,
MIO_HTTP_BPROPPATCH,
MIO_HTTP_BCOPY,
MIO_HTTP_BDELETE,
MIO_HTTP_BMOVE,
MIO_HTTP_NOTIFY,
MIO_HTTP_POLL,
MIO_HTTP_SUBSCRIBE,
MIO_HTTP_UNSUBSCRIBE,
#endif
};
typedef enum mio_http_method_t mio_http_method_t;
/** /**
* The #mio_http_range_int_t type defines an integer that can represent * The #mio_http_range_int_t type defines an integer that can represent
* a range offset. Depening on the size of #mio_foff_t, it is defined to * a range offset. Depening on the size of #mio_foff_t, it is defined to
@ -155,7 +90,6 @@ typedef enum mio_perenc_http_opt_t mio_perenc_bcstr_opt_t;
/* -------------------------------------------------------------- */ /* -------------------------------------------------------------- */
typedef struct mio_htre_t mio_htre_t;
typedef struct mio_svc_htts_t mio_svc_htts_t; typedef struct mio_svc_htts_t mio_svc_htts_t;
typedef struct mio_svc_httc_t mio_svc_httc_t; typedef struct mio_svc_httc_t mio_svc_httc_t;
@ -180,6 +114,14 @@ struct mio_svc_htts_rsrc_t
#define MIO_SVC_HTTS_RSRC_ATTACH(rsrc, var) do { (var) = (rsrc); ++(rsrc)->rsrc_refcnt; } while(0) #define MIO_SVC_HTTS_RSRC_ATTACH(rsrc, var) do { (var) = (rsrc); ++(rsrc)->rsrc_refcnt; } while(0)
#define MIO_SVC_HTTS_RSRC_DETACH(rsrc_var) do { if (--(rsrc_var)->rsrc_refcnt == 0) { mio_svc_htts_rsrc_t* __rsrc_tmp = (rsrc_var); (rsrc_var) = MIO_NULL; mio_svc_htts_rsrc_kill(__rsrc_tmp); } else { (rsrc_var) = MIO_NULL; } } while(0) #define MIO_SVC_HTTS_RSRC_DETACH(rsrc_var) do { if (--(rsrc_var)->rsrc_refcnt == 0) { mio_svc_htts_rsrc_t* __rsrc_tmp = (rsrc_var); (rsrc_var) = MIO_NULL; mio_svc_htts_rsrc_kill(__rsrc_tmp); } else { (rsrc_var) = MIO_NULL; } } while(0)
typedef int (*mio_svc_htts_proc_req_t) (
mio_svc_htts_t* htts,
mio_dev_sck_t* sck,
mio_htre_t* req
);
/* -------------------------------------------------------------- */ /* -------------------------------------------------------------- */
#if defined(__cplusplus) #if defined(__cplusplus)
@ -279,42 +221,32 @@ MIO_EXPORT mio_bch_t* mio_perenc_http_bcstrdup (
/* ------------------------------------------------------------------------- */ /* ------------------------------------------------------------------------- */
MIO_EXPORT mio_svc_htts_t* mio_svc_htts_start ( MIO_EXPORT mio_svc_htts_t* mio_svc_htts_start (
mio_t* mio, mio_t* mio,
const mio_skad_t* bind_addr const mio_skad_t* bind_addr,
mio_svc_htts_proc_req_t proc_req
); );
MIO_EXPORT void mio_svc_htts_stop ( MIO_EXPORT void mio_svc_htts_stop (
mio_svc_htts_t* htts mio_svc_htts_t* htts
); );
#if defined(MIO_HAVE_INLINE)
static MIO_INLINE mio_t* mio_svc_htts_getmio(mio_svc_htts_t* svc) { return mio_svc_getmio((mio_svc_t*)svc); }
#else
# define mio_svc_htts_getmio(svc) mio_svc_getmio(svc)
#endif
MIO_EXPORT int mio_svc_htts_setservernamewithbcstr ( MIO_EXPORT int mio_svc_htts_setservernamewithbcstr (
mio_svc_htts_t* htts, mio_svc_htts_t* htts,
const mio_bch_t* server_name const mio_bch_t* server_name
); );
MIO_EXPORT int mio_svc_htts_docgi ( MIO_EXPORT int mio_svc_htts_docgi (
mio_svc_htts_t* htts, mio_svc_htts_t* htts,
mio_dev_sck_t* csck, mio_dev_sck_t* csck,
mio_htre_t* req, mio_htre_t* req,
const mio_bch_t* docroot const mio_bch_t* docroot,
); const mio_bch_t* script
MIO_EXPORT int mio_svc_htts_sendfile (
mio_svc_htts_t* htts,
mio_dev_sck_t* csck,
const mio_bch_t* file_path,
int status_code,
mio_http_method_t method,
const mio_http_version_t* version,
int keepalive
);
MIO_EXPORT void mio_svc_htts_fmtgmtime (
mio_svc_htts_t* htts,
const mio_ntime_t* nt,
mio_bch_t* buf,
mio_oow_t len
); );
MIO_EXPORT mio_svc_htts_rsrc_t* mio_svc_htts_rsrc_make ( MIO_EXPORT mio_svc_htts_rsrc_t* mio_svc_htts_rsrc_make (
@ -335,6 +267,12 @@ MIO_EXPORT void mio_svc_htts_fmtgmtime (
mio_oow_t len mio_oow_t len
); );
MIO_EXPORT mio_bch_t* mio_svc_htts_dupmergepaths (
mio_svc_htts_t* htts,
const mio_bch_t* base,
const mio_bch_t* path
);
#if defined(__cplusplus) #if defined(__cplusplus)
} }
#endif #endif

View File

@ -1776,7 +1776,6 @@ static int fmt_put_bchars_to_bch_buf (mio_fmtout_t* fmtout, const mio_bch_t* ptr
return 1; /* success */ return 1; /* success */
} }
static int fmt_put_uchars_to_bch_buf (mio_fmtout_t* fmtout, const mio_uch_t* ptr, mio_oow_t len) static int fmt_put_uchars_to_bch_buf (mio_fmtout_t* fmtout, const mio_uch_t* ptr, mio_oow_t len)
{ {
fmt_bch_buf_t* b = (fmt_bch_buf_t*)fmtout->ctx; fmt_bch_buf_t* b = (fmt_bch_buf_t*)fmtout->ctx;

View File

@ -1113,6 +1113,18 @@ MIO_EXPORT mio_bch_t* mio_dupbcstr (
mio_oow_t* bcslen /* [OUT] length */ mio_oow_t* bcslen /* [OUT] length */
); );
MIO_EXPORT mio_uch_t* mio_dupucstrs (
mio_t* mio,
const mio_uch_t* ucs[],
mio_oow_t* ucslen
);
MIO_EXPORT mio_bch_t* mio_dupbcstrs (
mio_t* mio,
const mio_bch_t* bcs[],
mio_oow_t* bcslen
);
#if defined(MIO_OOCH_IS_UCH) #if defined(MIO_OOCH_IS_UCH)
# define mio_dupoochars(mio,oocs,oocslen) mio_dupuchars(mio,oocs,oocslen) # define mio_dupoochars(mio,oocs,oocslen) mio_dupuchars(mio,oocs,oocslen)
# define mio_dupoocstr(mio,oocs,oocslen) mio_dupucstr(mio,oocs,oocslen) # define mio_dupoocstr(mio,oocs,oocslen) mio_dupucstr(mio,oocs,oocslen)

View File

@ -1729,5 +1729,39 @@ mio_bch_t* mio_dupbcstr (mio_t* mio, const mio_bch_t* bcs, mio_oow_t* bcslen)
return ptr; return ptr;
} }
mio_uch_t* mio_dupucstrs (mio_t* mio, const mio_uch_t* ucs[], mio_oow_t* ucslen)
{
mio_uch_t* ptr;
mio_oow_t len, i;
for (i = 0, len = 0; ucs[i]; i++) len += mio_count_ucstr(ucs[i]);
ptr = (mio_uch_t*)mio_allocmem(mio, (len + 1) * MIO_SIZEOF(mio_uch_t));
if (!ptr) return MIO_NULL;
for (i = 0, len = 0; ucs[i]; i++)
len += mio_copy_ucstr_unlimited(&ptr[len], ucs[i]);
ptr[len] = '\0';
if (ucslen) *ucslen = len;
return ptr;
}
mio_bch_t* mio_dupbcstrs (mio_t* mio, const mio_bch_t* bcs[], mio_oow_t* bcslen)
{
mio_bch_t* ptr;
mio_oow_t len, i;
for (i = 0, len = 0; bcs[i]; i++) len += mio_count_bcstr(bcs[i]);
ptr = (mio_bch_t*)mio_allocmem(mio, (len + 1) * MIO_SIZEOF(mio_bch_t));
if (!ptr) return MIO_NULL;
for (i = 0, len = 0; bcs[i]; i++)
len += mio_copy_bcstr_unlimited(&ptr[len], bcs[i]);
ptr[len] = '\0';
if (bcslen) *bcslen = len;
return ptr;
}
/* ========================================================================= */ /* ========================================================================= */