fixed various bugs in http server handlers
regenrated build files
This commit is contained in:
@@ -59,6 +59,7 @@ include_HEADERS = \
|
||||
hio-sck.h \
|
||||
hio-shw.h \
|
||||
hio-skad.h \
|
||||
hio-spl.h \
|
||||
hio-str.h \
|
||||
hio-tar.h \
|
||||
hio-thr.h \
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
# Makefile.in generated by automake 1.16.2 from Makefile.am.
|
||||
# Makefile.in generated by automake 1.16.5 from Makefile.am.
|
||||
# @configure_input@
|
||||
|
||||
# Copyright (C) 1994-2020 Free Software Foundation, Inc.
|
||||
# Copyright (C) 1994-2021 Free Software Foundation, Inc.
|
||||
|
||||
# This Makefile.in is free software; the Free Software Foundation
|
||||
# gives unlimited permission to copy and/or distribute it,
|
||||
@@ -265,8 +265,8 @@ am__include_HEADERS_DIST = hio-chr.h hio-cmn.h hio-dhcp.h hio-dns.h \
|
||||
hio-ecs.h hio-fcgi.h hio-fmt.h hio-htb.h hio-htrd.h hio-htre.h \
|
||||
hio-http.h hio-json.h hio-md5.h hio-nwif.h hio-opt.h \
|
||||
hio-pac1.h hio-path.h hio-pipe.h hio-pro.h hio-pty.h hio-rad.h \
|
||||
hio-sck.h hio-shw.h hio-skad.h hio-str.h hio-tar.h hio-thr.h \
|
||||
hio-upac.h hio-utl.h hio.h hio-mar.h
|
||||
hio-sck.h hio-shw.h hio-skad.h hio-spl.h hio-str.h hio-tar.h \
|
||||
hio-thr.h hio-upac.h hio-utl.h hio.h hio-mar.h
|
||||
HEADERS = $(include_HEADERS)
|
||||
am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) \
|
||||
hio-cfg.h.in
|
||||
@@ -286,8 +286,6 @@ am__define_uniq_tagged_files = \
|
||||
unique=`for i in $$list; do \
|
||||
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
|
||||
done | $(am__uniquify_input)`
|
||||
ETAGS = etags
|
||||
CTAGS = ctags
|
||||
am__DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/hio-cfg.h.in \
|
||||
$(top_srcdir)/ac/depcomp
|
||||
DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
|
||||
@@ -306,6 +304,8 @@ CCDEPMODE = @CCDEPMODE@
|
||||
CFLAGS = @CFLAGS@
|
||||
CPP = @CPP@
|
||||
CPPFLAGS = @CPPFLAGS@
|
||||
CSCOPE = @CSCOPE@
|
||||
CTAGS = @CTAGS@
|
||||
CYGPATH_W = @CYGPATH_W@
|
||||
DEFS = @DEFS@
|
||||
DEPDIR = @DEPDIR@
|
||||
@@ -316,8 +316,10 @@ ECHO_C = @ECHO_C@
|
||||
ECHO_N = @ECHO_N@
|
||||
ECHO_T = @ECHO_T@
|
||||
EGREP = @EGREP@
|
||||
ETAGS = @ETAGS@
|
||||
EXEEXT = @EXEEXT@
|
||||
FGREP = @FGREP@
|
||||
FILECMD = @FILECMD@
|
||||
GREP = @GREP@
|
||||
HIO_PROJECT_AUTHOR = @HIO_PROJECT_AUTHOR@
|
||||
HIO_PROJECT_URL = @HIO_PROJECT_URL@
|
||||
@@ -364,6 +366,7 @@ PACKAGE_VERSION_PATCH = @PACKAGE_VERSION_PATCH@
|
||||
PATH_SEPARATOR = @PATH_SEPARATOR@
|
||||
PTHREAD_CC = @PTHREAD_CC@
|
||||
PTHREAD_CFLAGS = @PTHREAD_CFLAGS@
|
||||
PTHREAD_CXX = @PTHREAD_CXX@
|
||||
PTHREAD_LIBS = @PTHREAD_LIBS@
|
||||
QUADMATH_LIBS = @QUADMATH_LIBS@
|
||||
RANLIB = @RANLIB@
|
||||
@@ -468,8 +471,8 @@ include_HEADERS = hio-chr.h hio-cmn.h hio-dhcp.h hio-dns.h hio-ecs.h \
|
||||
hio-fcgi.h hio-fmt.h hio-htb.h hio-htrd.h hio-htre.h \
|
||||
hio-http.h hio-json.h hio-md5.h hio-nwif.h hio-opt.h \
|
||||
hio-pac1.h hio-path.h hio-pipe.h hio-pro.h hio-pty.h hio-rad.h \
|
||||
hio-sck.h hio-shw.h hio-skad.h hio-str.h hio-tar.h hio-thr.h \
|
||||
hio-upac.h hio-utl.h hio.h $(am__append_1)
|
||||
hio-sck.h hio-shw.h hio-skad.h hio-spl.h hio-str.h hio-tar.h \
|
||||
hio-thr.h hio-upac.h hio-utl.h hio.h $(am__append_1)
|
||||
lib_LTLIBRARIES = libhio.la
|
||||
libhio_la_SOURCES = chr.c dhcp-svr.c dns.c dns-cli.c ecs.c ecs-imp.h \
|
||||
err.c fcgi-cli.c fmt.c fmt-imp.h htb.c htrd.c htre.c http.c \
|
||||
@@ -1072,7 +1075,6 @@ cscopelist-am: $(am__tagged_files)
|
||||
|
||||
distclean-tags:
|
||||
-rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
|
||||
|
||||
distdir: $(BUILT_SOURCES)
|
||||
$(MAKE) $(AM_MAKEFLAGS) distdir-am
|
||||
|
||||
@@ -1116,7 +1118,8 @@ installdirs:
|
||||
done
|
||||
install: $(BUILT_SOURCES)
|
||||
$(MAKE) $(AM_MAKEFLAGS) install-am
|
||||
install-exec: install-exec-am
|
||||
install-exec: $(BUILT_SOURCES)
|
||||
$(MAKE) $(AM_MAKEFLAGS) install-exec-am
|
||||
install-data: install-data-am
|
||||
uninstall: uninstall-am
|
||||
|
||||
@@ -1313,8 +1316,8 @@ ps-am:
|
||||
uninstall-am: uninstall-includeHEADERS uninstall-libLTLIBRARIES
|
||||
@$(NORMAL_INSTALL)
|
||||
$(MAKE) $(AM_MAKEFLAGS) uninstall-hook
|
||||
.MAKE: all check install install-am install-data-am install-strip \
|
||||
uninstall-am
|
||||
.MAKE: all check install install-am install-data-am install-exec \
|
||||
install-strip uninstall-am
|
||||
|
||||
.PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-am clean \
|
||||
clean-generic clean-libLTLIBRARIES clean-libtool cscopelist-am \
|
||||
|
||||
@@ -730,7 +730,7 @@ hio_svc_dnc_t* hio_svc_dnc_start (hio_t* hio, const hio_skad_t* serv_addr, const
|
||||
if (HIO_UNLIKELY(!dnc)) goto oops;
|
||||
|
||||
dnc->hio = hio;
|
||||
dnc->svc_stop = hio_svc_dnc_stop;
|
||||
dnc->svc_stop = (hio_svc_stop_t)hio_svc_dnc_stop;
|
||||
dnc->serv_addr = *serv_addr;
|
||||
dnc->send_tmout = *send_tmout;
|
||||
dnc->reply_tmout = *reply_tmout;
|
||||
|
||||
@@ -212,7 +212,7 @@ static int sck_on_read (hio_dev_sck_t* sck, const void* data, hio_iolen_t dlen,
|
||||
conn->r.len = 0; /* reset to 0 to use the buffer to hold body */
|
||||
|
||||
/* the expected body length must not be too long */
|
||||
HIO_ASSERT (hio, conn->r.body_len <= HIO_SIZEOF(conn->r.buf));
|
||||
HIO_ASSERT (hio, conn->r.body_len <= HIO_SIZEOF(conn->r.buf));
|
||||
|
||||
if (conn->r.type == HIO_FCGI_END_REQUEST && conn->r.content_len < HIO_SIZEOF(hio_fcgi_end_request_body_t))
|
||||
{
|
||||
@@ -375,7 +375,7 @@ static hio_svc_fcgic_conn_t* get_connection (hio_svc_fcgic_t* fcgic, const hio_s
|
||||
static int destroy_connection_memory (hio_t* hio, hio_cfmb_t* cfmb)
|
||||
{
|
||||
hio_svc_fcgic_conn_t* conn = (hio_svc_fcgic_conn_t*)cfmb;
|
||||
if (conn->sess.ptr)
|
||||
if (conn->sess.ptr)
|
||||
{
|
||||
hio_oow_t i;
|
||||
|
||||
@@ -435,7 +435,7 @@ static hio_svc_fcgic_sess_t* new_session (hio_svc_fcgic_t* fcgic, const hio_skad
|
||||
/* reallocate the session pointer bucket */
|
||||
newcapa = conn->sess.capa + CONN_SESS_INC;
|
||||
newptr = (hio_svc_fcgic_sess_t**)hio_reallocmem(hio, conn->sess.ptr, HIO_SIZEOF(*newptr) * newcapa);
|
||||
if (HIO_UNLIKELY(!newptr))
|
||||
if (HIO_UNLIKELY(!newptr))
|
||||
{
|
||||
hio_freemem (hio, newblk);
|
||||
return HIO_NULL;
|
||||
@@ -459,7 +459,7 @@ static hio_svc_fcgic_sess_t* new_session (hio_svc_fcgic_t* fcgic, const hio_skad
|
||||
|
||||
sess = conn->sess.free;
|
||||
conn->sess.free = sess->next;
|
||||
|
||||
|
||||
sess->on_read = on_read;
|
||||
sess->on_write = on_write;
|
||||
sess->on_untie = on_untie;
|
||||
|
||||
@@ -77,6 +77,8 @@
|
||||
#endif
|
||||
#if defined(HAVE_QUADMATH_H)
|
||||
# include <quadmath.h> /* for quadmath_snprintf() */
|
||||
#elif defined(HAVE_QUADMATH_SNPRINTF)
|
||||
extern int quadmath_snprintf (const char *str, size_t size, const char *format, ...);
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
103
lib/hio-cfg.h.in
103
lib/hio-cfg.h.in
@@ -30,7 +30,8 @@
|
||||
/* Define to 1 if you have the `CRYPTO_cleanup_all_ex_data' function. */
|
||||
#undef HAVE_CRYPTO_CLEANUP_ALL_EX_DATA
|
||||
|
||||
/* Define to 1 if you have the <dirent.h> header file, and it defines `DIR'. */
|
||||
/* Define to 1 if you have the <dirent.h> header file, and it defines `DIR'.
|
||||
*/
|
||||
#undef HAVE_DIRENT_H
|
||||
|
||||
/* Define to 1 if you have the `dirfd' function. */
|
||||
@@ -192,8 +193,8 @@
|
||||
/* Define to 1 if you have the `mbsrtowcs' function. */
|
||||
#undef HAVE_MBSRTOWCS
|
||||
|
||||
/* Define to 1 if you have the <memory.h> header file. */
|
||||
#undef HAVE_MEMORY_H
|
||||
/* Define to 1 if you have the <minix/config.h> header file. */
|
||||
#undef HAVE_MINIX_CONFIG_H
|
||||
|
||||
/* Define to 1 if you have the `mmap' function. */
|
||||
#undef HAVE_MMAP
|
||||
@@ -342,6 +343,9 @@
|
||||
/* Define to 1 if you have the <stdint.h> header file. */
|
||||
#undef HAVE_STDINT_H
|
||||
|
||||
/* Define to 1 if you have the <stdio.h> header file. */
|
||||
#undef HAVE_STDIO_H
|
||||
|
||||
/* Define to 1 if you have the <stdlib.h> header file. */
|
||||
#undef HAVE_STDLIB_H
|
||||
|
||||
@@ -876,28 +880,96 @@
|
||||
/* The size of `__uint128_t', as computed by sizeof. */
|
||||
#undef SIZEOF___UINT128_T
|
||||
|
||||
/* Define to 1 if you have the ANSI C header files. */
|
||||
/* Define to 1 if all of the C90 standard headers exist (not just the ones
|
||||
required in a freestanding environment). This macro is provided for
|
||||
backward compatibility; new code need not use it. */
|
||||
#undef STDC_HEADERS
|
||||
|
||||
/* Enable extensions on AIX 3, Interix. */
|
||||
#ifndef _ALL_SOURCE
|
||||
# undef _ALL_SOURCE
|
||||
#endif
|
||||
/* Enable general extensions on macOS. */
|
||||
#ifndef _DARWIN_C_SOURCE
|
||||
# undef _DARWIN_C_SOURCE
|
||||
#endif
|
||||
/* Enable general extensions on Solaris. */
|
||||
#ifndef __EXTENSIONS__
|
||||
# undef __EXTENSIONS__
|
||||
#endif
|
||||
/* Enable GNU extensions on systems that have them. */
|
||||
#ifndef _GNU_SOURCE
|
||||
# undef _GNU_SOURCE
|
||||
#endif
|
||||
/* Enable threading extensions on Solaris. */
|
||||
/* Enable X/Open compliant socket functions that do not require linking
|
||||
with -lxnet on HP-UX 11.11. */
|
||||
#ifndef _HPUX_ALT_XOPEN_SOCKET_API
|
||||
# undef _HPUX_ALT_XOPEN_SOCKET_API
|
||||
#endif
|
||||
/* Identify the host operating system as Minix.
|
||||
This macro does not affect the system headers' behavior.
|
||||
A future release of Autoconf may stop defining this macro. */
|
||||
#ifndef _MINIX
|
||||
# undef _MINIX
|
||||
#endif
|
||||
/* Enable general extensions on NetBSD.
|
||||
Enable NetBSD compatibility extensions on Minix. */
|
||||
#ifndef _NETBSD_SOURCE
|
||||
# undef _NETBSD_SOURCE
|
||||
#endif
|
||||
/* Enable OpenBSD compatibility extensions on NetBSD.
|
||||
Oddly enough, this does nothing on OpenBSD. */
|
||||
#ifndef _OPENBSD_SOURCE
|
||||
# undef _OPENBSD_SOURCE
|
||||
#endif
|
||||
/* Define to 1 if needed for POSIX-compatible behavior. */
|
||||
#ifndef _POSIX_SOURCE
|
||||
# undef _POSIX_SOURCE
|
||||
#endif
|
||||
/* Define to 2 if needed for POSIX-compatible behavior. */
|
||||
#ifndef _POSIX_1_SOURCE
|
||||
# undef _POSIX_1_SOURCE
|
||||
#endif
|
||||
/* Enable POSIX-compatible threading on Solaris. */
|
||||
#ifndef _POSIX_PTHREAD_SEMANTICS
|
||||
# undef _POSIX_PTHREAD_SEMANTICS
|
||||
#endif
|
||||
/* Enable extensions specified by ISO/IEC TS 18661-5:2014. */
|
||||
#ifndef __STDC_WANT_IEC_60559_ATTRIBS_EXT__
|
||||
# undef __STDC_WANT_IEC_60559_ATTRIBS_EXT__
|
||||
#endif
|
||||
/* Enable extensions specified by ISO/IEC TS 18661-1:2014. */
|
||||
#ifndef __STDC_WANT_IEC_60559_BFP_EXT__
|
||||
# undef __STDC_WANT_IEC_60559_BFP_EXT__
|
||||
#endif
|
||||
/* Enable extensions specified by ISO/IEC TS 18661-2:2015. */
|
||||
#ifndef __STDC_WANT_IEC_60559_DFP_EXT__
|
||||
# undef __STDC_WANT_IEC_60559_DFP_EXT__
|
||||
#endif
|
||||
/* Enable extensions specified by ISO/IEC TS 18661-4:2015. */
|
||||
#ifndef __STDC_WANT_IEC_60559_FUNCS_EXT__
|
||||
# undef __STDC_WANT_IEC_60559_FUNCS_EXT__
|
||||
#endif
|
||||
/* Enable extensions specified by ISO/IEC TS 18661-3:2015. */
|
||||
#ifndef __STDC_WANT_IEC_60559_TYPES_EXT__
|
||||
# undef __STDC_WANT_IEC_60559_TYPES_EXT__
|
||||
#endif
|
||||
/* Enable extensions specified by ISO/IEC TR 24731-2:2010. */
|
||||
#ifndef __STDC_WANT_LIB_EXT2__
|
||||
# undef __STDC_WANT_LIB_EXT2__
|
||||
#endif
|
||||
/* Enable extensions specified by ISO/IEC 24747:2009. */
|
||||
#ifndef __STDC_WANT_MATH_SPEC_FUNCS__
|
||||
# undef __STDC_WANT_MATH_SPEC_FUNCS__
|
||||
#endif
|
||||
/* Enable extensions on HP NonStop. */
|
||||
#ifndef _TANDEM_SOURCE
|
||||
# undef _TANDEM_SOURCE
|
||||
#endif
|
||||
/* Enable general extensions on Solaris. */
|
||||
#ifndef __EXTENSIONS__
|
||||
# undef __EXTENSIONS__
|
||||
/* Enable X/Open extensions. Define to 500 only if necessary
|
||||
to make mbstate_t available. */
|
||||
#ifndef _XOPEN_SOURCE
|
||||
# undef _XOPEN_SOURCE
|
||||
#endif
|
||||
|
||||
|
||||
@@ -916,23 +988,8 @@
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/* Enable large inode numbers on Mac OS X 10.5. */
|
||||
#ifndef _DARWIN_USE_64_BIT_INODE
|
||||
# define _DARWIN_USE_64_BIT_INODE 1
|
||||
#endif
|
||||
|
||||
/* Number of bits in a file offset, on hosts where this is settable. */
|
||||
#undef _FILE_OFFSET_BITS
|
||||
|
||||
/* Define for large files, on AIX-style hosts. */
|
||||
#undef _LARGE_FILES
|
||||
|
||||
/* Define to 1 if on MINIX. */
|
||||
#undef _MINIX
|
||||
|
||||
/* Define to 2 if the system does not provide POSIX.1 features except with
|
||||
this defined. */
|
||||
#undef _POSIX_1_SOURCE
|
||||
|
||||
/* Define to 1 if you need to in order for `stat' and other things to work. */
|
||||
#undef _POSIX_SOURCE
|
||||
|
||||
@@ -917,6 +917,13 @@ struct hio_cmgr_t
|
||||
#define HIO_HAVE_BUILTIN_BSWAP128
|
||||
#endif
|
||||
|
||||
#if __has_builtin(__atomic_load_n)
|
||||
#define HIO_HAVE_BUILTIN_ATOMIC_LOAD_N
|
||||
#endif
|
||||
#if __has_builtin(__atomic_compare_exchange_n)
|
||||
#define HIO_HAVE_BUILTIN_ATOMIC_COMPARE_EXCHANGE_N
|
||||
#endif
|
||||
|
||||
#elif defined(__GNUC__) && defined(__GNUC_MINOR__)
|
||||
|
||||
#if (__GNUC__ >= 4)
|
||||
@@ -935,6 +942,11 @@ struct hio_cmgr_t
|
||||
#define HIO_HAVE_BUILTIN_EXPECT
|
||||
#endif
|
||||
|
||||
#if (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 7))
|
||||
#define HIO_HAVE_BUILTIN_ATOMIC_LOAD_N
|
||||
#define HIO_HAVE_BUILTIN_ATOMIC_COMPARE_EXCHANGE_N
|
||||
#endif
|
||||
|
||||
#if (__GNUC__ >= 5)
|
||||
#define HIO_HAVE_BUILTIN_UADD_OVERFLOW
|
||||
#define HIO_HAVE_BUILTIN_UADDL_OVERFLOW
|
||||
@@ -963,12 +975,12 @@ struct hio_cmgr_t
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if defined(__clang__) || (defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 7)))
|
||||
#define HCL_ATOMIC_LOAD(dst) __atomic_load_n(dst, __ATOMIC_RELAXED)
|
||||
#define HCL_ATOMIC_CMP_XCHG(dst,expected,desired) \
|
||||
#if defined(HIO_HAVE_BUILTIN_ATOMIC_LOAD_N)
|
||||
# define HCL_ATOMIC_LOAD(dst) __atomic_load_n(dst, __ATOMIC_RELAXED)
|
||||
#endif
|
||||
#if defined(HIO_HAVE_BUILTIN_ATOMIC_COMPARE_EXCHANGE_N)
|
||||
# define HCL_ATOMIC_CMP_XCHG(dst,expected,desired) \
|
||||
__atomic_compare_exchange_n(dst, expected, desired, 0, __ATOMIC_RELAXED, __ATOMIC_RELAXED)
|
||||
#else
|
||||
#error NOT SUPPORTED
|
||||
#endif
|
||||
|
||||
#if defined(HIO_HAVE_BUILTIN_EXPECT)
|
||||
|
||||
@@ -528,16 +528,13 @@ HIO_EXPORT int hio_svc_htts_dotxt (
|
||||
hio_svc_htts_t* htts,
|
||||
hio_dev_sck_t* csck,
|
||||
hio_htre_t* req,
|
||||
int status_code,
|
||||
int res_status_code,
|
||||
const hio_bch_t* content_type,
|
||||
const hio_bch_t* content_text,
|
||||
int options,
|
||||
hio_svc_htts_task_on_kill_t on_kill
|
||||
);
|
||||
|
||||
|
||||
|
||||
|
||||
HIO_EXPORT hio_svc_htts_task_t* hio_svc_htts_task_make (
|
||||
hio_svc_htts_t* htts,
|
||||
hio_oow_t task_size,
|
||||
@@ -606,7 +603,8 @@ HIO_EXPORT int hio_svc_htts_task_endbody (
|
||||
);
|
||||
|
||||
HIO_EXPORT int hio_svc_htts_task_handleexpect100 (
|
||||
hio_svc_htts_task_t* task
|
||||
hio_svc_htts_task_t* task,
|
||||
int no_continue
|
||||
);
|
||||
|
||||
HIO_EXPORT void hio_svc_htts_fmtgmtime (
|
||||
|
||||
271
lib/hio-spl.h
Normal file
271
lib/hio-spl.h
Normal file
@@ -0,0 +1,271 @@
|
||||
/*
|
||||
Copyright (c) 2016-2020 Chung, Hyung-Hwan. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
1. Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR
|
||||
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef _HIO_SPL_H_
|
||||
#define _HIO_SPL_H_
|
||||
|
||||
#include <hio-cmn.h>
|
||||
|
||||
#define HIO_SUPPORT_SPL
|
||||
|
||||
typedef volatile hio_uint32_t hio_spl_t;
|
||||
|
||||
#define HIO_SPL_INIT (0)
|
||||
|
||||
#if defined(HIO_HAVE_INLINE)
|
||||
static HIO_INLINE void hio_spl_init (hio_spl_t* spl) { *spl = HIO_SPL_INIT; }
|
||||
#else
|
||||
#define hio_spl_init(spl) ((*(spl)) = HIO_SPL_INIT)
|
||||
#endif
|
||||
|
||||
#if defined(HIO_HAVE_SYNC_LOCK_TEST_AND_SET) && defined(HIO_HAVE_SYNC_LOCK_RELEASE)
|
||||
/* =======================================================================
|
||||
* MODERN COMPILERS WITH BUILTIN ATOMICS
|
||||
* ======================================================================= */
|
||||
|
||||
#if defined(HIO_HAVE_INLINE)
|
||||
static HIO_INLINE int hio_spl_trylock (hio_spl_t* spl) { return !__sync_lock_test_and_set(spl, 1); }
|
||||
static HIO_INLINE void hio_spl_lock (hio_spl_t* spl) { do {} while(__sync_lock_test_and_set(spl, 1)); }
|
||||
static HIO_INLINE void hio_spl_unlock (hio_spl_t* spl) { __sync_lock_release(spl); }
|
||||
#else
|
||||
# define hio_spl_trylock(spl) (!__sync_lock_test_and_set(spl, 1))
|
||||
# define hio_spl_lock(spl) do {} while(__sync_lock_test_and_set(spl, 1))
|
||||
# define hio_spl_unlock(spl) (__sync_lock_release(spl))
|
||||
#endif
|
||||
|
||||
#elif defined(_SCO_DS)
|
||||
/* =======================================================================
|
||||
* SCO DEVELOPEMENT SYSTEM
|
||||
*
|
||||
* NOTE: when the asm macros were indented, the compiler/linker ended up
|
||||
* with undefined symbols. never indent hio_spl_xxx macros.
|
||||
* ======================================================================= */
|
||||
asm int hio_spl_trylock (hio_spl_t* spl)
|
||||
{
|
||||
%reg spl
|
||||
movl $1, %eax
|
||||
xchgl (spl), %eax
|
||||
xorl $1, %eax / return zero on failure, non-zero on success
|
||||
|
||||
%mem spl
|
||||
movl spl, %ecx
|
||||
movl $1, %eax
|
||||
xchgl (%ecx), %eax
|
||||
xorl $1, %eax / return zero on failure, non-zero on success
|
||||
}
|
||||
|
||||
#if 0
|
||||
/* i can't figure out how to make jump labels unique when there are
|
||||
* multiple occurrences of hio_spl_lock(). so let me just use the while loop
|
||||
* instead. */
|
||||
asm void hio_spl_lock (hio_spl_t* spl)
|
||||
{
|
||||
%reg spl
|
||||
.lock_set_loop:
|
||||
movl $1, %eax
|
||||
xchgl (spl), %eax
|
||||
testl %eax, %eax / set ZF to 1 if eax is zero, 0 if eax is non-zero
|
||||
jne .lock_set_loop / if ZF is 0(eax is non-zero), loop around
|
||||
|
||||
%mem spl
|
||||
.lock_set_loop:
|
||||
movl spl, %ecx
|
||||
movl $1, %eax
|
||||
xchgl (%ecx), %eax
|
||||
testl %eax, %eax / set ZF to 1 if eax is zero, 0 if eax is non-zero
|
||||
jne .lock_set_loop / if ZF is 0(eax is non-zero), loop around
|
||||
}
|
||||
#else
|
||||
#define hio_spl_lock(x) do {} while(!spl_trylock(x))
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
asm void hio_spl_unlock (moo_uint8_t* spl)
|
||||
{
|
||||
%reg spl
|
||||
movl $0, %eax
|
||||
xchgl (spl), %eax
|
||||
|
||||
%mem spl
|
||||
movl spl, %ecx
|
||||
movl $0, %eax
|
||||
xchgl (%ecx), %eax
|
||||
}
|
||||
#else
|
||||
asm void hio_spl_unlock (hio_spl_t* spl)
|
||||
{
|
||||
/* don't need xchg as movl on an aligned data is atomic */
|
||||
/* mfence is 0F AE F0 */
|
||||
%reg spl
|
||||
.byte 0x0F
|
||||
.byte 0xAE
|
||||
.byte 0xF0
|
||||
movl $0, (spl)
|
||||
|
||||
%mem spl
|
||||
.byte 0x0F
|
||||
.byte 0xAE
|
||||
.byte 0xF0
|
||||
movl spl, %ecx
|
||||
movl $0, (%ecx)
|
||||
}
|
||||
#endif
|
||||
|
||||
#elif defined(__GNUC__) && (defined(__x86_64) || defined(__amd64) || defined(__i386) || defined(i386))
|
||||
|
||||
/* =======================================================================
|
||||
* OLD GNU COMPILER FOR x86 and x86_64
|
||||
* ======================================================================= */
|
||||
|
||||
static HIO_INLINE int hio_spl_trylock (hio_spl_t* spl)
|
||||
{
|
||||
register int x = 1;
|
||||
__asm__ volatile (
|
||||
"xchgl %0, (%2)\n"
|
||||
: "=r"(x)
|
||||
: "0"(x), "r"(spl)
|
||||
: "memory"
|
||||
);
|
||||
return !x;
|
||||
}
|
||||
|
||||
static HIO_INLINE void hio_spl_lock (hio_spl_t* spl)
|
||||
{
|
||||
register int x = 1;
|
||||
do
|
||||
{
|
||||
__asm__ volatile (
|
||||
"xchgl %0, (%2)\n"
|
||||
: "=r"(x)
|
||||
: "0"(x), "r"(spl)
|
||||
: "memory"
|
||||
);
|
||||
}
|
||||
while (x);
|
||||
}
|
||||
|
||||
static HIO_INLINE void hio_spl_unlock (hio_spl_t* spl)
|
||||
{
|
||||
#if defined(__x86_64) || defined(__amd64)
|
||||
__asm__ volatile (
|
||||
"mfence\n\t"
|
||||
"movl $0, (%0)\n"
|
||||
:
|
||||
:"r"(spl)
|
||||
:"memory"
|
||||
);
|
||||
#else
|
||||
__asm__ volatile (
|
||||
"movl $0, (%0)\n"
|
||||
:
|
||||
:"r"(spl)
|
||||
:"memory"
|
||||
);
|
||||
#endif
|
||||
}
|
||||
|
||||
#elif defined(__GNUC__) && (defined(__POWERPC__) || defined(__powerpc) || defined(__powerpc__) || defined(__ppc))
|
||||
|
||||
/* =======================================================================
|
||||
* OLD GNU COMPILER FOR ppc
|
||||
* ======================================================================= */
|
||||
|
||||
static HIO_INLINE int hio_spl_trylock (hio_spl_t* spl)
|
||||
{
|
||||
|
||||
/* lwarx RT, RA, RB
|
||||
* RT Specifies target general-purpose register where result of operation is stored.
|
||||
* RA Specifies source general-purpose register for EA calculation.
|
||||
* RB Specifies source general-purpose register for EA calculation.
|
||||
*
|
||||
* If general-purpose register (GPR) RA = 0, the effective address (EA) is the
|
||||
* content of GPR RB. Otherwise, the EA is the sum of the content of GPR RA
|
||||
* plus the content of GPR RB.
|
||||
|
||||
* The lwarx instruction loads the word from the location in storage specified
|
||||
* by the EA into the target GPR RT. In addition, a reservation on the memory
|
||||
* location is created for use by a subsequent stwcx. instruction.
|
||||
|
||||
* The lwarx instruction has one syntax form and does not affect the
|
||||
* Fixed-Point Exception Register. If the EA is not a multiple of 4,
|
||||
* the results are boundedly undefined.
|
||||
*/
|
||||
|
||||
unsigned int rc;
|
||||
|
||||
__asm__ volatile (
|
||||
"1:\n"
|
||||
"lwarx %0,0,%1\n" /* load and reserve. rc(%0) = *spl(%1) */
|
||||
"cmpwi cr0,%0,0\n" /* cr0 = (rc compare-with 0) */
|
||||
"li %0,0\n" /* rc = 0(failure) */
|
||||
"bne cr0,2f\n" /* if cr0 != 0, goto 2; */
|
||||
"li %0,1\n" /* rc = 1(success) */
|
||||
"stwcx. %0,0,%1\n" /* *spl(%1) = 1(value in rc) if reserved */
|
||||
"bne cr0,1b\n" /* if reservation is lost, goto 1 */
|
||||
#if 1
|
||||
"lwsync\n"
|
||||
#else
|
||||
"isync\n"
|
||||
#endif
|
||||
"2:\n"
|
||||
: "=&r"(rc)
|
||||
: "r"(spl)
|
||||
: "cr0", "memory"
|
||||
);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static HIO_INLINE void hio_spl_lock (hio_spl_t* spl)
|
||||
{
|
||||
while (!hio_spl_trylock(spl)) /* nothing */;
|
||||
}
|
||||
|
||||
static HIO_INLINE void hio_spl_unlock (hio_spl_t* spl)
|
||||
{
|
||||
__asm__ volatile (
|
||||
#if 1
|
||||
"lwsync\n"
|
||||
#elif 0
|
||||
"sync\n"
|
||||
#else
|
||||
"eieio\n"
|
||||
#endif
|
||||
:
|
||||
:
|
||||
: "memory"
|
||||
);
|
||||
*spl = 0;
|
||||
}
|
||||
|
||||
#elif defined(HIO_SPL_NO_UNSUPPORTED_ERROR)
|
||||
/* don't raise the compile time error */
|
||||
#undef HIO_SUPPORT_SPL
|
||||
#else
|
||||
#undef HIO_SUPPORT_SPL
|
||||
# error UNSUPPORTED
|
||||
#endif
|
||||
|
||||
|
||||
#endif
|
||||
139
lib/http-cgi.c
139
lib/http-cgi.c
@@ -86,6 +86,7 @@ static void unbind_task_from_peer (cgi_t* cgi, int rcdown);
|
||||
|
||||
static int inc_ntask_cgis (hio_svc_htts_t* htts)
|
||||
{
|
||||
#if defined(HCL_ATOMIC_LOAD) && defined(HCL_ATOMIC_CMP_XCHG)
|
||||
int ok;
|
||||
do
|
||||
{
|
||||
@@ -94,16 +95,26 @@ static int inc_ntask_cgis (hio_svc_htts_t* htts)
|
||||
if (ntask_cgis >= htts->option.task_cgi_max)
|
||||
{
|
||||
hio_seterrbfmt (htts->hio, HIO_ENOCAPA, "too many cgi tasks");
|
||||
printf ("too many cgi task....\n");
|
||||
return -1;
|
||||
}
|
||||
ok = HCL_ATOMIC_CMP_XCHG(&htts->stat.ntask_cgis, &ntask_cgis, ntask_cgis + 1);
|
||||
}
|
||||
while (!ok);
|
||||
#else
|
||||
if (htts->stat.ntask_cgis >= htts->option.task_cgi_max)
|
||||
{
|
||||
hio_seterrbfmt (htts->hio, HIO_ENOCAPA, "too many cgi tasks");
|
||||
return -1;
|
||||
}
|
||||
htts->stat.ntask_cgis++;
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void dec_ntask_cgis (hio_svc_htts_t* htts)
|
||||
{
|
||||
#if defined(HCL_ATOMIC_LOAD) && defined(HCL_ATOMIC_CMP_XCHG)
|
||||
int ok;
|
||||
do
|
||||
{
|
||||
@@ -112,6 +123,9 @@ static void dec_ntask_cgis (hio_svc_htts_t* htts)
|
||||
ok = HCL_ATOMIC_CMP_XCHG(&htts->stat.ntask_cgis, &ntask_cgis, ntask_cgis - 1);
|
||||
}
|
||||
while (!ok);
|
||||
#else
|
||||
htts->stat.ntask_cgis--;
|
||||
#endif
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------- */
|
||||
@@ -785,54 +799,59 @@ static void bind_task_to_client (cgi_t* cgi, hio_dev_sck_t* csck)
|
||||
static void unbind_task_from_client (cgi_t* cgi, int rcdown)
|
||||
{
|
||||
hio_dev_sck_t* csck = cgi->task_csck;
|
||||
hio_svc_htts_cli_t* cli = hio_dev_sck_getxtn(csck);
|
||||
|
||||
HIO_ASSERT (cgi->htts->hio, cgi->task_client != HIO_NULL);
|
||||
HIO_ASSERT (cgi->htts->hio, cgi->task_csck != HIO_NULL);
|
||||
HIO_ASSERT (cgi->htts->hio, cgi->task_client->task == (hio_svc_htts_task_t*)cgi);
|
||||
HIO_ASSERT (cgi->htts->hio, cgi->task_client->htrd != HIO_NULL);
|
||||
|
||||
if (cgi->client_htrd_recbs_changed)
|
||||
if (cli->task) /* only if it's bound */
|
||||
{
|
||||
hio_htrd_setrecbs (cgi->task_client->htrd, &cgi->client_htrd_org_recbs);
|
||||
cgi->client_htrd_recbs_changed = 0;
|
||||
HIO_ASSERT (cgi->htts->hio, cgi->task_client != HIO_NULL);
|
||||
HIO_ASSERT (cgi->htts->hio, cgi->task_csck != HIO_NULL); /* cgi->task_csck is set by hio_svc_htts_task_make() */
|
||||
HIO_ASSERT (cgi->htts->hio, cgi->task_client->task == (hio_svc_htts_task_t*)cgi);
|
||||
HIO_ASSERT (cgi->htts->hio, cgi->task_client->htrd != HIO_NULL);
|
||||
|
||||
if (cgi->client_htrd_recbs_changed)
|
||||
{
|
||||
hio_htrd_setrecbs (cgi->task_client->htrd, &cgi->client_htrd_org_recbs);
|
||||
cgi->client_htrd_recbs_changed = 0;
|
||||
}
|
||||
|
||||
if (cgi->client_org_on_read)
|
||||
{
|
||||
csck->on_read = cgi->client_org_on_read;
|
||||
cgi->client_org_on_read = HIO_NULL;
|
||||
}
|
||||
|
||||
if (cgi->client_org_on_write)
|
||||
{
|
||||
csck->on_write = cgi->client_org_on_write;
|
||||
cgi->client_org_on_write = HIO_NULL;
|
||||
}
|
||||
|
||||
if (cgi->client_org_on_disconnect)
|
||||
{
|
||||
csck->on_disconnect = cgi->client_org_on_disconnect;
|
||||
cgi->client_org_on_disconnect = HIO_NULL;
|
||||
}
|
||||
|
||||
/* there is some ordering issue in using HIO_SVC_HTTS_TASK_UNREF()
|
||||
* because it can destroy the cgi itself. so reset cgi->task_client->task
|
||||
* to null and call RCDOWN() later */
|
||||
cgi->task_client->task = HIO_NULL;
|
||||
|
||||
/* these two lines are also done in csck_on_disconnect() in http-svr.c because the socket is destroyed.
|
||||
* the same lines here are because the task is unbound while the socket is still alive */
|
||||
cgi->task_client = HIO_NULL;
|
||||
cgi->task_csck = HIO_NULL;
|
||||
|
||||
/* enable input watching on the socket being unbound */
|
||||
if (cgi->task_keep_client_alive && hio_dev_sck_read(csck, 1) <= -1)
|
||||
{
|
||||
HIO_DEBUG2 (cgi->htts->hio, "HTTS(%p) - halting client(%p) for failure to enable input watching\n", cgi->htts, csck);
|
||||
hio_dev_sck_halt (csck);
|
||||
}
|
||||
|
||||
if (rcdown) HIO_SVC_HTTS_TASK_RCDOWN ((hio_svc_htts_task_t*)cgi);
|
||||
|
||||
}
|
||||
|
||||
if (cgi->client_org_on_read)
|
||||
{
|
||||
csck->on_read = cgi->client_org_on_read;
|
||||
cgi->client_org_on_read = HIO_NULL;
|
||||
}
|
||||
|
||||
if (cgi->client_org_on_write)
|
||||
{
|
||||
csck->on_write = cgi->client_org_on_write;
|
||||
cgi->client_org_on_write = HIO_NULL;
|
||||
}
|
||||
|
||||
if (cgi->client_org_on_disconnect)
|
||||
{
|
||||
csck->on_disconnect = cgi->client_org_on_disconnect;
|
||||
cgi->client_org_on_disconnect = HIO_NULL;
|
||||
}
|
||||
|
||||
/* there is some ordering issue in using HIO_SVC_HTTS_TASK_UNREF()
|
||||
* because it can destroy the cgi itself. so reset cgi->task_client->task
|
||||
* to null and call RCDOWN() later */
|
||||
cgi->task_client->task = HIO_NULL;
|
||||
|
||||
/* these two lines are also done in csck_on_disconnect() in http-svr.c because the socket is destroyed.
|
||||
* the same lines here are because the task is unbound while the socket is still alive */
|
||||
cgi->task_client = HIO_NULL;
|
||||
cgi->task_csck = HIO_NULL;
|
||||
|
||||
/* enable input watching on the socket being unbound */
|
||||
if (cgi->task_keep_client_alive && hio_dev_sck_read(csck, 1) <= -1)
|
||||
{
|
||||
HIO_DEBUG2 (cgi->htts->hio, "HTTS(%p) - halting client(%p) for failure to enable input watching\n", cgi->htts, csck);
|
||||
hio_dev_sck_halt (csck);
|
||||
}
|
||||
|
||||
if (rcdown) HIO_SVC_HTTS_TASK_RCDOWN ((hio_svc_htts_task_t*)cgi);
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------- */
|
||||
@@ -885,6 +904,7 @@ static int bind_task_to_peer (cgi_t* cgi, hio_dev_sck_t* csck, hio_htre_t* req,
|
||||
{
|
||||
hio_freemem (hio, fc.actual_script);
|
||||
hio_dev_pro_kill (cgi->peer);
|
||||
cgi->peer = HIO_NULL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -972,22 +992,28 @@ int hio_svc_htts_docgi (hio_svc_htts_t* htts, hio_dev_sck_t* csck, hio_htre_t* r
|
||||
hio_t* hio = htts->hio;
|
||||
hio_svc_htts_cli_t* cli = hio_dev_sck_getxtn(csck);
|
||||
cgi_t* cgi = HIO_NULL;
|
||||
int n, bound_to_client = 0, bound_to_peer = 0;
|
||||
int n, status_code = HIO_HTTP_STATUS_INTERNAL_SERVER_ERROR;
|
||||
int bound_to_client = 0, bound_to_peer = 0;
|
||||
|
||||
/* ensure that you call this function before any contents is received */
|
||||
HIO_ASSERT (hio, hio_htre_getcontentlen(req) == 0);
|
||||
HIO_ASSERT (hio, cli->sck == csck);
|
||||
|
||||
if (inc_ntask_cgis(htts) <= -1) return -1;
|
||||
cgi = (cgi_t*)hio_svc_htts_task_make(htts, HIO_SIZEOF(*cgi), cgi_on_kill, req, csck);
|
||||
if (HIO_UNLIKELY(!cgi))
|
||||
if (cli->task)
|
||||
{
|
||||
dec_ntask_cgis (htts);
|
||||
hio_seterrbfmt (hio, HIO_EPERM, "duplicate task request prohibited");
|
||||
goto oops;
|
||||
}
|
||||
|
||||
cgi = (cgi_t*)hio_svc_htts_task_make(htts, HIO_SIZEOF(*cgi), cgi_on_kill, req, csck);
|
||||
if (HIO_UNLIKELY(!cgi)) goto oops;
|
||||
HIO_SVC_HTTS_TASK_RCUP((hio_svc_htts_task_t*)cgi);
|
||||
if (inc_ntask_cgis(htts) <= -1)
|
||||
{
|
||||
status_code = HIO_HTTP_STATUS_SERVICE_UNAVAILABLE;
|
||||
goto oops;
|
||||
}
|
||||
HIO_SVC_HTTS_TASK_RCUP((hio_svc_htts_task_t*)cgi);
|
||||
|
||||
cgi->on_kill = on_kill;
|
||||
cgi->options = options;
|
||||
|
||||
bind_task_to_client (cgi, csck);
|
||||
@@ -995,12 +1021,12 @@ int hio_svc_htts_docgi (hio_svc_htts_t* htts, hio_dev_sck_t* csck, hio_htre_t* r
|
||||
|
||||
if ((n = bind_task_to_peer(cgi, csck, req, docroot, script)) <= -1)
|
||||
{
|
||||
hio_svc_htts_task_sendfinalres(cgi, (n == 2? HIO_HTTP_STATUS_FORBIDDEN: HIO_HTTP_STATUS_INTERNAL_SERVER_ERROR), HIO_NULL, HIO_NULL, 1);
|
||||
if (n == -2) status_code == HIO_HTTP_STATUS_FORBIDDEN;
|
||||
goto oops;
|
||||
}
|
||||
bound_to_peer = 1;
|
||||
|
||||
if (hio_svc_htts_task_handleexpect100(cgi) <= -1) goto oops;
|
||||
if (hio_svc_htts_task_handleexpect100(cgi, 0) <= -1) goto oops;
|
||||
if (setup_for_content_length(cgi, req) <= -1) goto oops;
|
||||
|
||||
/* TODO: store current input watching state and use it when destroying the cgi data */
|
||||
@@ -1008,12 +1034,17 @@ int hio_svc_htts_docgi (hio_svc_htts_t* htts, hio_dev_sck_t* csck, hio_htre_t* r
|
||||
|
||||
HIO_SVC_HTTS_TASKL_APPEND_TASK (&htts->task, (hio_svc_htts_task_t*)cgi);
|
||||
HIO_SVC_HTTS_TASK_RCDOWN((hio_svc_htts_task_t*)cgi);
|
||||
|
||||
/* set the on_kill callback only if this function can return success.
|
||||
* the on_kill callback won't be executed if this function returns failure. */
|
||||
cgi->on_kill = on_kill;
|
||||
return 0;
|
||||
|
||||
oops:
|
||||
HIO_DEBUG3 (hio, "HTTS(%p) - FAILURE in docgi - socket(%p) - %js\n", htts, csck, hio_geterrmsg(hio));
|
||||
if (cgi)
|
||||
{
|
||||
hio_svc_htts_task_sendfinalres(cgi, status_code, HIO_NULL, HIO_NULL, 1);
|
||||
if (bound_to_peer) unbind_task_from_peer (cgi, 1);
|
||||
if (bound_to_client) unbind_task_from_client (cgi, 1);
|
||||
cgi_halt_participating_devices (cgi);
|
||||
|
||||
129
lib/http-fcgi.c
129
lib/http-fcgi.c
@@ -145,9 +145,9 @@ static void fcgi_on_kill (hio_svc_htts_task_t* task)
|
||||
|
||||
if (fcgi->on_kill) fcgi->on_kill (task);
|
||||
|
||||
/* [NOTE]
|
||||
* 1. if hio_svc_htts_task_kill() is called, fcgi->peer, fcgi->peer_htrd, fcgi->task_csck,
|
||||
* fcgi->task_client may not not null.
|
||||
/* [NOTE]
|
||||
* 1. if hio_svc_htts_task_kill() is called, fcgi->peer, fcgi->peer_htrd, fcgi->task_csck,
|
||||
* fcgi->task_client may not not null.
|
||||
* 2. this callback function doesn't decrement the reference count on fcgi because
|
||||
* it is the task destruction callback. (passing 0 to unbind_task_from_peer/client)
|
||||
*/
|
||||
@@ -160,7 +160,7 @@ static void fcgi_on_kill (hio_svc_htts_task_t* task)
|
||||
}
|
||||
|
||||
/* detach from the htts service only if it's attached */
|
||||
if (fcgi->task_next) HIO_SVC_HTTS_TASKL_UNLINK_TASK (fcgi);
|
||||
if (fcgi->task_next) HIO_SVC_HTTS_TASKL_UNLINK_TASK (fcgi);
|
||||
|
||||
HIO_DEBUG5 (hio, "HTTS(%p) - fcgi(t=%p,c=%p[%d],p=%p) - killed the task\n", fcgi->htts, fcgi, fcgi->task_client, (fcgi->task_csck? fcgi->task_csck->hnd: -1), fcgi->peer);
|
||||
}
|
||||
@@ -171,7 +171,7 @@ static void fcgi_peer_on_untie (hio_svc_fcgic_sess_t* peer, void* ctx)
|
||||
hio_t* hio = fcgi->htts->hio;
|
||||
|
||||
/* in case this untie event originates from the fcgi client itself.
|
||||
* fcgi_halt_participating_devices() calls hio_svc_fcgi_untie() again
|
||||
* fcgi_halt_participating_devices() calls hio_svc_fcgi_untie() again
|
||||
* to cause an infinite loop if we don't reset fcgi->peer to HIO_NULL here */
|
||||
|
||||
HIO_DEBUG5 (hio, "HTTS(%p) - fcgi(t=%p,c=%p[%d],p=%p) - untieing peer\n", fcgi->htts, fcgi, fcgi->task_client, (fcgi->task_csck? fcgi->task_csck->hnd: -1), fcgi->peer);
|
||||
@@ -188,7 +188,7 @@ static int fcgi_peer_on_read (hio_svc_fcgic_sess_t* peer, const void* data, hio_
|
||||
fcgi_t* fcgi = (fcgi_t*)ctx;
|
||||
hio_svc_htts_t* htts = fcgi->htts;
|
||||
hio_t* hio = htts->hio;
|
||||
|
||||
|
||||
if (dlen <= -1)
|
||||
{
|
||||
HIO_DEBUG2 (hio, "HTTS(%p) - read error from peer %p\n", htts, peer);
|
||||
@@ -364,7 +364,7 @@ static void fcgi_client_on_disconnect (hio_dev_sck_t* sck)
|
||||
|
||||
HIO_DEBUG4 (hio, "HTTS(%p) - fcgi(t=%p,c=%p,csck=%p) - handling client socket disconnect\n", htts, fcgi, cli, sck);
|
||||
|
||||
/* fcgi may be null if there is no associated task or
|
||||
/* fcgi may be null if there is no associated task or
|
||||
* the previously associated one is already gone */
|
||||
if (fcgi)
|
||||
{
|
||||
@@ -605,54 +605,58 @@ static void bind_task_to_client (fcgi_t* fcgi, hio_dev_sck_t* csck)
|
||||
static void unbind_task_from_client (fcgi_t* fcgi, int rcdown)
|
||||
{
|
||||
hio_dev_sck_t* csck = fcgi->task_csck;
|
||||
hio_svc_htts_cli_t* cli = hio_dev_sck_getxtn(csck);
|
||||
|
||||
HIO_ASSERT (fcgi->htts->hio, fcgi->task_client != HIO_NULL);
|
||||
HIO_ASSERT (fcgi->htts->hio, fcgi->task_csck != HIO_NULL);
|
||||
HIO_ASSERT (fcgi->htts->hio, fcgi->task_client->task == (hio_svc_htts_task_t*)fcgi);
|
||||
HIO_ASSERT (fcgi->htts->hio, fcgi->task_client->htrd != HIO_NULL);
|
||||
|
||||
if (fcgi->client_htrd_recbs_changed)
|
||||
if (cli->task) /* only if it's bound */
|
||||
{
|
||||
hio_htrd_setrecbs (fcgi->task_client->htrd, &fcgi->client_htrd_org_recbs);
|
||||
fcgi->client_htrd_recbs_changed = 0;
|
||||
HIO_ASSERT (fcgi->htts->hio, fcgi->task_client != HIO_NULL);
|
||||
HIO_ASSERT (fcgi->htts->hio, fcgi->task_csck != HIO_NULL);
|
||||
HIO_ASSERT (fcgi->htts->hio, fcgi->task_client->task == (hio_svc_htts_task_t*)fcgi);
|
||||
HIO_ASSERT (fcgi->htts->hio, fcgi->task_client->htrd != HIO_NULL);
|
||||
|
||||
if (fcgi->client_htrd_recbs_changed)
|
||||
{
|
||||
hio_htrd_setrecbs (fcgi->task_client->htrd, &fcgi->client_htrd_org_recbs);
|
||||
fcgi->client_htrd_recbs_changed = 0;
|
||||
}
|
||||
|
||||
if (fcgi->client_org_on_read)
|
||||
{
|
||||
csck->on_read = fcgi->client_org_on_read;
|
||||
fcgi->client_org_on_read = HIO_NULL;
|
||||
}
|
||||
|
||||
if (fcgi->client_org_on_write)
|
||||
{
|
||||
csck->on_write = fcgi->client_org_on_write;
|
||||
fcgi->client_org_on_write = HIO_NULL;
|
||||
}
|
||||
|
||||
if (fcgi->client_org_on_disconnect)
|
||||
{
|
||||
csck->on_disconnect = fcgi->client_org_on_disconnect;
|
||||
fcgi->client_org_on_disconnect = HIO_NULL;
|
||||
}
|
||||
|
||||
/* there is some ordering issue in using HIO_SVC_HTTS_TASK_UNREF()
|
||||
* because it can destroy the fcgi itself. so reset fcgi->task_client->task
|
||||
* to null and call RCDOWN() later */
|
||||
fcgi->task_client->task = HIO_NULL;
|
||||
|
||||
/* these two lines are also done in csck_on_disconnect() in http-svr.c because the socket is destroyed.
|
||||
* the same lines here are because the task is unbound while the socket is still alive */
|
||||
fcgi->task_client = HIO_NULL;
|
||||
fcgi->task_csck = HIO_NULL;
|
||||
|
||||
/* enable input watching on the socket being unbound */
|
||||
if (fcgi->task_keep_client_alive && hio_dev_sck_read(csck, 1) <= -1)
|
||||
{
|
||||
HIO_DEBUG2 (fcgi->htts->hio, "HTTS(%p) - halting client(%p) for failure to enable input watching\n", fcgi->htts, csck);
|
||||
hio_dev_sck_halt (csck);
|
||||
}
|
||||
|
||||
if (rcdown) HIO_SVC_HTTS_TASK_RCDOWN ((hio_svc_htts_task_t*)fcgi);
|
||||
}
|
||||
|
||||
if (fcgi->client_org_on_read)
|
||||
{
|
||||
csck->on_read = fcgi->client_org_on_read;
|
||||
fcgi->client_org_on_read = HIO_NULL;
|
||||
}
|
||||
|
||||
if (fcgi->client_org_on_write)
|
||||
{
|
||||
csck->on_write = fcgi->client_org_on_write;
|
||||
fcgi->client_org_on_write = HIO_NULL;
|
||||
}
|
||||
|
||||
if (fcgi->client_org_on_disconnect)
|
||||
{
|
||||
csck->on_disconnect = fcgi->client_org_on_disconnect;
|
||||
fcgi->client_org_on_disconnect = HIO_NULL;
|
||||
}
|
||||
|
||||
/* there is some ordering issue in using HIO_SVC_HTTS_TASK_UNREF()
|
||||
* because it can destroy the fcgi itself. so reset fcgi->task_client->task
|
||||
* to null and call RCDOWN() later */
|
||||
fcgi->task_client->task = HIO_NULL;
|
||||
|
||||
/* these two lines are also done in csck_on_disconnect() in http-svr.c because the socket is destroyed.
|
||||
* the same lines here are because the task is unbound while the socket is still alive */
|
||||
fcgi->task_client = HIO_NULL;
|
||||
fcgi->task_csck = HIO_NULL;
|
||||
|
||||
/* enable input watching on the socket being unbound */
|
||||
if (fcgi->task_keep_client_alive && hio_dev_sck_read(csck, 1) <= -1)
|
||||
{
|
||||
HIO_DEBUG2 (fcgi->htts->hio, "HTTS(%p) - halting client(%p) for failure to enable input watching\n", fcgi->htts, csck);
|
||||
hio_dev_sck_halt (csck);
|
||||
}
|
||||
|
||||
if (rcdown) HIO_SVC_HTTS_TASK_RCDOWN ((hio_svc_htts_task_t*)fcgi);
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------- */
|
||||
@@ -669,7 +673,7 @@ static int bind_task_to_peer (fcgi_t* fcgi, const hio_skad_t* fcgis_addr)
|
||||
hio_htrd_setrecbs (htrd, &peer_htrd_recbs);
|
||||
|
||||
fcgi->peer = hio_svc_fcgic_tie(fcgi->htts->fcgic, fcgis_addr, fcgi_peer_on_read, fcgi_peer_on_write, fcgi_peer_on_untie, fcgi);
|
||||
if (HIO_UNLIKELY(!fcgi->peer))
|
||||
if (HIO_UNLIKELY(!fcgi->peer))
|
||||
{
|
||||
hio_htrd_close (htrd);
|
||||
return -1;
|
||||
@@ -753,14 +757,15 @@ int hio_svc_htts_dofcgi (hio_svc_htts_t* htts, hio_dev_sck_t* csck, hio_htre_t*
|
||||
hio_t* hio = htts->hio;
|
||||
hio_svc_htts_cli_t* cli = hio_dev_sck_getxtn(csck);
|
||||
fcgi_t* fcgi = HIO_NULL;
|
||||
int status_code = HIO_HTTP_STATUS_INTERNAL_SERVER_ERROR;
|
||||
int bound_to_client = 0, bound_to_peer = 0;
|
||||
|
||||
/* ensure that you call this function before any contents is received */
|
||||
HIO_ASSERT (hio, hio_htre_getcontentlen(req) == 0);
|
||||
|
||||
if (HIO_UNLIKELY(!htts->fcgic))
|
||||
if (cli->task)
|
||||
{
|
||||
hio_seterrbfmt (hio, HIO_ENOCAPA, "fcgi client service not enabled");
|
||||
hio_seterrbfmt (hio, HIO_EPERM, "duplicate task request prohibited");
|
||||
goto oops;
|
||||
}
|
||||
|
||||
@@ -768,7 +773,12 @@ int hio_svc_htts_dofcgi (hio_svc_htts_t* htts, hio_dev_sck_t* csck, hio_htre_t*
|
||||
if (HIO_UNLIKELY(!fcgi)) goto oops;
|
||||
HIO_SVC_HTTS_TASK_RCUP ((hio_svc_htts_task_t*)fcgi);
|
||||
|
||||
fcgi->on_kill = on_kill; /* custom on_kill handler by the caller */
|
||||
if (HIO_UNLIKELY(!htts->fcgic))
|
||||
{
|
||||
status_code = HIO_HTTP_STATUS_SERVICE_UNAVAILABLE;
|
||||
hio_seterrbfmt (hio, HIO_ENOCAPA, "fcgi client service not enabled");
|
||||
goto oops;
|
||||
}
|
||||
|
||||
bind_task_to_client (fcgi, csck);
|
||||
bound_to_client = 1;
|
||||
@@ -776,7 +786,7 @@ int hio_svc_htts_dofcgi (hio_svc_htts_t* htts, hio_dev_sck_t* csck, hio_htre_t*
|
||||
if (bind_task_to_peer(fcgi, fcgis_addr) <= -1) goto oops;
|
||||
bound_to_peer = 1;
|
||||
|
||||
if (hio_svc_htts_task_handleexpect100(fcgi) <= -1) goto oops;
|
||||
if (hio_svc_htts_task_handleexpect100(fcgi, 0) <= -1) goto oops;
|
||||
if (setup_for_content_length(fcgi, req) <= -1) goto oops;
|
||||
|
||||
/* TODO: store current input watching state and use it when destroying the fcgi data */
|
||||
@@ -790,12 +800,17 @@ int hio_svc_htts_dofcgi (hio_svc_htts_t* htts, hio_dev_sck_t* csck, hio_htre_t*
|
||||
|
||||
HIO_SVC_HTTS_TASKL_APPEND_TASK (&htts->task, (hio_svc_htts_task_t*)fcgi);
|
||||
HIO_SVC_HTTS_TASK_RCDOWN ((hio_svc_htts_task_t*)fcgi);
|
||||
|
||||
/* set the on_kill callback only if this function can return success.
|
||||
* the on_kill callback won't be executed if this function returns failure. */
|
||||
fcgi->on_kill = on_kill; /* custom on_kill handler by the caller */
|
||||
return 0;
|
||||
|
||||
oops:
|
||||
HIO_DEBUG2 (hio, "HTTS(%p) - FAILURE in dofcgi - socket(%p)\n", htts, csck);
|
||||
if (fcgi)
|
||||
{
|
||||
hio_svc_htts_task_sendfinalres(fcgi, status_code, HIO_NULL, HIO_NULL, 1);
|
||||
if (bound_to_peer) unbind_task_from_peer (fcgi, 1);
|
||||
if (bound_to_client) unbind_task_from_client (fcgi, 1);
|
||||
fcgi_halt_participating_devices (fcgi);
|
||||
|
||||
118
lib/http-file.c
118
lib/http-file.c
@@ -658,54 +658,58 @@ static void bind_task_to_client (file_t* file, hio_dev_sck_t* csck)
|
||||
static void unbind_task_from_client (file_t* file, int rcdown)
|
||||
{
|
||||
hio_dev_sck_t* csck = file->task_csck;
|
||||
hio_svc_htts_cli_t* cli = hio_dev_sck_getxtn(csck);
|
||||
|
||||
HIO_ASSERT (file->htts->hio, file->task_client != HIO_NULL);
|
||||
HIO_ASSERT (file->htts->hio, file->task_csck != HIO_NULL);
|
||||
HIO_ASSERT (file->htts->hio, file->task_client->task == (hio_svc_htts_task_t*)file);
|
||||
HIO_ASSERT (file->htts->hio, file->task_client->htrd != HIO_NULL);
|
||||
|
||||
if (file->client_htrd_recbs_changed)
|
||||
if (cli) /* only if it's bound */
|
||||
{
|
||||
hio_htrd_setrecbs (file->task_client->htrd, &file->client_htrd_org_recbs);
|
||||
file->client_htrd_recbs_changed = 0;
|
||||
HIO_ASSERT (file->htts->hio, file->task_client != HIO_NULL);
|
||||
HIO_ASSERT (file->htts->hio, file->task_csck != HIO_NULL);
|
||||
HIO_ASSERT (file->htts->hio, file->task_client->task == (hio_svc_htts_task_t*)file);
|
||||
HIO_ASSERT (file->htts->hio, file->task_client->htrd != HIO_NULL);
|
||||
|
||||
if (file->client_htrd_recbs_changed)
|
||||
{
|
||||
hio_htrd_setrecbs (file->task_client->htrd, &file->client_htrd_org_recbs);
|
||||
file->client_htrd_recbs_changed = 0;
|
||||
}
|
||||
|
||||
if (file->client_org_on_read)
|
||||
{
|
||||
csck->on_read = file->client_org_on_read;
|
||||
file->client_org_on_read = HIO_NULL;
|
||||
}
|
||||
|
||||
if (file->client_org_on_write)
|
||||
{
|
||||
csck->on_write = file->client_org_on_write;
|
||||
file->client_org_on_write = HIO_NULL;
|
||||
}
|
||||
|
||||
if (file->client_org_on_disconnect)
|
||||
{
|
||||
csck->on_disconnect = file->client_org_on_disconnect;
|
||||
file->client_org_on_disconnect = HIO_NULL;
|
||||
}
|
||||
|
||||
/* there is some ordering issue in using HIO_SVC_HTTS_TASK_UNREF()
|
||||
* because it can destroy the file itself. so reset file->task_client->task
|
||||
* to null and call RCDOWN() later */
|
||||
file->task_client->task = HIO_NULL;
|
||||
|
||||
/* these two lines are also done in csck_on_disconnect() in http-svr.c because the socket is destroyed.
|
||||
* the same lines here are because the task is unbound while the socket is still alive */
|
||||
file->task_client = HIO_NULL;
|
||||
file->task_csck = HIO_NULL;
|
||||
|
||||
/* enable input watching on the socket being unbound */
|
||||
if (file->task_keep_client_alive && hio_dev_sck_read(csck, 1) <= -1)
|
||||
{
|
||||
HIO_DEBUG2 (file->htts->hio, "HTTS(%p) - halting client(%p) for failure to enable input watching\n", file->htts, csck);
|
||||
hio_dev_sck_halt (csck);
|
||||
}
|
||||
|
||||
if (rcdown) HIO_SVC_HTTS_TASK_RCDOWN ((hio_svc_htts_task_t*)file);
|
||||
}
|
||||
|
||||
if (file->client_org_on_read)
|
||||
{
|
||||
csck->on_read = file->client_org_on_read;
|
||||
file->client_org_on_read = HIO_NULL;
|
||||
}
|
||||
|
||||
if (file->client_org_on_write)
|
||||
{
|
||||
csck->on_write = file->client_org_on_write;
|
||||
file->client_org_on_write = HIO_NULL;
|
||||
}
|
||||
|
||||
if (file->client_org_on_disconnect)
|
||||
{
|
||||
csck->on_disconnect = file->client_org_on_disconnect;
|
||||
file->client_org_on_disconnect = HIO_NULL;
|
||||
}
|
||||
|
||||
/* there is some ordering issue in using HIO_SVC_HTTS_TASK_UNREF()
|
||||
* because it can destroy the file itself. so reset file->task_client->task
|
||||
* to null and call RCDOWN() later */
|
||||
file->task_client->task = HIO_NULL;
|
||||
|
||||
/* these two lines are also done in csck_on_disconnect() in http-svr.c because the socket is destroyed.
|
||||
* the same lines here are because the task is unbound while the socket is still alive */
|
||||
file->task_client = HIO_NULL;
|
||||
file->task_csck = HIO_NULL;
|
||||
|
||||
/* enable input watching on the socket being unbound */
|
||||
if (file->task_keep_client_alive && hio_dev_sck_read(csck, 1) <= -1)
|
||||
{
|
||||
HIO_DEBUG2 (file->htts->hio, "HTTS(%p) - halting client(%p) for failure to enable input watching\n", file->htts, csck);
|
||||
hio_dev_sck_halt (csck);
|
||||
}
|
||||
|
||||
if (rcdown) HIO_SVC_HTTS_TASK_RCDOWN ((hio_svc_htts_task_t*)file);
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------- */
|
||||
@@ -874,6 +878,7 @@ int hio_svc_htts_dofile (hio_svc_htts_t* htts, hio_dev_sck_t* csck, hio_htre_t*
|
||||
hio_svc_htts_cli_t* cli = hio_dev_sck_getxtn(csck);
|
||||
file_t* file = HIO_NULL;
|
||||
hio_bch_t* actual_file = HIO_NULL;
|
||||
int status_code = HIO_HTTP_STATUS_INTERNAL_SERVER_ERROR;
|
||||
int bound_to_client = 0, bound_to_peer = 0;
|
||||
|
||||
/* ensure that you call this function before any contents is received */
|
||||
@@ -882,14 +887,19 @@ int hio_svc_htts_dofile (hio_svc_htts_t* htts, hio_dev_sck_t* csck, hio_htre_t*
|
||||
|
||||
HIO_DEBUG5 (hio, "HTTS(%p) - file(c=%d) - [%hs] %hs%hs\n", htts, (int)csck->hnd, cli->cli_addr_bcstr, (docroot[0] == '/' && docroot[1] == '\0' && filepath[0] == '/'? "": docroot), filepath);
|
||||
|
||||
actual_file = hio_svc_htts_dupmergepaths(htts, docroot, filepath);
|
||||
if (HIO_UNLIKELY(!actual_file)) goto oops;
|
||||
if (cli->task)
|
||||
{
|
||||
hio_seterrbfmt (hio, HIO_EPERM, "duplicate task request prohibited");
|
||||
goto oops;
|
||||
}
|
||||
|
||||
file = (file_t*)hio_svc_htts_task_make(htts, HIO_SIZEOF(*file), file_on_kill, req, csck);
|
||||
if (HIO_UNLIKELY(!file)) goto oops;
|
||||
HIO_SVC_HTTS_TASK_RCUP ((hio_svc_htts_task_t*)file); /* for temporary protection */
|
||||
|
||||
file->on_kill = on_kill;
|
||||
actual_file = hio_svc_htts_dupmergepaths(htts, docroot, filepath);
|
||||
if (HIO_UNLIKELY(!actual_file)) goto oops;
|
||||
|
||||
file->options = options;
|
||||
file->cbs = cbs; /* the given pointer must outlive the lifespan of the while file handling cycle. */
|
||||
file->sendfile_ok = hio_dev_sck_sendfileok(csck);
|
||||
@@ -898,8 +908,8 @@ int hio_svc_htts_dofile (hio_svc_htts_t* htts, hio_dev_sck_t* csck, hio_htre_t*
|
||||
|
||||
bind_task_to_client (file, csck); /* the file task's reference count is incremented */
|
||||
bound_to_client = 1;
|
||||
|
||||
if (hio_svc_htts_task_handleexpect100((hio_svc_htts_task_t*)file) <= -1) goto oops;
|
||||
|
||||
if (hio_svc_htts_task_handleexpect100((hio_svc_htts_task_t*)file, 0) <= -1) goto oops;
|
||||
if (setup_for_content_length(file, req) <= -1) goto oops;
|
||||
|
||||
if (bind_task_to_peer(file, req, actual_file, mime_type) <= -1) goto oops;
|
||||
@@ -911,18 +921,22 @@ int hio_svc_htts_dofile (hio_svc_htts_t* htts, hio_dev_sck_t* csck, hio_htre_t*
|
||||
|
||||
HIO_SVC_HTTS_TASKL_APPEND_TASK (&htts->task, (hio_svc_htts_task_t*)file);
|
||||
HIO_SVC_HTTS_TASK_RCDOWN ((hio_svc_htts_task_t*)file);
|
||||
|
||||
/* set the on_kill callback only if this function can return success.
|
||||
* the on_kill callback won't be executed if this function returns failure. */
|
||||
file->on_kill = on_kill;
|
||||
return 0;
|
||||
|
||||
oops:
|
||||
HIO_DEBUG2 (hio, "HTTS(%p) - file(c=%d) failure\n", htts, csck->hnd);
|
||||
if (file)
|
||||
{
|
||||
hio_svc_htts_task_sendfinalres(file, status_code, HIO_NULL, HIO_NULL, 1);
|
||||
if (bound_to_peer) unbind_task_from_peer (file, 0);
|
||||
if (bound_to_client) unbind_task_from_client (file, 0);
|
||||
|
||||
file_halt_participating_devices (file);
|
||||
if (actual_file) hio_freemem (hio, actual_file);
|
||||
HIO_SVC_HTTS_TASK_RCDOWN ((hio_svc_htts_task_t*)file);
|
||||
}
|
||||
if (actual_file) hio_freemem (hio, actual_file);
|
||||
return -1;
|
||||
}
|
||||
|
||||
110
lib/http-prxy.c
110
lib/http-prxy.c
@@ -722,54 +722,58 @@ static void bind_task_to_client (prxy_t* prxy, hio_dev_sck_t* csck)
|
||||
static void unbind_task_from_client (prxy_t* prxy, int rcdown)
|
||||
{
|
||||
hio_dev_sck_t* csck = prxy->task_csck;
|
||||
hio_svc_htts_cli_t* cli = hio_dev_sck_getxtn(csck);
|
||||
|
||||
HIO_ASSERT (prxy->htts->hio, prxy->task_client != HIO_NULL);
|
||||
HIO_ASSERT (prxy->htts->hio, prxy->task_csck != HIO_NULL);
|
||||
HIO_ASSERT (prxy->htts->hio, prxy->task_client->task == (hio_svc_htts_task_t*)prxy);
|
||||
HIO_ASSERT (prxy->htts->hio, prxy->task_client->htrd != HIO_NULL);
|
||||
|
||||
if (prxy->client_htrd_recbs_changed)
|
||||
if (cli->task) /* only if it's bound */
|
||||
{
|
||||
hio_htrd_setrecbs (prxy->task_client->htrd, &prxy->client_htrd_org_recbs);
|
||||
prxy->client_htrd_recbs_changed = 0;
|
||||
HIO_ASSERT (prxy->htts->hio, prxy->task_client != HIO_NULL);
|
||||
HIO_ASSERT (prxy->htts->hio, prxy->task_csck != HIO_NULL);
|
||||
HIO_ASSERT (prxy->htts->hio, prxy->task_client->task == (hio_svc_htts_task_t*)prxy);
|
||||
HIO_ASSERT (prxy->htts->hio, prxy->task_client->htrd != HIO_NULL);
|
||||
|
||||
if (prxy->client_htrd_recbs_changed)
|
||||
{
|
||||
hio_htrd_setrecbs (prxy->task_client->htrd, &prxy->client_htrd_org_recbs);
|
||||
prxy->client_htrd_recbs_changed = 0;
|
||||
}
|
||||
|
||||
if (prxy->client_org_on_read)
|
||||
{
|
||||
csck->on_read = prxy->client_org_on_read;
|
||||
prxy->client_org_on_read = HIO_NULL;
|
||||
}
|
||||
|
||||
if (prxy->client_org_on_write)
|
||||
{
|
||||
csck->on_write = prxy->client_org_on_write;
|
||||
prxy->client_org_on_write = HIO_NULL;
|
||||
}
|
||||
|
||||
if (prxy->client_org_on_disconnect)
|
||||
{
|
||||
csck->on_disconnect = prxy->client_org_on_disconnect;
|
||||
prxy->client_org_on_disconnect = HIO_NULL;
|
||||
}
|
||||
|
||||
/* there is some ordering issue in using HIO_SVC_HTTS_TASK_UNREF()
|
||||
* because it can destroy the prxy itself. so reset prxy->task_client->task
|
||||
* to null and call RCDOWN() later */
|
||||
prxy->task_client->task = HIO_NULL;
|
||||
|
||||
/* these two lines are also done in csck_on_disconnect() in http-svr.c because the socket is destroyed.
|
||||
* the same lines here are because the task is unbound while the socket is still alive */
|
||||
prxy->task_client = HIO_NULL;
|
||||
prxy->task_csck = HIO_NULL;
|
||||
|
||||
/* enable input watching on the socket being unbound */
|
||||
if (prxy->task_keep_client_alive && hio_dev_sck_read(csck, 1) <= -1)
|
||||
{
|
||||
HIO_DEBUG2 (prxy->htts->hio, "HTTS(%p) - halting client(%p) for failure to enable input watching\n", prxy->htts, csck);
|
||||
hio_dev_sck_halt (csck);
|
||||
}
|
||||
|
||||
if (rcdown) HIO_SVC_HTTS_TASK_RCDOWN ((hio_svc_htts_task_t*)prxy);
|
||||
}
|
||||
|
||||
if (prxy->client_org_on_read)
|
||||
{
|
||||
csck->on_read = prxy->client_org_on_read;
|
||||
prxy->client_org_on_read = HIO_NULL;
|
||||
}
|
||||
|
||||
if (prxy->client_org_on_write)
|
||||
{
|
||||
csck->on_write = prxy->client_org_on_write;
|
||||
prxy->client_org_on_write = HIO_NULL;
|
||||
}
|
||||
|
||||
if (prxy->client_org_on_disconnect)
|
||||
{
|
||||
csck->on_disconnect = prxy->client_org_on_disconnect;
|
||||
prxy->client_org_on_disconnect = HIO_NULL;
|
||||
}
|
||||
|
||||
/* there is some ordering issue in using HIO_SVC_HTTS_TASK_UNREF()
|
||||
* because it can destroy the prxy itself. so reset prxy->task_client->task
|
||||
* to null and call RCDOWN() later */
|
||||
prxy->task_client->task = HIO_NULL;
|
||||
|
||||
/* these two lines are also done in csck_on_disconnect() in http-svr.c because the socket is destroyed.
|
||||
* the same lines here are because the task is unbound while the socket is still alive */
|
||||
prxy->task_client = HIO_NULL;
|
||||
prxy->task_csck = HIO_NULL;
|
||||
|
||||
/* enable input watching on the socket being unbound */
|
||||
if (prxy->task_keep_client_alive && hio_dev_sck_read(csck, 1) <= -1)
|
||||
{
|
||||
HIO_DEBUG2 (prxy->htts->hio, "HTTS(%p) - halting client(%p) for failure to enable input watching\n", prxy->htts, csck);
|
||||
hio_dev_sck_halt (csck);
|
||||
}
|
||||
|
||||
if (rcdown) HIO_SVC_HTTS_TASK_RCDOWN ((hio_svc_htts_task_t*)prxy);
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------- */
|
||||
@@ -919,18 +923,23 @@ int hio_svc_htts_doprxy (hio_svc_htts_t* htts, hio_dev_sck_t* csck, hio_htre_t*
|
||||
hio_t* hio = htts->hio;
|
||||
hio_svc_htts_cli_t* cli = hio_dev_sck_getxtn(csck);
|
||||
prxy_t* prxy = HIO_NULL;
|
||||
int n, status_code = HIO_HTTP_STATUS_INTERNAL_SERVER_ERROR;
|
||||
int bound_to_client = 0, bound_to_peer = 0;
|
||||
int n;
|
||||
|
||||
/* ensure that you call this function before any contents is received */
|
||||
HIO_ASSERT (hio, hio_htre_getcontentlen(req) == 0);
|
||||
HIO_ASSERT (hio, cli->sck == csck);
|
||||
|
||||
if (cli->task)
|
||||
{
|
||||
hio_seterrbfmt (hio, HIO_EPERM, "duplicate task request prohibited");
|
||||
goto oops;
|
||||
}
|
||||
|
||||
prxy = (prxy_t*)hio_svc_htts_task_make(htts, HIO_SIZEOF(*prxy), prxy_on_kill, req, csck);
|
||||
if (HIO_UNLIKELY(!prxy)) goto oops;
|
||||
HIO_SVC_HTTS_TASK_RCUP ((hio_svc_htts_task_t*)prxy);
|
||||
|
||||
prxy->on_kill = on_kill;
|
||||
prxy->options = options;
|
||||
|
||||
bind_task_to_client (prxy, csck);
|
||||
@@ -943,7 +952,7 @@ int hio_svc_htts_doprxy (hio_svc_htts_t* htts, hio_dev_sck_t* csck, hio_htre_t*
|
||||
}
|
||||
bound_to_peer = 1;
|
||||
|
||||
if (hio_svc_htts_task_handleexpect100(prxy) <= -1) goto oops;
|
||||
if (hio_svc_htts_task_handleexpect100(prxy, 0) <= -1) goto oops;
|
||||
if (setup_for_content_length(prxy, req) <= -1) goto oops;
|
||||
|
||||
/* TODO: store current input watching state and use it when destroying the prxy data */
|
||||
@@ -951,12 +960,17 @@ int hio_svc_htts_doprxy (hio_svc_htts_t* htts, hio_dev_sck_t* csck, hio_htre_t*
|
||||
|
||||
HIO_SVC_HTTS_TASKL_APPEND_TASK (&htts->task, (hio_svc_htts_task_t*)prxy);
|
||||
HIO_SVC_HTTS_TASK_RCDOWN ((hio_svc_htts_task_t*)prxy);
|
||||
|
||||
/* set the on_kill callback only if this function can return success.
|
||||
* the on_kill callback won't be executed if this function returns failure. */
|
||||
prxy->on_kill = on_kill;
|
||||
return 0;
|
||||
|
||||
oops:
|
||||
HIO_DEBUG2 (hio, "HTTS(%p) - FAILURE in doprxy - socket(%p)\n", htts, csck);
|
||||
if (prxy)
|
||||
{
|
||||
hio_svc_htts_task_sendfinalres(prxy, status_code, HIO_NULL, HIO_NULL, 1);
|
||||
if (bound_to_peer) unbind_task_from_peer (prxy, 1);
|
||||
if (bound_to_client) unbind_task_from_client (prxy, 1);
|
||||
prxy_halt_participating_devices (prxy);
|
||||
|
||||
@@ -42,24 +42,35 @@ static void client_on_disconnect (hio_dev_sck_t* sck);
|
||||
|
||||
static int inc_ntasks (hio_svc_htts_t* htts)
|
||||
{
|
||||
#if defined(HCL_ATOMIC_LOAD) && defined(HCL_ATOMIC_CMP_XCHG)
|
||||
int ok;
|
||||
do
|
||||
{
|
||||
hio_oow_t ntasks;
|
||||
ntasks = HCL_ATOMIC_LOAD(&htts->stat.ntasks);
|
||||
if (ntasks >= htts->option.task_cgi_max)
|
||||
if (ntasks >= htts->option.task_max)
|
||||
{
|
||||
hio_seterrbfmt (htts->hio, HIO_ENOCAPA, "too many tasks");
|
||||
printf ("too many tasks...\n");
|
||||
return -1;
|
||||
}
|
||||
ok = HCL_ATOMIC_CMP_XCHG(&htts->stat.ntasks, &ntasks, ntasks + 1);
|
||||
}
|
||||
while (!ok);
|
||||
#else
|
||||
if (htts->stat.ntasks >= htts->option.task_max)
|
||||
{
|
||||
hio_seterrbfmt (htts->hio, HIO_ENOCAPA, "too many tasks");
|
||||
return -1;
|
||||
}
|
||||
htts->stat.ntasks++;
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void dec_ntasks (hio_svc_htts_t* htts)
|
||||
{
|
||||
#if defined(HCL_ATOMIC_LOAD) && defined(HCL_ATOMIC_CMP_XCHG)
|
||||
int ok;
|
||||
do
|
||||
{
|
||||
@@ -68,6 +79,9 @@ static void dec_ntasks (hio_svc_htts_t* htts)
|
||||
ok = HCL_ATOMIC_CMP_XCHG(&htts->stat.ntasks, &ntasks, ntasks - 1);
|
||||
}
|
||||
while (!ok);
|
||||
#else
|
||||
htts->stat.ntasks--;
|
||||
#endif
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------ */
|
||||
@@ -482,7 +496,7 @@ hio_svc_htts_t* hio_svc_htts_start (hio_t* hio, hio_oow_t xtnsize, hio_dev_sck_b
|
||||
HIO_DEBUG1 (hio, "HTTS - STARTING SERVICE %p\n", htts);
|
||||
|
||||
htts->hio = hio;
|
||||
htts->svc_stop = hio_svc_htts_stop;
|
||||
htts->svc_stop = (hio_svc_stop_t)hio_svc_htts_stop;
|
||||
htts->proc_req = proc_req;
|
||||
htts->idle_tmridx = HIO_TMRIDX_INVALID;
|
||||
|
||||
@@ -1145,7 +1159,7 @@ int hio_svc_htts_task_sendfinalres (hio_svc_htts_task_t* task, int status_code,
|
||||
return 1;
|
||||
}
|
||||
|
||||
int hio_svc_htts_task_handleexpect100 (hio_svc_htts_task_t* task)
|
||||
int hio_svc_htts_task_handleexpect100 (hio_svc_htts_task_t* task, int no_continue)
|
||||
{
|
||||
#if !defined(TASK_ALLOW_UNLIMITED_REQ_CONTENT_LENGTH)
|
||||
if (task->task_req_conlen_unlimited)
|
||||
@@ -1160,30 +1174,33 @@ int hio_svc_htts_task_handleexpect100 (hio_svc_htts_task_t* task)
|
||||
|
||||
if (task->task_req_flags & HIO_HTRE_ATTR_EXPECT100)
|
||||
{
|
||||
/* TODO: Expect: 100-continue? who should handle this? fcgi? or the http server? */
|
||||
/* CAN I LET the fcgi SCRIPT handle this? */
|
||||
if (hio_comp_http_version_numbers(&task->task_req_version, 1, 1) >= 0 &&
|
||||
(task->task_req_conlen_unlimited || task->task_req_conlen > 0) &&
|
||||
(task->task_req_method != HIO_HTTP_GET && task->task_req_method != HIO_HTTP_HEAD))
|
||||
if (!no_continue)
|
||||
{
|
||||
/*
|
||||
* Don't send 100 Continue if http verions is lower than 1.1
|
||||
* [RFC7231]
|
||||
* A server that receives a 100-continue expectation in an HTTP/1.0
|
||||
* request MUST ignore that expectation.
|
||||
*
|
||||
* Don't send 100 Continue if expected content length is 0.
|
||||
* [RFC7231]
|
||||
* A server MAY omit sending a 100 (Continue) response if it has
|
||||
* already received some or all of the message body for the
|
||||
* corresponding request, or if the framing indicates that there is
|
||||
* no message body.
|
||||
*/
|
||||
hio_bch_t msgbuf[64];
|
||||
hio_oow_t msglen;
|
||||
msglen = hio_fmttobcstr(task->htts->hio, msgbuf, HIO_COUNTOF(msgbuf), "HTTP/%d.%d %d %hs\r\n\r\n", task->task_req_version.major, task->task_req_version.minor, HIO_HTTP_STATUS_CONTINUE, hio_http_status_to_bcstr(HIO_HTTP_STATUS_CONTINUE));
|
||||
if (task->task_csck && write_raw_to_client(task, msgbuf, msglen) <= -1) return -1;
|
||||
task->task_res_ever_sent = 0; /* reset this as it's polluted for 100 continue */
|
||||
/* TODO: Expect: 100-continue? who should handle this? fcgi? or the http server? */
|
||||
/* CAN I LET the fcgi SCRIPT handle this? */
|
||||
if (hio_comp_http_version_numbers(&task->task_req_version, 1, 1) >= 0 &&
|
||||
(task->task_req_conlen_unlimited || task->task_req_conlen > 0) &&
|
||||
(task->task_req_method != HIO_HTTP_GET && task->task_req_method != HIO_HTTP_HEAD))
|
||||
{
|
||||
/*
|
||||
* Don't send 100 Continue if http verions is lower than 1.1
|
||||
* [RFC7231]
|
||||
* A server that receives a 100-continue expectation in an HTTP/1.0
|
||||
* request MUST ignore that expectation.
|
||||
*
|
||||
* Don't send 100 Continue if expected content length is 0.
|
||||
* [RFC7231]
|
||||
* A server MAY omit sending a 100 (Continue) response if it has
|
||||
* already received some or all of the message body for the
|
||||
* corresponding request, or if the framing indicates that there is
|
||||
* no message body.
|
||||
*/
|
||||
hio_bch_t msgbuf[64];
|
||||
hio_oow_t msglen;
|
||||
msglen = hio_fmttobcstr(task->htts->hio, msgbuf, HIO_COUNTOF(msgbuf), "HTTP/%d.%d %d %hs\r\n\r\n", task->task_req_version.major, task->task_req_version.minor, HIO_HTTP_STATUS_CONTINUE, hio_http_status_to_bcstr(HIO_HTTP_STATUS_CONTINUE));
|
||||
if (task->task_csck && write_raw_to_client(task, msgbuf, msglen) <= -1) return -1;
|
||||
task->task_res_ever_sent = 0; /* reset this as it's polluted for 100 continue */
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (task->task_req_flags & HIO_HTRE_ATTR_EXPECT)
|
||||
@@ -1272,3 +1289,4 @@ int hio_svc_htts_writetosidechan (hio_svc_htts_t* htts, hio_oow_t idx, const voi
|
||||
|
||||
return hio_dev_sck_writetosidechan(htts->l.sck[idx], dptr, dlen);
|
||||
}
|
||||
|
||||
|
||||
110
lib/http-thr.c
110
lib/http-thr.c
@@ -643,54 +643,58 @@ static void bind_task_to_client (thr_t* thr, hio_dev_sck_t* csck)
|
||||
static void unbind_task_from_client (thr_t* thr, int rcdown)
|
||||
{
|
||||
hio_dev_sck_t* csck = thr->task_csck;
|
||||
hio_svc_htts_cli_t* cli = hio_dev_sck_getxtn(csck);
|
||||
|
||||
HIO_ASSERT (thr->htts->hio, thr->task_client != HIO_NULL);
|
||||
HIO_ASSERT (thr->htts->hio, thr->task_csck != HIO_NULL);
|
||||
HIO_ASSERT (thr->htts->hio, thr->task_client->task == (hio_svc_htts_task_t*)thr);
|
||||
HIO_ASSERT (thr->htts->hio, thr->task_client->htrd != HIO_NULL);
|
||||
|
||||
if (thr->client_htrd_recbs_changed)
|
||||
if (cli->task) /* only if it's bound */
|
||||
{
|
||||
hio_htrd_setrecbs (thr->task_client->htrd, &thr->client_htrd_org_recbs);
|
||||
thr->client_htrd_recbs_changed = 0;
|
||||
HIO_ASSERT (thr->htts->hio, thr->task_client != HIO_NULL);
|
||||
HIO_ASSERT (thr->htts->hio, thr->task_csck != HIO_NULL);
|
||||
HIO_ASSERT (thr->htts->hio, thr->task_client->task == (hio_svc_htts_task_t*)thr);
|
||||
HIO_ASSERT (thr->htts->hio, thr->task_client->htrd != HIO_NULL);
|
||||
|
||||
if (thr->client_htrd_recbs_changed)
|
||||
{
|
||||
hio_htrd_setrecbs (thr->task_client->htrd, &thr->client_htrd_org_recbs);
|
||||
thr->client_htrd_recbs_changed = 0;
|
||||
}
|
||||
|
||||
if (thr->client_org_on_read)
|
||||
{
|
||||
csck->on_read = thr->client_org_on_read;
|
||||
thr->client_org_on_read = HIO_NULL;
|
||||
}
|
||||
|
||||
if (thr->client_org_on_write)
|
||||
{
|
||||
csck->on_write = thr->client_org_on_write;
|
||||
thr->client_org_on_write = HIO_NULL;
|
||||
}
|
||||
|
||||
if (thr->client_org_on_disconnect)
|
||||
{
|
||||
csck->on_disconnect = thr->client_org_on_disconnect;
|
||||
thr->client_org_on_disconnect = HIO_NULL;
|
||||
}
|
||||
|
||||
/* there is some ordering issue in using HIO_SVC_HTTS_TASK_UNREF()
|
||||
* because it can destroy the thr itself. so reset thr->task_client->task
|
||||
* to null and call RCDOWN() later */
|
||||
thr->task_client->task = HIO_NULL;
|
||||
|
||||
/* these two lines are also done in csck_on_disconnect() in http-svr.c because the socket is destroyed.
|
||||
* the same lines here are because the task is unbound while the socket is still alive */
|
||||
thr->task_client = HIO_NULL;
|
||||
thr->task_csck = HIO_NULL;
|
||||
|
||||
/* enable input watching on the socket being unbound */
|
||||
if (thr->task_keep_client_alive && hio_dev_sck_read(csck, 1) <= -1)
|
||||
{
|
||||
HIO_DEBUG2 (thr->htts->hio, "HTTS(%p) - halting client(%p) for failure to enable input watching\n", thr->htts, csck);
|
||||
hio_dev_sck_halt (csck);
|
||||
}
|
||||
|
||||
if (rcdown) HIO_SVC_HTTS_TASK_RCDOWN ((hio_svc_htts_task_t*)thr);
|
||||
}
|
||||
|
||||
if (thr->client_org_on_read)
|
||||
{
|
||||
csck->on_read = thr->client_org_on_read;
|
||||
thr->client_org_on_read = HIO_NULL;
|
||||
}
|
||||
|
||||
if (thr->client_org_on_write)
|
||||
{
|
||||
csck->on_write = thr->client_org_on_write;
|
||||
thr->client_org_on_write = HIO_NULL;
|
||||
}
|
||||
|
||||
if (thr->client_org_on_disconnect)
|
||||
{
|
||||
csck->on_disconnect = thr->client_org_on_disconnect;
|
||||
thr->client_org_on_disconnect = HIO_NULL;
|
||||
}
|
||||
|
||||
/* there is some ordering issue in using HIO_SVC_HTTS_TASK_UNREF()
|
||||
* because it can destroy the thr itself. so reset thr->task_client->task
|
||||
* to null and call RCDOWN() later */
|
||||
thr->task_client->task = HIO_NULL;
|
||||
|
||||
/* these two lines are also done in csck_on_disconnect() in http-svr.c because the socket is destroyed.
|
||||
* the same lines here are because the task is unbound while the socket is still alive */
|
||||
thr->task_client = HIO_NULL;
|
||||
thr->task_csck = HIO_NULL;
|
||||
|
||||
/* enable input watching on the socket being unbound */
|
||||
if (thr->task_keep_client_alive && hio_dev_sck_read(csck, 1) <= -1)
|
||||
{
|
||||
HIO_DEBUG2 (thr->htts->hio, "HTTS(%p) - halting client(%p) for failure to enable input watching\n", thr->htts, csck);
|
||||
hio_dev_sck_halt (csck);
|
||||
}
|
||||
|
||||
if (rcdown) HIO_SVC_HTTS_TASK_RCDOWN ((hio_svc_htts_task_t*)thr);
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------- */
|
||||
@@ -840,16 +844,23 @@ int hio_svc_htts_dothr (hio_svc_htts_t* htts, hio_dev_sck_t* csck, hio_htre_t* r
|
||||
hio_t* hio = htts->hio;
|
||||
hio_svc_htts_cli_t* cli = hio_dev_sck_getxtn(csck);
|
||||
thr_t* thr = HIO_NULL;
|
||||
int status_code = HIO_HTTP_STATUS_INTERNAL_SERVER_ERROR;
|
||||
int bound_to_client = 0, bound_to_peer = 0;
|
||||
|
||||
/* ensure that you call this function before any contents is received */
|
||||
HIO_ASSERT (hio, hio_htre_getcontentlen(req) == 0);
|
||||
HIO_ASSERT (hio, cli->sck == csck);
|
||||
|
||||
if (cli->task)
|
||||
{
|
||||
hio_seterrbfmt (hio, HIO_EPERM, "duplicate task request prohibited");
|
||||
goto oops;
|
||||
}
|
||||
|
||||
thr = (thr_t*)hio_svc_htts_task_make(htts, HIO_SIZEOF(*thr), thr_on_kill, req, csck);
|
||||
if (HIO_UNLIKELY(!thr)) goto oops;
|
||||
HIO_SVC_HTTS_TASK_RCUP ((hio_svc_htts_task_t*)thr);
|
||||
|
||||
thr->on_kill = on_kill;
|
||||
thr->options = options;
|
||||
|
||||
bind_task_to_client (thr, csck);
|
||||
@@ -858,7 +869,7 @@ int hio_svc_htts_dothr (hio_svc_htts_t* htts, hio_dev_sck_t* csck, hio_htre_t* r
|
||||
if (bind_task_to_peer(thr, csck, req, func, ctx) <= -1) goto oops;
|
||||
bound_to_peer = 1;
|
||||
|
||||
if (hio_svc_htts_task_handleexpect100(thr) <= -1) goto oops;
|
||||
if (hio_svc_htts_task_handleexpect100(thr, 0) <= -1) goto oops;
|
||||
if (setup_for_content_length(thr, req) <= -1) goto oops;
|
||||
|
||||
/* TODO: store current input watching state and use it when destroying the thr data */
|
||||
@@ -866,12 +877,17 @@ int hio_svc_htts_dothr (hio_svc_htts_t* htts, hio_dev_sck_t* csck, hio_htre_t* r
|
||||
|
||||
HIO_SVC_HTTS_TASKL_APPEND_TASK (&htts->task, (hio_svc_htts_task_t*)thr);
|
||||
HIO_SVC_HTTS_TASK_RCDOWN ((hio_svc_htts_task_t*)thr);
|
||||
|
||||
/* set the on_kill callback only if this function can return success.
|
||||
* the on_kill callback won't be executed if this function returns failure. */
|
||||
thr->on_kill = on_kill;
|
||||
return 0;
|
||||
|
||||
oops:
|
||||
HIO_DEBUG2 (hio, "HTTS(%p) - FAILURE in dothr - socket(%p)\n", htts, csck);
|
||||
if (thr)
|
||||
{
|
||||
hio_svc_htts_task_sendfinalres(thr, status_code, HIO_NULL, HIO_NULL, 1);
|
||||
if (bound_to_peer) unbind_task_from_peer (thr, 1);
|
||||
if (bound_to_client) unbind_task_from_client (thr, 1);
|
||||
thr_halt_participating_devices (thr);
|
||||
|
||||
125
lib/http-txt.c
125
lib/http-txt.c
@@ -245,54 +245,59 @@ static void bind_task_to_client (txt_t* txt, hio_dev_sck_t* csck)
|
||||
static void unbind_task_from_client (txt_t* txt, int rcdown)
|
||||
{
|
||||
hio_dev_sck_t* csck = txt->task_csck;
|
||||
hio_svc_htts_cli_t* cli = hio_dev_sck_getxtn(csck);
|
||||
|
||||
HIO_ASSERT (txt->htts->hio, txt->task_client != HIO_NULL);
|
||||
HIO_ASSERT (txt->htts->hio, txt->task_csck != HIO_NULL);
|
||||
HIO_ASSERT (txt->htts->hio, txt->task_client->task == (hio_svc_htts_task_t*)txt);
|
||||
HIO_ASSERT (txt->htts->hio, txt->task_client->htrd != HIO_NULL);
|
||||
|
||||
if (txt->client_htrd_recbs_changed)
|
||||
if (cli->task) /* only if it's bound */
|
||||
{
|
||||
hio_htrd_setrecbs (txt->task_client->htrd, &txt->client_htrd_org_recbs);
|
||||
txt->client_htrd_recbs_changed = 0;
|
||||
|
||||
HIO_ASSERT (txt->htts->hio, txt->task_client != HIO_NULL);
|
||||
HIO_ASSERT (txt->htts->hio, txt->task_csck != HIO_NULL);
|
||||
HIO_ASSERT (txt->htts->hio, txt->task_client->task == (hio_svc_htts_task_t*)txt);
|
||||
HIO_ASSERT (txt->htts->hio, txt->task_client->htrd != HIO_NULL);
|
||||
|
||||
if (txt->client_htrd_recbs_changed)
|
||||
{
|
||||
hio_htrd_setrecbs (txt->task_client->htrd, &txt->client_htrd_org_recbs);
|
||||
txt->client_htrd_recbs_changed = 0;
|
||||
}
|
||||
|
||||
if (txt->client_org_on_read)
|
||||
{
|
||||
csck->on_read = txt->client_org_on_read;
|
||||
txt->client_org_on_read = HIO_NULL;
|
||||
}
|
||||
|
||||
if (txt->client_org_on_write)
|
||||
{
|
||||
csck->on_write = txt->client_org_on_write;
|
||||
txt->client_org_on_write = HIO_NULL;
|
||||
}
|
||||
|
||||
if (txt->client_org_on_disconnect)
|
||||
{
|
||||
csck->on_disconnect = txt->client_org_on_disconnect;
|
||||
txt->client_org_on_disconnect = HIO_NULL;
|
||||
}
|
||||
|
||||
/* there is some ordering issue in using HIO_SVC_HTTS_TASK_UNREF()
|
||||
* because it can destroy the txt itself. so reset txt->task_client->task
|
||||
* to null and call RCDOWN() later */
|
||||
txt->task_client->task = HIO_NULL;
|
||||
|
||||
/* these two lines are also done in csck_on_disconnect() in http-svr.c because the socket is destroyed.
|
||||
* the same lines here are because the task is unbound while the socket is still alive */
|
||||
txt->task_client = HIO_NULL;
|
||||
txt->task_csck = HIO_NULL;
|
||||
|
||||
/* enable input watching on the socket being unbound */
|
||||
if (txt->task_keep_client_alive && hio_dev_sck_read(csck, 1) <= -1)
|
||||
{
|
||||
HIO_DEBUG2 (txt->htts->hio, "HTTS(%p) - halting client(%p) for failure to enable input watching\n", txt->htts, csck);
|
||||
hio_dev_sck_halt (csck);
|
||||
}
|
||||
|
||||
if (rcdown) HIO_SVC_HTTS_TASK_RCDOWN ((hio_svc_htts_task_t*)txt);
|
||||
}
|
||||
|
||||
if (txt->client_org_on_read)
|
||||
{
|
||||
csck->on_read = txt->client_org_on_read;
|
||||
txt->client_org_on_read = HIO_NULL;
|
||||
}
|
||||
|
||||
if (txt->client_org_on_write)
|
||||
{
|
||||
csck->on_write = txt->client_org_on_write;
|
||||
txt->client_org_on_write = HIO_NULL;
|
||||
}
|
||||
|
||||
if (txt->client_org_on_disconnect)
|
||||
{
|
||||
csck->on_disconnect = txt->client_org_on_disconnect;
|
||||
txt->client_org_on_disconnect = HIO_NULL;
|
||||
}
|
||||
|
||||
/* there is some ordering issue in using HIO_SVC_HTTS_TASK_UNREF()
|
||||
* because it can destroy the txt itself. so reset txt->task_client->task
|
||||
* to null and call RCDOWN() later */
|
||||
txt->task_client->task = HIO_NULL;
|
||||
|
||||
/* these two lines are also done in csck_on_disconnect() in http-svr.c because the socket is destroyed.
|
||||
* the same lines here are because the task is unbound while the socket is still alive */
|
||||
txt->task_client = HIO_NULL;
|
||||
txt->task_csck = HIO_NULL;
|
||||
|
||||
/* enable input watching on the socket being unbound */
|
||||
if (txt->task_keep_client_alive && hio_dev_sck_read(csck, 1) <= -1)
|
||||
{
|
||||
HIO_DEBUG2 (txt->htts->hio, "HTTS(%p) - halting client(%p) for failure to enable input watching\n", txt->htts, csck);
|
||||
hio_dev_sck_halt (csck);
|
||||
}
|
||||
|
||||
if (rcdown) HIO_SVC_HTTS_TASK_RCDOWN ((hio_svc_htts_task_t*)txt);
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------- */
|
||||
@@ -326,54 +331,54 @@ static int setup_for_content_length(txt_t* txt, hio_htre_t* req)
|
||||
|
||||
/* ----------------------------------------------------------------------- */
|
||||
|
||||
int hio_svc_htts_dotxt (hio_svc_htts_t* htts, hio_dev_sck_t* csck, hio_htre_t* req, int status_code, const hio_bch_t* content_type, const hio_bch_t* content_text, int options, hio_svc_htts_task_on_kill_t on_kill)
|
||||
int hio_svc_htts_dotxt (hio_svc_htts_t* htts, hio_dev_sck_t* csck, hio_htre_t* req, int res_status_code, const hio_bch_t* content_type, const hio_bch_t* content_text, int options, hio_svc_htts_task_on_kill_t on_kill)
|
||||
{
|
||||
hio_t* hio = htts->hio;
|
||||
hio_svc_htts_cli_t* cli = hio_dev_sck_getxtn(csck);
|
||||
txt_t* txt = HIO_NULL;
|
||||
int status_code = HIO_HTTP_STATUS_INTERNAL_SERVER_ERROR;
|
||||
int bound_to_client = 0;
|
||||
|
||||
/* ensure that you call this function before any contents is received */
|
||||
HIO_ASSERT (hio, hio_htre_getcontentlen(req) == 0);
|
||||
HIO_ASSERT (hio, cli->sck == csck);
|
||||
|
||||
if (cli->task)
|
||||
{
|
||||
hio_seterrbfmt (hio, HIO_EPERM, "duplicate task request prohibited");
|
||||
goto oops;
|
||||
}
|
||||
|
||||
txt = (txt_t*)hio_svc_htts_task_make(htts, HIO_SIZEOF(*txt), txt_on_kill, req, csck);
|
||||
if (HIO_UNLIKELY(!txt)) goto oops;
|
||||
HIO_SVC_HTTS_TASK_RCUP ((hio_svc_htts_task_t*)txt);
|
||||
|
||||
|
||||
txt->on_kill = on_kill;
|
||||
txt->options = options;
|
||||
|
||||
bind_task_to_client (txt, csck);
|
||||
bound_to_client = 1;
|
||||
|
||||
if (req->flags & HIO_HTRE_ATTR_EXPECT100)
|
||||
{
|
||||
/* don't send 100-Continue. If the client posts data regardless, ignore them later */
|
||||
}
|
||||
else if (req->flags & HIO_HTRE_ATTR_EXPECT)
|
||||
{
|
||||
/* 417 Expectation Failed */
|
||||
hio_svc_htts_task_sendfinalres(txt, HIO_HTTP_STATUS_EXPECTATION_FAILED, HIO_NULL, HIO_NULL, 1);
|
||||
goto oops;
|
||||
}
|
||||
|
||||
if (hio_svc_htts_task_handleexpect100(txt, 1) <= -1) goto oops;
|
||||
if (setup_for_content_length(txt, req) <= -1) goto oops;
|
||||
|
||||
/* TODO: store current input watching state and use it when destroying the txt data */
|
||||
if (hio_dev_sck_read(csck, !(txt->over & TXT_OVER_READ_FROM_CLIENT)) <= -1) goto oops;
|
||||
|
||||
if (hio_svc_htts_task_sendfinalres(txt, HIO_HTTP_STATUS_OK, content_type, content_text, 0) <= -1) goto oops;
|
||||
if (hio_svc_htts_task_sendfinalres(txt, res_status_code, content_type, content_text, 0) <= -1) goto oops;
|
||||
|
||||
HIO_SVC_HTTS_TASKL_APPEND_TASK (&htts->task, (hio_svc_htts_task_t*)txt);
|
||||
HIO_SVC_HTTS_TASK_RCDOWN ((hio_svc_htts_task_t*)txt);
|
||||
|
||||
/* set the on_kill callback only if this function can return success.
|
||||
* the on_kill callback won't be executed if this function returns failure. */
|
||||
txt->on_kill = on_kill;
|
||||
return 0;
|
||||
|
||||
oops:
|
||||
HIO_DEBUG2 (hio, "HTTS(%p) - FAILURE in dotxt - socket(%p)\n", htts, csck);
|
||||
if (txt)
|
||||
{
|
||||
hio_svc_htts_task_sendfinalres(txt, status_code, HIO_NULL, HIO_NULL, 1);
|
||||
if (bound_to_client) unbind_task_from_client (txt, 1);
|
||||
txt_halt_participating_devices (txt);
|
||||
HIO_SVC_HTTS_TASK_RCDOWN ((hio_svc_htts_task_t*)txt);
|
||||
|
||||
Reference in New Issue
Block a user