diff --git a/qse/configure b/qse/configure
index 50d04056..f19e69ce 100755
--- a/qse/configure
+++ b/qse/configure
@@ -16680,7 +16680,7 @@ QSE_PROJECT_AUTHOR="${PACKAGE_BUGREPORT}"
QSE_PROJECT_URL="${PACKAGE_URL}"
-ac_config_files="$ac_config_files Makefile README include/Makefile include/qse/Makefile include/qse/cmn/Makefile include/qse/awk/Makefile include/qse/cut/Makefile include/qse/sed/Makefile include/qse/stx/Makefile lib/Makefile lib/cmn/Makefile lib/awk/Makefile lib/cut/Makefile lib/sed/Makefile lib/stx/Makefile lib/http/Makefile cmd/Makefile cmd/awk/Makefile cmd/cut/Makefile cmd/sed/Makefile cmd/stx/Makefile samples/Makefile samples/cmn/Makefile samples/awk/Makefile samples/cut/Makefile samples/sed/Makefile samples/http/Makefile regress/Makefile regress/awk/Makefile regress/sed/Makefile doc/Makefile doc/page/Makefile doc/Doxyfile"
+ac_config_files="$ac_config_files Makefile README include/Makefile include/qse/Makefile include/qse/cmn/Makefile include/qse/awk/Makefile include/qse/cut/Makefile include/qse/sed/Makefile include/qse/stx/Makefile include/qse/net/Makefile lib/Makefile lib/cmn/Makefile lib/awk/Makefile lib/cut/Makefile lib/sed/Makefile lib/stx/Makefile lib/net/Makefile cmd/Makefile cmd/awk/Makefile cmd/cut/Makefile cmd/sed/Makefile cmd/stx/Makefile samples/Makefile samples/cmn/Makefile samples/awk/Makefile samples/cut/Makefile samples/sed/Makefile samples/net/Makefile regress/Makefile regress/awk/Makefile regress/sed/Makefile doc/Makefile doc/page/Makefile doc/Doxyfile"
cat >confcache <<\_ACEOF
# This file is a shell script that caches the results of configure
@@ -17780,13 +17780,14 @@ do
"include/qse/cut/Makefile") CONFIG_FILES="$CONFIG_FILES include/qse/cut/Makefile" ;;
"include/qse/sed/Makefile") CONFIG_FILES="$CONFIG_FILES include/qse/sed/Makefile" ;;
"include/qse/stx/Makefile") CONFIG_FILES="$CONFIG_FILES include/qse/stx/Makefile" ;;
+ "include/qse/net/Makefile") CONFIG_FILES="$CONFIG_FILES include/qse/net/Makefile" ;;
"lib/Makefile") CONFIG_FILES="$CONFIG_FILES lib/Makefile" ;;
"lib/cmn/Makefile") CONFIG_FILES="$CONFIG_FILES lib/cmn/Makefile" ;;
"lib/awk/Makefile") CONFIG_FILES="$CONFIG_FILES lib/awk/Makefile" ;;
"lib/cut/Makefile") CONFIG_FILES="$CONFIG_FILES lib/cut/Makefile" ;;
"lib/sed/Makefile") CONFIG_FILES="$CONFIG_FILES lib/sed/Makefile" ;;
"lib/stx/Makefile") CONFIG_FILES="$CONFIG_FILES lib/stx/Makefile" ;;
- "lib/http/Makefile") CONFIG_FILES="$CONFIG_FILES lib/http/Makefile" ;;
+ "lib/net/Makefile") CONFIG_FILES="$CONFIG_FILES lib/net/Makefile" ;;
"cmd/Makefile") CONFIG_FILES="$CONFIG_FILES cmd/Makefile" ;;
"cmd/awk/Makefile") CONFIG_FILES="$CONFIG_FILES cmd/awk/Makefile" ;;
"cmd/cut/Makefile") CONFIG_FILES="$CONFIG_FILES cmd/cut/Makefile" ;;
@@ -17797,7 +17798,7 @@ do
"samples/awk/Makefile") CONFIG_FILES="$CONFIG_FILES samples/awk/Makefile" ;;
"samples/cut/Makefile") CONFIG_FILES="$CONFIG_FILES samples/cut/Makefile" ;;
"samples/sed/Makefile") CONFIG_FILES="$CONFIG_FILES samples/sed/Makefile" ;;
- "samples/http/Makefile") CONFIG_FILES="$CONFIG_FILES samples/http/Makefile" ;;
+ "samples/net/Makefile") CONFIG_FILES="$CONFIG_FILES samples/net/Makefile" ;;
"regress/Makefile") CONFIG_FILES="$CONFIG_FILES regress/Makefile" ;;
"regress/awk/Makefile") CONFIG_FILES="$CONFIG_FILES regress/awk/Makefile" ;;
"regress/sed/Makefile") CONFIG_FILES="$CONFIG_FILES regress/sed/Makefile" ;;
diff --git a/qse/configure.ac b/qse/configure.ac
index 22b2b8d9..d6814580 100644
--- a/qse/configure.ac
+++ b/qse/configure.ac
@@ -236,13 +236,14 @@ AC_CONFIG_FILES([
include/qse/cut/Makefile
include/qse/sed/Makefile
include/qse/stx/Makefile
+ include/qse/net/Makefile
lib/Makefile
lib/cmn/Makefile
lib/awk/Makefile
lib/cut/Makefile
lib/sed/Makefile
lib/stx/Makefile
- lib/http/Makefile
+ lib/net/Makefile
cmd/Makefile
cmd/awk/Makefile
cmd/cut/Makefile
@@ -253,7 +254,7 @@ AC_CONFIG_FILES([
samples/awk/Makefile
samples/cut/Makefile
samples/sed/Makefile
- samples/http/Makefile
+ samples/net/Makefile
regress/Makefile
regress/awk/Makefile
regress/sed/Makefile
diff --git a/qse/include/qse/Makefile.am b/qse/include/qse/Makefile.am
index bd43512c..50742d31 100644
--- a/qse/include/qse/Makefile.am
+++ b/qse/include/qse/Makefile.am
@@ -1,4 +1,4 @@
-SUBDIRS = cmn awk cut sed stx
+SUBDIRS = cmn awk cut sed stx net
pkgincludedir = $(includedir)/qse
diff --git a/qse/include/qse/Makefile.in b/qse/include/qse/Makefile.in
index f8805abd..da301963 100644
--- a/qse/include/qse/Makefile.in
+++ b/qse/include/qse/Makefile.in
@@ -254,7 +254,7 @@ target_alias = @target_alias@
top_build_prefix = @top_build_prefix@
top_builddir = @top_builddir@
top_srcdir = @top_srcdir@
-SUBDIRS = cmn awk cut sed stx
+SUBDIRS = cmn awk cut sed stx net
pkginclude_HEADERS = conf_msw.h conf_os2.h conf_dos.h conf_vms.h \
types.h macros.h pack1.h unpack.h $(am__append_1)
all: config.h
diff --git a/qse/include/qse/http/Makefile.am b/qse/include/qse/http/Makefile.am
deleted file mode 100644
index 422a1e67..00000000
--- a/qse/include/qse/http/Makefile.am
+++ /dev/null
@@ -1,4 +0,0 @@
-pkgincludedir= $(includedir)/qse/http
-pkginclude_HEADERS = http.h
-
-
diff --git a/qse/include/qse/http/http.h b/qse/include/qse/http/http.h
deleted file mode 100644
index 07bcdf00..00000000
--- a/qse/include/qse/http/http.h
+++ /dev/null
@@ -1,167 +0,0 @@
-/*
- * $Id: http.h 223 2008-06-26 06:44:41Z 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 .
- */
-
-#ifndef _QSE_HTTP_HTTP_H_
-#define _QSE_HTTP_HTTP_H_
-
-#include
-
-typedef struct qse_http_t qse_http_t;
-
-enum qse_http_errnum_t
-{
- QSE_HTTP_ENOERR,
- QSE_HTTP_ENOMEM,
- QSE_HTTP_EBADRE,
- QSE_HTTP_EBADHDR,
- QSE_HTTP_EREQCBS
-};
-
-typedef enum qse_http_errnum_t qse_http_errnum_t;
-
-enum qse_http_option_t
-{
- QSE_HTTP_LEADINGEMPTYLINES = (1 << 0)
-};
-
-typedef enum qse_http_option_t qse_http_option_t;
-
-typedef struct qse_http_recbs_t qse_http_recbs_t;
-
-struct qse_http_recbs_t
-{
- int (*request) (qse_http_t* http, qse_htre_t* req);
- int (*response) (qse_http_t* http, qse_htre_t* res);
- int (*expect_continue) (qse_http_t* http, qse_htre_t* req);
-};
-
-struct qse_http_t
-{
- QSE_DEFINE_COMMON_FIELDS (http)
- qse_http_errnum_t errnum;
- int option;
-
- qse_http_recbs_t recbs;
-
- struct
- {
- struct
- {
- int crlf; /* crlf status */
- qse_size_t plen; /* raw request length excluding crlf */
- qse_size_t need; /* number of octets needed for contents */
-
- struct
- {
- qse_size_t len;
- qse_size_t count;
- int phase;
- } chunk;
- } s; /* state */
-
-
- /* buffers needed to for processing a request */
- struct
- {
- qse_htob_t raw; /* buffer to hold raw octets */
- qse_htob_t tra; /* buffer for handling trailers */
- qse_htob_t pen; /* buffer for raw octets during pending period */
- } b;
-
- /* points to the head of the combined header list */
- void* chl;
- } fed;
-
- enum
- {
- QSE_HTTP_RETYPE_Q,
- QSE_HTTP_RETYPE_S
- } retype;
-
- qse_htre_t re;
-};
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-QSE_DEFINE_COMMON_FUNCTIONS (http)
-
-/**
- * The qse_http_open() function creates a http processor.
- */
-qse_http_t* qse_http_open (
- qse_mmgr_t* mmgr, /**< memory manager */
- qse_size_t xtnsize /**< extension size in bytes */
-);
-
-/**
- * The qse_http_close() function destroys a http processor.
- */
-void qse_http_close (
- qse_http_t* http
-);
-
-qse_http_t* qse_http_init (
- qse_http_t* http,
- qse_mmgr_t* mmgr
-);
-
-void qse_http_fini (
- qse_http_t* http
-);
-
-void qse_http_clear (
- qse_http_t* http
-);
-
-int qse_http_getoption (
- qse_http_t* http
-);
-
-void qse_http_setoption (
- qse_http_t* http,
- int opts
-);
-
-const qse_http_recbs_t* qse_http_getrecbs (
- qse_http_t* http
-);
-
-void qse_http_setrecbs (
- qse_http_t* http,
- const qse_http_recbs_t* recbs
-);
-
-/**
- * The qse_http_feed() function accepts http request octets and invokes a
- * callback function if it has processed a proper http request.
- */
-int qse_http_feed (
- qse_http_t* http, /**< http */
- const qse_htoc_t* req, /**< request octets */
- qse_size_t len /**< number of octets */
-);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
diff --git a/qse/include/qse/net/Makefile.am b/qse/include/qse/net/Makefile.am
new file mode 100644
index 00000000..2a6b3d7d
--- /dev/null
+++ b/qse/include/qse/net/Makefile.am
@@ -0,0 +1,4 @@
+pkgincludedir= $(includedir)/qse/net
+pkginclude_HEADERS = htre.h htrd.h http.h
+
+
diff --git a/qse/include/qse/http/Makefile.in b/qse/include/qse/net/Makefile.in
similarity index 98%
rename from qse/include/qse/http/Makefile.in
rename to qse/include/qse/net/Makefile.in
index d583894a..f31c785c 100644
--- a/qse/include/qse/http/Makefile.in
+++ b/qse/include/qse/net/Makefile.in
@@ -33,7 +33,7 @@ PRE_UNINSTALL = :
POST_UNINSTALL = :
build_triplet = @build@
host_triplet = @host@
-subdir = include/qse/http
+subdir = include/qse/net
DIST_COMMON = $(pkginclude_HEADERS) $(srcdir)/Makefile.am \
$(srcdir)/Makefile.in
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
@@ -75,7 +75,7 @@ HEADERS = $(pkginclude_HEADERS)
ETAGS = etags
CTAGS = ctags
DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
-pkgincludedir = $(includedir)/qse/http
+pkgincludedir = $(includedir)/qse/net
ACLOCAL = @ACLOCAL@
AMTAR = @AMTAR@
AR = @AR@
@@ -213,7 +213,7 @@ target_alias = @target_alias@
top_build_prefix = @top_build_prefix@
top_builddir = @top_builddir@
top_srcdir = @top_srcdir@
-pkginclude_HEADERS = http.h
+pkginclude_HEADERS = htre.h htrd.h http.h
all: all-am
.SUFFIXES:
@@ -226,9 +226,9 @@ $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
exit 1;; \
esac; \
done; \
- echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign include/qse/http/Makefile'; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign include/qse/net/Makefile'; \
$(am__cd) $(top_srcdir) && \
- $(AUTOMAKE) --foreign include/qse/http/Makefile
+ $(AUTOMAKE) --foreign include/qse/net/Makefile
.PRECIOUS: Makefile
Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
@case '$?' in \
diff --git a/qse/include/qse/net/htrd.h b/qse/include/qse/net/htrd.h
new file mode 100644
index 00000000..22bd7a07
--- /dev/null
+++ b/qse/include/qse/net/htrd.h
@@ -0,0 +1,179 @@
+/*
+ * $Id: htrd.h 223 2008-06-26 06:44:41Z 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 .
+ */
+
+#ifndef _QSE_NET_HTRD_H_
+#define _QSE_NET_HTRD_H_
+
+#include
+#include
+
+typedef struct qse_htrd_t qse_htrd_t;
+
+enum qse_htrd_errnum_t
+{
+ QSE_HTRD_ENOERR,
+ QSE_HTRD_ENOMEM,
+
+ QSE_HTRD_EDISCON,
+ QSE_HTRD_EREADER,
+
+ QSE_HTRD_EBADRE,
+ QSE_HTRD_EBADHDR,
+ QSE_HTRD_EREQCBS
+};
+
+typedef enum qse_htrd_errnum_t qse_htrd_errnum_t;
+
+enum qse_htrd_option_t
+{
+ QSE_HTRD_LEADINGEMPTYLINES = (1 << 0)
+};
+
+typedef enum qse_htrd_option_t qse_htrd_option_t;
+
+typedef struct qse_htrd_recbs_t qse_htrd_recbs_t;
+
+struct qse_htrd_recbs_t
+{
+ /* octet reader and writer */
+ qse_ssize_t (*reader) (qse_htrd_t* htrd, qse_htoc_t* buf, qse_size_t len);
+
+ int (*request) (qse_htrd_t* htrd, qse_htre_t* req);
+ int (*response) (qse_htrd_t* htrd, qse_htre_t* res);
+ int (*expect_continue) (qse_htrd_t* htrd, qse_htre_t* req);
+};
+
+struct qse_htrd_t
+{
+ QSE_DEFINE_COMMON_FIELDS (htrd)
+ qse_htrd_errnum_t errnum;
+ int option;
+
+ qse_htrd_recbs_t recbs;
+
+ struct
+ {
+ struct
+ {
+ int crlf; /* crlf status */
+ qse_size_t plen; /* raw request length excluding crlf */
+ qse_size_t need; /* number of octets needed for contents */
+
+ struct
+ {
+ qse_size_t len;
+ qse_size_t count;
+ int phase;
+ } chunk;
+ } s; /* state */
+
+
+ /* buffers needed to for processing a request */
+ struct
+ {
+ qse_htob_t raw; /* buffer to hold raw octets */
+ qse_htob_t tra; /* buffer for handling trailers */
+ } b;
+
+ /* points to the head of the combined header list */
+ void* chl;
+ } fed;
+
+ enum
+ {
+ QSE_HTRD_RETYPE_Q,
+ QSE_HTRD_RETYPE_S
+ } retype;
+ qse_htre_t re;
+
+ qse_htoc_t rbuf[4096];
+};
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+QSE_DEFINE_COMMON_FUNCTIONS (htrd)
+
+/**
+ * The qse_htrd_open() function creates a htrd processor.
+ */
+qse_htrd_t* qse_htrd_open (
+ qse_mmgr_t* mmgr, /**< memory manager */
+ qse_size_t xtnsize /**< extension size in bytes */
+);
+
+/**
+ * The qse_htrd_close() function destroys a htrd processor.
+ */
+void qse_htrd_close (
+ qse_htrd_t* htrd
+);
+
+qse_htrd_t* qse_htrd_init (
+ qse_htrd_t* htrd,
+ qse_mmgr_t* mmgr
+);
+
+void qse_htrd_fini (
+ qse_htrd_t* htrd
+);
+
+void qse_htrd_clear (
+ qse_htrd_t* htrd
+);
+
+int qse_htrd_getoption (
+ qse_htrd_t* htrd
+);
+
+void qse_htrd_setoption (
+ qse_htrd_t* htrd,
+ int opts
+);
+
+const qse_htrd_recbs_t* qse_htrd_getrecbs (
+ qse_htrd_t* htrd
+);
+
+void qse_htrd_setrecbs (
+ qse_htrd_t* htrd,
+ const qse_htrd_recbs_t* recbs
+);
+
+/**
+ * The qse_htrd_feed() function accepts htrd request octets and invokes a
+ * callback function if it has processed a proper htrd request.
+ */
+int qse_htrd_feed (
+ qse_htrd_t* htrd, /**< htrd */
+ const qse_htoc_t* req, /**< request octets */
+ qse_size_t len /**< number of octets */
+);
+
+int qse_htrd_read (
+ qse_htrd_t* htrd /**< htrd */
+);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/qse/include/qse/http/htre.h b/qse/include/qse/net/htre.h
similarity index 53%
rename from qse/include/qse/http/htre.h
rename to qse/include/qse/net/htre.h
index 0af2d9c1..bc10baa9 100644
--- a/qse/include/qse/http/htre.h
+++ b/qse/include/qse/net/htre.h
@@ -18,30 +18,13 @@
License along with QSE. If not, see .
*/
-#ifndef _QSE_HTTP_HTRE_H_
-#define _QSE_HTTP_HTRE_H_
+#ifndef _QSE_NET_HTRE_H_
+#define _QSE_NET_HTRE_H_
-#include
-#include
+#include
#include
#include
-/*typedef qse_byte_t qse_htoc_t;*/
-typedef qse_mchar_t qse_htoc_t;
-
-/* octet buffer */
-typedef qse_mbs_t qse_htob_t;
-
-/* octet string */
-typedef qse_mxstr_t qse_htos_t;
-
-typedef struct qse_htvr_t qse_htvr_t;
-struct qse_htvr_t
-{
- short major;
- short minor;
-};
-
/* header and contents of request/response */
typedef struct qse_htre_t qse_htre_t;
struct qse_htre_t
@@ -49,34 +32,11 @@ struct qse_htre_t
qse_mmgr_t* mmgr;
/* version */
- qse_htvr_t version;
+ qse_http_version_t version;
- union
- {
- struct
- {
- enum
- {
- QSE_HTTP_REQ_GET,
- QSE_HTTP_REQ_HEAD,
- QSE_HTTP_REQ_POST,
- QSE_HTTP_REQ_PUT,
- QSE_HTTP_REQ_DELETE,
- QSE_HTTP_REQ_TRACE,
- QSE_HTTP_REQ_OPTIONS,
- QSE_HTTP_REQ_CONNECT
- } method;
-
- qse_htos_t path;
- /* qse_htos_t args; */
- } quest;
-
- struct
- {
- int code;
- qse_htos_t message;
- } sponse;
- } re;
+ int qmethod_or_sstatus;
+ qse_htob_t qpath_or_smesg;
+ qse_htob_t qparamstr;
/* special attributes derived from the header */
struct
@@ -84,8 +44,6 @@ struct qse_htre_t
int chunked;
int content_length;
int connection_close;
- qse_htos_t content_type;
- qse_htos_t host;
int expect_continue;
} attr;
@@ -99,8 +57,27 @@ struct qse_htre_t
int discard;
};
-#define qse_htre_getversion(re) &((re)->version)
+#define qse_htre_getversion(re) (&((re)->version))
+#define qse_htre_getmajorversion(re) ((re)->version.major)
+#define qse_htre_getminorversion(re) ((re)->version.minor)
#define qse_htre_setversion(re,v) QSE_BLOCK((re)->version = *(v);)
+
+#define qse_htre_getqmethod(re) ((re)->qmethod_or_sstatus)
+#define qse_htre_setqmethod(re,v) QSE_BLOCK((re)->qmethod_or_sstatus=(v);)
+
+#define qse_htre_getsstatus(re) ((re)->qmethod_or_sstatus)
+#define qse_htre_setsstatus(re,v) QSE_BLOCK((re)->qmethod_or_sstatus=(v);)
+
+#define qse_htre_setqpath(re,v) qse_htre_setbuf((re),&(re)->qpath_or_smesg,(v))
+#define qse_htre_setsmessage(re,v) qse_htre_setbuf((re),&(re)->qpath_or_smesg,(v))
+
+#define qse_htre_getqpathptr(re) QSE_MBS_PTR(&(re)->qpath_or_smesg)
+#define qse_htre_getqpathlen(re) QSE_MBS_LEN(&(re)->qpath_or_smesg)
+#define qse_htre_getqparamsptr(re) QSE_MBS_PTR(&(re)->qparamstr)
+#define qse_htre_getqparamslen(re) QSE_MBS_LEN(&(re)->qparamstr)
+#define qse_htre_getsmessageptr(re) QSE_MBS_PTR(&(re)->qpath_or_smesg)
+#define qse_htre_getsmessagelen(re) QSE_MBS_LEN(&(re)->qpath_or_smesg)
+
#define qse_htre_setdiscard(re,v) QSE_BLOCK((re)->discard = (v);)
#ifdef __cplusplus
@@ -120,6 +97,23 @@ void qse_htre_clear (
qse_htre_t* re
);
+int qse_htre_setbuf (
+ qse_htre_t* re,
+ qse_htob_t* buf,
+ const qse_htos_t* str
+);
+
+void qse_htre_getbuf (
+ qse_htre_t* re,
+ const qse_htob_t* buf,
+ qse_htos_t* str
+);
+
+int qse_htre_setqparamstr (
+ qse_htre_t* re,
+ const qse_htoc_t* str
+);
+
#ifdef __cplusplus
}
#endif
diff --git a/qse/include/qse/net/http.h b/qse/include/qse/net/http.h
new file mode 100644
index 00000000..6bd49489
--- /dev/null
+++ b/qse/include/qse/net/http.h
@@ -0,0 +1,94 @@
+/*
+ * $Id: http.h 223 2008-06-26 06:44:41Z 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 .
+ */
+
+#ifndef _QSE_NET_HTTP_H_
+#define _QSE_NET_HTTP_H_
+
+#include
+#include
+#include
+#include
+
+/*typedef qse_byte_t qse_htoc_t;*/
+typedef qse_mchar_t qse_htoc_t;
+
+/* octet buffer */
+typedef qse_mbs_t qse_htob_t;
+
+/* octet string */
+typedef qse_mxstr_t qse_htos_t;
+
+typedef struct qse_http_version_t qse_http_version_t;
+struct qse_http_version_t
+{
+ short major;
+ short minor;
+};
+
+enum qse_http_method_t
+{
+ QSE_HTTP_GET,
+ QSE_HTTP_HEAD,
+ QSE_HTTP_POST,
+ QSE_HTTP_PUT,
+ QSE_HTTP_DELETE,
+ QSE_HTTP_TRACE,
+ QSE_HTTP_OPTIONS,
+ QSE_HTTP_CONNECT
+};
+
+typedef enum qse_http_method_t qse_http_method_t;
+
+typedef int (*qse_scanhttpparamstr_callback_t) (
+ void* ctx,
+ const qse_mcstr_t* key,
+ const qse_mcstr_t* val
+);
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+const qse_htoc_t* qse_gethttpmethodname (
+ qse_http_method_t type
+);
+
+int qse_gethttpmethodtype (
+ const qse_htoc_t* name,
+ qse_http_method_t* method
+);
+
+int qse_gethttpmethodtypefromstr (
+ const qse_htos_t* name,
+ qse_http_method_t* type
+);
+
+int qse_scanhttpparamstr (
+ const qse_htoc_t* paramstr,
+ qse_scanhttpparamstr_callback_t callback,
+ void* ctx
+);
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif
diff --git a/qse/lib/Makefile.am b/qse/lib/Makefile.am
index d0ce9da9..c64a3ea3 100644
--- a/qse/lib/Makefile.am
+++ b/qse/lib/Makefile.am
@@ -1,2 +1,2 @@
-SUBDIRS = cmn sed awk cut stx
+SUBDIRS = cmn sed awk cut stx net
DIST_SUBDIRS = $(SUBDIRS)
diff --git a/qse/lib/Makefile.in b/qse/lib/Makefile.in
index 5682a57c..4838d92c 100644
--- a/qse/lib/Makefile.in
+++ b/qse/lib/Makefile.in
@@ -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
diff --git a/qse/lib/cmn/str_dynm.c b/qse/lib/cmn/str_dynm.c
index 7f56ea17..3c2110bd 100644
--- a/qse/lib/cmn/str_dynm.c
+++ b/qse/lib/cmn/str_dynm.c
@@ -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;
}
diff --git a/qse/lib/cmn/str_dynw.c b/qse/lib/cmn/str_dynw.c
index 74052954..3c3a6f3c 100644
--- a/qse/lib/cmn/str_dynw.c
+++ b/qse/lib/cmn/str_dynw.c
@@ -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;
}
diff --git a/qse/lib/http/Makefile.am b/qse/lib/http/Makefile.am
deleted file mode 100644
index 7bd1aa65..00000000
--- a/qse/lib/http/Makefile.am
+++ /dev/null
@@ -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
diff --git a/qse/lib/http/htre.c b/qse/lib/http/htre.c
deleted file mode 100644
index f02898d0..00000000
--- a/qse/lib/http/htre.c
+++ /dev/null
@@ -1,99 +0,0 @@
-/*
- * $Id$
- */
-#include
-#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;
-}
-
-
diff --git a/qse/lib/net/Makefile.am b/qse/lib/net/Makefile.am
new file mode 100644
index 00000000..57a9cb92
--- /dev/null
+++ b/qse/lib/net/Makefile.am
@@ -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
diff --git a/qse/lib/http/Makefile.in b/qse/lib/net/Makefile.in
similarity index 95%
rename from qse/lib/http/Makefile.in
rename to qse/lib/net/Makefile.in
index ef8bfebd..354797f0 100644
--- a/qse/lib/http/Makefile.in
+++ b/qse/lib/net/Makefile.in
@@ -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@
diff --git a/qse/lib/http/http.c b/qse/lib/net/htrd.c
similarity index 80%
rename from qse/lib/http/http.c
rename to qse/lib/net/htrd.c
index 8f31e56b..10f54928 100644
--- a/qse/lib/http/http.c
+++ b/qse/lib/net/htrd.c
@@ -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 .
*/
-#include
+#include
#include
#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);
+}
+
diff --git a/qse/lib/net/htre.c b/qse/lib/net/htre.c
new file mode 100644
index 00000000..5e185db6
--- /dev/null
+++ b/qse/lib/net/htre.c
@@ -0,0 +1,68 @@
+/*
+ * $Id$
+ */
+
+#include
+#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;
+}
+
+
diff --git a/qse/lib/net/http.c b/qse/lib/net/http.c
new file mode 100644
index 00000000..e5d0cc44
--- /dev/null
+++ b/qse/lib/net/http.c
@@ -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 .
+ */
+
+#include
+#include
+#include
+
+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;
+}
diff --git a/qse/lib/stx/par.c b/qse/lib/stx/par.c
index 08d9a884..b1541613 100644
--- a/qse/lib/stx/par.c
+++ b/qse/lib/stx/par.c
@@ -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)
diff --git a/qse/samples/http/Makefile.am b/qse/samples/net/Makefile.am
similarity index 66%
rename from qse/samples/http/Makefile.am
rename to qse/samples/net/Makefile.am
index f8bf1f90..c72c98de 100644
--- a/qse/samples/http/Makefile.am
+++ b/qse/samples/net/Makefile.am
@@ -7,8 +7,8 @@ AM_CPPFLAGS = \
bin_PROGRAMS = http01
-LDFLAGS = -L../../lib/cmn -L../../lib/http
-LDADD = -lqsehttp -lqsecmn $(LIBM) -lpthread
+LDFLAGS = -L../../lib/cmn -L../../lib/net
+LDADD = -lqsenet -lqsecmn $(LIBM) -lpthread
http01_SOURCES = http01.c
diff --git a/qse/samples/http/Makefile.in b/qse/samples/net/Makefile.in
similarity index 98%
rename from qse/samples/http/Makefile.in
rename to qse/samples/net/Makefile.in
index 51b30888..60304230 100644
--- a/qse/samples/http/Makefile.in
+++ b/qse/samples/net/Makefile.in
@@ -35,7 +35,7 @@ POST_UNINSTALL = :
build_triplet = @build@
host_triplet = @host@
bin_PROGRAMS = http01$(EXEEXT)
-subdir = samples/http
+subdir = samples/net
DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
am__aclocal_m4_deps = $(top_srcdir)/m4/libtool.m4 \
@@ -111,7 +111,7 @@ INSTALL_PROGRAM = @INSTALL_PROGRAM@
INSTALL_SCRIPT = @INSTALL_SCRIPT@
INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
LD = @LD@
-LDFLAGS = -L../../lib/cmn -L../../lib/http
+LDFLAGS = -L../../lib/cmn -L../../lib/net
LIBM = @LIBM@
LIBOBJS = @LIBOBJS@
LIBS = @LIBS@
@@ -216,7 +216,7 @@ AM_CPPFLAGS = \
-I$(top_srcdir)/include \
-I$(includedir)
-LDADD = -lqsehttp -lqsecmn $(LIBM) -lpthread
+LDADD = -lqsenet -lqsecmn $(LIBM) -lpthread
http01_SOURCES = http01.c
all: all-am
@@ -231,9 +231,9 @@ $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
exit 1;; \
esac; \
done; \
- echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign samples/http/Makefile'; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign samples/net/Makefile'; \
$(am__cd) $(top_srcdir) && \
- $(AUTOMAKE) --foreign samples/http/Makefile
+ $(AUTOMAKE) --foreign samples/net/Makefile
.PRECIOUS: Makefile
Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
@case '$?' in \
diff --git a/qse/samples/http/http01.c b/qse/samples/net/http01.c
similarity index 80%
rename from qse/samples/http/http01.c
rename to qse/samples/net/http01.c
index ec3a5237..4d53d36a 100644
--- a/qse/samples/http/http01.c
+++ b/qse/samples/net/http01.c
@@ -1,4 +1,4 @@
-#include
+#include
#include
#include
#include
@@ -60,7 +60,7 @@ struct client_t
{
int fd;
struct sockaddr_storage addr;
- qse_http_t* http;
+ qse_htrd_t* http;
pthread_mutex_t action_mutex;
struct
@@ -163,8 +163,90 @@ static int enqueue_sendtext_locked (client_t* client, const char* text)
return enqueue_client_action_locked (client, &action);
}
-static int enqueue_sendfmt_locked (client_t* client, const char* fmt, ...)
+static int format_and_do (int (*task) (void* arg, char* text), void* arg, const char* fmt, ...)
{
+ va_list ap;
+ char n[2];
+ char* buf;
+ int bytes_req;
+
+ va_start (ap, fmt);
+#if defined(_WIN32) && defined(_MSC_VER)
+ bytes_req = _vsnprintf (n, 1, fmt, ap);
+#else
+ bytes_req = vsnprintf (n, 1, fmt, ap);
+#endif
+ va_end (ap);
+ if (bytes_req == -1)
+ {
+ qse_size_t capa = 256;
+ buf = (char*) malloc (capa + 1);
+
+ /* an old vsnprintf behaves differently from C99 standard.
+ * thus, it returns -1 when it can't write all the input given. */
+ for (;;)
+ {
+ int l;
+ va_start (ap, fmt);
+#if defined(_WIN32) && defined(_MSC_VER)
+ if ((l = _vsnprintf (buf, capa + 1, fmt, ap)) == -1)
+#else
+ if ((l = vsnprintf (buf, capa + 1, fmt, ap)) == -1)
+#endif
+ {
+ va_end (ap);
+
+ free (buf);
+ capa = capa * 2;
+ buf = (char*)malloc (capa + 1);
+ if (buf == NULL) return -1;
+
+ continue;
+ }
+
+ va_end (ap);
+ break;
+ }
+ }
+ else
+ {
+ /* vsnprintf returns the number of characters that would
+ * have been written not including the terminating '\0'
+ * if the _data buffer were large enough */
+ buf = (char*)malloc (bytes_req + 1);
+ if (buf == NULL) return -1;
+
+ va_start (ap, fmt);
+#if defined(_WIN32) && defined(_MSC_VER)
+ _vsnprintf (buf, bytes_req + 1, fmt, ap);
+#else
+ vsnprintf (buf, bytes_req + 1, fmt, ap);
+#endif
+
+ //_data[_size] = '\0';
+ va_end (ap);
+ }
+
+ return task (arg, buf);
+}
+
+static int enqueue_format (void* arg, char* text)
+{
+ client_t* client = (client_t*)arg;
+
+ client_action_t action;
+
+ memset (&action, 0, sizeof(action));
+ action.type = ACTION_SENDTEXTDUP;
+ action.u.sendtextdup.ptr = text;
+ action.u.sendtextdup.left = strlen(text);
+
+ if (enqueue_client_action_locked (client, &action) <= -1)
+ {
+ free (text);
+ return -1;
+ }
+
return 0;
}
@@ -221,16 +303,28 @@ qse_printf (QSE_T("HEADER OK %d[%S] %d[%S]\n"), (int)QSE_HTB_KLEN(pair), QSE_HT
return QSE_HTB_WALK_FORWARD;
}
-static int handle_request (qse_http_t* http, qse_htre_t* req)
+static capture_param (void* ctx, const qse_mcstr_t* key, const qse_mcstr_t* val)
{
- http_xtn_t* xtn = (http_xtn_t*) qse_http_getxtn (http);
+}
+
+static int handle_request (qse_htrd_t* http, qse_htre_t* req)
+{
+ http_xtn_t* xtn = (http_xtn_t*) qse_htrd_getxtn (http);
client_t* client = &xtn->array->data[xtn->index];
+ int method;
qse_printf (QSE_T("================================\n"));
qse_printf (QSE_T("REQUEST ==> [%S] version[%d.%d] method[%d]\n"),
- req->re.quest.path.ptr, req->version.major, req->version.minor, req->re.quest.method);
+ qse_htre_getqpathptr(req),
+ qse_htre_getmajorversion(req),
+ qse_htre_getminorversion(req),
+ qse_htre_getqmethod(req)
+);
+if (qse_htre_getqparamslen(req) > 0)
+{
+qse_printf (QSE_T("PARAMS ==> [%S]\n"), qse_htre_getqparamsptr(req));
+}
-if (req->attr.host.ptr) qse_printf (QSE_T("HOST===> %S\n"), req->attr.host.ptr);
qse_htb_walk (&http->re.hdrtab, walk, QSE_NULL);
if (QSE_MBS_LEN(&http->re.content) > 0)
{
@@ -239,30 +333,29 @@ qse_printf (QSE_T("content = [%.*S]\n"),
QSE_MBS_PTR(&http->re.content));
}
+ method = qse_htre_getqmethod (req);
- if (req->re.quest.method == QSE_HTTP_REQ_GET || req->re.quest.method == QSE_HTTP_REQ_POST)
+ if (method == QSE_HTTP_GET || method == QSE_HTTP_POST)
{
- qse_htre_decodereqpath (req, );
+ //qse_htre_decodereqpath (req, );
/* original path not available anymore */
- int fd = open (req->re.quest.path.ptr, O_RDONLY);
+ qse_scanhttpparamstr (qse_htre_getqparamstrptr(req), capture_param, xxx);
+
+ int fd = open (qse_htre_getqpathptr(req), O_RDONLY);
if (fd <= -1)
{
-char text[256];
const char* msg = "NOT FOUNDREQUESTD FILE NOT FOUND";
-snprintf (text, sizeof(text),
+if (format_and_do (enqueue_format, client,
"HTTP/%d.%d 404 Not found\r\nContent-Length: %d\r\n\r\n%s\r\n\r\n",
req->version.major,
req->version.minor,
- (int)strlen(msg) + 4, msg);
-
-qse_printf (QSE_T("open failure.... sending 404 not found\n"));
-
- if (enqueue_sendtextdup_locked (client, text) <= -1)
- {
+ (int)strlen(msg) + 4, msg) <= -1)
+{
qse_printf (QSE_T("failed to push action....\n"));
- return -1;
- }
+ return -1;
+}
+
}
else
{
@@ -279,7 +372,7 @@ qse_printf (QSE_T("fstat failure....\n"));
qse_printf (QSE_T("empty file....\n"));
#if 0
- qse_htre_t* res = qse_http_newresponse (http);
+ qse_htre_t* res = qse_htrd_newresponse (http);
if (req == QSE_NULL)
{
/* hard failure... can't answer */
@@ -287,7 +380,7 @@ qse_printf (QSE_T("empty file....\n"));
}
- ptr = qse_http_emitresponse (http, res, &len);
+ ptr = qse_htrd_emitresponse (http, res, &len);
if (ptr == QSE_NULL)
{
/* hard failure... can't answer */
@@ -301,11 +394,13 @@ qse_printf (QSE_T("empty file....\n"));
}
else
{
+
char text[128];
snprintf (text, sizeof(text),
"HTTP/%d.%d 200 OK\r\nContent-Length: %llu\r\n\r\n",
- req->version.major,
- req->version.minor, (unsigned long long)st.st_size);
+ qse_htre_getmajorversion(req),
+ qse_htre_getminorversion(req),
+ (unsigned long long)st.st_size);
#if 0
if (enqueue_sendfmt_locked (client,
@@ -347,8 +442,9 @@ char text[256];
const char* msg = "Method not allowedMETHOD NOT ALLOWED";
snprintf (text, sizeof(text),
"HTTP/%d.%d 405 Method not allowed\r\nContent-Length: %d\r\n\r\n%s\r\n\r\n",
- req->version.major,
- req->version.minor, (int)strlen(msg)+4, msg);
+ qse_htre_getmajorversion(req),
+ qse_htre_getminorversion(req),
+ (int)strlen(msg)+4, msg);
if (enqueue_sendtextdup_locked (client, text) <= -1)
{
qse_printf (QSE_T("failed to push action....\n"));
@@ -361,12 +457,25 @@ return -1;
return 0;
}
-static int handle_expect_continue (qse_http_t* http, qse_htre_t* req)
+static int handle_expect_continue (qse_htrd_t* http, qse_htre_t* req)
{
- http_xtn_t* xtn = (http_xtn_t*) qse_http_getxtn (http);
+ http_xtn_t* xtn = (http_xtn_t*) qse_htrd_getxtn (http);
client_t* client = &xtn->array->data[xtn->index];
- if (req->re.quest.method == QSE_HTTP_REQ_GET)
+ if (qse_htre_getqmethod(req) == QSE_HTTP_POST)
+ {
+ char text[32];
+
+ snprintf (text, sizeof(text),
+ "HTTP/%d.%d 100 OK\r\n\r\n",
+ req->version.major, req->version.minor);
+
+ if (enqueue_sendtextdup_locked (client, text) <= -1)
+ {
+ return -1;
+ }
+ }
+ else
{
char text[32];
@@ -381,24 +490,11 @@ static int handle_expect_continue (qse_http_t* http, qse_htre_t* req)
return -1;
}
}
- else
- {
- char text[32];
-
- snprintf (text, sizeof(text),
- "HTTP/%d.%d 100 OK\r\n\r\n",
- req->version.major, req->version.minor);
-
- if (enqueue_sendtextdup_locked (client, text) <= -1)
- {
- return -1;
- }
- }
return 0;
}
-static int handle_response (qse_http_t* http, qse_htre_t* res)
+static int handle_response (qse_htrd_t* http, qse_htre_t* res)
{
#if 0
if (res->code >= 100 && res->code <= 199)
@@ -408,13 +504,31 @@ static int handle_response (qse_http_t* http, qse_htre_t* res)
#endif
qse_printf (QSE_T("response received... HTTP/%d.%d %d %.*S\n"),
- res->version.major, res->version.minor, res->re.sponse.code,
- (int)res->re.sponse.message.len, res->re.sponse.message.ptr);
+ qse_htre_getmajorversion(res),
+ qse_htre_getminorversion(res),
+ qse_htre_getsstatus(res),
+ (int)qse_htre_getsmessagelen(res),
+ qse_htre_getsmessageptr(res)
+ );
return -1;
}
-qse_http_recbs_t http_recbs =
+static qse_ssize_t receive_octets (qse_htrd_t* http, qse_htoc_t* buf, qse_size_t size)
{
+ http_xtn_t* xtn = (http_xtn_t*) qse_htrd_getxtn (http);
+ client_t* client = &xtn->array->data[xtn->index];
+ ssize_t n;
+
+ n = recv (client->fd, buf, size, 0);
+ if (n <= -1 && (errno == EAGAIN || errno == EWOULDBLOCK))
+ http->errnum = 99999;
+
+ return n;
+}
+
+qse_htrd_recbs_t http_recbs =
+{
+ receive_octets,
handle_request,
handle_response,
handle_expect_continue
@@ -469,7 +583,7 @@ static void delete_from_client_array (client_array_t* array, int fd)
purge_client_actions_locked (&array->data[fd]);
pthread_mutex_destroy (&array->data[fd].action_mutex);
- qse_http_close (array->data[fd].http);
+ qse_htrd_close (array->data[fd].http);
array->data[fd].http = QSE_NULL;
close (array->data[fd].fd);
array->size--;
@@ -518,15 +632,15 @@ static client_t* insert_into_client_array (
array->data[fd].fd = fd;
array->data[fd].addr = *addr;
- array->data[fd].http = qse_http_open (QSE_MMGR_GETDFL(), QSE_SIZEOF(*xtn));
+ array->data[fd].http = qse_htrd_open (QSE_MMGR_GETDFL(), QSE_SIZEOF(*xtn));
if (array->data[fd].http == QSE_NULL) return QSE_NULL;
pthread_mutex_init (&array->data[fd].action_mutex, NULL);
- xtn = (http_xtn_t*)qse_http_getxtn (array->data[fd].http);
+ xtn = (http_xtn_t*)qse_htrd_getxtn (array->data[fd].http);
xtn->array = array;
xtn->index = fd;
- qse_http_setrecbs (array->data[fd].http, &http_recbs);
+ qse_htrd_setrecbs (array->data[fd].http, &http_recbs);
array->size++;
return &array->data[fd];
}
@@ -653,6 +767,9 @@ qse_printf (QSE_T("finished sending text dup...\n"));
if (count >= action->u.sendfile.left)
count = action->u.sendfile.left;
+//n = qse_htrd_write (client->http, sendfile, joins);
+
+
n = sendfile (
client->fd,
action->u.sendfile.fd,
@@ -858,48 +975,19 @@ qse_printf (QSE_T("connection %d accepted\n"), c);
if (FD_ISSET(client->fd, &r))
{
/* got input */
-
- qse_htoc_t buf[1024];
- ssize_t m;
-
- reread:
- m = read (client->fd, buf, sizeof(buf));
- if (m <= -1)
+ if (qse_htrd_read (client->http) <= -1)
{
- if (errno != EINTR)
+ int errnum = client->http->errnum;
+ if (errnum != 99999)
{
pthread_mutex_lock (&appdata.camutex);
delete_from_client_array (&appdata.ca, fd);
pthread_mutex_unlock (&appdata.camutex);
- qse_fprintf (QSE_STDERR, QSE_T("Error: failed to read from a client %d\n"), fd);
- continue;
+ if (errnum == QSE_HTRD_EDISCON)
+ qse_fprintf (QSE_STDERR, QSE_T("Debug: connection closed %d\n"), client->fd);
+ else
+ qse_fprintf (QSE_STDERR, QSE_T("Error: failed to read/process a request from a client %d\n"), client->fd);
}
- goto reread;
- }
- else if (m == 0)
- {
- pthread_mutex_lock (&appdata.camutex);
- delete_from_client_array (&appdata.ca, fd);
- pthread_mutex_unlock (&appdata.camutex);
- qse_fprintf (QSE_STDERR, QSE_T("Debug: connection closed %d\n"), fd);
- continue;
- }
-
- /* feed may have called the request callback multiple times...
- * that's because we don't know how many valid requests
- * are included in 'buf' */
- n = qse_http_feed (client->http, buf, m);
- if (n <= -1)
- {
- if (client->http->errnum == QSE_HTTP_EBADRE)
- {
- /* TODO: write a response to indicate bad request... */
- }
-
- pthread_mutex_lock (&appdata.camutex);
- delete_from_client_array (&appdata.ca, fd);
- pthread_mutex_unlock (&appdata.camutex);
- qse_fprintf (QSE_STDERR, QSE_T("Error: http error while processing \n"));
continue;
}
}