added some http processing code

This commit is contained in:
hyung-hwan 2020-05-01 18:01:29 +00:00
parent a2f0fa9c7f
commit 49ad401433
12 changed files with 322 additions and 139 deletions

View File

@ -27,6 +27,7 @@ include_HEADERS = \
mio-ecs.h \ mio-ecs.h \
mio-fmt.h \ mio-fmt.h \
mio-htb.h \ mio-htb.h \
mio-htrd.h \
mio-htre.h \ mio-htre.h \
mio-http.h \ mio-http.h \
mio-nwif.h \ mio-nwif.h \

View File

@ -407,6 +407,7 @@ include_HEADERS = \
mio-ecs.h \ mio-ecs.h \
mio-fmt.h \ mio-fmt.h \
mio-htb.h \ mio-htb.h \
mio-htrd.h \
mio-htre.h \ mio-htre.h \
mio-http.h \ mio-http.h \
mio-nwif.h \ mio-nwif.h \

View File

@ -22,10 +22,9 @@
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
#include <mio/http/htrd.h> #include "mio-htrd.h"
#include <mio/cmn/chr.h> #include "mio-chr.h"
#include <mio/cmn/path.h> #include "mio-prv.h"
#include "../cmn/mem-prv.h"
static const mio_bch_t NUL = '\0'; static const mio_bch_t NUL = '\0';
@ -78,19 +77,17 @@ static MIO_INLINE int is_xdigit_octet (mio_bch_t c)
static MIO_INLINE int digit_to_num (mio_bch_t c) static MIO_INLINE int digit_to_num (mio_bch_t c)
{ {
if (c >= '0' && c <= '9') return c - '0'; return MIO_DIGIT_TO_NUM(c);
return -1;
} }
static MIO_INLINE int xdigit_to_num (mio_bch_t c) static MIO_INLINE int xdigit_to_num (mio_bch_t c)
{ {
return MIO_MXDIGITTONUM (c); return MIO_XDIGIT_TO_NUM(c);
} }
static MIO_INLINE int push_to_buffer (mio_htrd_t* htrd, mio_htob_t* octb, const mio_bch_t* ptr, mio_oow_t len) static MIO_INLINE int push_to_buffer (mio_htrd_t* htrd, mio_htob_t* octb, const mio_bch_t* ptr, mio_oow_t len)
{ {
if (mio_mbs_ncat (octb, ptr, len) == (mio_oow_t)-1) if (mio_becs_ncat (octb, ptr, len) == (mio_oow_t)-1)
{ {
htrd->errnum = MIO_HTRD_ENOMEM; htrd->errnum = MIO_HTRD_ENOMEM;
return -1; return -1;
@ -100,7 +97,7 @@ static MIO_INLINE int push_to_buffer (mio_htrd_t* htrd, mio_htob_t* octb, const
static MIO_INLINE int push_content (mio_htrd_t* htrd, const mio_bch_t* ptr, mio_oow_t len) static MIO_INLINE int push_content (mio_htrd_t* htrd, const mio_bch_t* ptr, mio_oow_t len)
{ {
MIO_ASSERT (len > 0); MIO_ASSERT (htrd->mio, len > 0);
if (mio_htre_addcontent(&htrd->re, ptr, len) <= -1) if (mio_htre_addcontent(&htrd->re, ptr, len) <= -1)
{ {
@ -120,8 +117,8 @@ static MIO_INLINE void clear_feed (mio_htrd_t* htrd)
htrd->clean = 1; htrd->clean = 1;
mio_htre_clear (&htrd->re); mio_htre_clear (&htrd->re);
mio_mbs_clear (&htrd->fed.b.tra); mio_becs_clear (&htrd->fed.b.tra);
mio_mbs_clear (&htrd->fed.b.raw); mio_becs_clear (&htrd->fed.b.raw);
MIO_MEMSET (&htrd->fed.s, 0, MIO_SIZEOF(htrd->fed.s)); MIO_MEMSET (&htrd->fed.s, 0, MIO_SIZEOF(htrd->fed.s));
} }
@ -138,7 +135,7 @@ mio_htrd_t* mio_htrd_open (mio_t* mio, mio_oow_t xtnsize)
mio_freemem (mio, htrd); mio_freemem (mio, htrd);
return MIO_NULL; return MIO_NULL;
} }
else MIO_MEMSET (MIO_XTN(htrd), 0, xtnsize); else MIO_MEMSET (htrd + 1, 0, xtnsize);
} }
return htrd; return htrd;
} }
@ -179,17 +176,17 @@ void mio_htrd_fini (mio_htrd_t* htrd)
{ {
mio_htre_fini (&htrd->re); mio_htre_fini (&htrd->re);
mio_mbs_fini (&htrd->fed.b.tra); mio_becs_fini (&htrd->fed.b.tra);
mio_mbs_fini (&htrd->fed.b.raw); mio_becs_fini (&htrd->fed.b.raw);
#if 0 #if 0
mio_mbs_fini (&htrd->tmp.qparam); mio_becs_fini (&htrd->tmp.qparam);
#endif #endif
} }
static mio_bch_t* parse_initial_line (mio_htrd_t* htrd, mio_bch_t* line) static mio_bch_t* parse_initial_line (mio_htrd_t* htrd, mio_bch_t* line)
{ {
mio_bch_t* p = line; mio_bch_t* p = line;
mio_mcstr_t tmp; mio_bcs_t tmp;
#if 0 #if 0
/* ignore leading spaces excluding crlf */ /* ignore leading spaces excluding crlf */
@ -212,11 +209,10 @@ static mio_bch_t* parse_initial_line (mio_htrd_t* htrd, mio_bch_t* line)
*p = '\0'; /* null-terminate the method name */ *p = '\0'; /* null-terminate the method name */
htrd->re.u.q.method.type = mio_mcstrtohttpmethod (&tmp); htrd->re.u.q.method.type = mio_bchars_to_http_method(tmp.ptr, tmp.len);
htrd->re.u.q.method.name = tmp.ptr; htrd->re.u.q.method.name = tmp.ptr;
} }
else if ((htrd->option & MIO_HTRD_RESPONSE) && else if ((htrd->option & MIO_HTRD_RESPONSE) && mio_comp_bchars_bcstr(tmp.ptr, tmp.len, "HTTP", 1) == 0)
mio_mbsxcmp (tmp.ptr, tmp.len, "HTTP") == 0)
{ {
/* it begins with HTTP. it may be a response */ /* it begins with HTTP. it may be a response */
htrd->re.type = MIO_HTRE_S; htrd->re.type = MIO_HTRE_S;
@ -296,7 +292,7 @@ static mio_bch_t* parse_initial_line (mio_htrd_t* htrd, mio_bch_t* line)
#if 0 #if 0
mio_bch_t* out; mio_bch_t* out;
#endif #endif
mio_mcstr_t param; mio_bcs_t param;
/* skip spaces */ /* skip spaces */
do p++; while (is_space_octet(*p)); do p++; while (is_space_octet(*p));
@ -412,16 +408,16 @@ static mio_bch_t* parse_initial_line (mio_htrd_t* htrd, mio_bch_t* line)
/* if the url begins with xxx://, /* if the url begins with xxx://,
* skip xxx:/ and canonicalize from the second slash */ * skip xxx:/ and canonicalize from the second slash */
while (is_alpha_octet(*qpath)) qpath++; while (is_alpha_octet(*qpath)) qpath++;
if (mio_mbszcmp (qpath, "://", 3) == 0) if (mio_comp_bcstr_limited(qpath, "://", 3, 1) == 0)
{ {
qpath = qpath + 2; /* set the position to the second / in :// */ qpath = qpath + 2; /* set the position to the second / in :// */
htrd->re.u.q.path.len = mio_canonmbspath (qpath, qpath, 0); htrd->re.u.q.path.len = mio_canon_bcstr_path(qpath, qpath, 0);
htrd->re.u.q.path.len += qpath - htrd->re.u.q.path.ptr; htrd->re.u.q.path.len += qpath - htrd->re.u.q.path.ptr;
} }
else else
{ {
qpath = htrd->re.u.q.path.ptr; qpath = htrd->re.u.q.path.ptr;
htrd->re.u.q.path.len = mio_canonmbspath (qpath, qpath, 0); htrd->re.u.q.path.len = mio_canon_bcstr_path(qpath, qpath, 0);
} }
} }
@ -481,12 +477,6 @@ void mio_htrd_clear (mio_htrd_t* htrd)
htrd->flags = 0; htrd->flags = 0;
} }
void* mio_htrd_getxtn (mio_htrd_t* htrd)
{
return MIO_XTN (htrd);
}
mio_htrd_errnum_t mio_htrd_geterrnum (mio_htrd_t* htrd) mio_htrd_errnum_t mio_htrd_geterrnum (mio_htrd_t* htrd)
{ {
return htrd->errnum; return htrd->errnum;
@ -520,15 +510,15 @@ static int capture_connection (mio_htrd_t* htrd, mio_htb_pair_t* pair)
while (val->next) val = val->next; while (val->next) val = val->next;
/* The value for Connection: may get comma-separated. /* The value for Connection: may get comma-separated.
* so use mio_mbscaseword() instead of mio_mbscmp(). */ * so use mio_find_bcstr_word_in_bcstr() instead of mio_comp_bcstr(). */
if (mio_mbscaseword (val->ptr, "close", ',')) if (mio_find_bcstr_word_in_bcstr(val->ptr, "close", ',', 1))
{ {
htrd->re.flags &= ~MIO_HTRE_ATTR_KEEPALIVE; htrd->re.flags &= ~MIO_HTRE_ATTR_KEEPALIVE;
return 0; return 0;
} }
if (mio_mbscaseword (val->ptr, "keep-alive", ',')) if (mio_find_bcstr_word_in_bcstr(val->ptr, "keep-alive", ',', 1))
{ {
htrd->re.flags |= MIO_HTRE_ATTR_KEEPALIVE; htrd->re.flags |= MIO_HTRE_ATTR_KEEPALIVE;
return 0; return 0;
@ -543,8 +533,7 @@ static int capture_connection (mio_htrd_t* htrd, mio_htb_pair_t* pair)
* For the second Keep-Alive, this function sees 'Keep-Alive,Keep-Alive' * For the second Keep-Alive, this function sees 'Keep-Alive,Keep-Alive'
* That's because values of the same keys are concatenated. * That's because values of the same keys are concatenated.
*/ */
if (htrd->re.version.major < 1 || if (htrd->re.version.major < 1 || (htrd->re.version.major == 1 && htrd->re.version.minor <= 0))
(htrd->re.version.major == 1 && htrd->re.version.minor <= 0))
{ {
htrd->re.flags &= ~MIO_HTRE_ATTR_KEEPALIVE; htrd->re.flags &= ~MIO_HTRE_ATTR_KEEPALIVE;
} }
@ -615,7 +604,7 @@ static int capture_expect (mio_htrd_t* htrd, mio_htb_pair_t* pair)
while (val) while (val)
{ {
/* Expect: 100-continue is included */ /* Expect: 100-continue is included */
if (mio_mbscasecmp(val->ptr, "100-continue") == 0) htrd->re.flags |= MIO_HTRE_ATTR_EXPECT100; if (mio_comp_bcstr(val->ptr, "100-continue", 1) == 0) htrd->re.flags |= MIO_HTRE_ATTR_EXPECT100;
val = val->next; val = val->next;
} }
@ -641,7 +630,7 @@ static int capture_transfer_encoding (mio_htrd_t* htrd, mio_htb_pair_t* pair)
val = MIO_HTB_VPTR(pair); val = MIO_HTB_VPTR(pair);
while (val->next) val = val->next; while (val->next) val = val->next;
n = mio_mbscasecmp(val->ptr, "chunked"); n = mio_comp_bcstr(val->ptr, "chunked", 1);
if (n == 0) if (n == 0)
{ {
/* if (htrd->re.attr.content_length > 0) */ /* if (htrd->re.attr.content_length > 0) */
@ -685,15 +674,11 @@ static MIO_INLINE int capture_key_header (mio_htrd_t* htrd, mio_htb_pair_t* pair
{ {
mid = base + count / 2; mid = base + count / 2;
n = mio_mbsxncasecmp ( n = mio_comp_bchars(MIO_HTB_KPTR(pair), MIO_HTB_KLEN(pair), hdrtab[mid].ptr, hdrtab[mid].len, 1);
MIO_HTB_KPTR(pair), MIO_HTB_KLEN(pair),
hdrtab[mid].ptr, hdrtab[mid].len
);
if (n == 0) if (n == 0)
{ {
/* bingo! */ /* bingo! */
return hdrtab[mid].handler (htrd, pair); return hdrtab[mid].handler(htrd, pair);
} }
if (n > 0) { base = mid + 1; count--; } if (n > 0) { base = mid + 1; count--; }
@ -723,7 +708,7 @@ static mio_htb_pair_t* hdr_cbserter (
mio_htre_hdrval_t *val; mio_htre_hdrval_t *val;
val = mio_allocmem(htb->mio, MIO_SIZEOF(*val)); val = mio_allocmem(htb->mio, MIO_SIZEOF(*val));
if (HAWK_UNLIKELY(!val)) if (MIO_UNLIKELY(!val))
{ {
tx->htrd->errnum = MIO_HTRD_ENOMEM; tx->htrd->errnum = MIO_HTRD_ENOMEM;
return MIO_NULL; return MIO_NULL;
@ -787,7 +772,7 @@ static mio_htb_pair_t* hdr_cbserter (
mio_htre_hdrval_t* tmp; mio_htre_hdrval_t* tmp;
val = (mio_htre_hdrval_t*)mio_allocmem(tx->htrd->mio, MIO_SIZEOF(*val)); val = (mio_htre_hdrval_t*)mio_allocmem(tx->htrd->mio, MIO_SIZEOF(*val));
if (HAWK_UNLIKELY(!val)) if (MIO_UNLIKELY(!val))
{ {
tx->htrd->errnum = MIO_HTRD_ENOMEM; tx->htrd->errnum = MIO_HTRD_ENOMEM;
return MIO_NULL; return MIO_NULL;
@ -800,7 +785,7 @@ static mio_htb_pair_t* hdr_cbserter (
/* TODO: doubly linked list for speed-up??? */ /* TODO: doubly linked list for speed-up??? */
tmp = MIO_HTB_VPTR(pair); tmp = MIO_HTB_VPTR(pair);
MIO_ASSERT (tmp != MIO_NULL); MIO_ASSERT (tx->htrd->mio, tmp != MIO_NULL);
/* find the tail */ /* find the tail */
while (tmp->next) tmp = tmp->next; while (tmp->next) tmp = tmp->next;
@ -826,7 +811,7 @@ mio_bch_t* parse_header_field (mio_htrd_t* htrd, mio_bch_t* line, mio_htb_t* tab
while (is_space_octet(*p)) p++; while (is_space_octet(*p)) p++;
#endif #endif
MIO_ASSERT (!is_whspace_octet(*p)); MIO_ASSERT (htrd->mio, !is_whspace_octet(*p));
/* check the field name */ /* check the field name */
name.ptr = last = p; name.ptr = last = p;
@ -932,7 +917,7 @@ static MIO_INLINE int parse_initial_line_and_headers (
/* add the terminating null for easier parsing */ /* add the terminating null for easier parsing */
if (push_to_buffer (htrd, &htrd->fed.b.raw, &NUL, 1) <= -1) return -1; if (push_to_buffer (htrd, &htrd->fed.b.raw, &NUL, 1) <= -1) return -1;
p = MIO_MBS_PTR(&htrd->fed.b.raw); p = MIO_BECS_PTR(&htrd->fed.b.raw);
#if 0 #if 0
if (htrd->option & MIO_HTRD_SKIPEMPTYLINES) if (htrd->option & MIO_HTRD_SKIPEMPTYLINES)
@ -941,7 +926,7 @@ static MIO_INLINE int parse_initial_line_and_headers (
#endif #endif
while (is_space_octet(*p)) p++; while (is_space_octet(*p)) p++;
MIO_ASSERT (*p != '\0'); MIO_ASSERT (htrd->mio, *p != '\0');
/* parse the initial line */ /* parse the initial line */
if (!(htrd->option & MIO_HTRD_SKIPINITIALLINE)) if (!(htrd->option & MIO_HTRD_SKIPINITIALLINE))
@ -979,7 +964,7 @@ static const mio_bch_t* getchunklen (mio_htrd_t* htrd, const mio_bch_t* ptr, mio
const mio_bch_t* end = ptr + len; const mio_bch_t* end = ptr + len;
/* this function must be called in the GET_CHUNK_LEN context */ /* this function must be called in the GET_CHUNK_LEN context */
MIO_ASSERT (htrd->fed.s.chunk.phase == GET_CHUNK_LEN); MIO_ASSERT (htrd->mio, htrd->fed.s.chunk.phase == GET_CHUNK_LEN);
if (htrd->fed.s.chunk.count <= 0) if (htrd->fed.s.chunk.count <= 0)
{ {
@ -1063,7 +1048,7 @@ static const mio_bch_t* get_trailing_headers (
{ {
mio_bch_t* p; mio_bch_t* p;
MIO_ASSERT (htrd->fed.s.crlf <= 3); MIO_ASSERT (htrd->mio, htrd->fed.s.crlf <= 3);
htrd->fed.s.crlf = 0; htrd->fed.s.crlf = 0;
if (push_to_buffer ( if (push_to_buffer (
@ -1073,7 +1058,7 @@ static const mio_bch_t* get_trailing_headers (
htrd, &htrd->fed.b.tra, &NUL, 1) <= -1) htrd, &htrd->fed.b.tra, &NUL, 1) <= -1)
return MIO_NULL; return MIO_NULL;
p = MIO_MBS_PTR(&htrd->fed.b.tra); p = MIO_BECS_PTR(&htrd->fed.b.tra);
do do
{ {
@ -1123,7 +1108,7 @@ int mio_htrd_feed (mio_htrd_t* htrd, const mio_bch_t* req, mio_oow_t len)
int header_completed_during_this_feed = 0; int header_completed_during_this_feed = 0;
mio_oow_t avail; mio_oow_t avail;
MIO_ASSERT (len > 0); MIO_ASSERT (htrd->mio, len > 0);
if (htrd->flags & FEEDING_SUSPENDED) if (htrd->flags & FEEDING_SUSPENDED)
{ {
@ -1212,7 +1197,7 @@ int mio_htrd_feed (mio_htrd_t* htrd, const mio_bch_t* req, mio_oow_t len)
*/ */
/* we got a complete request header. */ /* we got a complete request header. */
MIO_ASSERT (htrd->fed.s.crlf <= 3); MIO_ASSERT (htrd->mio, htrd->fed.s.crlf <= 3);
/* reset the crlf state */ /* reset the crlf state */
htrd->fed.s.crlf = 0; htrd->fed.s.crlf = 0;
@ -1260,7 +1245,7 @@ int mio_htrd_feed (mio_htrd_t* htrd, const mio_bch_t* req, mio_oow_t len)
if (htrd->re.flags & MIO_HTRE_ATTR_CHUNKED) if (htrd->re.flags & MIO_HTRE_ATTR_CHUNKED)
{ {
/* transfer-encoding: chunked */ /* transfer-encoding: chunked */
MIO_ASSERT (!(htrd->re.flags & MIO_HTRE_ATTR_LENGTH)); MIO_ASSERT (htrd->mio, !(htrd->re.flags & MIO_HTRE_ATTR_LENGTH));
dechunk_start: dechunk_start:
htrd->fed.s.chunk.phase = GET_CHUNK_LEN; htrd->fed.s.chunk.phase = GET_CHUNK_LEN;
@ -1411,7 +1396,7 @@ XXXXXXXX
if (htrd->fed.s.chunk.phase == GET_CHUNK_DATA) if (htrd->fed.s.chunk.phase == GET_CHUNK_DATA)
{ {
MIO_ASSERT (htrd->fed.s.need == 0); MIO_ASSERT (htrd->mio, htrd->fed.s.need == 0);
htrd->fed.s.chunk.phase = GET_CHUNK_CRLF; htrd->fed.s.chunk.phase = GET_CHUNK_CRLF;
dechunk_crlf: dechunk_crlf:
@ -1495,8 +1480,8 @@ XXXXXXXX
#if 0 #if 0
mio_printf (MIO_T("CONTENT_LENGTH %d, RAW HEADER LENGTH %d\n"), mio_printf (MIO_T("CONTENT_LENGTH %d, RAW HEADER LENGTH %d\n"),
(int)MIO_MBS_LEN(&htrd->re.content), (int)MIO_BECS_LEN(&htrd->re.content),
(int)MIO_MBS_LEN(&htrd->fed.b.raw)); (int)MIO_BECS_LEN(&htrd->fed.b.raw));
#endif #endif
clear_feed (htrd); clear_feed (htrd);
@ -1621,9 +1606,9 @@ void mio_htrd_undummify (mio_htrd_t* htrd)
} }
#if 0 #if 0
int mio_htrd_scanqparam (mio_htrd_t* htrd, const mio_mcstr_t* cstr) int mio_htrd_scanqparam (mio_htrd_t* htrd, const mio_bcs_t* cstr)
{ {
mio_mcstr_t key, val; mio_bcs_t key, val;
const mio_bch_t* p, * end; const mio_bch_t* p, * end;
mio_bch_t* out; mio_bch_t* out;
@ -1637,11 +1622,11 @@ int mio_htrd_scanqparam (mio_htrd_t* htrd, const mio_mcstr_t* cstr)
/* a key and a value pair including two terminating null /* a key and a value pair including two terminating null
* can't exceed the the qparamstrlen + 2. only +1 below as there is * can't exceed the the qparamstrlen + 2. only +1 below as there is
* one more space for an internal terminating null */ * one more space for an internal terminating null */
mio_mbs_setlen (&htrd->tmp.qparam, cstr->len + 1); mio_becs_setlen (&htrd->tmp.qparam, cstr->len + 1);
/* let out point to the beginning of the qparam buffer. /* let out point to the beginning of the qparam buffer.
* the loop below emits percent-decode key and value to this buffer. */ * the loop below emits percent-decode key and value to this buffer. */
out = MIO_MBS_PTR(&htrd->tmp.qparam); out = MIO_BECS_PTR(&htrd->tmp.qparam);
key.ptr = out; key.len = 0; key.ptr = out; key.len = 0;
val.ptr = MIO_NULL; val.len = 0; val.ptr = MIO_NULL; val.len = 0;
@ -1650,7 +1635,7 @@ int mio_htrd_scanqparam (mio_htrd_t* htrd, const mio_mcstr_t* cstr)
{ {
if (p >= end || *p == '&' || *p == ';') if (p >= end || *p == '&' || *p == ';')
{ {
MIO_ASSERT (key.ptr != MIO_NULL); MIO_ASSERT (htrd->mio, key.ptr != MIO_NULL);
*out++ = '\0'; *out++ = '\0';
if (val.ptr == MIO_NULL) if (val.ptr == MIO_NULL)
@ -1664,13 +1649,11 @@ int mio_htrd_scanqparam (mio_htrd_t* htrd, const mio_mcstr_t* cstr)
val.ptr = out; val.ptr = out;
*out++ = '\0'; *out++ = '\0';
MIO_ASSERT (val.len == 0); MIO_ASSERT (htrd->mio, val.len == 0);
} }
MIO_ASSERTX ( /* set request parameter string callback before scanning */
htrd->recbs->qparamstr != MIO_NULL, MIO_ASSERT (htrd->mio, htrd->recbs->qparamstr != MIO_NULL);
"set request parameter string callback before scanning"
);
htrd->errnum = MIO_HTRD_ENOERR; htrd->errnum = MIO_HTRD_ENOERR;
if (htrd->recbs->qparamstr (htrd, &key, &val) <= -1) if (htrd->recbs->qparamstr (htrd, &key, &val) <= -1)
@ -1684,7 +1667,7 @@ int mio_htrd_scanqparam (mio_htrd_t* htrd, const mio_mcstr_t* cstr)
if (p >= end) break; if (p >= end) break;
p++; p++;
out = MIO_MBS_PTR(&htrd->tmp.qparam); out = MIO_BECS_PTR(&htrd->tmp.qparam);
key.ptr = out; key.len = 0; key.ptr = out; key.len = 0;
val.ptr = MIO_NULL; val.len = 0; val.ptr = MIO_NULL; val.len = 0;
} }
@ -1723,7 +1706,7 @@ int mio_htrd_scanqparam (mio_htrd_t* htrd, const mio_mcstr_t* cstr)
} }
while (1); while (1);
mio_mbs_clear (&htrd->tmp.qparam); mio_becs_clear (&htrd->tmp.qparam);
return 0; return 0;
} }
#endif #endif

View File

@ -395,11 +395,6 @@ mio_bch_t* mio_fmt_http_time_to_bcstr (const mio_ntime_t* nt, mio_bch_t* buf, mi
return buf; return buf;
} }
#define XDIGIT_TO_NUM(c) \
(((c) >= '0' && (c) <= '9')? ((c) - '0'): \
((c) >= 'A' && (c) <= 'F')? ((c) - 'A' + 10): \
((c) >= 'a' && (c) <= 'f')? ((c) - 'a' + 10): -1)
int mio_is_perenced_http_bcstr (const mio_bch_t* str) int mio_is_perenced_http_bcstr (const mio_bch_t* str)
{ {
const mio_bch_t* p = str; const mio_bch_t* p = str;
@ -408,11 +403,11 @@ int mio_is_perenced_http_bcstr (const mio_bch_t* str)
{ {
if (*p == '%' && *(p + 1) != '\0' && *(p + 2) != '\0') if (*p == '%' && *(p + 1) != '\0' && *(p + 2) != '\0')
{ {
int q = XDIGIT_TO_NUM(*(p + 1)); int q = MIO_XDIGIT_TO_NUM(*(p + 1));
if (q >= 0) if (q >= 0)
{ {
/* return true if the first valid percent-encoded sequence is found */ /* return true if the first valid percent-encoded sequence is found */
int w = XDIGIT_TO_NUM(*(p + 2)); int w = MIO_XDIGIT_TO_NUM(*(p + 2));
if (w >= 0) return 1; if (w >= 0) return 1;
} }
} }
@ -433,10 +428,10 @@ mio_oow_t mio_perdechttpstr (const mio_bch_t* str, mio_bch_t* buf, mio_oow_t* nd
{ {
if (*p == '%' && *(p + 1) != '\0' && *(p + 2) != '\0') if (*p == '%' && *(p + 1) != '\0' && *(p + 2) != '\0')
{ {
int q = XDIGIT_TO_NUM(*(p + 1)); int q = MIO_XDIGIT_TO_NUM(*(p + 1));
if (q >= 0) if (q >= 0)
{ {
int w = XDIGIT_TO_NUM(*(p + 2)); int w = MIO_XDIGIT_TO_NUM(*(p + 2));
if (w >= 0) if (w >= 0)
{ {
/* we don't care if it contains a null character */ /* we don't care if it contains a null character */

View File

@ -84,6 +84,13 @@ typedef enum mio_ooch_prop_t mio_ooch_prop_t;
typedef enum mio_ooch_prop_t mio_uch_prop_t; typedef enum mio_ooch_prop_t mio_uch_prop_t;
typedef enum mio_ooch_prop_t mio_bch_prop_t; typedef enum mio_ooch_prop_t mio_bch_prop_t;
#define MIO_DIGIT_TO_NUM(c) (((c) >= '0' && (c) <= '9')? ((c) - '0'): -1)
#define MIO_XDIGIT_TO_NUM(c) \
(((c) >= '0' && (c) <= '9')? ((c) - '0'): \
((c) >= 'A' && (c) <= 'F')? ((c) - 'A' + 10): \
((c) >= 'a' && (c) <= 'f')? ((c) - 'a' + 10): -1)
#if defined(__cplusplus) #if defined(__cplusplus)
extern "C" { extern "C" {
#endif #endif

View File

@ -76,7 +76,7 @@ struct mio_htrd_recbs_t
struct mio_htrd_t struct mio_htrd_t
{ {
mio_mmgr_t* mmgr; mio_t* mio;
mio_htrd_errnum_t errnum; mio_htrd_errnum_t errnum;
int option; int option;
int flags; int flags;
@ -90,13 +90,13 @@ struct mio_htrd_t
int flags; int flags;
int crlf; /* crlf status */ int crlf; /* crlf status */
mio_size_t plen; /* raw request length excluding crlf */ mio_oow_t plen; /* raw request length excluding crlf */
mio_size_t need; /* number of octets needed for contents */ mio_oow_t need; /* number of octets needed for contents */
struct struct
{ {
mio_size_t len; mio_oow_t len;
mio_size_t count; mio_oow_t count;
int phase; int phase;
} chunk; } chunk;
} s; /* state */ } s; /* state */
@ -104,8 +104,8 @@ struct mio_htrd_t
/* buffers needed for processing a request */ /* buffers needed for processing a request */
struct struct
{ {
mio_htob_t raw; /* buffer to hold raw octets */ mio_becs_t raw; /* buffer to hold raw octets */
mio_htob_t tra; /* buffer for handling trailers */ mio_becs_t tra; /* buffer for handling trailers */
} b; } b;
} fed; } fed;
@ -121,8 +121,8 @@ extern "C" {
* The mio_htrd_open() function creates a htrd processor. * The mio_htrd_open() function creates a htrd processor.
*/ */
MIO_EXPORT mio_htrd_t* mio_htrd_open ( MIO_EXPORT mio_htrd_t* mio_htrd_open (
mio_mmgr_t* mmgr, /**< memory manager */ mio_t* mio, /**< memory manager */
mio_size_t xtnsize /**< extension size in bytes */ mio_oow_t xtnsize /**< extension size in bytes */
); );
/** /**
@ -134,20 +134,18 @@ MIO_EXPORT void mio_htrd_close (
MIO_EXPORT int mio_htrd_init ( MIO_EXPORT int mio_htrd_init (
mio_htrd_t* htrd, mio_htrd_t* htrd,
mio_mmgr_t* mmgr mio_t* mio
); );
MIO_EXPORT void mio_htrd_fini ( MIO_EXPORT void mio_htrd_fini (
mio_htrd_t* htrd mio_htrd_t* htrd
); );
MIO_EXPORT mio_mmgr_t* mio_htrd_getmmgr ( #if defined(MIO_HAVE_INLINE)
mio_htrd_t* htrd static MIO_INLINE void* mio_htrd_getxtn (mio_htrd_t* htrd) { return (void*)(htrd + 1); }
); #else
#define mio_htrd_getxtn(htrd) ((void*)((mio_htrd_t*)(htrd) + 1))
MIO_EXPORT void* mio_htrd_getxtn ( #endif
mio_htrd_t* htrd
);
MIO_EXPORT mio_htrd_errnum_t mio_htrd_geterrnum ( MIO_EXPORT mio_htrd_errnum_t mio_htrd_geterrnum (
mio_htrd_t* htrd mio_htrd_t* htrd
@ -181,8 +179,8 @@ MIO_EXPORT void mio_htrd_setrecbs (
*/ */
MIO_EXPORT int mio_htrd_feed ( MIO_EXPORT int mio_htrd_feed (
mio_htrd_t* htrd, /**< htrd */ mio_htrd_t* htrd, /**< htrd */
const mio_mchar_t* req, /**< request octets */ const mio_bch_t* req, /**< request octets */
mio_size_t len /**< number of octets */ mio_oow_t len /**< number of octets */
); );
/** /**
@ -210,10 +208,12 @@ MIO_EXPORT void mio_htrd_undummify (
mio_htrd_t* htrd mio_htrd_t* htrd
); );
/*
MIO_EXPORT int mio_htrd_scanqparam ( MIO_EXPORT int mio_htrd_scanqparam (
mio_htrd_t* http, mio_htrd_t* http,
const mio_mcstr_t* cstr const mio_bcs_t* cstr
); );
*/
#if defined(__cplusplus) #if defined(__cplusplus)
} }

View File

@ -130,7 +130,7 @@ struct mio_htre_t
mio_htb_t trailers; mio_htb_t trailers;
/* content octets */ /* content octets */
mio_htob_t content; mio_becs_t content;
/* content callback */ /* content callback */
mio_htre_concb_t concb; mio_htre_concb_t concb;

View File

@ -31,12 +31,6 @@
* This file provides basic data types and functions for the http protocol. * This file provides basic data types and functions for the http protocol.
*/ */
/* octet buffer */
typedef mio_becs_t mio_htob_t;
/* octet string */
typedef mio_bcs_t mio_htos_t;
/** /**
* The mio_http_version_t type defines http version. * The mio_http_version_t type defines http version.
*/ */

View File

@ -274,6 +274,20 @@ MIO_EXPORT int mio_comp_bcstr (
int ignorecase int ignorecase
); );
MIO_EXPORT int mio_comp_ucstr_limited (
const mio_uch_t* str1,
const mio_uch_t* str2,
mio_oow_t maxlen,
int ignorecase
);
MIO_EXPORT int mio_comp_bcstr_limited (
const mio_bch_t* str1,
const mio_bch_t* str2,
mio_oow_t maxlen,
int ignorecase
);
MIO_EXPORT int mio_comp_ucstr_bcstr ( MIO_EXPORT int mio_comp_ucstr_bcstr (
const mio_uch_t* str1, const mio_uch_t* str1,
const mio_bch_t* str2, const mio_bch_t* str2,
@ -391,6 +405,20 @@ MIO_EXPORT void mio_fill_bchars (
mio_oow_t len mio_oow_t len
); );
MIO_EXPORT const mio_bch_t* mio_find_bcstr_word_in_bcstr (
const mio_bch_t* str,
const mio_bch_t* word,
mio_bch_t extra_delim,
int ignorecase
);
MIO_EXPORT const mio_uch_t* mio_find_ucstr_word_in_ucstr (
const mio_uch_t* str,
const mio_uch_t* word,
mio_uch_t extra_delim,
int ignorecase
);
MIO_EXPORT mio_uch_t* mio_find_uchar ( MIO_EXPORT mio_uch_t* mio_find_uchar (
const mio_uch_t* ptr, const mio_uch_t* ptr,
mio_oow_t len, mio_oow_t len,
@ -469,10 +497,11 @@ MIO_EXPORT mio_oow_t mio_count_bcstr (
# define mio_copy_oocstr mio_copy_ucstr # define mio_copy_oocstr mio_copy_ucstr
# define mio_copy_oocstr_unlimited mio_copy_ucstr_unlimited # define mio_copy_oocstr_unlimited mio_copy_ucstr_unlimited
# define mio_fill_oochars(dst,ch,len) mio_fill_uchars(dst,ch,len) # define mio_fill_oochars mio_fill_uchars
# define mio_find_oochar(ptr,len,c) mio_find_uchar(ptr,len,c) # define mio_find_oocstr_word_in_oocstr mio_find_ucstr_word_in_ucstr
# define mio_rfind_oochar(ptr,len,c) mio_rfind_uchar(ptr,len,c) # define mio_find_oochar mio_find_uchar
# define mio_find_oochar_in_oocstr(ptr,c) mio_find_uchar_in_ucstr(ptr,c) # define mio_rfind_oochar mio_rfind_uchar
# define mio_find_oochar_in_oocstr mio_find_uchar_in_ucstr
# define mio_split_oocstr mio_split_ucstr # define mio_split_oocstr mio_split_ucstr
# define mio_count_oocstr mio_count_ucstr # define mio_count_oocstr mio_count_ucstr
@ -496,10 +525,11 @@ MIO_EXPORT mio_oow_t mio_count_bcstr (
# define mio_copy_oocstr mio_copy_bcstr # define mio_copy_oocstr mio_copy_bcstr
# define mio_copy_oocstr_unlimited mio_copy_bcstr_unlimited # define mio_copy_oocstr_unlimited mio_copy_bcstr_unlimited
# define mio_fill_oochars(dst,ch,len) mio_fill_bchars(dst,ch,len) # define mio_fill_oochars mio_fill_bchars
# define mio_find_oochar(ptr,len,c) mio_find_bchar(ptr,len,c) # define mio_find_oocstr_word_in_oocstr mio_find_bcstr_word_in_bcstr
# define mio_rfind_oochar(ptr,len,c) mio_rfind_bchar(ptr,len,c) # define mio_find_oochar mio_find_bchar
# define mio_find_oochar_in_oocstr(ptr,c) mio_find_bchar_in_bcstr(ptr,c) # define mio_rfind_oochar mio_rfind_bchar
# define mio_find_oochar_in_oocstr mio_find_bchar_in_bcstr
# define mio_split_oocstr mio_split_bcstr # define mio_split_oocstr mio_split_bcstr
# define mio_count_oocstr mio_count_bcstr # define mio_count_oocstr mio_count_bcstr

View File

@ -1606,7 +1606,7 @@ static int fmt_put_bchars_to_uch_buf (mio_fmtout_t* fmtout, const mio_bch_t* ptr
} }
else else
{ {
if (b->mio) mio_seterrnum (b->mio, MIO_EECERR); mio_seterrnum (b->mio, MIO_EECERR);
return -1; return -1;
} }
} }
@ -1717,7 +1717,7 @@ static int fmt_put_uchars_to_bch_buf (mio_fmtout_t* fmtout, const mio_uch_t* ptr
} }
else else
{ {
if (b->mio) mio_seterrnum (b->mio, MIO_EECERR); mio_seterrnum (b->mio, MIO_EECERR);
return -1; return -1;
} }
} }

View File

@ -32,6 +32,7 @@
#include <errno.h> #include <errno.h>
#include <signal.h> #include <signal.h>
#include <sys/wait.h> #include <sys/wait.h>
#include <sys/uio.h>
/* ========================================================================= */ /* ========================================================================= */

View File

@ -25,7 +25,7 @@
*/ */
#include "mio-prv.h" #include "mio-prv.h"
#include <mio-chr.h> #include "mio-chr.h"
/* ========================================================================= */ /* ========================================================================= */
@ -173,7 +173,7 @@ int mio_comp_bcstr (const mio_bch_t* str1, const mio_bch_t* str2, int ignorecase
str1++; str2++; str1++; str2++;
} }
return ((mio_bchu_t)mio_to_bch_lower(*str1) > (mio_bchu_t)mio_to_bch_lower(*str2))? 1: -1; return ((mio_bchu_t)mio_to_bch_lower(*str1) > (mio_bchu_t)mio_to_bch_lower(*str2))? 1: -1;
} }
else else
{ {
@ -187,6 +187,58 @@ int mio_comp_bcstr (const mio_bch_t* str1, const mio_bch_t* str2, int ignorecase
} }
} }
int mio_comp_ucstr_limited (const mio_uch_t* str1, const mio_uch_t* str2, mio_oow_t maxlen, int ignorecase)
{
if (maxlen == 0) return 0;
if (ignorecase)
{
while (mio_to_uch_lower(*str1) == mio_to_uch_lower(*str2))
{
if (*str1 == '\0' || maxlen == 1) return 0;
str1++; str2++; maxlen--;
}
return ((mio_uchu_t)mio_to_uch_lower(*str1) > (mio_uchu_t)mio_to_uch_lower(*str2))? 1: -1;
}
else
{
while (*str1 == *str2)
{
if (*str1 == '\0' || maxlen == 1) return 0;
str1++; str2++; maxlen--;
}
return ((mio_uchu_t)*str1 > (mio_uchu_t)*str2)? 1: -1;
}
}
int mio_comp_bcstr_limited (const mio_bch_t* str1, const mio_bch_t* str2, mio_oow_t maxlen, int ignorecase)
{
if (maxlen == 0) return 0;
if (ignorecase)
{
while (mio_to_uch_lower(*str1) == mio_to_uch_lower(*str2))
{
if (*str1 == '\0' || maxlen == 1) return 0;
str1++; str2++; maxlen--;
}
return ((mio_bchu_t)mio_to_uch_lower(*str1) > (mio_bchu_t)mio_to_uch_lower(*str2))? 1: -1;
}
else
{
while (*str1 == *str2)
{
if (*str1 == '\0' || maxlen == 1) return 0;
str1++; str2++; maxlen--;
}
return ((mio_bchu_t)*str1 > (mio_bchu_t)*str2)? 1: -1;
}
}
int mio_comp_ucstr_bcstr (const mio_uch_t* str1, const mio_bch_t* str2, int ignorecase) int mio_comp_ucstr_bcstr (const mio_uch_t* str1, const mio_bch_t* str2, int ignorecase)
{ {
while (*str1 == *str2) while (*str1 == *str2)
@ -204,46 +256,114 @@ int mio_comp_uchars_ucstr (const mio_uch_t* str1, mio_oow_t len, const mio_uch_t
* of the first string is equal to the terminating null of * of the first string is equal to the terminating null of
* the second string. the first string is still considered * the second string. the first string is still considered
* bigger */ * bigger */
const mio_uch_t* end = str1 + len; if (ignorecase)
while (str1 < end && *str2 != '\0')
{ {
if (*str1 != *str2) return ((mio_uchu_t)*str1 > (mio_uchu_t)*str2)? 1: -1; const mio_uch_t* end = str1 + len;
str1++; str2++; while (str1 < end && *str2 != '\0')
{
if (*str1 != *str2) return ((mio_uchu_t)*str1 > (mio_uchu_t)*str2)? 1: -1;
str1++; str2++;
}
return (str1 < end)? 1: (*str2 == '\0'? 0: -1);
}
else
{
const mio_uch_t* end = str1 + len;
mio_uch_t c1;
mio_uch_t c2;
while (str1 < end && *str2 != '\0')
{
c1 = mio_to_uch_lower(*str1);
c2 = mio_to_uch_lower(*str2);
if (c1 != c2) return ((mio_uchu_t)c1 > (mio_uchu_t)c2)? 1: -1;
str1++; str2++;
}
return (str1 < end)? 1: (*str2 == '\0'? 0: -1);
} }
return (str1 < end)? 1: (*str2 == '\0'? 0: -1);
} }
int mio_comp_uchars_bcstr (const mio_uch_t* str1, mio_oow_t len, const mio_bch_t* str2, int ignorecase) int mio_comp_uchars_bcstr (const mio_uch_t* str1, mio_oow_t len, const mio_bch_t* str2, int ignorecase)
{ {
const mio_uch_t* end = str1 + len; if (ignorecase)
while (str1 < end && *str2 != '\0')
{ {
if (*str1 != *str2) return ((mio_uchu_t)*str1 > (mio_bchu_t)*str2)? 1: -1; const mio_uch_t* end = str1 + len;
str1++; str2++; while (str1 < end && *str2 != '\0')
{
if (*str1 != *str2) return ((mio_uchu_t)*str1 > (mio_bchu_t)*str2)? 1: -1;
str1++; str2++;
}
return (str1 < end)? 1: (*str2 == '\0'? 0: -1);
}
else
{
const mio_uch_t* end = str1 + len;
mio_uch_t c1;
mio_bch_t c2;
while (str1 < end && *str2 != '\0')
{
c1 = mio_to_uch_lower(*str1);
c2 = mio_to_bch_lower(*str2);
if (c1 != c2) return ((mio_uchu_t)c1 > (mio_bchu_t)c2)? 1: -1;
str1++; str2++;
}
return (str1 < end)? 1: (*str2 == '\0'? 0: -1);
} }
return (str1 < end)? 1: (*str2 == '\0'? 0: -1);
} }
int mio_comp_bchars_bcstr (const mio_bch_t* str1, mio_oow_t len, const mio_bch_t* str2, int ignorecase) int mio_comp_bchars_bcstr (const mio_bch_t* str1, mio_oow_t len, const mio_bch_t* str2, int ignorecase)
{ {
const mio_bch_t* end = str1 + len; if (ignorecase)
while (str1 < end && *str2 != '\0')
{ {
if (*str1 != *str2) return ((mio_bchu_t)*str1 > (mio_bchu_t)*str2)? 1: -1; const mio_bch_t* end = str1 + len;
str1++; str2++; while (str1 < end && *str2 != '\0')
{
if (*str1 != *str2) return ((mio_bchu_t)*str1 > (mio_bchu_t)*str2)? 1: -1;
str1++; str2++;
}
return (str1 < end)? 1: (*str2 == '\0'? 0: -1);
}
else
{
const mio_bch_t* end = str1 + len;
mio_bch_t c1;
mio_bch_t c2;
while (str1 < end && *str2 != '\0')
{
c1 = mio_to_bch_lower(*str1);
c2 = mio_to_bch_lower(*str2);
if (c1 != c2) return ((mio_bchu_t)c1 > (mio_bchu_t)c2)? 1: -1;
str1++; str2++;
}
return (str1 < end)? 1: (*str2 == '\0'? 0: -1);
} }
return (str1 < end)? 1: (*str2 == '\0'? 0: -1);
} }
int mio_comp_bchars_ucstr (const mio_bch_t* str1, mio_oow_t len, const mio_uch_t* str2, int ignorecase) int mio_comp_bchars_ucstr (const mio_bch_t* str1, mio_oow_t len, const mio_uch_t* str2, int ignorecase)
{ {
const mio_bch_t* end = str1 + len; if (ignorecase)
while (str1 < end && *str2 != '\0')
{ {
if (*str1 != *str2) return ((mio_bchu_t)*str1 > (mio_uchu_t)*str2)? 1: -1; const mio_bch_t* end = str1 + len;
str1++; str2++; while (str1 < end && *str2 != '\0')
{
if (*str1 != *str2) return ((mio_bchu_t)*str1 > (mio_uchu_t)*str2)? 1: -1;
str1++; str2++;
}
return (str1 < end)? 1: (*str2 == '\0'? 0: -1);
}
else
{
const mio_bch_t* end = str1 + len;
mio_bch_t c1;
mio_uch_t c2;
while (str1 < end && *str2 != '\0')
{
c1 = mio_to_bch_lower(*str1);
c2 = mio_to_uch_lower(*str2);
if (c1 != c2) return ((mio_bchu_t)c1 > (mio_uchu_t)c2)? 1: -1;
str1++; str2++;
}
return (str1 < end)? 1: (*str2 == '\0'? 0: -1);
} }
return (str1 < end)? 1: (*str2 == '\0'? 0: -1);
} }
/* ========================================================================= */ /* ========================================================================= */
@ -466,6 +586,57 @@ mio_bch_t* mio_find_bchar_in_bcstr (const mio_bch_t* ptr, mio_bch_t c)
return MIO_NULL; return MIO_NULL;
} }
#define IS_BCH_WORD_DELIM(x,delim) (mio_is_bch_space(x) || (x) == delim)
#define IS_UCH_WORD_DELIM(x,delim) (mio_is_uch_space(x) || (x) == delim)
const mio_bch_t* mio_find_bcstr_word_in_bcstr (const mio_bch_t* str, const mio_bch_t* word, mio_bch_t extra_delim, int ignorecase)
{
/* find a full word in a string */
const mio_bch_t* ptr = str;
if (extra_delim == '\0') extra_delim = ' ';
do
{
const mio_bch_t* s;
while (IS_BCH_WORD_DELIM(*ptr,extra_delim)) ptr++;
if (*ptr == '\0') return MIO_NULL;
s = ptr;
while (*ptr != '\0' && !IS_BCH_WORD_DELIM(*ptr,extra_delim)) ptr++;
if (mio_comp_bchars_bcstr(s, ptr - s, word, ignorecase) == 0) return s;
}
while (*ptr != '\0');
return MIO_NULL;
}
const mio_uch_t* mio_find_ucstr_word_in_ucstr (const mio_uch_t* str, const mio_uch_t* word, mio_uch_t extra_delim, int ignorecase)
{
/* find a full word in a string */
const mio_uch_t* ptr = str;
if (extra_delim == '\0') extra_delim = ' ';
do
{
const mio_uch_t* s;
while (IS_UCH_WORD_DELIM(*ptr,extra_delim)) ptr++;
if (*ptr == '\0') return MIO_NULL;
s = ptr;
while (*ptr != '\0' && !IS_UCH_WORD_DELIM(*ptr,extra_delim)) ptr++;
if (mio_comp_uchars_ucstr(s, ptr - s, word, ignorecase) == 0) return s;
}
while (*ptr != '\0');
return MIO_NULL;
}
/* ========================================================================= */ /* ========================================================================= */
#define IS_UCH_SPACE(x) ((x) ==' ' || (x) == '\t' || (x) == '\n' || (x) == '\r') #define IS_UCH_SPACE(x) ((x) ==' ' || (x) == '\t' || (x) == '\n' || (x) == '\r')
#define IS_BCH_SPACE(x) ((x) ==' ' || (x) == '\t' || (x) == '\n' || (x) == '\r') #define IS_BCH_SPACE(x) ((x) ==' ' || (x) == '\t' || (x) == '\n' || (x) == '\r')