reorganizing http functions
This commit is contained in:
@ -1,2 +1,2 @@
|
||||
SUBDIRS = cmn sed awk cut stx
|
||||
SUBDIRS = cmn sed awk cut stx net
|
||||
DIST_SUBDIRS = $(SUBDIRS)
|
||||
|
@ -225,7 +225,7 @@ target_alias = @target_alias@
|
||||
top_build_prefix = @top_build_prefix@
|
||||
top_builddir = @top_builddir@
|
||||
top_srcdir = @top_srcdir@
|
||||
SUBDIRS = cmn sed awk cut stx
|
||||
SUBDIRS = cmn sed awk cut stx net
|
||||
DIST_SUBDIRS = $(SUBDIRS)
|
||||
all: all-recursive
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* $Id: str_dynm.c 497 2011-06-20 14:56:40Z hyunghwan.chung $
|
||||
* $Id: str_dynm.c 501 2011-07-05 15:45:00Z hyunghwan.chung $
|
||||
*
|
||||
Copyright 2006-2011 Chung, Hyung-Hwan.
|
||||
This file is part of QSE.
|
||||
@ -249,7 +249,7 @@ qse_size_t qse_mbs_ncpy (qse_mbs_t* str, const qse_mchar_t* s, qse_size_t len)
|
||||
}
|
||||
|
||||
str->val.len = qse_mbsncpy (str->val.ptr, s, len);
|
||||
str->val.ptr[str->val.len] = QSE_MT('\0');
|
||||
/*str->val.ptr[str->val.len] = QSE_MT('\0'); -> mbsncpy does this*/
|
||||
return str->val.len;
|
||||
}
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* $Id: str_dynw.c 497 2011-06-20 14:56:40Z hyunghwan.chung $
|
||||
* $Id: str_dynw.c 501 2011-07-05 15:45:00Z hyunghwan.chung $
|
||||
*
|
||||
Copyright 2006-2011 Chung, Hyung-Hwan.
|
||||
This file is part of QSE.
|
||||
@ -249,7 +249,7 @@ qse_size_t qse_wcs_ncpy (qse_wcs_t* str, const qse_wchar_t* s, qse_size_t len)
|
||||
}
|
||||
|
||||
str->val.len = qse_wcsncpy (str->val.ptr, s, len);
|
||||
str->val.ptr[str->val.len] = QSE_WT('\0');
|
||||
/* str->val.ptr[str->val.len] = QSE_WT('\0'); -> wcsncpy does this */
|
||||
return str->val.len;
|
||||
}
|
||||
|
||||
|
@ -1,14 +0,0 @@
|
||||
AUTOMAKE_OPTIONS = nostdinc
|
||||
|
||||
AM_CPPFLAGS = \
|
||||
-I$(top_builddir)/include \
|
||||
-I$(top_srcdir)/include \
|
||||
-I$(includedir)
|
||||
|
||||
lib_LTLIBRARIES = libqsehttp.la
|
||||
libqsehttp_la_SOURCES = \
|
||||
htre.c \
|
||||
http.c
|
||||
|
||||
libqsehttp_la_LDFLAGS = -version-info 1:0:0 -no-undefined -L../cmn -L$(libdir)
|
||||
libqsehttp_la_LIBADD = -lqsecmn
|
@ -1,99 +0,0 @@
|
||||
/*
|
||||
* $Id$
|
||||
*/
|
||||
#include <qse/http/htre.h>
|
||||
#include "../cmn/mem.h"
|
||||
|
||||
qse_htre_t* qse_htre_init (qse_htre_t* re, qse_mmgr_t* mmgr)
|
||||
{
|
||||
QSE_MEMSET (re, 0, QSE_SIZEOF(*re));
|
||||
re->mmgr = mmgr;
|
||||
|
||||
if (qse_htb_init (&re->hdrtab, mmgr, 60, 70, 1, 1) == QSE_NULL)
|
||||
{
|
||||
return QSE_NULL;
|
||||
}
|
||||
|
||||
if (qse_mbs_init (&re->content, mmgr, 0) == QSE_NULL)
|
||||
{
|
||||
return QSE_NULL;
|
||||
}
|
||||
|
||||
return re;
|
||||
}
|
||||
|
||||
void qse_htre_fini (qse_htre_t* re)
|
||||
{
|
||||
qse_mbs_fini (&re->content);
|
||||
qse_htb_fini (&re->hdrtab);
|
||||
}
|
||||
|
||||
void qse_htre_clear (qse_htre_t* re)
|
||||
{
|
||||
QSE_MEMSET (&re->version, 0, QSE_SIZEOF(re->version));
|
||||
QSE_MEMSET (&re->re, 0, QSE_SIZEOF(re->re));
|
||||
QSE_MEMSET (&re->attr, 0, QSE_SIZEOF(re->attr));
|
||||
|
||||
qse_htb_clear (&re->hdrtab);
|
||||
qse_mbs_clear (&re->content);
|
||||
|
||||
re->discard = 0;
|
||||
}
|
||||
|
||||
static QSE_INLINE int xdigit_to_num (qse_htoc_t c)
|
||||
{
|
||||
if (c >= '0' && c <= '9') return c - '0';
|
||||
if (c >= 'A' && c <= 'Z') return c - 'A' + 10;
|
||||
if (c >= 'a' && c <= 'z') return c - 'a' + 10;
|
||||
return -1;
|
||||
}
|
||||
|
||||
int qse_htre_decodereqpath (qse_htre_t* re, int )
|
||||
{
|
||||
qse_htoc_t* p = re->re.quest.path.ptr;
|
||||
qse_htoc_t* tmp = re->re.quest.path.ptr;
|
||||
|
||||
while (*p != '\0')
|
||||
{
|
||||
if (*p == '%')
|
||||
{
|
||||
int q = xdigit_to_num(*(p+1));
|
||||
int w = xdigit_to_num(*(p+2));
|
||||
|
||||
if (q >= 0 && w >= 0)
|
||||
{
|
||||
int t = (q << 4) + w;
|
||||
if (t == 0)
|
||||
{
|
||||
/* percent enconding contains a null character */
|
||||
return -1;
|
||||
}
|
||||
|
||||
*tmp++ = t;
|
||||
p += 3;
|
||||
}
|
||||
else *tmp++ = *p++;
|
||||
}
|
||||
else if (*p == '?')
|
||||
{
|
||||
#if 0
|
||||
if (!http->re.re.quest.args.ptr)
|
||||
{
|
||||
/* ? must be explicit to be a argument instroducer.
|
||||
* %3f is just a literal. */
|
||||
http->re.re.quest.path.len = tmp - http->re.re.quest.path.ptr;
|
||||
*tmp++ = '\0';
|
||||
http->re.re.quest.args.ptr = tmp;
|
||||
p++;
|
||||
}
|
||||
else *tmp++ = *p++;
|
||||
#endif
|
||||
}
|
||||
else *tmp++ = *p++;
|
||||
}
|
||||
*tmp = '\0';
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
15
qse/lib/net/Makefile.am
Normal file
15
qse/lib/net/Makefile.am
Normal file
@ -0,0 +1,15 @@
|
||||
AUTOMAKE_OPTIONS = nostdinc
|
||||
|
||||
AM_CPPFLAGS = \
|
||||
-I$(top_builddir)/include \
|
||||
-I$(top_srcdir)/include \
|
||||
-I$(includedir)
|
||||
|
||||
lib_LTLIBRARIES = libqsenet.la
|
||||
libqsenet_la_SOURCES = \
|
||||
http.c \
|
||||
htre.c \
|
||||
htrd.c
|
||||
|
||||
libqsenet_la_LDFLAGS = -version-info 1:0:0 -no-undefined -L../cmn -L$(libdir)
|
||||
libqsenet_la_LIBADD = -lqsecmn
|
@ -34,7 +34,7 @@ PRE_UNINSTALL = :
|
||||
POST_UNINSTALL = :
|
||||
build_triplet = @build@
|
||||
host_triplet = @host@
|
||||
subdir = lib/http
|
||||
subdir = lib/net
|
||||
DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
|
||||
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
|
||||
am__aclocal_m4_deps = $(top_srcdir)/m4/libtool.m4 \
|
||||
@ -70,12 +70,12 @@ am__base_list = \
|
||||
sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g'
|
||||
am__installdirs = "$(DESTDIR)$(libdir)"
|
||||
LTLIBRARIES = $(lib_LTLIBRARIES)
|
||||
libqsehttp_la_DEPENDENCIES =
|
||||
am_libqsehttp_la_OBJECTS = htre.lo http.lo
|
||||
libqsehttp_la_OBJECTS = $(am_libqsehttp_la_OBJECTS)
|
||||
libqsehttp_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \
|
||||
libqsenet_la_DEPENDENCIES =
|
||||
am_libqsenet_la_OBJECTS = http.lo htre.lo htrd.lo
|
||||
libqsenet_la_OBJECTS = $(am_libqsenet_la_OBJECTS)
|
||||
libqsenet_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \
|
||||
$(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
|
||||
$(libqsehttp_la_LDFLAGS) $(LDFLAGS) -o $@
|
||||
$(libqsenet_la_LDFLAGS) $(LDFLAGS) -o $@
|
||||
DEFAULT_INCLUDES =
|
||||
depcomp = $(SHELL) $(top_srcdir)/ac/depcomp
|
||||
am__depfiles_maybe = depfiles
|
||||
@ -89,8 +89,8 @@ CCLD = $(CC)
|
||||
LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
|
||||
--mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \
|
||||
$(LDFLAGS) -o $@
|
||||
SOURCES = $(libqsehttp_la_SOURCES)
|
||||
DIST_SOURCES = $(libqsehttp_la_SOURCES)
|
||||
SOURCES = $(libqsenet_la_SOURCES)
|
||||
DIST_SOURCES = $(libqsenet_la_SOURCES)
|
||||
ETAGS = etags
|
||||
CTAGS = ctags
|
||||
DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
|
||||
@ -237,13 +237,14 @@ AM_CPPFLAGS = \
|
||||
-I$(top_srcdir)/include \
|
||||
-I$(includedir)
|
||||
|
||||
lib_LTLIBRARIES = libqsehttp.la
|
||||
libqsehttp_la_SOURCES = \
|
||||
lib_LTLIBRARIES = libqsenet.la
|
||||
libqsenet_la_SOURCES = \
|
||||
http.c \
|
||||
htre.c \
|
||||
http.c
|
||||
htrd.c
|
||||
|
||||
libqsehttp_la_LDFLAGS = -version-info 1:0:0 -no-undefined -L../cmn -L$(libdir)
|
||||
libqsehttp_la_LIBADD = -lqsecmn
|
||||
libqsenet_la_LDFLAGS = -version-info 1:0:0 -no-undefined -L../cmn -L$(libdir)
|
||||
libqsenet_la_LIBADD = -lqsecmn
|
||||
all: all-am
|
||||
|
||||
.SUFFIXES:
|
||||
@ -257,9 +258,9 @@ $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
|
||||
exit 1;; \
|
||||
esac; \
|
||||
done; \
|
||||
echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign lib/http/Makefile'; \
|
||||
echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign lib/net/Makefile'; \
|
||||
$(am__cd) $(top_srcdir) && \
|
||||
$(AUTOMAKE) --foreign lib/http/Makefile
|
||||
$(AUTOMAKE) --foreign lib/net/Makefile
|
||||
.PRECIOUS: Makefile
|
||||
Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
|
||||
@case '$?' in \
|
||||
@ -309,8 +310,8 @@ clean-libLTLIBRARIES:
|
||||
echo "rm -f \"$${dir}/so_locations\""; \
|
||||
rm -f "$${dir}/so_locations"; \
|
||||
done
|
||||
libqsehttp.la: $(libqsehttp_la_OBJECTS) $(libqsehttp_la_DEPENDENCIES)
|
||||
$(libqsehttp_la_LINK) -rpath $(libdir) $(libqsehttp_la_OBJECTS) $(libqsehttp_la_LIBADD) $(LIBS)
|
||||
libqsenet.la: $(libqsenet_la_OBJECTS) $(libqsenet_la_DEPENDENCIES)
|
||||
$(libqsenet_la_LINK) -rpath $(libdir) $(libqsenet_la_OBJECTS) $(libqsenet_la_LIBADD) $(LIBS)
|
||||
|
||||
mostlyclean-compile:
|
||||
-rm -f *.$(OBJEXT)
|
||||
@ -318,6 +319,7 @@ mostlyclean-compile:
|
||||
distclean-compile:
|
||||
-rm -f *.tab.c
|
||||
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/htrd.Plo@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/htre.Plo@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/http.Plo@am__quote@
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* $Id: http.c 341 2008-08-20 10:58:19Z baconevi $
|
||||
* $Id: htrd.c 341 2008-08-20 10:58:19Z baconevi $
|
||||
*
|
||||
Copyright 2006-2011 Chung, Hyung-Hwan.
|
||||
This file is part of QSE.
|
||||
@ -18,11 +18,11 @@
|
||||
License along with QSE. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <qse/http/http.h>
|
||||
#include <qse/net/htrd.h>
|
||||
#include <qse/cmn/chr.h>
|
||||
#include "../cmn/mem.h"
|
||||
|
||||
QSE_IMPLEMENT_COMMON_FUNCTIONS (http)
|
||||
QSE_IMPLEMENT_COMMON_FUNCTIONS (htrd)
|
||||
|
||||
static const qse_htoc_t NUL = '\0';
|
||||
|
||||
@ -84,12 +84,12 @@ static QSE_INLINE int xdigit_to_num (qse_htoc_t c)
|
||||
}
|
||||
|
||||
static QSE_INLINE int push_to_buffer (
|
||||
qse_http_t* http, qse_htob_t* octb,
|
||||
qse_htrd_t* http, qse_htob_t* octb,
|
||||
const qse_htoc_t* ptr, qse_size_t len)
|
||||
{
|
||||
if (qse_mbs_ncat (octb, ptr, len) == (qse_size_t)-1)
|
||||
{
|
||||
http->errnum = QSE_HTTP_ENOMEM;
|
||||
http->errnum = QSE_HTRD_ENOMEM;
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
@ -100,7 +100,7 @@ struct hdr_cmb_t
|
||||
struct hdr_cmb_t* next;
|
||||
};
|
||||
|
||||
static QSE_INLINE void clear_combined_headers (qse_http_t* http)
|
||||
static QSE_INLINE void clear_combined_headers (qse_htrd_t* http)
|
||||
{
|
||||
struct hdr_cmb_t* cmb = (struct hdr_cmb_t*)http->fed.chl;
|
||||
|
||||
@ -114,7 +114,7 @@ static QSE_INLINE void clear_combined_headers (qse_http_t* http)
|
||||
http->fed.chl = QSE_NULL;
|
||||
}
|
||||
|
||||
static QSE_INLINE void clear_feed (qse_http_t* http)
|
||||
static QSE_INLINE void clear_feed (qse_htrd_t* http)
|
||||
{
|
||||
/* clear necessary part of the request/response before
|
||||
* reading the next request/response */
|
||||
@ -127,13 +127,13 @@ static QSE_INLINE void clear_feed (qse_http_t* http)
|
||||
QSE_MEMSET (&http->fed.s, 0, QSE_SIZEOF(http->fed.s));
|
||||
}
|
||||
|
||||
#define QSE_HTTP_STATE_REQ 1
|
||||
#define QSE_HTTP_STATE_HDR 2
|
||||
#define QSE_HTTP_STATE_POST 3
|
||||
#define QSE_HTRD_STATE_REQ 1
|
||||
#define QSE_HTRD_STATE_HDR 2
|
||||
#define QSE_HTRD_STATE_POST 3
|
||||
|
||||
qse_http_t* qse_http_open (qse_mmgr_t* mmgr, qse_size_t xtnsize)
|
||||
qse_htrd_t* qse_htrd_open (qse_mmgr_t* mmgr, qse_size_t xtnsize)
|
||||
{
|
||||
qse_http_t* http;
|
||||
qse_htrd_t* http;
|
||||
|
||||
if (mmgr == QSE_NULL)
|
||||
{
|
||||
@ -145,12 +145,12 @@ qse_http_t* qse_http_open (qse_mmgr_t* mmgr, qse_size_t xtnsize)
|
||||
if (mmgr == QSE_NULL) return QSE_NULL;
|
||||
}
|
||||
|
||||
http = (qse_http_t*) QSE_MMGR_ALLOC (
|
||||
mmgr, QSE_SIZEOF(qse_http_t) + xtnsize
|
||||
http = (qse_htrd_t*) QSE_MMGR_ALLOC (
|
||||
mmgr, QSE_SIZEOF(qse_htrd_t) + xtnsize
|
||||
);
|
||||
if (http == QSE_NULL) return QSE_NULL;
|
||||
|
||||
if (qse_http_init (http, mmgr) == QSE_NULL)
|
||||
if (qse_htrd_init (http, mmgr) == QSE_NULL)
|
||||
{
|
||||
QSE_MMGR_FREE (http->mmgr, http);
|
||||
return QSE_NULL;
|
||||
@ -159,13 +159,13 @@ qse_http_t* qse_http_open (qse_mmgr_t* mmgr, qse_size_t xtnsize)
|
||||
return http;
|
||||
}
|
||||
|
||||
void qse_http_close (qse_http_t* http)
|
||||
void qse_htrd_close (qse_htrd_t* http)
|
||||
{
|
||||
qse_http_fini (http);
|
||||
qse_htrd_fini (http);
|
||||
QSE_MMGR_FREE (http->mmgr, http);
|
||||
}
|
||||
|
||||
qse_http_t* qse_http_init (qse_http_t* http, qse_mmgr_t* mmgr)
|
||||
qse_htrd_t* qse_htrd_init (qse_htrd_t* http, qse_mmgr_t* mmgr)
|
||||
{
|
||||
if (mmgr == QSE_NULL) mmgr = QSE_MMGR_GETDFL();
|
||||
|
||||
@ -174,11 +174,9 @@ qse_http_t* qse_http_init (qse_http_t* http, qse_mmgr_t* mmgr)
|
||||
|
||||
qse_mbs_init (&http->fed.b.raw, http->mmgr, 0);
|
||||
qse_mbs_init (&http->fed.b.tra, http->mmgr, 0);
|
||||
qse_mbs_init (&http->fed.b.pen, http->mmgr, 0);
|
||||
|
||||
if (qse_htre_init (&http->re, mmgr) == QSE_NULL)
|
||||
{
|
||||
qse_mbs_fini (&http->fed.b.pen);
|
||||
qse_mbs_fini (&http->fed.b.tra);
|
||||
qse_mbs_fini (&http->fed.b.raw);
|
||||
return QSE_NULL;
|
||||
@ -187,22 +185,21 @@ qse_http_t* qse_http_init (qse_http_t* http, qse_mmgr_t* mmgr)
|
||||
return http;
|
||||
}
|
||||
|
||||
void qse_http_fini (qse_http_t* http)
|
||||
void qse_htrd_fini (qse_htrd_t* http)
|
||||
{
|
||||
qse_htre_fini (&http->re);
|
||||
|
||||
clear_combined_headers (http);
|
||||
qse_mbs_fini (&http->fed.b.pen);
|
||||
qse_mbs_fini (&http->fed.b.tra);
|
||||
qse_mbs_fini (&http->fed.b.raw);
|
||||
}
|
||||
|
||||
static qse_htoc_t* parse_initial_line (
|
||||
qse_http_t* http, qse_htoc_t* line)
|
||||
qse_htrd_t* http, qse_htoc_t* line)
|
||||
{
|
||||
qse_htoc_t* p = line;
|
||||
qse_htoc_t* tmp;
|
||||
qse_size_t tmplen;
|
||||
qse_htos_t tmp;
|
||||
qse_http_method_t mtype;
|
||||
|
||||
#if 0
|
||||
/* ignore leading spaces excluding crlf */
|
||||
@ -213,88 +210,25 @@ static qse_htoc_t* parse_initial_line (
|
||||
if (!is_upalpha_octet(*p)) goto badre;
|
||||
|
||||
/* get the method name */
|
||||
tmp = p;
|
||||
tmp.ptr = p;
|
||||
do { p++; } while (is_upalpha_octet(*p));
|
||||
tmplen = p - tmp;
|
||||
tmp.len = p - tmp.ptr;
|
||||
|
||||
http->retype = QSE_HTTP_RETYPE_Q;
|
||||
|
||||
/* test the method name */
|
||||
switch (tmplen)
|
||||
http->retype = QSE_HTRD_RETYPE_Q;
|
||||
if (qse_gethttpmethodtypefromstr (&tmp, &mtype) >= 0)
|
||||
{
|
||||
case 3:
|
||||
/* GET, PUT */
|
||||
if (tmp[0] == 'G' && tmp[1] == 'E' && tmp[2] == 'T')
|
||||
{
|
||||
http->re.re.quest.method = QSE_HTTP_REQ_GET;
|
||||
break;
|
||||
}
|
||||
else if (tmp[0] == 'P' && tmp[1] == 'U' && tmp[2] == 'T')
|
||||
{
|
||||
http->re.re.quest.method = QSE_HTTP_REQ_PUT;
|
||||
break;
|
||||
}
|
||||
goto badre;
|
||||
|
||||
case 4:
|
||||
/* POST, HEAD */
|
||||
if (tmp[0] == 'P' && tmp[1] == 'O' && tmp[2] == 'S' && tmp[3] == 'T')
|
||||
{
|
||||
http->re.re.quest.method = QSE_HTTP_REQ_POST;
|
||||
break;
|
||||
}
|
||||
else if (tmp[0] == 'H' && tmp[1] == 'E' && tmp[2] == 'A' && tmp[3] == 'D')
|
||||
{
|
||||
http->re.re.quest.method = QSE_HTTP_REQ_HEAD;
|
||||
break;
|
||||
}
|
||||
else if (tmp[0] == 'H' && tmp[1] == 'T' && tmp[2] == 'T' && tmp[3] == 'P')
|
||||
{
|
||||
http->retype = QSE_HTTP_RETYPE_S;
|
||||
break;
|
||||
}
|
||||
/* TODO: more methods */
|
||||
goto badre;
|
||||
|
||||
case 5:
|
||||
/* TRACE */
|
||||
if (tmp[0] == 'T' && tmp[1] == 'R' && tmp[2] == 'A' && tmp[3] == 'C' && tmp[4] == 'E')
|
||||
{
|
||||
http->re.re.quest.method = QSE_HTTP_REQ_TRACE;
|
||||
break;
|
||||
}
|
||||
goto badre;
|
||||
|
||||
case 6:
|
||||
/* DELETE */
|
||||
if (tmp[0] == 'D' && tmp[1] == 'E' && tmp[2] == 'L' && tmp[3] == 'E' && tmp[4] == 'T' && tmp[5] == 'E')
|
||||
{
|
||||
http->re.re.quest.method = QSE_HTTP_REQ_DELETE;
|
||||
break;
|
||||
}
|
||||
goto badre;
|
||||
|
||||
case 7:
|
||||
/* OPTIONS, CONNECT */
|
||||
if (tmp[0] == 'O' && tmp[1] == 'P' && tmp[2] == 'T' && tmp[3] == 'I' && tmp[4] == 'O' && tmp[5] == 'N' && tmp[6] == 'S')
|
||||
{
|
||||
http->re.re.quest.method = QSE_HTTP_REQ_OPTIONS;
|
||||
break;
|
||||
}
|
||||
else if (tmp[0] == 'C' && tmp[1] == 'O' && tmp[2] == 'N' && tmp[3] == 'N' && tmp[4] == 'E' && tmp[5] == 'C' && tmp[6] == 'T')
|
||||
{
|
||||
http->re.re.quest.method = QSE_HTTP_REQ_OPTIONS;
|
||||
break;
|
||||
}
|
||||
goto badre;
|
||||
|
||||
default:
|
||||
goto badre;
|
||||
qse_htre_setqmethod (&http->re, mtype);
|
||||
}
|
||||
|
||||
if (http->retype == QSE_HTTP_RETYPE_S)
|
||||
else if (qse_mbsxcmp (tmp.ptr, tmp.len, "HTTP") == 0)
|
||||
{
|
||||
int n;
|
||||
/* it begins with HTTP. it may be a response */
|
||||
http->retype = QSE_HTRD_RETYPE_S;
|
||||
}
|
||||
else goto badre;
|
||||
|
||||
if (http->retype == QSE_HTRD_RETYPE_S)
|
||||
{
|
||||
int n, status;
|
||||
|
||||
if (*p == '/' && p[1] != '\0' && p[2] == '.')
|
||||
{
|
||||
@ -319,21 +253,27 @@ static qse_htoc_t* parse_initial_line (
|
||||
n = digit_to_num(*p);
|
||||
if (n <= -1) goto badre;
|
||||
|
||||
status = 0;
|
||||
do
|
||||
{
|
||||
http->re.re.sponse.code = http->re.re.sponse.code * 10 + n;
|
||||
status = status * 10 + n;
|
||||
p++;
|
||||
}
|
||||
while ((n = digit_to_num(*p)) >= 0);
|
||||
|
||||
/* status code must be followed by space */
|
||||
if (!is_space_octet(*p)) goto badre;
|
||||
|
||||
qse_htre_setsstatus (&http->re, status);
|
||||
|
||||
/* skip spaces */
|
||||
do p++; while (is_space_octet(*p));
|
||||
|
||||
http->re.re.sponse.message.ptr = p;
|
||||
tmp.ptr = p;
|
||||
while (*p != '\0' && *p != '\n') p++;
|
||||
http->re.re.sponse.message.len = p - http->re.re.sponse.message.ptr;
|
||||
tmp.len = p - tmp.ptr;
|
||||
|
||||
if (qse_htre_setsmessage (&http->re, &tmp) <= -1) goto outofmem;
|
||||
|
||||
/* adjust Connection: close for HTTP 1.0 or eariler */
|
||||
if (http->re.version.major < 1 ||
|
||||
@ -344,6 +284,9 @@ static qse_htoc_t* parse_initial_line (
|
||||
}
|
||||
else
|
||||
{
|
||||
qse_htoc_t* out;
|
||||
qse_htos_t param;
|
||||
|
||||
/* method name must be followed by space */
|
||||
if (!is_space_octet(*p)) goto badre;
|
||||
|
||||
@ -351,12 +294,10 @@ static qse_htoc_t* parse_initial_line (
|
||||
do p++; while (is_space_octet(*p));
|
||||
|
||||
/* process the url part */
|
||||
http->re.re.quest.path.ptr = p;
|
||||
#if 0
|
||||
http->re.re.quest.args.ptr = QSE_NULL;
|
||||
#endif
|
||||
tmp.ptr = p; /* remember the beginning of path*/
|
||||
param.ptr = QSE_NULL;
|
||||
|
||||
tmp = p;
|
||||
out = p;
|
||||
while (*p != '\0' && !is_space_octet(*p))
|
||||
{
|
||||
if (*p == '%')
|
||||
@ -373,41 +314,42 @@ static qse_htoc_t* parse_initial_line (
|
||||
goto badre;
|
||||
}
|
||||
|
||||
*tmp++ = t;
|
||||
*out++ = t;
|
||||
p += 3;
|
||||
}
|
||||
else *tmp++ = *p++;
|
||||
else *out++ = *p++;
|
||||
}
|
||||
#if 0
|
||||
else if (*p == '?')
|
||||
{
|
||||
if (!http->re.re.quest.args.ptr)
|
||||
if (!param.ptr)
|
||||
{
|
||||
/* ? must be explicit to be a argument instroducer.
|
||||
* %3f is just a literal. */
|
||||
http->re.re.quest.path.len = tmp - http->re.re.quest.path.ptr;
|
||||
*tmp++ = '\0';
|
||||
http->re.re.quest.args.ptr = tmp;
|
||||
tmp.len = out - tmp.ptr;
|
||||
*out++ = '\0'; /* null-terminate the path part */
|
||||
param.ptr = out;
|
||||
p++;
|
||||
}
|
||||
else *tmp++ = *p++;
|
||||
else *out++ = *p++;
|
||||
}
|
||||
#endif
|
||||
else *tmp++ = *p++;
|
||||
else *out++ = *p++;
|
||||
}
|
||||
|
||||
/* the url must be followed by a space */
|
||||
if (!is_space_octet(*p)) goto badre;
|
||||
|
||||
#if 0
|
||||
if (http->re.re.quest.args.ptr)
|
||||
http->re.re.quest.args.len = tmp - http->re.re.quest.args.ptr;
|
||||
else
|
||||
#endif
|
||||
http->re.re.quest.path.len = tmp - http->re.re.quest.path.ptr;
|
||||
/* null-terminate the url part though we record the length */
|
||||
*tmp = '\0';
|
||||
|
||||
/* null-terminate the url part though we know the length */
|
||||
*out = '\0';
|
||||
|
||||
if (param.ptr)
|
||||
{
|
||||
param.len = out - param.ptr;
|
||||
if (qse_htre_setqparamstr (&http->re, param.ptr) <= -1) goto outofmem;
|
||||
}
|
||||
else tmp.len = out - tmp.ptr;
|
||||
|
||||
if (qse_htre_setqpath (&http->re, &tmp) <= -1) goto outofmem;
|
||||
|
||||
/* skip spaces after the url part */
|
||||
do { p++; } while (is_space_octet(*p));
|
||||
|
||||
@ -447,31 +389,36 @@ static qse_htoc_t* parse_initial_line (
|
||||
return ++p;
|
||||
|
||||
badre:
|
||||
http->errnum = QSE_HTTP_EBADRE;
|
||||
http->errnum = QSE_HTRD_EBADRE;
|
||||
return QSE_NULL;
|
||||
|
||||
outofmem:
|
||||
http->errnum = QSE_HTRD_ENOMEM;
|
||||
return QSE_NULL;
|
||||
|
||||
}
|
||||
|
||||
void qse_http_clear (qse_http_t* http)
|
||||
void qse_htrd_clear (qse_htrd_t* http)
|
||||
{
|
||||
clear_feed (http);
|
||||
}
|
||||
|
||||
int qse_http_getoption (qse_http_t* http)
|
||||
int qse_htrd_getoption (qse_htrd_t* http)
|
||||
{
|
||||
return http->option;
|
||||
}
|
||||
|
||||
void qse_http_setoption (qse_http_t* http, int opts)
|
||||
void qse_htrd_setoption (qse_htrd_t* http, int opts)
|
||||
{
|
||||
http->option = opts;
|
||||
}
|
||||
|
||||
const qse_http_recbs_t* qse_http_getrecbs (qse_http_t* http)
|
||||
const qse_htrd_recbs_t* qse_htrd_getrecbs (qse_htrd_t* http)
|
||||
{
|
||||
return &http->recbs;
|
||||
}
|
||||
|
||||
void qse_http_setrecbs (qse_http_t* http, const qse_http_recbs_t* recbs)
|
||||
void qse_htrd_setrecbs (qse_htrd_t* http, const qse_htrd_recbs_t* recbs)
|
||||
{
|
||||
http->recbs = *recbs;
|
||||
}
|
||||
@ -504,7 +451,7 @@ static QSE_INLINE int compare_octets (
|
||||
}
|
||||
|
||||
static QSE_INLINE int capture_connection (
|
||||
qse_http_t* http, qse_htb_pair_t* pair)
|
||||
qse_htrd_t* http, qse_htb_pair_t* pair)
|
||||
{
|
||||
int n;
|
||||
|
||||
@ -527,7 +474,7 @@ static QSE_INLINE int capture_connection (
|
||||
}
|
||||
|
||||
static QSE_INLINE int capture_content_length (
|
||||
qse_http_t* http, qse_htb_pair_t* pair)
|
||||
qse_htrd_t* http, qse_htb_pair_t* pair)
|
||||
{
|
||||
qse_size_t len = 0, off = 0, tmp;
|
||||
const qse_htoc_t* ptr = QSE_HTB_VPTR(pair);
|
||||
@ -538,7 +485,7 @@ static QSE_INLINE int capture_content_length (
|
||||
if (num <= -1)
|
||||
{
|
||||
/* the length contains a non-digit */
|
||||
http->errnum = QSE_HTTP_EBADRE;
|
||||
http->errnum = QSE_HTRD_EBADRE;
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -546,7 +493,7 @@ static QSE_INLINE int capture_content_length (
|
||||
if (tmp < len)
|
||||
{
|
||||
/* the length has overflown */
|
||||
http->errnum = QSE_HTTP_EBADRE;
|
||||
http->errnum = QSE_HTRD_EBADRE;
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -557,7 +504,7 @@ static QSE_INLINE int capture_content_length (
|
||||
if (off == 0)
|
||||
{
|
||||
/* no length was provided */
|
||||
http->errnum = QSE_HTTP_EBADRE;
|
||||
http->errnum = QSE_HTRD_EBADRE;
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -565,7 +512,7 @@ static QSE_INLINE int capture_content_length (
|
||||
{
|
||||
/* content-length is greater than 0
|
||||
* while transfer-encoding: chunked is specified. */
|
||||
http->errnum = QSE_HTTP_EBADRE;
|
||||
http->errnum = QSE_HTRD_EBADRE;
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -573,16 +520,8 @@ static QSE_INLINE int capture_content_length (
|
||||
return 0;
|
||||
}
|
||||
|
||||
static QSE_INLINE int capture_content_type (
|
||||
qse_http_t* http, qse_htb_pair_t* pair)
|
||||
{
|
||||
http->re.attr.content_type.ptr = QSE_HTB_VPTR(pair);
|
||||
http->re.attr.content_type.len = QSE_HTB_VLEN(pair);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static QSE_INLINE int capture_expect (
|
||||
qse_http_t* http, qse_htb_pair_t* pair)
|
||||
qse_htrd_t* http, qse_htb_pair_t* pair)
|
||||
{
|
||||
int n;
|
||||
|
||||
@ -598,16 +537,8 @@ static QSE_INLINE int capture_expect (
|
||||
return 0;
|
||||
}
|
||||
|
||||
static QSE_INLINE int capture_host (
|
||||
qse_http_t* http, qse_htb_pair_t* pair)
|
||||
{
|
||||
http->re.attr.host.ptr = QSE_HTB_VPTR(pair);
|
||||
http->re.attr.host.len = QSE_HTB_VLEN(pair);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static QSE_INLINE int capture_transfer_encoding (
|
||||
qse_http_t* http, qse_htb_pair_t* pair)
|
||||
qse_htrd_t* http, qse_htb_pair_t* pair)
|
||||
{
|
||||
int n;
|
||||
|
||||
@ -627,25 +558,23 @@ static QSE_INLINE int capture_transfer_encoding (
|
||||
|
||||
/* other encoding type not supported yet */
|
||||
badre:
|
||||
http->errnum = QSE_HTTP_EBADRE;
|
||||
http->errnum = QSE_HTRD_EBADRE;
|
||||
return -1;
|
||||
}
|
||||
|
||||
static QSE_INLINE int capture_key_header (
|
||||
qse_http_t* http, qse_htb_pair_t* pair)
|
||||
qse_htrd_t* http, qse_htb_pair_t* pair)
|
||||
{
|
||||
static struct
|
||||
{
|
||||
const qse_htoc_t* ptr;
|
||||
qse_size_t len;
|
||||
int (*handler) (qse_http_t*, qse_htb_pair_t*);
|
||||
int (*handler) (qse_htrd_t*, qse_htb_pair_t*);
|
||||
} hdrtab[] =
|
||||
{
|
||||
{ "Connection", 10, capture_connection },
|
||||
{ "Content-Length", 14, capture_content_length },
|
||||
{ "Content-Type", 12, capture_content_type },
|
||||
{ "Expect", 6, capture_expect },
|
||||
{ "Host", 4, capture_host },
|
||||
{ "Transfer-Encoding", 17, capture_transfer_encoding }
|
||||
};
|
||||
|
||||
@ -677,7 +606,7 @@ static QSE_INLINE int capture_key_header (
|
||||
|
||||
struct hdr_cbserter_ctx_t
|
||||
{
|
||||
qse_http_t* http;
|
||||
qse_htrd_t* http;
|
||||
void* vptr;
|
||||
qse_size_t vlen;
|
||||
};
|
||||
@ -695,7 +624,7 @@ static qse_htb_pair_t* hdr_cbserter (
|
||||
|
||||
p = qse_htb_allocpair (htb, kptr, klen, tx->vptr, tx->vlen);
|
||||
|
||||
if (p == QSE_NULL) tx->http->errnum = QSE_HTTP_ENOMEM;
|
||||
if (p == QSE_NULL) tx->http->errnum = QSE_HTRD_ENOMEM;
|
||||
else
|
||||
{
|
||||
if (capture_key_header (tx->http, p) <= -1)
|
||||
@ -736,7 +665,7 @@ static qse_htb_pair_t* hdr_cbserter (
|
||||
);
|
||||
if (cmb == QSE_NULL)
|
||||
{
|
||||
tx->http->errnum = QSE_HTTP_ENOMEM;
|
||||
tx->http->errnum = QSE_HTRD_ENOMEM;
|
||||
return QSE_NULL;
|
||||
}
|
||||
|
||||
@ -785,7 +714,7 @@ Change it to doubly linked for this?
|
||||
}
|
||||
}
|
||||
|
||||
qse_htoc_t* parse_header_fields (qse_http_t* http, qse_htoc_t* line)
|
||||
qse_htoc_t* parse_header_fields (qse_htrd_t* http, qse_htoc_t* line)
|
||||
{
|
||||
qse_htoc_t* p = line, * last;
|
||||
struct
|
||||
@ -859,13 +788,13 @@ qse_htoc_t* parse_header_fields (qse_http_t* http, qse_htoc_t* line)
|
||||
ctx.vptr = value.ptr;
|
||||
ctx.vlen = value.len;
|
||||
|
||||
http->errnum = QSE_HTTP_ENOERR;
|
||||
http->errnum = QSE_HTRD_ENOERR;
|
||||
if (qse_htb_cbsert (
|
||||
&http->re.hdrtab, name.ptr, name.len,
|
||||
hdr_cbserter, &ctx) == QSE_NULL)
|
||||
{
|
||||
if (http->errnum == QSE_HTTP_ENOERR)
|
||||
http->errnum = QSE_HTTP_ENOMEM;
|
||||
if (http->errnum == QSE_HTRD_ENOERR)
|
||||
http->errnum = QSE_HTRD_ENOMEM;
|
||||
return QSE_NULL;
|
||||
}
|
||||
}
|
||||
@ -873,12 +802,12 @@ qse_htoc_t* parse_header_fields (qse_http_t* http, qse_htoc_t* line)
|
||||
return p;
|
||||
|
||||
badhdr:
|
||||
http->errnum = QSE_HTTP_EBADHDR;
|
||||
http->errnum = QSE_HTRD_EBADHDR;
|
||||
return QSE_NULL;
|
||||
}
|
||||
|
||||
static QSE_INLINE int parse_initial_line_and_headers (
|
||||
qse_http_t* http, const qse_htoc_t* req, qse_size_t rlen)
|
||||
qse_htrd_t* http, const qse_htoc_t* req, qse_size_t rlen)
|
||||
{
|
||||
qse_htoc_t* p;
|
||||
|
||||
@ -890,7 +819,7 @@ static QSE_INLINE int parse_initial_line_and_headers (
|
||||
|
||||
p = QSE_MBS_PTR(&http->fed.b.raw);
|
||||
|
||||
if (http->option & QSE_HTTP_LEADINGEMPTYLINES)
|
||||
if (http->option & QSE_HTRD_LEADINGEMPTYLINES)
|
||||
while (is_whspace_octet(*p)) p++;
|
||||
else
|
||||
while (is_space_octet(*p)) p++;
|
||||
@ -925,7 +854,7 @@ static QSE_INLINE int parse_initial_line_and_headers (
|
||||
#define GET_CHUNK_CRLF 3
|
||||
#define GET_CHUNK_TRAILERS 4
|
||||
|
||||
static const qse_htoc_t* getchunklen (qse_http_t* http, const qse_htoc_t* ptr, qse_size_t len)
|
||||
static const qse_htoc_t* getchunklen (qse_htrd_t* http, const qse_htoc_t* ptr, qse_size_t len)
|
||||
{
|
||||
const qse_htoc_t* end = ptr + len;
|
||||
|
||||
@ -985,7 +914,7 @@ static const qse_htoc_t* getchunklen (qse_http_t* http, const qse_htoc_t* ptr, q
|
||||
else
|
||||
{
|
||||
//qse_printf (QSE_T("XXXXXXXXXXXXXXXXXxxx [%c]\n"), *ptr);
|
||||
http->errnum = QSE_HTTP_EBADRE;
|
||||
http->errnum = QSE_HTRD_EBADRE;
|
||||
return QSE_NULL;
|
||||
}
|
||||
}
|
||||
@ -994,7 +923,7 @@ static const qse_htoc_t* getchunklen (qse_http_t* http, const qse_htoc_t* ptr, q
|
||||
}
|
||||
|
||||
static const qse_htoc_t* get_trailing_headers (
|
||||
qse_http_t* http, const qse_htoc_t* req, const qse_htoc_t* end)
|
||||
qse_htrd_t* http, const qse_htoc_t* req, const qse_htoc_t* end)
|
||||
{
|
||||
const qse_htoc_t* ptr = req;
|
||||
|
||||
@ -1007,7 +936,7 @@ static const qse_htoc_t* get_trailing_headers (
|
||||
case '\0':
|
||||
/* guarantee that the request does not contain a null
|
||||
* character */
|
||||
http->errnum = QSE_HTTP_EBADRE;
|
||||
http->errnum = QSE_HTRD_EBADRE;
|
||||
return QSE_NULL;
|
||||
|
||||
case '\n':
|
||||
@ -1069,7 +998,7 @@ done:
|
||||
}
|
||||
|
||||
/* feed the percent encoded string */
|
||||
int qse_http_feed (qse_http_t* http, const qse_htoc_t* req, qse_size_t len)
|
||||
int qse_htrd_feed (qse_htrd_t* http, const qse_htoc_t* req, qse_size_t len)
|
||||
{
|
||||
const qse_htoc_t* end = req + len;
|
||||
const qse_htoc_t* ptr = req;
|
||||
@ -1104,7 +1033,7 @@ int qse_http_feed (qse_http_t* http, const qse_htoc_t* req, qse_size_t len)
|
||||
{
|
||||
register qse_htoc_t b = *ptr++;
|
||||
|
||||
if (http->option & QSE_HTTP_LEADINGEMPTYLINES &&
|
||||
if (http->option & QSE_HTRD_LEADINGEMPTYLINES &&
|
||||
http->fed.s.plen <= 0 && is_whspace_octet(b))
|
||||
{
|
||||
/* let's drop leading whitespaces across multiple
|
||||
@ -1118,7 +1047,7 @@ int qse_http_feed (qse_http_t* http, const qse_htoc_t* req, qse_size_t len)
|
||||
case '\0':
|
||||
/* guarantee that the request does not contain
|
||||
* a null character */
|
||||
http->errnum = QSE_HTTP_EBADRE;
|
||||
http->errnum = QSE_HTRD_EBADRE;
|
||||
return -1;
|
||||
|
||||
case '\n':
|
||||
@ -1153,7 +1082,7 @@ int qse_http_feed (qse_http_t* http, const qse_htoc_t* req, qse_size_t len)
|
||||
if (parse_initial_line_and_headers (http, req, ptr - req) <= -1)
|
||||
return -1;
|
||||
|
||||
if (http->retype == QSE_HTTP_RETYPE_Q &&
|
||||
if (http->retype == QSE_HTRD_RETYPE_Q &&
|
||||
http->re.attr.expect_continue &&
|
||||
http->recbs.expect_continue && ptr >= end)
|
||||
{
|
||||
@ -1170,8 +1099,8 @@ int qse_http_feed (qse_http_t* http, const qse_htoc_t* req, qse_size_t len)
|
||||
|
||||
if (n <= -1)
|
||||
{
|
||||
if (http->errnum == QSE_HTTP_ENOERR)
|
||||
http->errnum = QSE_HTTP_EREQCBS;
|
||||
if (http->errnum == QSE_HTRD_ENOERR)
|
||||
http->errnum = QSE_HTRD_EREQCBS;
|
||||
|
||||
/* need to clear request on error?
|
||||
clear_feed (http); */
|
||||
@ -1287,7 +1216,7 @@ int qse_http_feed (qse_http_t* http, const qse_htoc_t* req, qse_size_t len)
|
||||
else
|
||||
{
|
||||
/* redundant character ... */
|
||||
http->errnum = QSE_HTTP_EBADRE;
|
||||
http->errnum = QSE_HTRD_EBADRE;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
@ -1302,9 +1231,9 @@ int qse_http_feed (qse_http_t* http, const qse_htoc_t* req, qse_size_t len)
|
||||
{
|
||||
int n;
|
||||
|
||||
http->errnum = QSE_HTTP_ENOERR;
|
||||
http->errnum = QSE_HTRD_ENOERR;
|
||||
|
||||
if (http->retype == QSE_HTTP_RETYPE_S)
|
||||
if (http->retype == QSE_HTRD_RETYPE_S)
|
||||
{
|
||||
QSE_ASSERTX (
|
||||
http->recbs.response != QSE_NULL,
|
||||
@ -1325,8 +1254,8 @@ int qse_http_feed (qse_http_t* http, const qse_htoc_t* req, qse_size_t len)
|
||||
|
||||
if (n <= -1)
|
||||
{
|
||||
if (http->errnum == QSE_HTTP_ENOERR)
|
||||
http->errnum = QSE_HTTP_EREQCBS;
|
||||
if (http->errnum == QSE_HTRD_ENOERR)
|
||||
http->errnum = QSE_HTRD_EREQCBS;
|
||||
|
||||
/* need to clear request on error?
|
||||
clear_feed (http); */
|
||||
@ -1368,3 +1297,28 @@ feedme_more:
|
||||
return 0;
|
||||
}
|
||||
|
||||
int qse_htrd_read (qse_htrd_t* http)
|
||||
{
|
||||
qse_ssize_t n;
|
||||
|
||||
QSE_ASSERTX (
|
||||
http->recbs.reader != QSE_NULL,
|
||||
"You must set the octet reader to be able to call qse_htrd_read()"
|
||||
);
|
||||
|
||||
http->errnum = QSE_HTRD_ENOERR;
|
||||
n = http->recbs.reader (http, http->rbuf, QSE_SIZEOF(http->rbuf));
|
||||
if (n <= -1)
|
||||
{
|
||||
if (http->errnum == QSE_HTRD_ENOERR) http->errnum = QSE_HTRD_EREADER;
|
||||
return -1;
|
||||
}
|
||||
if (n == 0)
|
||||
{
|
||||
http->errnum = QSE_HTRD_EDISCON;
|
||||
return -1;
|
||||
}
|
||||
|
||||
return qse_htrd_feed (http, http->rbuf, n);
|
||||
}
|
||||
|
68
qse/lib/net/htre.c
Normal file
68
qse/lib/net/htre.c
Normal file
@ -0,0 +1,68 @@
|
||||
/*
|
||||
* $Id$
|
||||
*/
|
||||
|
||||
#include <qse/net/htre.h>
|
||||
#include "../cmn/mem.h"
|
||||
|
||||
qse_htre_t* qse_htre_init (qse_htre_t* re, qse_mmgr_t* mmgr)
|
||||
{
|
||||
QSE_MEMSET (re, 0, QSE_SIZEOF(*re));
|
||||
re->mmgr = mmgr;
|
||||
|
||||
if (qse_htb_init (&re->hdrtab, mmgr, 60, 70, 1, 1) == QSE_NULL)
|
||||
{
|
||||
return QSE_NULL;
|
||||
}
|
||||
|
||||
qse_mbs_init (&re->content, mmgr, 0);
|
||||
|
||||
qse_mbs_init (&re->qpath_or_smesg, mmgr, 0);
|
||||
qse_mbs_init (&re->qparamstr, mmgr, 0);
|
||||
|
||||
return re;
|
||||
}
|
||||
|
||||
void qse_htre_fini (qse_htre_t* re)
|
||||
{
|
||||
qse_mbs_fini (&re->qparamstr);
|
||||
qse_mbs_fini (&re->qpath_or_smesg);
|
||||
qse_mbs_fini (&re->content);
|
||||
qse_htb_fini (&re->hdrtab);
|
||||
}
|
||||
|
||||
void qse_htre_clear (qse_htre_t* re)
|
||||
{
|
||||
QSE_MEMSET (&re->version, 0, QSE_SIZEOF(re->version));
|
||||
QSE_MEMSET (&re->attr, 0, QSE_SIZEOF(re->attr));
|
||||
|
||||
qse_htb_clear (&re->hdrtab);
|
||||
|
||||
qse_mbs_clear (&re->content);
|
||||
qse_mbs_clear (&re->qpath_or_smesg);
|
||||
qse_mbs_clear (&re->qparamstr);
|
||||
|
||||
re->discard = 0;
|
||||
}
|
||||
|
||||
int qse_htre_setbuf (
|
||||
qse_htre_t* re, qse_htob_t* buf, const qse_htos_t* str)
|
||||
{
|
||||
qse_mbs_clear (buf);
|
||||
return (qse_mbs_ncat (buf, str->ptr, str->len) == (qse_size_t)-1)? -1: 0;
|
||||
}
|
||||
|
||||
void qse_htre_getbuf (
|
||||
qse_htre_t* re, const qse_htob_t* buf, qse_htos_t* str)
|
||||
{
|
||||
str->ptr = QSE_MBS_PTR(buf);
|
||||
str->len = QSE_MBS_LEN(buf);
|
||||
}
|
||||
|
||||
int qse_htre_setqparamstr (qse_htre_t* re, const qse_htoc_t* str)
|
||||
|
||||
{
|
||||
return (qse_mbs_cpy (&re->qparamstr, str) == (qse_size_t)-1)? -1: 0;
|
||||
}
|
||||
|
||||
|
175
qse/lib/net/http.c
Normal file
175
qse/lib/net/http.c
Normal file
@ -0,0 +1,175 @@
|
||||
/*
|
||||
* $Id: http.c 341 2008-08-20 10:58:19Z baconevi $
|
||||
*
|
||||
Copyright 2006-2011 Chung, Hyung-Hwan.
|
||||
This file is part of QSE.
|
||||
|
||||
QSE is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as
|
||||
published by the Free Software Foundation, either version 3 of
|
||||
the License, or (at your option) any later version.
|
||||
|
||||
QSE is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with QSE. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <qse/net/http.h>
|
||||
#include <qse/cmn/str.h>
|
||||
#include <qse/cmn/htb.h>
|
||||
|
||||
const qse_htoc_t* qse_gethttpmethodname (qse_http_method_t type)
|
||||
{
|
||||
static qse_htoc_t* names[] =
|
||||
{
|
||||
"GET",
|
||||
"HEAD",
|
||||
"POST",
|
||||
"PUT",
|
||||
"DELETE",
|
||||
"TRACE",
|
||||
"OPTIONS",
|
||||
"CONNECT"
|
||||
};
|
||||
|
||||
return (type < 0 || type >= QSE_COUNTOF(names))? QSE_NULL: names[type];
|
||||
}
|
||||
|
||||
struct mtab_t
|
||||
{
|
||||
const qse_htoc_t* name;
|
||||
qse_http_method_t type;
|
||||
};
|
||||
|
||||
static struct mtab_t mtab[] =
|
||||
{
|
||||
{ "CONNECT", QSE_HTTP_CONNECT },
|
||||
{ "DELETE", QSE_HTTP_DELETE },
|
||||
{ "GET", QSE_HTTP_GET },
|
||||
{ "HEAD", QSE_HTTP_HEAD },
|
||||
{ "OPTIONS", QSE_HTTP_OPTIONS },
|
||||
{ "POST", QSE_HTTP_POST },
|
||||
{ "PUT", QSE_HTTP_PUT },
|
||||
{ "TRACE", QSE_HTTP_TRACE }
|
||||
};
|
||||
|
||||
int qse_gethttpmethodtype (
|
||||
const qse_htoc_t* name,
|
||||
qse_http_method_t* type)
|
||||
{
|
||||
|
||||
/* perform binary search */
|
||||
|
||||
/* declaring left, right, mid to be of int is ok
|
||||
* because we know mtab is small enough. */
|
||||
int left = 0, right = QSE_COUNTOF(mtab) - 1, mid;
|
||||
|
||||
while (left <= right)
|
||||
{
|
||||
int n;
|
||||
struct mtab_t* entry;
|
||||
|
||||
mid = (left + right) / 2;
|
||||
entry = &mtab[mid];
|
||||
|
||||
n = qse_mbscmp (name, entry->name);
|
||||
if (n < 0)
|
||||
{
|
||||
/* if left, right, mid were of qse_size_t,
|
||||
* you would need the following line.
|
||||
if (mid == 0) break;
|
||||
*/
|
||||
right = mid - 1;
|
||||
}
|
||||
else if (n > 0) left = mid + 1;
|
||||
else
|
||||
{
|
||||
*type = entry->type;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
int qse_gethttpmethodtypefromstr (
|
||||
const qse_htos_t* name,
|
||||
qse_http_method_t* type)
|
||||
{
|
||||
/* perform binary search */
|
||||
|
||||
/* declaring left, right, mid to be of int is ok
|
||||
* because we know mtab is small enough. */
|
||||
int left = 0, right = QSE_COUNTOF(mtab) - 1, mid;
|
||||
|
||||
while (left <= right)
|
||||
{
|
||||
int n;
|
||||
struct mtab_t* entry;
|
||||
|
||||
mid = (left + right) / 2;
|
||||
entry = &mtab[mid];
|
||||
|
||||
n = qse_mbsxcmp (name->ptr, name->len, entry->name);
|
||||
if (n < 0)
|
||||
{
|
||||
/* if left, right, mid were of qse_size_t,
|
||||
* you would need the following line.
|
||||
if (mid == 0) break;
|
||||
*/
|
||||
right = mid - 1;
|
||||
}
|
||||
else if (n > 0) left = mid + 1;
|
||||
else
|
||||
{
|
||||
*type = entry->type;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
int qse_scanhttpparamstr (
|
||||
const qse_htoc_t* paramstr,
|
||||
qse_scanhttpparamstr_callback_t callback,
|
||||
void* ctx)
|
||||
{
|
||||
qse_mcstr_t key, val;
|
||||
const qse_htoc_t* p = paramstr;
|
||||
|
||||
key.ptr = p; key.len = 0;
|
||||
val.ptr = QSE_NULL; val.len = 0;
|
||||
|
||||
while (1)
|
||||
{
|
||||
if (*p == '&' || *p == ';' || *p == '\0')
|
||||
{
|
||||
QSE_ASSERT (key.ptr != QSE_NULL);
|
||||
if (val.ptr == QSE_NULL) val.ptr = "";
|
||||
|
||||
if (callback (ctx, &key, &val) <= -1) return -1;
|
||||
|
||||
if (*p == '\0') break;
|
||||
|
||||
key.ptr = ++p; key.len = 0;
|
||||
val.ptr = QSE_NULL; val.len = 0;
|
||||
}
|
||||
else if (*p == '=')
|
||||
{
|
||||
val.ptr = ++p;
|
||||
val.len = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (val.ptr) val.len++;
|
||||
else key.len++;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
@ -117,6 +117,11 @@ qse_stc_t* qse_stc_init (qse_stc_t* stc, qse_mmgr_t* mmgr, qse_stx_t* stx)
|
||||
}
|
||||
stc->token.type = TOKEN_END;
|
||||
|
||||
/* TODO:create a bytearray data type...
|
||||
* i think i can reuse qse_mbs_t ... by dropping the null-termination part...
|
||||
qse_bar_t bryte array....
|
||||
qse_lba_t linear byte array
|
||||
*/
|
||||
if (qse_lda_init (
|
||||
&stc->bytecode, mmgr, 256,
|
||||
QSE_SIZEOF(qse_byte_t), QSE_NULL) == QSE_NULL)
|
||||
|
Reference in New Issue
Block a user