Compare commits

...
4 Commits
31 changed files with 848 additions and 474 deletions
-7
View File
@@ -90,10 +90,3 @@ hio_t05_CPPFLAGS = $(CPPFLAGS_COMMON)
hio_t05_CFLAGS = $(CFLAGS_COMMON)
hio_t05_LDFLAGS = $(LDFLAGS_COMMON)
hio_t05_LDADD = $(LIBADD_COMMON)
noinst_PROGRAMS += hio-t06
hio_t06_SOURCES = t06.c
hio_t06_CPPFLAGS = $(CPPFLAGS_COMMON)
hio_t06_CFLAGS = $(CFLAGS_COMMON)
hio_t06_LDFLAGS = $(LDFLAGS_COMMON)
hio_t06_LDADD = $(LIBADD_COMMON)
+6 -41
View File
@@ -94,7 +94,7 @@ bin_PROGRAMS = hio-execd$(EXEEXT) $(am__EXEEXT_1) hio-untar$(EXEEXT) \
hio-webs$(EXEEXT)
@HAVE_X11_LIB_TRUE@am__append_1 = hio-te
noinst_PROGRAMS = hio-t01$(EXEEXT) hio-t02$(EXEEXT) hio-t03$(EXEEXT) \
hio-t04$(EXEEXT) hio-t05$(EXEEXT) hio-t06$(EXEEXT)
hio-t04$(EXEEXT) hio-t05$(EXEEXT)
@ENABLE_MARIADB_TRUE@am__append_2 = $(MARIADB_CFLAGS)
@ENABLE_MARIADB_TRUE@am__append_3 = $(MARIADB_LDFLAGS)
@ENABLE_MARIADB_TRUE@am__append_4 = $(MARIADB_LIBS)
@@ -158,12 +158,6 @@ hio_t05_DEPENDENCIES = $(LIBADD_COMMON)
hio_t05_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
$(LIBTOOLFLAGS) --mode=link $(CCLD) $(hio_t05_CFLAGS) \
$(CFLAGS) $(hio_t05_LDFLAGS) $(LDFLAGS) -o $@
am_hio_t06_OBJECTS = hio_t06-t06.$(OBJEXT)
hio_t06_OBJECTS = $(am_hio_t06_OBJECTS)
hio_t06_DEPENDENCIES = $(LIBADD_COMMON)
hio_t06_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
$(LIBTOOLFLAGS) --mode=link $(CCLD) $(hio_t06_CFLAGS) \
$(CFLAGS) $(hio_t06_LDFLAGS) $(LDFLAGS) -o $@
am__hio_te_SOURCES_DIST = te.c
@HAVE_X11_LIB_TRUE@am_hio_te_OBJECTS = hio_te-te.$(OBJEXT)
hio_te_OBJECTS = $(am_hio_te_OBJECTS)
@@ -201,9 +195,8 @@ am__maybe_remake_depfiles = depfiles
am__depfiles_remade = ./$(DEPDIR)/hio_execd-execd.Po \
./$(DEPDIR)/hio_t01-t01.Po ./$(DEPDIR)/hio_t02-t02.Po \
./$(DEPDIR)/hio_t03-t03.Po ./$(DEPDIR)/hio_t04-t04.Po \
./$(DEPDIR)/hio_t05-t05.Po ./$(DEPDIR)/hio_t06-t06.Po \
./$(DEPDIR)/hio_te-te.Po ./$(DEPDIR)/hio_untar-untar.Po \
./$(DEPDIR)/hio_webs-webs.Po
./$(DEPDIR)/hio_t05-t05.Po ./$(DEPDIR)/hio_te-te.Po \
./$(DEPDIR)/hio_untar-untar.Po ./$(DEPDIR)/hio_webs-webs.Po
am__mv = mv -f
COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
$(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
@@ -225,13 +218,11 @@ am__v_CCLD_0 = @echo " CCLD " $@;
am__v_CCLD_1 =
SOURCES = $(hio_execd_SOURCES) $(hio_t01_SOURCES) $(hio_t02_SOURCES) \
$(hio_t03_SOURCES) $(hio_t04_SOURCES) $(hio_t05_SOURCES) \
$(hio_t06_SOURCES) $(hio_te_SOURCES) $(hio_untar_SOURCES) \
$(hio_webs_SOURCES)
$(hio_te_SOURCES) $(hio_untar_SOURCES) $(hio_webs_SOURCES)
DIST_SOURCES = $(hio_execd_SOURCES) $(hio_t01_SOURCES) \
$(hio_t02_SOURCES) $(hio_t03_SOURCES) $(hio_t04_SOURCES) \
$(hio_t05_SOURCES) $(hio_t06_SOURCES) \
$(am__hio_te_SOURCES_DIST) $(hio_untar_SOURCES) \
$(hio_webs_SOURCES)
$(hio_t05_SOURCES) $(am__hio_te_SOURCES_DIST) \
$(hio_untar_SOURCES) $(hio_webs_SOURCES)
am__can_run_installinfo = \
case $$AM_UPDATE_INFO_DIR in \
n|no|NO) false;; \
@@ -460,11 +451,6 @@ hio_t05_CPPFLAGS = $(CPPFLAGS_COMMON)
hio_t05_CFLAGS = $(CFLAGS_COMMON)
hio_t05_LDFLAGS = $(LDFLAGS_COMMON)
hio_t05_LDADD = $(LIBADD_COMMON)
hio_t06_SOURCES = t06.c
hio_t06_CPPFLAGS = $(CPPFLAGS_COMMON)
hio_t06_CFLAGS = $(CFLAGS_COMMON)
hio_t06_LDFLAGS = $(LDFLAGS_COMMON)
hio_t06_LDADD = $(LIBADD_COMMON)
all: all-am
.SUFFIXES:
@@ -571,10 +557,6 @@ hio-t05$(EXEEXT): $(hio_t05_OBJECTS) $(hio_t05_DEPENDENCIES) $(EXTRA_hio_t05_DEP
@rm -f hio-t05$(EXEEXT)
$(AM_V_CCLD)$(hio_t05_LINK) $(hio_t05_OBJECTS) $(hio_t05_LDADD) $(LIBS)
hio-t06$(EXEEXT): $(hio_t06_OBJECTS) $(hio_t06_DEPENDENCIES) $(EXTRA_hio_t06_DEPENDENCIES)
@rm -f hio-t06$(EXEEXT)
$(AM_V_CCLD)$(hio_t06_LINK) $(hio_t06_OBJECTS) $(hio_t06_LDADD) $(LIBS)
hio-te$(EXEEXT): $(hio_te_OBJECTS) $(hio_te_DEPENDENCIES) $(EXTRA_hio_te_DEPENDENCIES)
@rm -f hio-te$(EXEEXT)
$(AM_V_CCLD)$(hio_te_LINK) $(hio_te_OBJECTS) $(hio_te_LDADD) $(LIBS)
@@ -599,7 +581,6 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/hio_t03-t03.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/hio_t04-t04.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/hio_t05-t05.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/hio_t06-t06.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/hio_te-te.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/hio_untar-untar.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/hio_webs-webs.Po@am__quote@ # am--include-marker
@@ -718,20 +699,6 @@ hio_t05-t05.obj: t05.c
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(hio_t05_CPPFLAGS) $(CPPFLAGS) $(hio_t05_CFLAGS) $(CFLAGS) -c -o hio_t05-t05.obj `if test -f 't05.c'; then $(CYGPATH_W) 't05.c'; else $(CYGPATH_W) '$(srcdir)/t05.c'; fi`
hio_t06-t06.o: t06.c
@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(hio_t06_CPPFLAGS) $(CPPFLAGS) $(hio_t06_CFLAGS) $(CFLAGS) -MT hio_t06-t06.o -MD -MP -MF $(DEPDIR)/hio_t06-t06.Tpo -c -o hio_t06-t06.o `test -f 't06.c' || echo '$(srcdir)/'`t06.c
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/hio_t06-t06.Tpo $(DEPDIR)/hio_t06-t06.Po
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='t06.c' object='hio_t06-t06.o' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(hio_t06_CPPFLAGS) $(CPPFLAGS) $(hio_t06_CFLAGS) $(CFLAGS) -c -o hio_t06-t06.o `test -f 't06.c' || echo '$(srcdir)/'`t06.c
hio_t06-t06.obj: t06.c
@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(hio_t06_CPPFLAGS) $(CPPFLAGS) $(hio_t06_CFLAGS) $(CFLAGS) -MT hio_t06-t06.obj -MD -MP -MF $(DEPDIR)/hio_t06-t06.Tpo -c -o hio_t06-t06.obj `if test -f 't06.c'; then $(CYGPATH_W) 't06.c'; else $(CYGPATH_W) '$(srcdir)/t06.c'; fi`
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/hio_t06-t06.Tpo $(DEPDIR)/hio_t06-t06.Po
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='t06.c' object='hio_t06-t06.obj' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(hio_t06_CPPFLAGS) $(CPPFLAGS) $(hio_t06_CFLAGS) $(CFLAGS) -c -o hio_t06-t06.obj `if test -f 't06.c'; then $(CYGPATH_W) 't06.c'; else $(CYGPATH_W) '$(srcdir)/t06.c'; fi`
hio_te-te.o: te.c
@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(hio_te_CPPFLAGS) $(CPPFLAGS) $(hio_te_CFLAGS) $(CFLAGS) -MT hio_te-te.o -MD -MP -MF $(DEPDIR)/hio_te-te.Tpo -c -o hio_te-te.o `test -f 'te.c' || echo '$(srcdir)/'`te.c
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/hio_te-te.Tpo $(DEPDIR)/hio_te-te.Po
@@ -914,7 +881,6 @@ distclean: distclean-am
-rm -f ./$(DEPDIR)/hio_t03-t03.Po
-rm -f ./$(DEPDIR)/hio_t04-t04.Po
-rm -f ./$(DEPDIR)/hio_t05-t05.Po
-rm -f ./$(DEPDIR)/hio_t06-t06.Po
-rm -f ./$(DEPDIR)/hio_te-te.Po
-rm -f ./$(DEPDIR)/hio_untar-untar.Po
-rm -f ./$(DEPDIR)/hio_webs-webs.Po
@@ -969,7 +935,6 @@ maintainer-clean: maintainer-clean-am
-rm -f ./$(DEPDIR)/hio_t03-t03.Po
-rm -f ./$(DEPDIR)/hio_t04-t04.Po
-rm -f ./$(DEPDIR)/hio_t05-t05.Po
-rm -f ./$(DEPDIR)/hio_t06-t06.Po
-rm -f ./$(DEPDIR)/hio_te-te.Po
-rm -f ./$(DEPDIR)/hio_untar-untar.Po
-rm -f ./$(DEPDIR)/hio_webs-webs.Po
+22 -2
View File
@@ -107,9 +107,8 @@ typedef void (*hio_svc_htts_task_on_kill_t) (
hio_svc_htts_task_on_kill_t task_on_kill; \
hio_dev_sck_t* task_csck; \
hio_svc_htts_cli_t* task_client; \
hio_dev_sck_evcb_link_t task_client_evcb_link; \
const hio_dev_sck_evcb_t* task_evcb; \
hio_htrd_recbs_t task_client_htrd_org_recbs; \
unsigned int task_client_evcb_pushed: 1; \
unsigned int task_client_htrd_recbs_changed: 1; \
unsigned int task_keep_client_alive: 1; \
unsigned int task_req_qpath_ending_with_slash: 1; \
@@ -545,6 +544,27 @@ HIO_EXPORT void hio_svc_htts_task_bindtoclient (
const hio_dev_sck_evcb_t* evcb
);
/* The http service's own client handling. While a task is bound its
* handlers run instead of these; a task that wants the default behaviour
* as well calls the matching function explicitly. */
HIO_EXPORT int hio_svc_htts_client_default_on_read (
hio_dev_sck_t* sck,
const void* buf,
hio_iolen_t len,
const hio_skad_t* srcaddr
);
HIO_EXPORT int hio_svc_htts_client_default_on_write (
hio_dev_sck_t* sck,
hio_iolen_t wrlen,
void* wrctx,
const hio_skad_t* dstaddr
);
HIO_EXPORT void hio_svc_htts_client_default_on_disconnect (
hio_dev_sck_t* sck
);
/* Release the client socket. Pass a non-zero 'rcdown' to drop the reference
* the binding took; pass 0 when the caller is already inside the task's own
* destruction path. */
-27
View File
@@ -258,7 +258,6 @@ typedef void (*hio_dev_sck_on_raw_accept_t) (
);
typedef struct hio_dev_sck_evcb_t hio_dev_sck_evcb_t;
typedef struct hio_dev_sck_evcb_link_t hio_dev_sck_evcb_link_t;
struct hio_dev_sck_evcb_t
{
@@ -267,12 +266,6 @@ struct hio_dev_sck_evcb_t
hio_dev_sck_on_disconnect_t on_disconnect;
};
struct hio_dev_sck_evcb_link_t
{
hio_dev_sck_evcb_t saved;
void* ctx;
hio_dev_sck_evcb_link_t* prev;
};
enum hio_dev_sck_type_t
{
@@ -412,7 +405,6 @@ struct hio_dev_sck_t
/* original destination address */
hio_skad_t orgdstaddr;
hio_dev_sck_evcb_link_t* evcb_top;
hio_dev_sck_on_write_t on_write;
hio_dev_sck_on_read_t on_read;
@@ -537,25 +529,6 @@ HIO_EXPORT int hio_dev_sck_timedwritev (
const hio_skad_t* dstaddr
);
HIO_EXPORT void hio_dev_sck_pushevcb (
hio_dev_sck_t* dev,
hio_dev_sck_evcb_link_t* link,
const hio_dev_sck_evcb_t* evcb,
void* ctx
);
HIO_EXPORT hio_dev_sck_evcb_link_t* hio_dev_sck_popevcb (
hio_dev_sck_t* dev
);
HIO_EXPORT void* hio_dev_sck_getevcbctx (
hio_dev_sck_t* dev
);
HIO_EXPORT hio_dev_sck_evcb_t* hio_dev_sck_getparentevcb (
hio_dev_sck_t* dev
);
#if defined(HIO_HAVE_INLINE)
static HIO_INLINE void hio_dev_sck_kill (hio_dev_sck_t* sck)
-32
View File
@@ -1029,11 +1029,7 @@ hio_dev_t* hio_dev_make (hio_t* hio, hio_oow_t dev_size, hio_dev_mth_t* dev_mth,
dev->dev_cap = HIO_DEV_CAP_IN | HIO_DEV_CAP_OUT;
dev->dev_mth = dev_mth;
dev->dev_evcb_base.evcb = dev_evcb;
dev->dev_evcb_base.ctx = HIO_NULL;
dev->dev_evcb_base.prev = HIO_NULL;
dev->dev_evcb = dev_evcb;
dev->dev_evcb_top = &dev->dev_evcb_base;
HIO_INIT_NTIME(&dev->rtmout, 0, 0);
dev->rtmridx = HIO_TMRIDX_INVALID;
@@ -2017,34 +2013,6 @@ int hio_dev_timedsendfile (hio_dev_t* dev, hio_syshnd_t in_fd, hio_foff_t foff,
/* -------------------------------------------------------------------------- */
void hio_dev_pushevcb (hio_dev_t* dev, hio_dev_evcb_link_t* link, hio_dev_evcb_t *evcb, void* ctx)
{
link->evcb = evcb;
link->ctx = ctx;
link->prev = dev->dev_evcb_top;
dev->dev_evcb_top = link;
dev->dev_evcb = evcb; /* cached */
}
hio_dev_evcb_link_t* hio_dev_popevcb (hio_dev_t* dev)
{
hio_dev_evcb_link_t* link;
link = dev->dev_evcb_top;
if (!link->prev) return HIO_NULL; /* the base cannot be popped off */
dev->dev_evcb_top = link->prev;
dev->dev_evcb = link->prev->evcb;
link->prev = HIO_NULL; /* clear the stale pointer */
return link;
}
void * hio_dev_getevcbctx (hio_dev_t* dev)
{
return dev->dev_evcb_top->ctx;
}
/* -------------------------------------------------------------------------- */
void hio_gettime (hio_t* hio, hio_ntime_t* now)
+2 -25
View File
@@ -58,7 +58,6 @@ typedef struct hio_t hio_t;
typedef struct hio_dev_t hio_dev_t;
typedef struct hio_dev_mth_t hio_dev_mth_t;
typedef struct hio_dev_evcb_t hio_dev_evcb_t;
typedef struct hio_dev_evcb_link_t hio_dev_evcb_link_t;
typedef struct hio_svc_t hio_svc_t;
typedef struct hio_q_t hio_q_t;
@@ -264,13 +263,6 @@ struct hio_dev_evcb_t
int (*on_write) (hio_dev_t* dev, hio_iolen_t wrlen, void* wrctx, const hio_devaddr_t* dstaddr);
};
struct hio_dev_evcb_link_t
{
hio_dev_evcb_t* evcb;
void* ctx;
hio_dev_evcb_link_t* prev;
};
/**
* The #hio_q_t type is a basic structure that holds two pointers to the previous
* item and the next to form a circular doubly linked list to used as a queue.
@@ -385,9 +377,7 @@ struct hio_wq_t
hio_oow_t dev_size; \
hio_bitmask_t dev_cap; \
hio_dev_mth_t* dev_mth; \
hio_dev_evcb_t* dev_evcb; /* cached for faster access. must be equal to dev_evcb_top->evcb */ \
hio_dev_evcb_link_t* dev_evcb_top; /* top evcb pointer */ \
hio_dev_evcb_link_t dev_evcb_base; /* base space to hold the actual evcb data */ \
hio_dev_evcb_t* dev_evcb; \
hio_ntime_t rtmout; \
hio_tmridx_t rtmridx; \
hio_wq_t wq; \
@@ -1043,6 +1033,7 @@ HIO_EXPORT int hio_dev_timedread (
const hio_ntime_t* tmout
);
/**
* The hio_dev_write() function posts a writing request.
* It attempts to write data immediately if there is no pending requests.
@@ -1104,20 +1095,6 @@ HIO_EXPORT int hio_dev_timedsendfile (
void* wrctx
);
HIO_EXPORT void hio_dev_pushevcb (
hio_dev_t* dev,
hio_dev_evcb_link_t* link,
hio_dev_evcb_t* evcb,
void* ctx
);
HIO_EXPORT hio_dev_evcb_link_t* hio_dev_popevcb (
hio_dev_t* dev
);
HIO_EXPORT void * hio_dev_getevcbctx (
hio_dev_t* dev
);
/* =========================================================================
* SERVICE
+9 -5
View File
@@ -483,8 +483,14 @@ static int cgi_client_htrd_poke (hio_htrd_t* htrd, hio_htre_t* req)
/* client request got completed */
hio_svc_htts_cli_htrd_xtn_t* htrdxtn = (hio_svc_htts_cli_htrd_xtn_t*)hio_htrd_getxtn(htrd);
hio_dev_sck_t* sck = htrdxtn->sck;
#if 0
hio_svc_htts_cli_t* cli = hio_dev_sck_getxtn(sck);
cgi_t* cgi = (cgi_t*)cli->task;
#else
/* this one is one call only. it must return the same value as the above two lines */
hio_svc_htts_cli_t* cli = hio_dev_sck_getxtn(sck);
cgi_t* cgi = (cgi_t*)cli->task;
#endif
/* indicate EOF to the client peer */
if (cgi_write_to_peer(cgi, HIO_NULL, 0) <= -1) return -1;
@@ -542,7 +548,7 @@ static void cgi_client_on_disconnect (hio_dev_sck_t* sck)
/* call the parent handler*/
/*if (fcgi->client_org_on_disconnect) fcgi->client_org_on_disconnect (sck);*/
if (sck->on_disconnect) sck->on_disconnect (sck); /* restored to the orginal parent handler in unbind_task_from_client() */
hio_svc_htts_client_default_on_disconnect (sck); /* restored to the orginal parent handler in unbind_task_from_client() */
/* if the client side is closed, the data from the child process is not read and the write() of the child process call may block.
* just close the input side of the pipe to the child to prevense this situation */
@@ -558,7 +564,6 @@ static void cgi_client_on_disconnect (hio_dev_sck_t* sck)
static int cgi_client_on_read (hio_dev_sck_t* sck, const void* buf, hio_iolen_t len, const hio_skad_t* srcaddr)
{
hio_dev_sck_evcb_t* parent = hio_dev_sck_getparentevcb(sck);
hio_t* hio = sck->hio;
hio_svc_htts_cli_t* cli = hio_dev_sck_getxtn(sck);
cgi_t* cgi = (cgi_t*)cli->task;
@@ -566,7 +571,7 @@ static int cgi_client_on_read (hio_dev_sck_t* sck, const void* buf, hio_iolen_t
HIO_ASSERT(hio, sck == cli->sck);
n = parent && parent->on_read? parent->on_read(sck, buf, len, srcaddr): 0;
n = hio_svc_htts_client_default_on_read(sck, buf, len, srcaddr);
if (len <= -1)
{
@@ -599,13 +604,12 @@ oops:
static int cgi_client_on_write (hio_dev_sck_t* sck, hio_iolen_t wrlen, void* wrctx, const hio_skad_t* dstaddr)
{
hio_dev_sck_evcb_t* parent = hio_dev_sck_getparentevcb(sck);
hio_t* hio = sck->hio;
hio_svc_htts_cli_t* cli = hio_dev_sck_getxtn(sck);
cgi_t* cgi = (cgi_t*)cli->task;
int n;
n = parent && parent->on_write? parent->on_write(sck, wrlen, wrctx, dstaddr): 0;
n = hio_svc_htts_client_default_on_write(sck, wrlen, wrctx, dstaddr);
if (wrlen == 0)
{
+23 -8
View File
@@ -383,7 +383,7 @@ static void fcgi_client_on_disconnect (hio_dev_sck_t* sck)
/* call the parent handler*/
/*if (fcgi->client_org_on_disconnect) fcgi->client_org_on_disconnect (sck);*/
if (sck->on_disconnect) sck->on_disconnect (sck); /* restored to the orginal parent handelr in unbind_task_from_client() */
hio_svc_htts_client_default_on_disconnect (sck); /* restored to the orginal parent handelr in unbind_task_from_client() */
HIO_SVC_HTTS_TASK_RCDOWN ((hio_svc_htts_task_t*)fcgi);
}
@@ -394,7 +394,6 @@ static void fcgi_client_on_disconnect (hio_dev_sck_t* sck)
static int fcgi_client_on_read (hio_dev_sck_t* sck, const void* buf, hio_iolen_t len, const hio_skad_t* srcaddr)
{
hio_dev_sck_evcb_t* parent = hio_dev_sck_getparentevcb(sck);
hio_t* hio HIO_UNUSED = sck->hio;
hio_svc_htts_cli_t* cli = hio_dev_sck_getxtn(sck);
fcgi_t* fcgi = (fcgi_t*)cli->task;
@@ -402,7 +401,7 @@ static int fcgi_client_on_read (hio_dev_sck_t* sck, const void* buf, hio_iolen_t
HIO_ASSERT(hio, sck == cli->sck);
n = parent && parent->on_read? parent->on_read(sck, buf, len, srcaddr): 0;
n = hio_svc_htts_client_default_on_read(sck, buf, len, srcaddr);
if (len <= -1)
{
@@ -436,13 +435,12 @@ oops:
static int fcgi_client_on_write (hio_dev_sck_t* sck, hio_iolen_t wrlen, void* wrctx, const hio_skad_t* dstaddr)
{
hio_dev_sck_evcb_t* parent = hio_dev_sck_getparentevcb(sck);
hio_t* hio HIO_UNUSED = sck->hio;
hio_svc_htts_cli_t* cli = hio_dev_sck_getxtn(sck);
fcgi_t* fcgi = (fcgi_t*)cli->task;
int n;
n = parent && parent->on_write? parent->on_write(sck, wrlen, wrctx, dstaddr): 0;
n = hio_svc_htts_client_default_on_write(sck, wrlen, wrctx, dstaddr);
if (wrlen == 0)
{
@@ -717,10 +715,20 @@ int hio_svc_htts_dofcgi (hio_svc_htts_t* htts, hio_dev_sck_t* csck, hio_htre_t*
bound_to_peer = 1;
if (hio_svc_htts_task_handleexpect100((hio_svc_htts_task_t*)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 */
if (hio_dev_sck_read(csck, !(fcgi->over & FCGI_OVER_READ_FROM_CLIENT)) <= -1) goto oops;
/* [NOTE] the records must reach the peer in the order the FastCGI
* specification lays down: FCGI_BEGIN_REQUEST, then the FCGI_PARAMS
* stream, then the FCGI_STDIN stream. setup_for_content_length() ends
* the stdin stream for a request that carries no body, so it has to
* run after the params - not before, or the peer sees the end of a
* request that has not been begun.
*
* if a call like this is made to this funciton:
* fcgi_write_stdin_to_peer(fcgi, HIO_NULL, 0)
* setup_for_content_length() marks the end of stream.
* if i call setup_for_content_length() after beginrequest(),
* it always sends FCGI_BEGIN_REQUEST even for a body-less request.
*/
/* send FCGI_BEGIN_REQUEST */
if (hio_svc_fcgic_beginrequest(fcgi->peer) <= -1) goto oops;
@@ -728,6 +736,13 @@ int hio_svc_htts_dofcgi (hio_svc_htts_t* htts, hio_dev_sck_t* csck, hio_htre_t*
if (write_params(fcgi, csck, req, docroot, script) <= -1) goto oops;
if (hio_svc_fcgic_writeparam(fcgi->peer, HIO_NULL, 0, HIO_NULL, 0) <= -1) goto oops; /* end of params */
/* this may end the stdin stream, so it must follow the params above.
* it also settles the 'over' bits that the read arming below reads. */
if (setup_for_content_length(fcgi, req) <= -1) goto oops;
/* TODO: store current input watching state and use it when destroying the fcgi data */
if (hio_dev_sck_read(csck, !(fcgi->over & FCGI_OVER_READ_FROM_CLIENT)) <= -1) goto oops;
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);
+9 -8
View File
@@ -219,7 +219,7 @@ static void file_client_on_disconnect (hio_dev_sck_t* sck)
{
hio_t* hio = sck->hio;
hio_svc_htts_cli_t* cli = hio_dev_sck_getxtn(sck);
file_t* file = (file_t*)hio_dev_sck_getevcbctx(sck);
file_t* file = (file_t*)cli->task;
hio_svc_htts_t* htts = file->htts;
HIO_ASSERT(hio, sck == cli->sck);
@@ -242,7 +242,7 @@ static void file_client_on_disconnect (hio_dev_sck_t* sck)
/* call the parent handler. unbind_task_from_client() above popped
* this task's layer off, so sck->on_disconnect is the handler that
* was displaced when the layer was pushed. */
if (sck->on_disconnect) sck->on_disconnect(sck);
hio_svc_htts_client_default_on_disconnect (sck);
HIO_SVC_HTTS_TASK_RCDOWN((hio_svc_htts_task_t*)file);
}
@@ -255,7 +255,7 @@ static int file_client_on_read (hio_dev_sck_t* sck, const void* buf, hio_iolen_t
{
hio_t* hio = sck->hio;
hio_svc_htts_cli_t* cli = hio_dev_sck_getxtn(sck);
file_t* file = (file_t*)hio_dev_sck_getevcbctx(sck);
file_t* file = (file_t*)cli->task;
HIO_ASSERT(hio, sck == cli->sck);
HIO_ASSERT(hio, sck == file->task_csck);
@@ -312,11 +312,11 @@ oops:
static int file_client_on_write (hio_dev_sck_t* sck, hio_iolen_t wrlen, void* wrctx, const hio_skad_t* dstaddr)
{
hio_t* hio = sck->hio;
file_t* file = (file_t*)hio_dev_sck_getevcbctx(sck);
hio_dev_sck_evcb_t* parent = hio_dev_sck_getparentevcb(sck);
hio_svc_htts_cli_t* cli = hio_dev_sck_getxtn(sck);
file_t* file = (file_t*)cli->task;
int n;
n = parent && parent->on_write? parent->on_write(sck, wrlen, wrctx, dstaddr): 0;
n = hio_svc_htts_client_default_on_write(sck, wrlen, wrctx, dstaddr);
if (wrlen == 0)
{
@@ -352,7 +352,8 @@ static int file_client_htrd_poke (hio_htrd_t* htrd, hio_htre_t* req)
/* client request got completed */
hio_svc_htts_cli_htrd_xtn_t* htrdxtn = (hio_svc_htts_cli_htrd_xtn_t*)hio_htrd_getxtn(htrd);
hio_dev_sck_t* sck = htrdxtn->sck;
file_t* file = (file_t*)hio_dev_sck_getevcbctx(sck);
hio_svc_htts_cli_t* cli = hio_dev_sck_getxtn(sck);
file_t* file = (file_t*)cli->task;
/* indicate EOF to the client peer */
if (file_write_to_peer(file, HIO_NULL, 0) <= -1) return -1;
@@ -371,7 +372,7 @@ static int file_client_htrd_push_content (hio_htrd_t* htrd, hio_htre_t* req, con
hio_svc_htts_cli_htrd_xtn_t* htrdxtn = (hio_svc_htts_cli_htrd_xtn_t*)hio_htrd_getxtn(htrd);
hio_dev_sck_t* sck = htrdxtn->sck;
hio_svc_htts_cli_t* cli = hio_dev_sck_getxtn(sck);
file_t* file = (file_t*)hio_dev_sck_getevcbctx(sck);
file_t* file = (file_t*)cli->task;
HIO_ASSERT(sck->hio, cli->sck == sck);
return file_write_to_peer(file, data, dlen);
+3 -5
View File
@@ -460,7 +460,7 @@ static void prxy_client_on_disconnect (hio_dev_sck_t* sck)
/* call the parent handler*/
/*if (fprxy->client_org_on_disconnect) fprxy->client_org_on_disconnect (sck);*/
if (sck->on_disconnect) sck->on_disconnect (sck); /* restored to the orginal parent handler in unbind_task_from_client() */
hio_svc_htts_client_default_on_disconnect(sck); /* restored to the orginal parent handler in unbind_task_from_client() */
HIO_SVC_HTTS_TASK_RCDOWN ((hio_svc_htts_task_t*)prxy);
}
@@ -471,7 +471,6 @@ static void prxy_client_on_disconnect (hio_dev_sck_t* sck)
static int prxy_client_on_read (hio_dev_sck_t* sck, const void* buf, hio_iolen_t len, const hio_skad_t* srcaddr)
{
hio_dev_sck_evcb_t* parent = hio_dev_sck_getparentevcb(sck);
hio_t* hio = sck->hio;
hio_svc_htts_cli_t* cli = hio_dev_sck_getxtn(sck);
prxy_t* prxy = (prxy_t*)cli->task;
@@ -479,7 +478,7 @@ static int prxy_client_on_read (hio_dev_sck_t* sck, const void* buf, hio_iolen_t
HIO_ASSERT(hio, sck == cli->sck);
n = parent && parent->on_read? parent->on_read(sck, buf, len, srcaddr): 0;
n = hio_svc_htts_client_default_on_read(sck, buf, len, srcaddr);
if (len <= -1)
{
@@ -512,13 +511,12 @@ oops:
static int prxy_client_on_write (hio_dev_sck_t* sck, hio_iolen_t wrlen, void* wrctx, const hio_skad_t* dstaddr)
{
hio_dev_sck_evcb_t* parent = hio_dev_sck_getparentevcb(sck);
hio_t* hio = sck->hio;
hio_svc_htts_cli_t* cli = hio_dev_sck_getxtn(sck);
prxy_t* prxy = (prxy_t*)cli->task;
int n;
n = parent && parent->on_write? parent->on_write(sck, wrlen, wrctx, dstaddr): 0;
n = hio_svc_htts_client_default_on_write(sck, wrlen, wrctx, dstaddr);
if (wrlen == 0)
{
+42 -20
View File
@@ -324,6 +324,19 @@ static void listener_on_disconnect (hio_dev_sck_t* sck)
static int client_on_read (hio_dev_sck_t* sck, const void* buf, hio_iolen_t len, const hio_skad_t* srcaddr)
{
hio_svc_htts_cli_t* cli = hio_dev_sck_getxtn(sck);
/* a bound task services the client. it calls
* hio_svc_htts_client_default_on_read() itself if it also wants the
* handling below. */
if (cli->task && cli->task->task_evcb && cli->task->task_evcb->on_read)
return cli->task->task_evcb->on_read(sck, buf, len, srcaddr);
return hio_svc_htts_client_default_on_read(sck, buf, len, srcaddr);
}
int hio_svc_htts_client_default_on_read (hio_dev_sck_t* sck, const void* buf, hio_iolen_t len, const hio_skad_t* srcaddr)
{
hio_svc_htts_cli_t* cli = hio_dev_sck_getxtn(sck);
hio_t* hio = sck->hio;
@@ -381,6 +394,16 @@ oops:
}
static int client_on_write (hio_dev_sck_t* sck, hio_iolen_t wrlen, void* wrctx, const hio_skad_t* dstaddr)
{
hio_svc_htts_cli_t* cli = hio_dev_sck_getxtn(sck);
if (cli->task && cli->task->task_evcb && cli->task->task_evcb->on_write)
return cli->task->task_evcb->on_write(sck, wrlen, wrctx, dstaddr);
return hio_svc_htts_client_default_on_write(sck, wrlen, wrctx, dstaddr);
}
int hio_svc_htts_client_default_on_write (hio_dev_sck_t* sck, hio_iolen_t wrlen, void* wrctx, const hio_skad_t* dstaddr)
{
hio_svc_htts_cli_t* cli = hio_dev_sck_getxtn(sck);
hio_t* hio = sck->hio;
@@ -420,6 +443,19 @@ static int client_on_write (hio_dev_sck_t* sck, hio_iolen_t wrlen, void* wrctx,
}
static void client_on_disconnect (hio_dev_sck_t* sck)
{
hio_svc_htts_cli_t* cli = hio_dev_sck_getxtn(sck);
if (cli->task && cli->task->task_evcb && cli->task->task_evcb->on_disconnect)
{
cli->task->task_evcb->on_disconnect (sck);
return;
}
hio_svc_htts_client_default_on_disconnect (sck);
}
void hio_svc_htts_client_default_on_disconnect (hio_dev_sck_t* sck)
{
hio_t* hio = sck->hio;
hio_svc_htts_cli_t* cli = hio_dev_sck_getxtn(sck);
@@ -947,22 +983,12 @@ void hio_svc_htts_task_bindtoclient (hio_svc_htts_task_t* task, hio_dev_sck_t* c
/* task->task_client and task->task_csck are set in hio_svc_htts_task_make() */
/* layer this task's handlers over whatever the socket was using. the
* displaced set is remembered in the link, and the task becomes the
* layer context its handlers read back with hio_dev_sck_getevcbctx() */
hio_dev_sck_pushevcb(csck, &task->task_client_evcb_link, evcb, task);
task->task_client_evcb_pushed = 1;
/* the socket keeps the service's handlers installed throughout. while
* this task is the client's current one, they route to this table. */
task->task_evcb = evcb;
cli->task = task;
HIO_SVC_HTTS_TASK_RCUP(task);
/* somehow the backpointer to the task is available via two means:
*
* - cli->task
* - hio_dev_sck_getevcbctx()
*
* the two above returns the same pointer.
*/
}
void hio_svc_htts_task_unbindfromclient (hio_svc_htts_task_t* task, int rcdown)
@@ -986,12 +1012,6 @@ void hio_svc_htts_task_unbindfromclient (hio_svc_htts_task_t* task, int rcdown)
task->task_client_htrd_recbs_changed = 0;
}
if (task->task_client_evcb_pushed)
{
hio_dev_sck_popevcb(csck);
task->task_client_evcb_pushed = 0;
}
/* there is some ordering issue in using HIO_SVC_HTTS_TASK_UNREF()
* because it can destroy the task itself. so reset
* task->task_client->task to null and call RCDOWN() later */
@@ -1370,7 +1390,9 @@ hio_bch_t* hio_svc_htts_dupmergepaths (hio_svc_htts_t* htts, const hio_bch_t* ba
ta[idx++] = base;
if (path[0] != '\0')
{
if (base[hio_count_bcstr(base) - 1] != '/') ta[idx++] = "/";
/* [NOTE] guard the length. an empty base would index base[-1] */
hio_oow_t baselen = hio_count_bcstr(base);
if (baselen <= 0 || base[baselen - 1] != '/') ta[idx++] = "/";
ta[idx++] = path;
}
ta[idx++] = HIO_NULL;
+3 -5
View File
@@ -473,7 +473,7 @@ static void thr_client_on_disconnect (hio_dev_sck_t* sck)
/* call the parent handler*/
/*if (thr->client_org_on_disconnect) thr->client_org_on_disconnect (sck);*/
if (sck->on_disconnect) sck->on_disconnect (sck); /* restored to the orginal parent handler in unbind_task_from_client() */
hio_svc_htts_client_default_on_disconnect (sck); /* restored to the orginal parent handler in unbind_task_from_client() */
HIO_SVC_HTTS_TASK_RCDOWN ((hio_svc_htts_task_t*)thr);
}
@@ -484,7 +484,6 @@ static void thr_client_on_disconnect (hio_dev_sck_t* sck)
static int thr_client_on_read (hio_dev_sck_t* sck, const void* buf, hio_iolen_t len, const hio_skad_t* srcaddr)
{
hio_dev_sck_evcb_t* parent = hio_dev_sck_getparentevcb(sck);
hio_t* hio = sck->hio;
hio_svc_htts_cli_t* cli = hio_dev_sck_getxtn(sck);
thr_t* thr = (thr_t*)cli->task;
@@ -492,7 +491,7 @@ static int thr_client_on_read (hio_dev_sck_t* sck, const void* buf, hio_iolen_t
HIO_ASSERT(hio, sck == cli->sck);
n = parent && parent->on_read? parent->on_read(sck, buf, len, srcaddr): 0;
n = hio_svc_htts_client_default_on_read(sck, buf, len, srcaddr);
if (len <= -1)
{
@@ -525,13 +524,12 @@ oops:
static int thr_client_on_write (hio_dev_sck_t* sck, hio_iolen_t wrlen, void* wrctx, const hio_skad_t* dstaddr)
{
hio_dev_sck_evcb_t* parent = hio_dev_sck_getparentevcb(sck);
hio_t* hio = sck->hio;
hio_svc_htts_cli_t* cli = hio_dev_sck_getxtn(sck);
thr_t* thr = (thr_t*)cli->task;
int n;
n = parent && parent->on_write? parent->on_write(sck, wrlen, wrctx, dstaddr): 0;
n = hio_svc_htts_client_default_on_write(sck, wrlen, wrctx, dstaddr);
if (wrlen == 0)
{
+3 -5
View File
@@ -154,7 +154,7 @@ static void txt_client_on_disconnect (hio_dev_sck_t* sck)
/* call the parent handler*/
/*if (txt->client_org_on_disconnect) txt->client_org_on_disconnect (sck);*/
if (sck->on_disconnect) sck->on_disconnect (sck); /* restored to the orginal parent handler in unbind_task_from_client() */
hio_svc_htts_client_default_on_disconnect (sck); /* restored to the orginal parent handler in unbind_task_from_client() */
HIO_SVC_HTTS_TASK_RCDOWN ((hio_svc_htts_task_t*)txt);
}
@@ -162,7 +162,6 @@ static void txt_client_on_disconnect (hio_dev_sck_t* sck)
static int txt_client_on_read (hio_dev_sck_t* sck, const void* buf, hio_iolen_t len, const hio_skad_t* srcaddr)
{
hio_dev_sck_evcb_t* parent = hio_dev_sck_getparentevcb(sck);
hio_t* hio = sck->hio;
hio_svc_htts_cli_t* cli = hio_dev_sck_getxtn(sck);
txt_t* txt = (txt_t*)cli->task;
@@ -170,7 +169,7 @@ static int txt_client_on_read (hio_dev_sck_t* sck, const void* buf, hio_iolen_t
HIO_ASSERT(hio, sck == cli->sck);
n = parent && parent->on_read? parent->on_read(sck, buf, len, srcaddr): 0;
n = hio_svc_htts_client_default_on_read(sck, buf, len, srcaddr);
if (len <= -1)
{
@@ -200,13 +199,12 @@ oops:
static int txt_client_on_write (hio_dev_sck_t* sck, hio_iolen_t wrlen, void* wrctx, const hio_skad_t* dstaddr)
{
hio_dev_sck_evcb_t* parent = hio_dev_sck_getparentevcb(sck);
hio_t* hio = sck->hio;
hio_svc_htts_cli_t* cli = hio_dev_sck_getxtn(sck);
txt_t* txt = (txt_t*)cli->task;
int n;
n = parent && parent->on_write? parent->on_write(sck, wrlen, wrctx, dstaddr): 0;
n = hio_svc_htts_client_default_on_write(sck, wrlen, wrctx, dstaddr);
if (wrlen == 0)
{
+1 -1
View File
@@ -1,5 +1,5 @@
/*
Copyright (c) 2016-2018 Chung, Hyung-Hwan. All rights reserved.
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
-41
View File
@@ -2633,47 +2633,6 @@ int hio_dev_sck_writetosidechan (hio_dev_sck_t* dev, const void* dptr, hio_oow_t
/* ========================================================================= */
void hio_dev_sck_pushevcb (hio_dev_sck_t* dev, hio_dev_sck_evcb_link_t* link, const hio_dev_sck_evcb_t* evcb, void* ctx)
{
link->saved.on_read = dev->on_read;
link->saved.on_write = dev->on_write;
link->saved.on_disconnect = dev->on_disconnect;
link->ctx = ctx;
link->prev = dev->evcb_top;
dev->evcb_top = link;
/* a null member means "leave the layer below in place" */
if (evcb->on_read) dev->on_read = evcb->on_read;
if (evcb->on_write) dev->on_write = evcb->on_write;
if (evcb->on_disconnect) dev->on_disconnect = evcb->on_disconnect;
}
hio_dev_sck_evcb_link_t* hio_dev_sck_popevcb (hio_dev_sck_t* dev)
{
hio_dev_sck_evcb_link_t* link;
link = dev->evcb_top;
if (!link) return HIO_NULL; /* nothing in the stack */
dev->on_read = link->saved.on_read;
dev->on_write = link->saved.on_write;
dev->on_disconnect = link->saved.on_disconnect;
dev->evcb_top = link->prev;
link->prev = HIO_NULL;
return link;
}
void* hio_dev_sck_getevcbctx (hio_dev_sck_t* dev)
{
return dev->evcb_top? dev->evcb_top->ctx: HIO_NULL;
}
hio_dev_sck_evcb_t* hio_dev_sck_getparentevcb (hio_dev_sck_t* dev)
{
return dev->evcb_top? &dev->evcb_top->saved: HIO_NULL;
}
/* ========================================================================= */
hio_uint16_t hio_checksum_ip (const void* hdr, hio_oow_t len)
+24 -3
View File
@@ -14,10 +14,17 @@ LDFLAGS_COMMON=-L$(abs_builddir)/../lib -L$(libdir)
LIBADD_COMMON = ../lib/libhio.la $(LIBM)
check_SCRIPTS = s-001.sh
check_SCRIPTS = s-001.sh s-002.sh
EXTRA_DIST = $(check_SCRIPTS) tap.inc t-cgi.sh
check_PROGRAMS = t-001 t-002 t-003 t-004 t-005 t-006 t-007 t-008
## programs run as tests
TESTPROGS = t-001 t-002 t-003 t-004 t-005 t-006 t-007 t-008
## helpers the test scripts drive. built with the tests, but not tests
## themselves - they are servers and would never exit.
HELPERPROGS = fcgis httssvr
check_PROGRAMS = $(TESTPROGS) $(HELPERPROGS)
t_001_SOURCES = t-001.c tap.h
t_001_CPPFLAGS = $(CPPFLAGS_COMMON)
@@ -69,8 +76,22 @@ t_008_CFLAGS = $(CFLAGS_COMMON)
t_008_LDFLAGS = $(LDFLAGS_COMMON)
t_008_LDADD = $(LIBADD_COMMON)
## a minimal FastCGI responder, driven by s-002.sh
fcgis_SOURCES = fcgis.c
fcgis_CPPFLAGS = $(CPPFLAGS_COMMON)
fcgis_CFLAGS = $(CFLAGS_COMMON)
fcgis_LDFLAGS = $(LDFLAGS_COMMON)
fcgis_LDADD = $(LIBADD_COMMON)
## an http server exercising the htts task types, driven by s-002.sh
httssvr_SOURCES = httssvr.c
httssvr_CPPFLAGS = $(CPPFLAGS_COMMON)
httssvr_CFLAGS = $(CFLAGS_COMMON)
httssvr_LDFLAGS = $(LDFLAGS_COMMON)
httssvr_LDADD = $(LIBADD_COMMON)
LOG_DRIVER = env AM_TAP_AWK='$(AWK)' $(SHELL) $(top_srcdir)/ac/tap-driver.sh
TESTS = $(check_PROGRAMS) $(check_SCRIPTS)
TESTS = $(TESTPROGS) $(check_SCRIPTS)
TEST_EXTENSIONS = .sh
SH_LOG_DRIVER = $(LOG_DRIVER)
+86 -15
View File
@@ -89,9 +89,8 @@ PRE_UNINSTALL = :
POST_UNINSTALL = :
build_triplet = @build@
host_triplet = @host@
check_PROGRAMS = t-001$(EXEEXT) t-002$(EXEEXT) t-003$(EXEEXT) \
t-004$(EXEEXT) t-005$(EXEEXT) t-006$(EXEEXT) t-007$(EXEEXT) \
t-008$(EXEEXT)
check_PROGRAMS = $(am__EXEEXT_1) $(am__EXEEXT_2)
TESTS = $(am__EXEEXT_1) $(check_SCRIPTS)
subdir = t
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
am__aclocal_m4_deps = $(top_srcdir)/m4/ax_check_sign.m4 \
@@ -107,15 +106,31 @@ mkinstalldirs = $(install_sh) -d
CONFIG_HEADER = $(top_builddir)/lib/hio-cfg.h
CONFIG_CLEAN_FILES =
CONFIG_CLEAN_VPATH_FILES =
am_t_001_OBJECTS = t_001-t-001.$(OBJEXT)
t_001_OBJECTS = $(am_t_001_OBJECTS)
am__EXEEXT_1 = t-001$(EXEEXT) t-002$(EXEEXT) t-003$(EXEEXT) \
t-004$(EXEEXT) t-005$(EXEEXT) t-006$(EXEEXT) t-007$(EXEEXT) \
t-008$(EXEEXT)
am__EXEEXT_2 = fcgis$(EXEEXT) httssvr$(EXEEXT)
am_fcgis_OBJECTS = fcgis-fcgis.$(OBJEXT)
fcgis_OBJECTS = $(am_fcgis_OBJECTS)
am__DEPENDENCIES_1 =
am__DEPENDENCIES_2 = ../lib/libhio.la $(am__DEPENDENCIES_1)
t_001_DEPENDENCIES = $(am__DEPENDENCIES_2)
fcgis_DEPENDENCIES = $(am__DEPENDENCIES_2)
AM_V_lt = $(am__v_lt_@AM_V@)
am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@)
am__v_lt_0 = --silent
am__v_lt_1 =
fcgis_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
$(LIBTOOLFLAGS) --mode=link $(CCLD) $(fcgis_CFLAGS) $(CFLAGS) \
$(fcgis_LDFLAGS) $(LDFLAGS) -o $@
am_httssvr_OBJECTS = httssvr-httssvr.$(OBJEXT)
httssvr_OBJECTS = $(am_httssvr_OBJECTS)
httssvr_DEPENDENCIES = $(am__DEPENDENCIES_2)
httssvr_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
$(LIBTOOLFLAGS) --mode=link $(CCLD) $(httssvr_CFLAGS) \
$(CFLAGS) $(httssvr_LDFLAGS) $(LDFLAGS) -o $@
am_t_001_OBJECTS = t_001-t-001.$(OBJEXT)
t_001_OBJECTS = $(am_t_001_OBJECTS)
t_001_DEPENDENCIES = $(am__DEPENDENCIES_2)
t_001_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
$(LIBTOOLFLAGS) --mode=link $(CCLD) $(t_001_CFLAGS) $(CFLAGS) \
$(t_001_LDFLAGS) $(LDFLAGS) -o $@
@@ -176,7 +191,8 @@ am__v_at_1 =
DEFAULT_INCLUDES =
depcomp = $(SHELL) $(top_srcdir)/ac/depcomp
am__maybe_remake_depfiles = depfiles
am__depfiles_remade = ./$(DEPDIR)/t_001-t-001.Po \
am__depfiles_remade = ./$(DEPDIR)/fcgis-fcgis.Po \
./$(DEPDIR)/httssvr-httssvr.Po ./$(DEPDIR)/t_001-t-001.Po \
./$(DEPDIR)/t_002-t-002.Po ./$(DEPDIR)/t_003-t-003.Po \
./$(DEPDIR)/t_004-t-004.Po ./$(DEPDIR)/t_005-t-005.Po \
./$(DEPDIR)/t_006-t-006.Po ./$(DEPDIR)/t_007-t-007.Po \
@@ -200,12 +216,14 @@ AM_V_CCLD = $(am__v_CCLD_@AM_V@)
am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@)
am__v_CCLD_0 = @echo " CCLD " $@;
am__v_CCLD_1 =
SOURCES = $(t_001_SOURCES) $(t_002_SOURCES) $(t_003_SOURCES) \
$(t_004_SOURCES) $(t_005_SOURCES) $(t_006_SOURCES) \
$(t_007_SOURCES) $(t_008_SOURCES)
DIST_SOURCES = $(t_001_SOURCES) $(t_002_SOURCES) $(t_003_SOURCES) \
$(t_004_SOURCES) $(t_005_SOURCES) $(t_006_SOURCES) \
$(t_007_SOURCES) $(t_008_SOURCES)
SOURCES = $(fcgis_SOURCES) $(httssvr_SOURCES) $(t_001_SOURCES) \
$(t_002_SOURCES) $(t_003_SOURCES) $(t_004_SOURCES) \
$(t_005_SOURCES) $(t_006_SOURCES) $(t_007_SOURCES) \
$(t_008_SOURCES)
DIST_SOURCES = $(fcgis_SOURCES) $(httssvr_SOURCES) $(t_001_SOURCES) \
$(t_002_SOURCES) $(t_003_SOURCES) $(t_004_SOURCES) \
$(t_005_SOURCES) $(t_006_SOURCES) $(t_007_SOURCES) \
$(t_008_SOURCES)
am__can_run_installinfo = \
case $$AM_UPDATE_INFO_DIR in \
n|no|NO) false;; \
@@ -593,8 +611,10 @@ CPPFLAGS_COMMON = \
CFLAGS_COMMON =
LDFLAGS_COMMON = -L$(abs_builddir)/../lib -L$(libdir)
LIBADD_COMMON = ../lib/libhio.la $(LIBM)
check_SCRIPTS = s-001.sh
check_SCRIPTS = s-001.sh s-002.sh
EXTRA_DIST = $(check_SCRIPTS) tap.inc t-cgi.sh
TESTPROGS = t-001 t-002 t-003 t-004 t-005 t-006 t-007 t-008
HELPERPROGS = fcgis httssvr
t_001_SOURCES = t-001.c tap.h
t_001_CPPFLAGS = $(CPPFLAGS_COMMON)
t_001_CFLAGS = $(CFLAGS_COMMON)
@@ -635,8 +655,17 @@ t_008_CPPFLAGS = $(CPPFLAGS_COMMON)
t_008_CFLAGS = $(CFLAGS_COMMON)
t_008_LDFLAGS = $(LDFLAGS_COMMON)
t_008_LDADD = $(LIBADD_COMMON)
fcgis_SOURCES = fcgis.c
fcgis_CPPFLAGS = $(CPPFLAGS_COMMON)
fcgis_CFLAGS = $(CFLAGS_COMMON)
fcgis_LDFLAGS = $(LDFLAGS_COMMON)
fcgis_LDADD = $(LIBADD_COMMON)
httssvr_SOURCES = httssvr.c
httssvr_CPPFLAGS = $(CPPFLAGS_COMMON)
httssvr_CFLAGS = $(CFLAGS_COMMON)
httssvr_LDFLAGS = $(LDFLAGS_COMMON)
httssvr_LDADD = $(LIBADD_COMMON)
LOG_DRIVER = env AM_TAP_AWK='$(AWK)' $(SHELL) $(top_srcdir)/ac/tap-driver.sh
TESTS = $(check_PROGRAMS) $(check_SCRIPTS)
TEST_EXTENSIONS = .sh
SH_LOG_DRIVER = $(LOG_DRIVER)
SH_LOG_COMPILER = /bin/sh
@@ -678,6 +707,14 @@ clean-checkPROGRAMS:
$(am__rm_f) $(check_PROGRAMS)
test -z "$(EXEEXT)" || $(am__rm_f) $(check_PROGRAMS:$(EXEEXT)=)
fcgis$(EXEEXT): $(fcgis_OBJECTS) $(fcgis_DEPENDENCIES) $(EXTRA_fcgis_DEPENDENCIES)
@rm -f fcgis$(EXEEXT)
$(AM_V_CCLD)$(fcgis_LINK) $(fcgis_OBJECTS) $(fcgis_LDADD) $(LIBS)
httssvr$(EXEEXT): $(httssvr_OBJECTS) $(httssvr_DEPENDENCIES) $(EXTRA_httssvr_DEPENDENCIES)
@rm -f httssvr$(EXEEXT)
$(AM_V_CCLD)$(httssvr_LINK) $(httssvr_OBJECTS) $(httssvr_LDADD) $(LIBS)
t-001$(EXEEXT): $(t_001_OBJECTS) $(t_001_DEPENDENCIES) $(EXTRA_t_001_DEPENDENCIES)
@rm -f t-001$(EXEEXT)
$(AM_V_CCLD)$(t_001_LINK) $(t_001_OBJECTS) $(t_001_LDADD) $(LIBS)
@@ -716,6 +753,8 @@ mostlyclean-compile:
distclean-compile:
-rm -f *.tab.c
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fcgis-fcgis.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/httssvr-httssvr.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/t_001-t-001.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/t_002-t-002.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/t_003-t-003.Po@am__quote@ # am--include-marker
@@ -755,6 +794,34 @@ am--depfiles: $(am__depfiles_remade)
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $<
fcgis-fcgis.o: fcgis.c
@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(fcgis_CPPFLAGS) $(CPPFLAGS) $(fcgis_CFLAGS) $(CFLAGS) -MT fcgis-fcgis.o -MD -MP -MF $(DEPDIR)/fcgis-fcgis.Tpo -c -o fcgis-fcgis.o `test -f 'fcgis.c' || echo '$(srcdir)/'`fcgis.c
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/fcgis-fcgis.Tpo $(DEPDIR)/fcgis-fcgis.Po
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='fcgis.c' object='fcgis-fcgis.o' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(fcgis_CPPFLAGS) $(CPPFLAGS) $(fcgis_CFLAGS) $(CFLAGS) -c -o fcgis-fcgis.o `test -f 'fcgis.c' || echo '$(srcdir)/'`fcgis.c
fcgis-fcgis.obj: fcgis.c
@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(fcgis_CPPFLAGS) $(CPPFLAGS) $(fcgis_CFLAGS) $(CFLAGS) -MT fcgis-fcgis.obj -MD -MP -MF $(DEPDIR)/fcgis-fcgis.Tpo -c -o fcgis-fcgis.obj `if test -f 'fcgis.c'; then $(CYGPATH_W) 'fcgis.c'; else $(CYGPATH_W) '$(srcdir)/fcgis.c'; fi`
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/fcgis-fcgis.Tpo $(DEPDIR)/fcgis-fcgis.Po
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='fcgis.c' object='fcgis-fcgis.obj' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(fcgis_CPPFLAGS) $(CPPFLAGS) $(fcgis_CFLAGS) $(CFLAGS) -c -o fcgis-fcgis.obj `if test -f 'fcgis.c'; then $(CYGPATH_W) 'fcgis.c'; else $(CYGPATH_W) '$(srcdir)/fcgis.c'; fi`
httssvr-httssvr.o: httssvr.c
@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(httssvr_CPPFLAGS) $(CPPFLAGS) $(httssvr_CFLAGS) $(CFLAGS) -MT httssvr-httssvr.o -MD -MP -MF $(DEPDIR)/httssvr-httssvr.Tpo -c -o httssvr-httssvr.o `test -f 'httssvr.c' || echo '$(srcdir)/'`httssvr.c
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/httssvr-httssvr.Tpo $(DEPDIR)/httssvr-httssvr.Po
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='httssvr.c' object='httssvr-httssvr.o' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(httssvr_CPPFLAGS) $(CPPFLAGS) $(httssvr_CFLAGS) $(CFLAGS) -c -o httssvr-httssvr.o `test -f 'httssvr.c' || echo '$(srcdir)/'`httssvr.c
httssvr-httssvr.obj: httssvr.c
@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(httssvr_CPPFLAGS) $(CPPFLAGS) $(httssvr_CFLAGS) $(CFLAGS) -MT httssvr-httssvr.obj -MD -MP -MF $(DEPDIR)/httssvr-httssvr.Tpo -c -o httssvr-httssvr.obj `if test -f 'httssvr.c'; then $(CYGPATH_W) 'httssvr.c'; else $(CYGPATH_W) '$(srcdir)/httssvr.c'; fi`
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/httssvr-httssvr.Tpo $(DEPDIR)/httssvr-httssvr.Po
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='httssvr.c' object='httssvr-httssvr.obj' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(httssvr_CPPFLAGS) $(CPPFLAGS) $(httssvr_CFLAGS) $(CFLAGS) -c -o httssvr-httssvr.obj `if test -f 'httssvr.c'; then $(CYGPATH_W) 'httssvr.c'; else $(CYGPATH_W) '$(srcdir)/httssvr.c'; fi`
t_001-t-001.o: t-001.c
@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(t_001_CPPFLAGS) $(CPPFLAGS) $(t_001_CFLAGS) $(CFLAGS) -MT t_001-t-001.o -MD -MP -MF $(DEPDIR)/t_001-t-001.Tpo -c -o t_001-t-001.o `test -f 't-001.c' || echo '$(srcdir)/'`t-001.c
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/t_001-t-001.Tpo $(DEPDIR)/t_001-t-001.Po
@@ -1240,6 +1307,8 @@ clean-am: clean-checkPROGRAMS clean-generic clean-libtool \
mostlyclean-am
distclean: distclean-am
-rm -f ./$(DEPDIR)/fcgis-fcgis.Po
-rm -f ./$(DEPDIR)/httssvr-httssvr.Po
-rm -f ./$(DEPDIR)/t_001-t-001.Po
-rm -f ./$(DEPDIR)/t_002-t-002.Po
-rm -f ./$(DEPDIR)/t_003-t-003.Po
@@ -1293,6 +1362,8 @@ install-ps-am:
installcheck-am:
maintainer-clean: maintainer-clean-am
-rm -f ./$(DEPDIR)/fcgis-fcgis.Po
-rm -f ./$(DEPDIR)/httssvr-httssvr.Po
-rm -f ./$(DEPDIR)/t_001-t-001.Po
-rm -f ./$(DEPDIR)/t_002-t-002.Po
-rm -f ./$(DEPDIR)/t_003-t-003.Po
+303
View File
@@ -0,0 +1,303 @@
/*
* A minimal FastCGI responder, built on hio itself, for the test suite.
*
* It speaks just enough of the protocol to answer a request:
* BEGIN_REQUEST / PARAMS / STDIN in, STDOUT / END_REQUEST out. The reply
* body is a fixed marker so a test can tell that a request really
* travelled through the fcgi task and the FastCGI protocol both ways
* rather than being answered somewhere else.
*
* The client keeps a connection open across requests, so a connection is
* served until the peer closes it rather than being torn down after one.
*
* Usage: hio-fcgis <ipaddr:port> [ready-file]
*
* If ready-file is given it is created once the listener is accepting,
* which lets a harness start requests without racing this process.
*/
#include <hio.h>
#include <hio-sck.h>
#include <hio-fcgi.h>
#include <hio-utl.h>
#include <stdio.h>
#include <string.h>
#include <stddef.h>
#include <signal.h>
#include <stdlib.h>
#define RESPONSE_BODY "fcgi-ok\r\n"
/* what a connection has accumulated but not yet consumed */
#define INBUF_CAPA 65536
typedef struct conn_xtn_t conn_xtn_t;
struct conn_xtn_t
{
hio_uint8_t buf[INBUF_CAPA];
hio_oow_t len;
/* a request is answerable once it has been begun and both of its
* streams have ended. they are tracked separately because the order
* they arrive in is not guaranteed - see the note in consume_records() */
hio_uint16_t id;
unsigned int begun: 1;
unsigned int params_done: 1;
unsigned int stdin_done: 1;
};
static void reset_request (conn_xtn_t* cx)
{
cx->id = 0;
cx->begun = 0;
cx->params_done = 0;
cx->stdin_done = 0;
}
static hio_t* g_hio = HIO_NULL;
static int g_verbose = 0;
static void on_sigint (int sig)
{
if (g_hio) hio_stop (g_hio, HIO_STOPREQ_TERMINATION);
}
/* ------------------------------------------------------------------ */
/* The record layout is taken from hio-fcgi.h. Since both this responder
* and the library's client read it from the same header, a packing
* mistake would make the two agree with each other while disagreeing
* with the wire. Check it against the specification once at startup so
* that shows up as a loud failure instead of a silent one. */
static int check_wire_layout (void)
{
if (HIO_SIZEOF(hio_fcgi_record_header_t) != 8 ||
offsetof(hio_fcgi_record_header_t, version) != 0 ||
offsetof(hio_fcgi_record_header_t, type) != 1 ||
offsetof(hio_fcgi_record_header_t, id) != 2 ||
offsetof(hio_fcgi_record_header_t, content_len) != 4 ||
offsetof(hio_fcgi_record_header_t, padding_len) != 6)
{
fprintf (stderr, "hio_fcgi_record_header_t does not match the FastCGI wire layout\n");
return -1;
}
if (HIO_SIZEOF(hio_fcgi_begin_request_body_t) != 8 ||
HIO_SIZEOF(hio_fcgi_end_request_body_t) != 8)
{
fprintf (stderr, "FastCGI body structures do not match the wire layout\n");
return -1;
}
return 0;
}
static int write_record (hio_dev_sck_t* sck, int type, hio_uint16_t id, const void* data, hio_uint16_t len)
{
hio_fcgi_record_header_t hdr;
memset (&hdr, 0, HIO_SIZEOF(hdr));
hdr.version = HIO_FCGI_VERSION;
hdr.type = type;
hdr.id = hio_hton16(id);
hdr.content_len = hio_hton16(len);
if (hio_dev_sck_write(sck, &hdr, HIO_SIZEOF(hdr), HIO_NULL, HIO_NULL) <= -1) return -1;
if (len > 0 && hio_dev_sck_write(sck, data, len, HIO_NULL, HIO_NULL) <= -1) return -1;
return 0;
}
static int respond (hio_dev_sck_t* sck, hio_uint16_t id)
{
static const char out[] = "Content-Type: text/plain\r\n\r\n" RESPONSE_BODY;
hio_fcgi_end_request_body_t end;
if (write_record(sck, HIO_FCGI_STDOUT, id, out, HIO_SIZEOF(out) - 1) <= -1) return -1;
if (write_record(sck, HIO_FCGI_STDOUT, id, HIO_NULL, 0) <= -1) return -1; /* end of stream */
memset (&end, 0, HIO_SIZEOF(end));
end.app_status = hio_hton32(0);
end.proto_status = HIO_FCGI_REQUEST_COMPLETE;
return write_record(sck, HIO_FCGI_END_REQUEST, id, &end, HIO_SIZEOF(end));
}
/* consume as many whole records as the buffer holds */
static int consume_records (hio_dev_sck_t* sck, conn_xtn_t* cx)
{
while (cx->len >= HIO_SIZEOF(hio_fcgi_record_header_t))
{
hio_fcgi_record_header_t hdr;
hio_oow_t clen, plen, total;
memcpy (&hdr, cx->buf, HIO_SIZEOF(hdr));
clen = hio_ntoh16(hdr.content_len);
plen = hdr.padding_len;
total = HIO_SIZEOF(hdr) + clen + plen;
if (g_verbose) fprintf (stderr, "record type=%d id=%d clen=%d have=%d\n",
(int)hdr.type, (int)hio_ntoh16(hdr.id), (int)clen, (int)cx->len);
if (cx->len < total) break; /* wait for the rest of this record */
/* Answer once the request has been begun and both of its streams
* have ended, rather than on any single record. A responder has no
* business assuming the three arrive in one particular order, and
* tracking them separately keeps this working whatever order a
* client picks. */
switch (hdr.type)
{
case HIO_FCGI_BEGIN_REQUEST:
cx->id = hio_ntoh16(hdr.id);
cx->begun = 1;
break;
case HIO_FCGI_PARAMS:
if (clen == 0) cx->params_done = 1;
break;
case HIO_FCGI_STDIN:
if (clen == 0) cx->stdin_done = 1;
break;
}
if (cx->begun && cx->params_done && cx->stdin_done)
{
if (respond(sck, cx->id) <= -1) return -1;
reset_request (cx); /* the connection may carry more requests */
}
memmove (cx->buf, &cx->buf[total], cx->len - total);
cx->len -= total;
}
return 0;
}
/* ------------------------------------------------------------------ */
static int on_read (hio_dev_sck_t* sck, const void* buf, hio_iolen_t len, const hio_skad_t* srcaddr)
{
conn_xtn_t* cx = hio_dev_sck_getxtn(sck);
if (len <= 0) return 0; /* error or peer closed - let the device wind down */
if (cx->len + len > HIO_SIZEOF(cx->buf))
{
/* a test request never gets near this; treat it as a protocol error */
hio_dev_sck_halt (sck);
return 0;
}
memcpy (&cx->buf[cx->len], buf, len);
cx->len += len;
if (consume_records(sck, cx) <= -1) hio_dev_sck_halt (sck);
return 0;
}
static int on_write (hio_dev_sck_t* sck, hio_iolen_t wrlen, void* wrctx, const hio_skad_t* dstaddr)
{
return 0;
}
static void on_connect (hio_dev_sck_t* sck)
{
if (sck->state & HIO_DEV_SCK_ACCEPTED)
{
conn_xtn_t* cx = hio_dev_sck_getxtn(sck);
cx->len = 0;
reset_request (cx);
if (g_verbose) fprintf (stderr, "accepted\n");
}
}
static void on_disconnect (hio_dev_sck_t* sck)
{
}
/* ------------------------------------------------------------------ */
int main (int argc, char* argv[])
{
hio_dev_sck_t* svr;
hio_dev_sck_make_t m;
hio_dev_sck_bind_t b;
hio_dev_sck_listen_t l;
hio_skad_t addr;
int ret = -1;
if (argc < 2 || argc > 3)
{
fprintf (stderr, "Usage: %s <ipaddr:port> [ready-file]\n", argv[0]);
return -1;
}
if (check_wire_layout() <= -1) return -1;
g_verbose = (getenv("HIO_FCGIS_VERBOSE") != HIO_NULL);
g_hio = hio_open(HIO_NULL, 0, HIO_NULL, HIO_FEATURE_ALL, 256, HIO_NULL);
if (!g_hio)
{
fprintf (stderr, "unable to open hio\n");
return -1;
}
signal (SIGINT, on_sigint);
signal (SIGTERM, on_sigint);
signal (SIGPIPE, SIG_IGN);
if (hio_bcstrtoskad(g_hio, argv[1], &addr) <= -1)
{
fprintf (stderr, "invalid address - %s\n", argv[1]);
goto oops;
}
memset (&m, 0, HIO_SIZEOF(m));
m.type = (hio_skad_get_family(&addr) == HIO_AF_INET)? HIO_DEV_SCK_TCP4: HIO_DEV_SCK_TCP6;
m.on_read = on_read;
m.on_write = on_write;
m.on_connect = on_connect;
m.on_disconnect = on_disconnect;
svr = hio_dev_sck_make(g_hio, HIO_SIZEOF(conn_xtn_t), &m);
if (!svr)
{
fprintf (stderr, "unable to make a socket - %s\n", hio_geterrbmsg(g_hio));
goto oops;
}
memset (&b, 0, HIO_SIZEOF(b));
b.localaddr = addr;
b.options = HIO_DEV_SCK_BIND_REUSEADDR;
if (hio_dev_sck_bind(svr, &b) <= -1)
{
fprintf (stderr, "unable to bind - %s\n", hio_geterrbmsg(g_hio));
goto oops;
}
memset (&l, 0, HIO_SIZEOF(l));
l.backlogs = 64;
if (hio_dev_sck_listen(svr, &l) <= -1)
{
fprintf (stderr, "unable to listen - %s\n", hio_geterrbmsg(g_hio));
goto oops;
}
if (argc >= 3)
{
/* tell the harness the listener is up, so it never races us */
FILE* fp = fopen(argv[2], "w");
if (fp)
{
fputs ("ready\n", fp);
fclose (fp);
}
}
hio_loop (g_hio);
ret = 0;
oops:
if (g_hio) hio_close (g_hio);
return ret;
}
+20
View File
@@ -215,6 +215,14 @@ if (hio_htre_getcontentlen(req) > 0)
x = hio_svc_htts_dotxt(htts, csck, req, HIO_HTTP_STATUS_OK, "text/plain", qpath, 0, HIO_NULL);
else if (hio_comp_bcstr_limited(qpath, "/cgi/", 5, 1) == 0)
x = hio_svc_htts_docgi(htts, csck, req, "", qpath + 4, 0, HIO_NULL);
else if (hio_comp_bcstr_limited(qpath, "/prxy/", 6, 1) == 0)
{
/* forward to an upstream http server. the test harness runs
* one on this port. */
hio_skad_t prxy_addr;
hio_bcstrtoskad(hio, "127.0.0.1:9001", &prxy_addr);
x = hio_svc_htts_doprxy(htts, csck, req, &prxy_addr, 0, HIO_NULL);
}
else if (hio_comp_bcstr_limited(qpath, "/fcgi/", 5, 1) == 0)
{
hio_skad_t fcgis_addr;
@@ -270,6 +278,18 @@ void* thr_func (void* arg)
goto oops;
}
{
/* the fcgi task refuses with 503 unless the client service is up.
* the timeouts must be non-zero: a zeroed 'c' is a 0-second connect
* deadline, so the peer is untied before it ever connects. */
hio_svc_fcgic_tmout_t fcgic_tmout;
memset (&fcgic_tmout, 0, HIO_SIZEOF(fcgic_tmout));
HIO_INIT_NTIME (&fcgic_tmout.c, 5, 0);
HIO_INIT_NTIME (&fcgic_tmout.r, 60, 0);
HIO_INIT_NTIME (&fcgic_tmout.w, -1, 0);
hio_svc_htts_enablefcgic (htts, &fcgic_tmout);
}
pthread_mutex_lock (&g_htts_mutex);
htts_no = g_htts_no;
g_htts[htts_no] = htts;
Executable
+146
View File
@@ -0,0 +1,146 @@
#!/bin/sh
# End-to-end coverage for the http task modules that s-001.sh does not
# reach. httssvr routes by path prefix, so txt, thr and fcgi are all
# exercisable here; fcgi talks to fcgis, the minimal responder in
# this directory.
#
# prxy is still uncovered: http-prxy.c never connects its peer socket
# (no hio_dev_sck_connect anywhere in the file) so the task cannot
# currently reach an upstream. httssvr has a /prxy/ route ready for when
# that is finished.
[ -z "$srcdir" ] && srcdir=$(dirname "$0")
. "${srcdir}/tap.inc"
SRVPORT=9988
SRVADDR="127.0.0.1:${SRVPORT}"
start_server()
{
# the fcgi task needs a responder listening on the port httssvr targets
fcgiready="/tmp/s-002-fcgi.$$.ready"
rm -f "${fcgiready}"
./fcgis 127.0.0.1:9000 "${fcgiready}" >/dev/null 2>&1 &
fcgipid=$!
# it creates the ready file once it is accepting, so nothing races it
i=0
while [ $i -lt 50 ] && [ ! -f "${fcgiready}" ]; do
i=$((i + 1))
sleep 0.1
done
[ -f "${fcgiready}" ] || fcgipid=""
./httssvr >/dev/null 2>&1 &
srvpid=$!
# wait for the listener rather than sleeping a fixed amount
i=0
while [ $i -lt 50 ]; do
curl -s -m 1 -o /dev/null "http://${SRVADDR}/txt/ping" 2>/dev/null && return 0
i=$((i + 1))
sleep 0.1
done
return 1
}
stop_server()
{
kill -TERM ${srvpid} 2>/dev/null
wait ${srvpid} 2>/dev/null
if [ -n "${fcgipid}" ]; then
kill -TERM ${fcgipid} 2>/dev/null
wait ${fcgipid} 2>/dev/null
fi
rm -f "${fcgiready}"
}
test_fcgi()
{
local msg="httssvr fcgi task"
if [ -z "${fcgipid}" ]; then
tap_fail "$msg - fcgis did not come up"
tap_fail "$msg - fcgis did not come up"
return
fi
local hc=$(curl -s -m 10 -w '%{http_code}' -o /dev/null "http://${SRVADDR}/fcgi/x.php")
tap_ensure "$hc" "200" "$msg - got $hc"
# the body can only come from the responder, so this proves the
# request traversed the fcgi task and the FastCGI protocol both ways
local body=$(curl -s -m 10 "http://${SRVADDR}/fcgi/x.php" | tr -d '\r\n')
tap_ensure "$body" "fcgi-ok" "$msg - body came from the fcgi responder"
}
test_txt()
{
local msg="httssvr txt task"
local hc=$(curl -s -m 5 -w '%{http_code}' -o /dev/null "http://${SRVADDR}/txt/hello")
tap_ensure "$hc" "200" "$msg - got $hc"
# dotxt() echoes the query path back as the body
local body=$(curl -s -m 5 "http://${SRVADDR}/txt/hello")
tap_ensure "$body" "/txt/hello" "$msg - body echoes the query path"
# the task must release the client so the next request reuses the
# connection. each -w applies to its own request, so the second line
# is the one that matters.
local n=$(curl -s -m 5 -o /dev/null -w '%{num_connects}\n' "http://${SRVADDR}/txt/one" \
-o /dev/null -w '%{num_connects}\n' "http://${SRVADDR}/txt/two" | tail -1)
tap_ensure "$n" "0" "$msg - connection is reused after the task completes"
}
test_thr()
{
local msg="httssvr thr task"
local hc=$(curl -s -m 5 -w '%{http_code}' -o /dev/null "http://${SRVADDR}/thr/x")
tap_ensure "$hc" "200" "$msg - got $hc"
# thr2 serves the filesystem path following /thr2, so point it at a
# real file to exercise the success path...
local tmpf="/tmp/s-002.$$.txt"
echo "thr2-payload" > "${tmpf}"
local body=$(curl -s -m 5 "http://${SRVADDR}/thr2${tmpf}")
tap_ensure "$body" "thr2-payload" "$msg - thr2 serves a file through the thread"
# ...and at a missing one to exercise the error path
local hc2=$(curl -s -m 5 -w '%{http_code}' -o /dev/null "http://${SRVADDR}/thr2/no/such/file")
tap_ensure "$hc2" "404" "$msg - thr2 reports 404 for a missing file"
rm -f "${tmpf}"
}
test_mixed_load()
{
local msg="httssvr mixed task load"
local ok=0 i=0
# alternate task types on the same server to shake out cross-task
# client-binding mistakes
while [ $i -lt 12 ]; do
for p in /txt/a /thr/b /txt/c; do
local hc=$(curl -s -m 5 -o /dev/null -w '%{http_code}' "http://${SRVADDR}${p}")
[ "$hc" = "200" ] && ok=$((ok + 1))
done
i=$((i + 1))
done
tap_ensure "$ok" "36" "$msg - 36/36 requests succeeded"
# and the server must still be alive afterwards
kill -0 ${srvpid} 2>/dev/null && tap_ok "$msg - server still running" \
|| tap_fail "$msg - server died"
}
if start_server; then
test_txt
test_thr
test_fcgi
test_mixed_load
stop_server
else
tap_skip "httssvr did not come up"
fi
tap_end
-78
View File
@@ -574,83 +574,6 @@ done:
if (b && b->magic == TDEV_LIVE) hio_dev_kill ((hio_dev_t*)b);
}
/* ------------------------------------------------------------------ */
/* evcb stack */
/* ------------------------------------------------------------------ */
static int g_layer_read[2];
static int layer_x_on_read (hio_dev_t* dev, const void* p, hio_iolen_t l, const hio_devaddr_t* s)
{
g_layer_read[0]++;
return 0;
}
static int layer_y_on_read (hio_dev_t* dev, const void* p, hio_iolen_t l, const hio_devaddr_t* s)
{
g_layer_read[1]++;
return 0;
}
static int layer_on_write (hio_dev_t* dev, hio_iolen_t l, void* c, const hio_devaddr_t* a)
{
return 0;
}
/* declared the way every device type in the library declares its own: one
* file-scope table per role, shared by every device playing that role.
* that sharing is the whole point of the pattern, and it is what any
* stack-link stored inside the table has to survive. */
static hio_dev_evcb_t g_layer_x = { HIO_NULL, layer_x_on_read, layer_on_write };
static hio_dev_evcb_t g_layer_y = { HIO_NULL, layer_y_on_read, layer_on_write };
/* the stack links are per-device storage owned by the pusher */
static hio_dev_evcb_link_t g_link_a, g_link_b0, g_link_b1;
static void test_evcb_stack (void)
{
tdev_t* a = HIO_NULL, * b = HIO_NULL;
int pa = -1, pb = -1;
obs_reset ();
g_layer_read[0] = g_layer_read[1] = 0;
a = make_tdev(11, &pa);
b = make_tdev(12, &pb);
if (!a || !b) { skip ("device creation failed", 7); goto done; }
OK (a->dev_evcb == &tdev_evcb && b->dev_evcb == &tdev_evcb,
"both devices start on the base handler table");
hio_dev_pushevcb ((hio_dev_t*)a, &g_link_a, &g_layer_x, a);
OK (a->dev_evcb == &g_layer_x, "push swaps the device onto the pushed table");
OK (hio_dev_getevcbctx((hio_dev_t*)a) == a, "the pushed layer's context is readable");
/* b stacks two deep and reuses the very table a is already sitting on -
* the ordinary case when one handler set serves many connections */
hio_dev_pushevcb ((hio_dev_t*)b, &g_link_b0, &g_layer_y, b);
hio_dev_pushevcb ((hio_dev_t*)b, &g_link_b1, &g_layer_x, b);
OK (b->dev_evcb == &g_layer_x, "a second device can stack two layers deep");
OK (hio_dev_getevcbctx((hio_dev_t*)a) == a && hio_dev_getevcbctx((hio_dev_t*)b) == b,
"each device keeps its own context for the same shared table");
hio_dev_popevcb ((hio_dev_t*)a);
OK (a->dev_evcb == (hio_dev_evcb_t*)&tdev_evcb,
"popping restores a device's own previous table, not another device's");
/* and behaviourally: input on 'a' must reach the base handler again */
if (write(pa, "z", 1) == 1) pump ();
OK (g_on_read_calls == 1 && g_layer_read[0] == 0 && g_layer_read[1] == 0,
"after popping, events are delivered to the base handler");
done:
if (b) { while (hio_dev_popevcb((hio_dev_t*)b)) ; }
if (pa >= 0) close (pa);
if (pb >= 0) close (pb);
if (a && a->magic == TDEV_LIVE) hio_dev_kill ((hio_dev_t*)a);
if (b && b->magic == TDEV_LIVE) hio_dev_kill ((hio_dev_t*)b);
}
static void test_fini_kills_survivors (void)
{
/* devices still active or halted at hio_close() time must be destroyed */
@@ -707,7 +630,6 @@ int main (void)
test_zombie_escalation ();
test_read_and_eof ();
test_kill_peer_from_callback ();
test_evcb_stack ();
test_fini_kills_survivors ();
hio_close (g_hio);