fixed various bugs in http server handlers

regenrated build files
This commit is contained in:
2023-11-18 16:31:24 +09:00
parent b8378ce280
commit 76f42800a5
39 changed files with 10355 additions and 7803 deletions

View File

@@ -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 \

View File

@@ -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 \

View File

@@ -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;

View File

@@ -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;

View File

@@ -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

View File

@@ -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

View File

@@ -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)

View File

@@ -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
View 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

View File

@@ -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);

View File

@@ -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);

View File

@@ -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;
}

View File

@@ -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);

View File

@@ -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);
}

View File

@@ -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);

View File

@@ -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);