adding some functions for multi-threading
This commit is contained in:
		| @ -52,3 +52,9 @@ mio_t05_SOURCES = t05.c | |||||||
| mio_t05_CPPFLAGS = $(CPPFLAGS_LIB_COMMON) | mio_t05_CPPFLAGS = $(CPPFLAGS_LIB_COMMON) | ||||||
| mio_t05_LDFLAGS = $(LDFLAGS_LIB_COMMON) | mio_t05_LDFLAGS = $(LDFLAGS_LIB_COMMON) | ||||||
| mio_t05_LDADD = $(LIBADD_LIB_COMMON) -lmio $(SSL_LIBS) $(SOCKET_LIBS) $(SENDFILE_LIBS) | mio_t05_LDADD = $(LIBADD_LIB_COMMON) -lmio $(SSL_LIBS) $(SOCKET_LIBS) $(SENDFILE_LIBS) | ||||||
|  |  | ||||||
|  | bin_PROGRAMS += mio-t06 | ||||||
|  | mio_t06_SOURCES = t06.c | ||||||
|  | mio_t06_CPPFLAGS = $(CPPFLAGS_LIB_COMMON) | ||||||
|  | mio_t06_LDFLAGS = $(LDFLAGS_LIB_COMMON) | ||||||
|  | mio_t06_LDADD = $(LIBADD_LIB_COMMON) -lmio $(SSL_LIBS) $(SOCKET_LIBS) $(SENDFILE_LIBS) | ||||||
|  | |||||||
| @ -89,7 +89,8 @@ POST_UNINSTALL = : | |||||||
| build_triplet = @build@ | build_triplet = @build@ | ||||||
| host_triplet = @host@ | host_triplet = @host@ | ||||||
| bin_PROGRAMS = mio-execd$(EXEEXT) mio-t01$(EXEEXT) mio-t02$(EXEEXT) \ | bin_PROGRAMS = mio-execd$(EXEEXT) mio-t01$(EXEEXT) mio-t02$(EXEEXT) \ | ||||||
| 	mio-t03$(EXEEXT) mio-t04$(EXEEXT) mio-t05$(EXEEXT) | 	mio-t03$(EXEEXT) mio-t04$(EXEEXT) mio-t05$(EXEEXT) \ | ||||||
|  | 	mio-t06$(EXEEXT) | ||||||
| subdir = bin | subdir = bin | ||||||
| ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 | ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 | ||||||
| am__aclocal_m4_deps = $(top_srcdir)/m4/ax_check_sign.m4 \ | am__aclocal_m4_deps = $(top_srcdir)/m4/ax_check_sign.m4 \ | ||||||
| @ -155,6 +156,13 @@ mio_t05_DEPENDENCIES = $(am__DEPENDENCIES_2) $(am__DEPENDENCIES_1) \ | |||||||
| mio_t05_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ | mio_t05_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ | ||||||
| 	$(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ | 	$(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ | ||||||
| 	$(mio_t05_LDFLAGS) $(LDFLAGS) -o $@ | 	$(mio_t05_LDFLAGS) $(LDFLAGS) -o $@ | ||||||
|  | am_mio_t06_OBJECTS = mio_t06-t06.$(OBJEXT) | ||||||
|  | mio_t06_OBJECTS = $(am_mio_t06_OBJECTS) | ||||||
|  | mio_t06_DEPENDENCIES = $(am__DEPENDENCIES_2) $(am__DEPENDENCIES_1) \ | ||||||
|  | 	$(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) | ||||||
|  | mio_t06_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ | ||||||
|  | 	$(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ | ||||||
|  | 	$(mio_t06_LDFLAGS) $(LDFLAGS) -o $@ | ||||||
| AM_V_P = $(am__v_P_@AM_V@) | AM_V_P = $(am__v_P_@AM_V@) | ||||||
| am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) | am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) | ||||||
| am__v_P_0 = false | am__v_P_0 = false | ||||||
| @ -173,7 +181,7 @@ am__maybe_remake_depfiles = depfiles | |||||||
| am__depfiles_remade = ./$(DEPDIR)/mio_execd-execd.Po \ | am__depfiles_remade = ./$(DEPDIR)/mio_execd-execd.Po \ | ||||||
| 	./$(DEPDIR)/mio_t01-t01.Po ./$(DEPDIR)/mio_t02-t02.Po \ | 	./$(DEPDIR)/mio_t01-t01.Po ./$(DEPDIR)/mio_t02-t02.Po \ | ||||||
| 	./$(DEPDIR)/mio_t03-t03.Po ./$(DEPDIR)/mio_t04-t04.Po \ | 	./$(DEPDIR)/mio_t03-t03.Po ./$(DEPDIR)/mio_t04-t04.Po \ | ||||||
| 	./$(DEPDIR)/mio_t05-t05.Po | 	./$(DEPDIR)/mio_t05-t05.Po ./$(DEPDIR)/mio_t06-t06.Po | ||||||
| am__mv = mv -f | am__mv = mv -f | ||||||
| COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ | COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ | ||||||
| 	$(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) | 	$(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) | ||||||
| @ -194,10 +202,11 @@ am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) | |||||||
| am__v_CCLD_0 = @echo "  CCLD    " $@; | am__v_CCLD_0 = @echo "  CCLD    " $@; | ||||||
| am__v_CCLD_1 =  | am__v_CCLD_1 =  | ||||||
| SOURCES = $(mio_execd_SOURCES) $(mio_t01_SOURCES) $(mio_t02_SOURCES) \ | SOURCES = $(mio_execd_SOURCES) $(mio_t01_SOURCES) $(mio_t02_SOURCES) \ | ||||||
| 	$(mio_t03_SOURCES) $(mio_t04_SOURCES) $(mio_t05_SOURCES) | 	$(mio_t03_SOURCES) $(mio_t04_SOURCES) $(mio_t05_SOURCES) \ | ||||||
|  | 	$(mio_t06_SOURCES) | ||||||
| DIST_SOURCES = $(mio_execd_SOURCES) $(mio_t01_SOURCES) \ | DIST_SOURCES = $(mio_execd_SOURCES) $(mio_t01_SOURCES) \ | ||||||
| 	$(mio_t02_SOURCES) $(mio_t03_SOURCES) $(mio_t04_SOURCES) \ | 	$(mio_t02_SOURCES) $(mio_t03_SOURCES) $(mio_t04_SOURCES) \ | ||||||
| 	$(mio_t05_SOURCES) | 	$(mio_t05_SOURCES) $(mio_t06_SOURCES) | ||||||
| am__can_run_installinfo = \ | am__can_run_installinfo = \ | ||||||
|   case $$AM_UPDATE_INFO_DIR in \ |   case $$AM_UPDATE_INFO_DIR in \ | ||||||
|     n|no|NO) false;; \ |     n|no|NO) false;; \ | ||||||
| @ -411,6 +420,10 @@ mio_t05_SOURCES = t05.c | |||||||
| mio_t05_CPPFLAGS = $(CPPFLAGS_LIB_COMMON) | mio_t05_CPPFLAGS = $(CPPFLAGS_LIB_COMMON) | ||||||
| mio_t05_LDFLAGS = $(LDFLAGS_LIB_COMMON) | mio_t05_LDFLAGS = $(LDFLAGS_LIB_COMMON) | ||||||
| mio_t05_LDADD = $(LIBADD_LIB_COMMON) -lmio $(SSL_LIBS) $(SOCKET_LIBS) $(SENDFILE_LIBS) | mio_t05_LDADD = $(LIBADD_LIB_COMMON) -lmio $(SSL_LIBS) $(SOCKET_LIBS) $(SENDFILE_LIBS) | ||||||
|  | mio_t06_SOURCES = t06.c | ||||||
|  | mio_t06_CPPFLAGS = $(CPPFLAGS_LIB_COMMON) | ||||||
|  | mio_t06_LDFLAGS = $(LDFLAGS_LIB_COMMON) | ||||||
|  | mio_t06_LDADD = $(LIBADD_LIB_COMMON) -lmio $(SSL_LIBS) $(SOCKET_LIBS) $(SENDFILE_LIBS) | ||||||
| all: all-am | all: all-am | ||||||
|  |  | ||||||
| .SUFFIXES: | .SUFFIXES: | ||||||
| @ -518,6 +531,10 @@ mio-t05$(EXEEXT): $(mio_t05_OBJECTS) $(mio_t05_DEPENDENCIES) $(EXTRA_mio_t05_DEP | |||||||
| 	@rm -f mio-t05$(EXEEXT) | 	@rm -f mio-t05$(EXEEXT) | ||||||
| 	$(AM_V_CCLD)$(mio_t05_LINK) $(mio_t05_OBJECTS) $(mio_t05_LDADD) $(LIBS) | 	$(AM_V_CCLD)$(mio_t05_LINK) $(mio_t05_OBJECTS) $(mio_t05_LDADD) $(LIBS) | ||||||
|  |  | ||||||
|  | mio-t06$(EXEEXT): $(mio_t06_OBJECTS) $(mio_t06_DEPENDENCIES) $(EXTRA_mio_t06_DEPENDENCIES)  | ||||||
|  | 	@rm -f mio-t06$(EXEEXT) | ||||||
|  | 	$(AM_V_CCLD)$(mio_t06_LINK) $(mio_t06_OBJECTS) $(mio_t06_LDADD) $(LIBS) | ||||||
|  |  | ||||||
| mostlyclean-compile: | mostlyclean-compile: | ||||||
| 	-rm -f *.$(OBJEXT) | 	-rm -f *.$(OBJEXT) | ||||||
|  |  | ||||||
| @ -530,6 +547,7 @@ distclean-compile: | |||||||
| @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mio_t03-t03.Po@am__quote@ # am--include-marker | @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mio_t03-t03.Po@am__quote@ # am--include-marker | ||||||
| @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mio_t04-t04.Po@am__quote@ # am--include-marker | @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mio_t04-t04.Po@am__quote@ # am--include-marker | ||||||
| @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mio_t05-t05.Po@am__quote@ # am--include-marker | @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mio_t05-t05.Po@am__quote@ # am--include-marker | ||||||
|  | @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mio_t06-t06.Po@am__quote@ # am--include-marker | ||||||
|  |  | ||||||
| $(am__depfiles_remade): | $(am__depfiles_remade): | ||||||
| 	@$(MKDIR_P) $(@D) | 	@$(MKDIR_P) $(@D) | ||||||
| @ -645,6 +663,20 @@ mio_t05-t05.obj: t05.c | |||||||
| @AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ | @AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ | ||||||
| @am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mio_t05_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o mio_t05-t05.obj `if test -f 't05.c'; then $(CYGPATH_W) 't05.c'; else $(CYGPATH_W) '$(srcdir)/t05.c'; fi` | @am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mio_t05_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o mio_t05-t05.obj `if test -f 't05.c'; then $(CYGPATH_W) 't05.c'; else $(CYGPATH_W) '$(srcdir)/t05.c'; fi` | ||||||
|  |  | ||||||
|  | mio_t06-t06.o: t06.c | ||||||
|  | @am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mio_t06_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT mio_t06-t06.o -MD -MP -MF $(DEPDIR)/mio_t06-t06.Tpo -c -o mio_t06-t06.o `test -f 't06.c' || echo '$(srcdir)/'`t06.c | ||||||
|  | @am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/mio_t06-t06.Tpo $(DEPDIR)/mio_t06-t06.Po | ||||||
|  | @AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='t06.c' object='mio_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) $(mio_t06_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o mio_t06-t06.o `test -f 't06.c' || echo '$(srcdir)/'`t06.c | ||||||
|  |  | ||||||
|  | mio_t06-t06.obj: t06.c | ||||||
|  | @am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mio_t06_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT mio_t06-t06.obj -MD -MP -MF $(DEPDIR)/mio_t06-t06.Tpo -c -o mio_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)/mio_t06-t06.Tpo $(DEPDIR)/mio_t06-t06.Po | ||||||
|  | @AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='t06.c' object='mio_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) $(mio_t06_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o mio_t06-t06.obj `if test -f 't06.c'; then $(CYGPATH_W) 't06.c'; else $(CYGPATH_W) '$(srcdir)/t06.c'; fi` | ||||||
|  |  | ||||||
| mostlyclean-libtool: | mostlyclean-libtool: | ||||||
| 	-rm -f *.lo | 	-rm -f *.lo | ||||||
|  |  | ||||||
| @ -784,6 +816,7 @@ distclean: distclean-am | |||||||
| 	-rm -f ./$(DEPDIR)/mio_t03-t03.Po | 	-rm -f ./$(DEPDIR)/mio_t03-t03.Po | ||||||
| 	-rm -f ./$(DEPDIR)/mio_t04-t04.Po | 	-rm -f ./$(DEPDIR)/mio_t04-t04.Po | ||||||
| 	-rm -f ./$(DEPDIR)/mio_t05-t05.Po | 	-rm -f ./$(DEPDIR)/mio_t05-t05.Po | ||||||
|  | 	-rm -f ./$(DEPDIR)/mio_t06-t06.Po | ||||||
| 	-rm -f Makefile | 	-rm -f Makefile | ||||||
| distclean-am: clean-am distclean-compile distclean-generic \ | distclean-am: clean-am distclean-compile distclean-generic \ | ||||||
| 	distclean-tags | 	distclean-tags | ||||||
| @ -835,6 +868,7 @@ maintainer-clean: maintainer-clean-am | |||||||
| 	-rm -f ./$(DEPDIR)/mio_t03-t03.Po | 	-rm -f ./$(DEPDIR)/mio_t03-t03.Po | ||||||
| 	-rm -f ./$(DEPDIR)/mio_t04-t04.Po | 	-rm -f ./$(DEPDIR)/mio_t04-t04.Po | ||||||
| 	-rm -f ./$(DEPDIR)/mio_t05-t05.Po | 	-rm -f ./$(DEPDIR)/mio_t05-t05.Po | ||||||
|  | 	-rm -f ./$(DEPDIR)/mio_t06-t06.Po | ||||||
| 	-rm -f Makefile | 	-rm -f Makefile | ||||||
| maintainer-clean-am: distclean-am maintainer-clean-generic | maintainer-clean-am: distclean-am maintainer-clean-generic | ||||||
|  |  | ||||||
|  | |||||||
| @ -969,7 +969,7 @@ if (mio_htre_getcontentlen(req) > 0) | |||||||
| 			else if (mio_comp_bcstr_limited(qpath, "/cgi/", 5, 1) == 0) | 			else if (mio_comp_bcstr_limited(qpath, "/cgi/", 5, 1) == 0) | ||||||
| 				x = mio_svc_htts_docgi(htts, csck, req, "", mio_htre_getqpath(req)); | 				x = mio_svc_htts_docgi(htts, csck, req, "", mio_htre_getqpath(req)); | ||||||
| 			else | 			else | ||||||
| 				x = mio_svc_htts_dofile(htts, csck, req, "", mio_htre_getqpath(req)); | 				x = mio_svc_htts_dofile(htts, csck, req, "", mio_htre_getqpath(req), "text/plain"); | ||||||
| 			if (x <= -1) goto oops; | 			if (x <= -1) goto oops; | ||||||
|  |  | ||||||
| 	return 0; | 	return 0; | ||||||
|  | |||||||
							
								
								
									
										2
									
								
								mio/configure
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								mio/configure
									
									
									
									
										vendored
									
									
								
							| @ -17924,7 +17924,7 @@ _ACEOF | |||||||
| fi | fi | ||||||
| done | done | ||||||
|  |  | ||||||
| for ac_func in accept4 sendmsg recvmsg writev readv | for ac_func in pipe2 accept4 sendmsg recvmsg writev readv | ||||||
| do : | do : | ||||||
|   as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` |   as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` | ||||||
| ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" | ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" | ||||||
|  | |||||||
| @ -160,7 +160,7 @@ AC_CHECK_FUNCS([backtrace backtrace_symbols]) | |||||||
| AC_CHECK_FUNCS([fork vfork posix_spawn gettid nanosleep select]) | AC_CHECK_FUNCS([fork vfork posix_spawn gettid nanosleep select]) | ||||||
| AC_CHECK_FUNCS([makecontext swapcontext getcontext setcontext]) | AC_CHECK_FUNCS([makecontext swapcontext getcontext setcontext]) | ||||||
| AC_CHECK_FUNCS([snprintf _vsnprintf _vsnwprintf]) | AC_CHECK_FUNCS([snprintf _vsnprintf _vsnwprintf]) | ||||||
| AC_CHECK_FUNCS([accept4 sendmsg recvmsg writev readv]) | AC_CHECK_FUNCS([pipe2 accept4 sendmsg recvmsg writev readv]) | ||||||
| AC_CHECK_FUNCS([isatty mmap munmap]) | AC_CHECK_FUNCS([isatty mmap munmap]) | ||||||
|  |  | ||||||
| OLDLIBS="$LIBS" | OLDLIBS="$LIBS" | ||||||
|  | |||||||
| @ -444,7 +444,7 @@ static mio_htrd_recbs_t file_client_htrd_recbs = | |||||||
|  |  | ||||||
| /* --------------------------------------------------------------------- */ | /* --------------------------------------------------------------------- */ | ||||||
|  |  | ||||||
| static int file_state_send_header_to_client (file_state_t* file_state, int status_code, int force_close) | static int file_state_send_header_to_client (file_state_t* file_state, int status_code, int force_close, const mio_bch_t* mime_type) | ||||||
| { | { | ||||||
| 	mio_svc_htts_cli_t* cli = file_state->client; | 	mio_svc_htts_cli_t* cli = file_state->client; | ||||||
| 	mio_bch_t dtbuf[64]; | 	mio_bch_t dtbuf[64]; | ||||||
| @ -457,11 +457,11 @@ static int file_state_send_header_to_client (file_state_t* file_state, int statu | |||||||
| 	content_length = file_state->end_offset - file_state->start_offset + 1; | 	content_length = file_state->end_offset - file_state->start_offset + 1; | ||||||
| 	if (status_code == 200 && file_state->total_size != content_length) status_code = 206; | 	if (status_code == 200 && file_state->total_size != content_length) status_code = 206; | ||||||
|  |  | ||||||
| 	if (mio_becs_fmt(cli->sbuf, "HTTP/%d.%d %d %hs\r\nServer: %hs\r\nDate: %s\r\nConnection: %hs\r\nAccept-Ranges: bytes\r\n", | 	if (mio_becs_fmt(cli->sbuf, "HTTP/%d.%d %d %hs\r\nServer: %hs\r\nDate: %s\r\nConnection: %hs\r\nAccept-Ranges: bytes\r\nContent-Type: %hs\r\n", | ||||||
| 		file_state->req_version.major, file_state->req_version.minor, | 		file_state->req_version.major, file_state->req_version.minor, | ||||||
| 		status_code, mio_http_status_to_bcstr(status_code), | 		status_code, mio_http_status_to_bcstr(status_code), | ||||||
| 		cli->htts->server_name, dtbuf, | 		cli->htts->server_name, dtbuf, | ||||||
| 		(force_close? "close": "keep-alive")) == (mio_oow_t)-1) return -1; | 		(force_close? "close": "keep-alive"), mime_type) == (mio_oow_t)-1) return -1; | ||||||
|  |  | ||||||
| /* TODO: content_type */ | /* TODO: content_type */ | ||||||
|  |  | ||||||
| @ -687,7 +687,7 @@ static MIO_INLINE void fadvise_on_peer (file_state_t* file_state) | |||||||
| #endif | #endif | ||||||
| } | } | ||||||
|  |  | ||||||
| int mio_svc_htts_dofile (mio_svc_htts_t* htts, mio_dev_sck_t* csck, mio_htre_t* req, const mio_bch_t* docroot, const mio_bch_t* file) | int mio_svc_htts_dofile (mio_svc_htts_t* htts, mio_dev_sck_t* csck, mio_htre_t* req, const mio_bch_t* docroot, const mio_bch_t* file, const mio_bch_t* mime_type) | ||||||
| { | { | ||||||
| /* TODO: ETag, Last-Modified... */ | /* TODO: ETag, Last-Modified... */ | ||||||
|  |  | ||||||
| @ -824,14 +824,13 @@ int mio_svc_htts_dofile (mio_svc_htts_t* htts, mio_dev_sck_t* csck, mio_htre_t* | |||||||
| 			mio_dev_sck_setsockopt(file_state->client->sck, SOL_TCP, TCP_CORK, &tcp_cork, MIO_SIZEOF(tcp_cork)); | 			mio_dev_sck_setsockopt(file_state->client->sck, SOL_TCP, TCP_CORK, &tcp_cork, MIO_SIZEOF(tcp_cork)); | ||||||
| 		#endif | 		#endif | ||||||
|  |  | ||||||
| 			if (file_state_send_header_to_client(file_state, 200, 0) <= -1 || | 			if (file_state_send_header_to_client(file_state, 200, 0, mime_type) <= -1 || | ||||||
| 			    file_state_send_contents_to_client(file_state) <= -1) goto oops; | 			    file_state_send_contents_to_client(file_state) <= -1) goto oops; | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 	else if (file_state->req_method == MIO_HTTP_HEAD) | 	else if (file_state->req_method == MIO_HTTP_HEAD) | ||||||
| 	{ | 	{ | ||||||
|  | 		if (file_state_send_header_to_client(file_state, 200, 0, mime_type) <= -1) goto oops; | ||||||
| 		if (file_state_send_header_to_client(file_state, 200, 0) <= -1) goto oops; |  | ||||||
| 		file_state_mark_over (file_state, FILE_STATE_OVER_READ_FROM_PEER | FILE_STATE_OVER_WRITE_TO_PEER); | 		file_state_mark_over (file_state, FILE_STATE_OVER_READ_FROM_PEER | FILE_STATE_OVER_WRITE_TO_PEER); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | |||||||
| @ -25,6 +25,7 @@ | |||||||
|  */ |  */ | ||||||
|  |  | ||||||
| #include "http-prv.h" | #include "http-prv.h" | ||||||
|  | #include <mio-path.h> | ||||||
|  |  | ||||||
| /* ------------------------------------------------------------------------ */ | /* ------------------------------------------------------------------------ */ | ||||||
| static int client_htrd_peek_request (mio_htrd_t* htrd, mio_htre_t* req) | static int client_htrd_peek_request (mio_htrd_t* htrd, mio_htre_t* req) | ||||||
| @ -482,3 +483,9 @@ mio_bch_t* mio_svc_htts_dupmergepaths (mio_svc_htts_t* htts, const mio_bch_t* ba | |||||||
| 	return xpath; | 	return xpath; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | int mio_svc_htts_writetosidechan (mio_svc_htts_t* htts, const void* dptr, mio_oow_t dlen) | ||||||
|  | { | ||||||
|  | 	return mio_dev_sck_writetosidechan(htts->lsck, dptr, dlen); | ||||||
|  | } | ||||||
|  |  | ||||||
|  |  | ||||||
|  | |||||||
| @ -376,6 +376,9 @@ | |||||||
| /* Define to 1 if you have the <openssl/ssl.h> header file. */ | /* Define to 1 if you have the <openssl/ssl.h> header file. */ | ||||||
| #undef HAVE_OPENSSL_SSL_H | #undef HAVE_OPENSSL_SSL_H | ||||||
|  |  | ||||||
|  | /* Define to 1 if you have the `pipe2' function. */ | ||||||
|  | #undef HAVE_PIPE2 | ||||||
|  |  | ||||||
| /* Define to 1 if you have the `posix_fadvise' function. */ | /* Define to 1 if you have the `posix_fadvise' function. */ | ||||||
| #undef HAVE_POSIX_FADVISE | #undef HAVE_POSIX_FADVISE | ||||||
|  |  | ||||||
|  | |||||||
| @ -264,6 +264,12 @@ static MIO_INLINE mio_t* mio_svc_htts_getmio(mio_svc_htts_t* svc) { return mio_s | |||||||
| #	define mio_svc_htts_getmio(svc) mio_svc_getmio(svc) | #	define mio_svc_htts_getmio(svc) mio_svc_getmio(svc) | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
|  | MIO_EXPORT int mio_svc_htts_writetosidechan ( | ||||||
|  | 	mio_svc_htts_t* htts, | ||||||
|  | 	const void*     dptr, | ||||||
|  | 	mio_oow_t       dlen | ||||||
|  | ); | ||||||
|  |  | ||||||
| MIO_EXPORT int mio_svc_htts_setservernamewithbcstr ( | MIO_EXPORT int mio_svc_htts_setservernamewithbcstr ( | ||||||
| 	mio_svc_htts_t*  htts, | 	mio_svc_htts_t*  htts, | ||||||
| 	const mio_bch_t* server_name | 	const mio_bch_t* server_name | ||||||
| @ -282,7 +288,8 @@ MIO_EXPORT int mio_svc_htts_dofile ( | |||||||
| 	mio_dev_sck_t*   csck, | 	mio_dev_sck_t*   csck, | ||||||
| 	mio_htre_t*      req, | 	mio_htre_t*      req, | ||||||
| 	const mio_bch_t* docroot, | 	const mio_bch_t* docroot, | ||||||
| 	const mio_bch_t* script | 	const mio_bch_t* file, | ||||||
|  | 	const mio_bch_t* mime_type | ||||||
| ); | ); | ||||||
|  |  | ||||||
| MIO_EXPORT int mio_svc_htts_dothr ( | MIO_EXPORT int mio_svc_htts_dothr ( | ||||||
|  | |||||||
| @ -114,6 +114,11 @@ int mio_makesyshndasync ( | |||||||
| 	mio_syshnd_t hnd | 	mio_syshnd_t hnd | ||||||
| ); | ); | ||||||
|  |  | ||||||
|  | int mio_makesyshndcloexec ( | ||||||
|  | 	mio_t*       mio, | ||||||
|  | 	mio_syshnd_t hnd | ||||||
|  | ); | ||||||
|  |  | ||||||
| void mio_cleartmrjobs ( | void mio_cleartmrjobs ( | ||||||
| 	mio_t* mio | 	mio_t* mio | ||||||
| ); | ); | ||||||
|  | |||||||
| @ -186,23 +186,6 @@ typedef struct mio_icmphdr_t mio_icmphdr_t; | |||||||
| 	typedef int mio_scklen_t; | 	typedef int mio_scklen_t; | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
| #if defined(_WIN32) |  | ||||||
| #	define MIO_IOCP_KEY 1 |  | ||||||
| 	/* |  | ||||||
| 	typedef HANDLE mio_syshnd_t; |  | ||||||
| 	typedef SOCKET mio_sckhnd_t; |  | ||||||
| #	define MIO_SCKHND_INVALID (INVALID_SOCKET) |  | ||||||
| 	*/ |  | ||||||
|  |  | ||||||
| 	typedef mio_uintptr_t mio_sckhnd_t; |  | ||||||
| #	define MIO_SCKHND_INVALID (~(mio_sck_hnd_t)0) |  | ||||||
|  |  | ||||||
| #else |  | ||||||
| 	typedef int mio_sckhnd_t; |  | ||||||
| #	define MIO_SCKHND_INVALID (-1) |  | ||||||
| 	 |  | ||||||
| #endif |  | ||||||
|  |  | ||||||
|  |  | ||||||
| /* ========================================================================= */ | /* ========================================================================= */ | ||||||
|  |  | ||||||
| @ -270,8 +253,16 @@ typedef void (*mio_dev_sck_on_connect_t) ( | |||||||
| 	mio_dev_sck_t* dev | 	mio_dev_sck_t* dev | ||||||
| ); | ); | ||||||
|  |  | ||||||
|  | typedef void (*mio_dev_sck_on_raw_accept_t) ( | ||||||
|  | 	mio_dev_sck_t* dev, | ||||||
|  | 	mio_syshnd_t   syshnd | ||||||
|  | ); | ||||||
|  |  | ||||||
| enum mio_dev_sck_type_t | enum mio_dev_sck_type_t | ||||||
| { | { | ||||||
|  | 	MIO_DEV_SCK_QX, | ||||||
|  |  | ||||||
|  |  | ||||||
| 	MIO_DEV_SCK_TCP4, | 	MIO_DEV_SCK_TCP4, | ||||||
| 	MIO_DEV_SCK_TCP6, | 	MIO_DEV_SCK_TCP6, | ||||||
| 	MIO_DEV_SCK_UDP4, | 	MIO_DEV_SCK_UDP4, | ||||||
| @ -285,22 +276,33 @@ enum mio_dev_sck_type_t | |||||||
| 	MIO_DEV_SCK_ICMP4, | 	MIO_DEV_SCK_ICMP4, | ||||||
|  |  | ||||||
| 	/* ICMP at the IPv6 layer */ | 	/* ICMP at the IPv6 layer */ | ||||||
| 	MIO_DEV_SCK_ICMP6 | 	MIO_DEV_SCK_ICMP6, | ||||||
|  |  | ||||||
| #if 0 | 	/* raw L2-level packet */ | ||||||
| 	MIO_DEV_SCK_RAW,  /* raw L2-level packet */ | 	MIO_DEV_SCK_PACKET | ||||||
| #endif |  | ||||||
| }; | }; | ||||||
| typedef enum mio_dev_sck_type_t mio_dev_sck_type_t; | typedef enum mio_dev_sck_type_t mio_dev_sck_type_t; | ||||||
|  |  | ||||||
|  | enum mio_dev_sck_make_option_t | ||||||
|  | { | ||||||
|  | 	/* import the system handle specified in the hnd field */ | ||||||
|  | 	MIO_DEV_SCK_MAKE_IMPSYSHND = (1 << 0)  | ||||||
|  | }; | ||||||
|  | typedef enum mio_dev_sck_make_option_t mio_dev_sck_make_option_t; | ||||||
|  |  | ||||||
| typedef struct mio_dev_sck_make_t mio_dev_sck_make_t; | typedef struct mio_dev_sck_make_t mio_dev_sck_make_t; | ||||||
| struct mio_dev_sck_make_t | struct mio_dev_sck_make_t | ||||||
| { | { | ||||||
| 	mio_dev_sck_type_t type; | 	mio_dev_sck_type_t type; | ||||||
|  |  | ||||||
|  | 	int options; | ||||||
|  | 	mio_syshnd_t syshnd; | ||||||
|  |  | ||||||
| 	mio_dev_sck_on_write_t on_write; | 	mio_dev_sck_on_write_t on_write; | ||||||
| 	mio_dev_sck_on_read_t on_read; | 	mio_dev_sck_on_read_t on_read; | ||||||
| 	mio_dev_sck_on_connect_t on_connect; | 	mio_dev_sck_on_connect_t on_connect; | ||||||
| 	mio_dev_sck_on_disconnect_t on_disconnect; | 	mio_dev_sck_on_disconnect_t on_disconnect; | ||||||
|  | 	mio_dev_sck_on_raw_accept_t on_raw_accept; /* optional */ | ||||||
| }; | }; | ||||||
|  |  | ||||||
| enum mio_dev_sck_bind_option_t | enum mio_dev_sck_bind_option_t | ||||||
| @ -362,7 +364,7 @@ struct mio_dev_sck_t | |||||||
| 	MIO_DEV_HEADER; | 	MIO_DEV_HEADER; | ||||||
|  |  | ||||||
| 	mio_dev_sck_type_t type; | 	mio_dev_sck_type_t type; | ||||||
| 	mio_sckhnd_t hnd; | 	mio_syshnd_t hnd; | ||||||
|  |  | ||||||
| 	int state; | 	int state; | ||||||
|  |  | ||||||
| @ -387,11 +389,11 @@ struct mio_dev_sck_t | |||||||
| 	mio_dev_sck_on_write_t on_write; | 	mio_dev_sck_on_write_t on_write; | ||||||
| 	mio_dev_sck_on_read_t on_read; | 	mio_dev_sck_on_read_t on_read; | ||||||
|  |  | ||||||
| 	/* return 0 on succes, -1 on failure. | 	/* called on a new tcp device for an accepted client or | ||||||
| 	 * called on a new tcp device for an accepted client or |  | ||||||
| 	 *        on a tcp device conntected to a remote server */ | 	 *        on a tcp device conntected to a remote server */ | ||||||
| 	mio_dev_sck_on_connect_t on_connect; | 	mio_dev_sck_on_connect_t on_connect; | ||||||
| 	mio_dev_sck_on_disconnect_t on_disconnect; | 	mio_dev_sck_on_disconnect_t on_disconnect; | ||||||
|  | 	mio_dev_sck_on_raw_accept_t on_raw_accept; | ||||||
|  |  | ||||||
| 	/* timer job index for handling | 	/* timer job index for handling | ||||||
| 	 *  - connect() timeout for a connecting socket. | 	 *  - connect() timeout for a connecting socket. | ||||||
| @ -406,6 +408,7 @@ struct mio_dev_sck_t | |||||||
| 	void* ssl_ctx; | 	void* ssl_ctx; | ||||||
| 	void* ssl; | 	void* ssl; | ||||||
|  |  | ||||||
|  | 	mio_syshnd_t side_chan; /* side-channel for MIO_DEV_SCK_QX */ | ||||||
| }; | }; | ||||||
|  |  | ||||||
| enum mio_dev_sck_shutdown_how_t | enum mio_dev_sck_shutdown_how_t | ||||||
| @ -415,15 +418,26 @@ enum mio_dev_sck_shutdown_how_t | |||||||
| }; | }; | ||||||
| typedef enum mio_dev_sck_shutdown_how_t mio_dev_sck_shutdown_how_t; | typedef enum mio_dev_sck_shutdown_how_t mio_dev_sck_shutdown_how_t; | ||||||
|  |  | ||||||
|  | enum mio_dev_sck_qxmsg_cmd_t | ||||||
|  | { | ||||||
|  | 	MIO_DEV_SCK_QXMSG_NEWCONN = 0 | ||||||
|  | }; | ||||||
|  | typedef enum mio_dev_sck_qxmsg_cmd_t mio_dev_sck_qxmsg_cmd_t; | ||||||
|  |  | ||||||
|  | struct mio_dev_sck_qxmsg_t | ||||||
|  | { | ||||||
|  | 	mio_dev_sck_qxmsg_cmd_t cmd; | ||||||
|  | 	mio_dev_sck_type_t scktype; | ||||||
|  | 	mio_syshnd_t syshnd; | ||||||
|  | 	mio_skad_t remoteaddr; | ||||||
|  | }; | ||||||
|  | typedef struct mio_dev_sck_qxmsg_t mio_dev_sck_qxmsg_t; | ||||||
|  |  | ||||||
|  |  | ||||||
| #ifdef __cplusplus | #ifdef __cplusplus | ||||||
| extern "C" { | extern "C" { | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
| MIO_EXPORT int mio_makesckasync ( |  | ||||||
| 	mio_t*       mio, |  | ||||||
| 	mio_sckhnd_t sck |  | ||||||
| ); |  | ||||||
|  |  | ||||||
| /* ========================================================================= */ | /* ========================================================================= */ | ||||||
|  |  | ||||||
| MIO_EXPORT mio_dev_sck_t* mio_dev_sck_make ( | MIO_EXPORT mio_dev_sck_t* mio_dev_sck_make ( | ||||||
| @ -434,14 +448,14 @@ MIO_EXPORT mio_dev_sck_t* mio_dev_sck_make ( | |||||||
|  |  | ||||||
| #if defined(MIO_HAVE_INLINE) | #if defined(MIO_HAVE_INLINE) | ||||||
| static MIO_INLINE mio_t* mio_dev_sck_getmio (mio_dev_sck_t* sck) { return mio_dev_getmio((mio_dev_t*)sck); } | static MIO_INLINE mio_t* mio_dev_sck_getmio (mio_dev_sck_t* sck) { return mio_dev_getmio((mio_dev_t*)sck); } | ||||||
|  | static MIO_INLINE void* mio_dev_sck_getxtn (mio_dev_sck_t* sck) { return (void*)(sck + 1); } | ||||||
|  | static MIO_INLINE mio_dev_sck_type_t mio_dev_sck_gettype (mio_dev_sck_t* sck) { return sck->type; } | ||||||
|  | static MIO_INLINE mio_syshnd_t mio_dev_sck_getsyshnd (mio_dev_sck_t* sck) { return sck->hnd; } | ||||||
| #else | #else | ||||||
| #	define mio_dev_sck_getmio(sck) mio_dev_getmio(sck) | #	define mio_dev_sck_getmio(sck) mio_dev_getmio(sck) | ||||||
| #endif |  | ||||||
|  |  | ||||||
| #if defined(MIO_HAVE_INLINE) |  | ||||||
| static MIO_INLINE void* mio_dev_sck_getxtn (mio_dev_sck_t* sck) { return (void*)(sck + 1); } |  | ||||||
| #else |  | ||||||
| #	define mio_dev_sck_getxtn(sck) ((void*)(((mio_dev_sck_t*)sck) + 1)) | #	define mio_dev_sck_getxtn(sck) ((void*)(((mio_dev_sck_t*)sck) + 1)) | ||||||
|  | #	define mio_dev_sck_gettype(sck) (((mio_dev_sck_t*)sck)->type) | ||||||
|  | #	define mio_dev_sck_getsyshnd(sck) (((mio_dev_sck_t*)sck)->hnd) | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
| MIO_EXPORT int mio_dev_sck_bind ( | MIO_EXPORT int mio_dev_sck_bind ( | ||||||
| @ -566,6 +580,13 @@ MIO_EXPORT int mio_dev_sck_sendfileok ( | |||||||
| 	mio_dev_sck_t* dev | 	mio_dev_sck_t* dev | ||||||
| ); | ); | ||||||
|  |  | ||||||
|  | MIO_EXPORT int mio_dev_sck_writetosidechan ( | ||||||
|  | 	mio_dev_sck_t* htts, | ||||||
|  | 	const void*    dptr, | ||||||
|  | 	mio_oow_t      dlen | ||||||
|  | ); | ||||||
|  |  | ||||||
|  |  | ||||||
| MIO_EXPORT mio_uint16_t mio_checksum_ip ( | MIO_EXPORT mio_uint16_t mio_checksum_ip ( | ||||||
| 	const void* hdr, | 	const void* hdr, | ||||||
| 	mio_oow_t   len | 	mio_oow_t   len | ||||||
|  | |||||||
							
								
								
									
										401
									
								
								mio/lib/sck.c
									
									
									
									
									
								
							
							
						
						
									
										401
									
								
								mio/lib/sck.c
									
									
									
									
									
								
							| @ -35,6 +35,7 @@ | |||||||
|  |  | ||||||
| #include <netinet/in.h> | #include <netinet/in.h> | ||||||
| #include <arpa/inet.h> | #include <arpa/inet.h> | ||||||
|  | #include <netinet/if_ether.h> | ||||||
|  |  | ||||||
| #if defined(HAVE_NETPACKET_PACKET_H) | #if defined(HAVE_NETPACKET_PACKET_H) | ||||||
| #	include <netpacket/packet.h> | #	include <netpacket/packet.h> | ||||||
| @ -78,28 +79,22 @@ | |||||||
|  |  | ||||||
| /* ========================================================================= */ | /* ========================================================================= */ | ||||||
|  |  | ||||||
| int mio_makesckasync (mio_t* mio, mio_sckhnd_t sck) | static void close_async_socket (mio_t* mio, mio_syshnd_t sck) | ||||||
| { |  | ||||||
| 	return mio_makesyshndasync (mio, (mio_syshnd_t)sck); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| static void close_async_socket (mio_t* mio, mio_sckhnd_t sck) |  | ||||||
| { | { | ||||||
| 	close (sck); | 	close (sck); | ||||||
| } | } | ||||||
|  |  | ||||||
| static mio_sckhnd_t open_async_socket (mio_t* mio, int domain, int type, int proto) | static mio_syshnd_t open_async_socket (mio_t* mio, int domain, int type, int proto) | ||||||
| { | { | ||||||
| 	mio_sckhnd_t sck = MIO_SCKHND_INVALID; | 	mio_syshnd_t sck = MIO_SYSHND_INVALID; | ||||||
| 	int flags; | 	int flags; | ||||||
|  |  | ||||||
| #if defined(SOCK_NONBLOCK) && defined(SOCK_CLOEXEC) | #if defined(SOCK_NONBLOCK) && defined(SOCK_CLOEXEC) | ||||||
| 	type |= SOCK_NONBLOCK; | 	type |= SOCK_NONBLOCK | SOCK_CLOEXEC; | ||||||
| 	type |= SOCK_CLOEXEC; |  | ||||||
| open_socket: | open_socket: | ||||||
| #endif | #endif | ||||||
| 	sck = socket(domain, type, proto);  | 	sck = socket(domain, type, proto);  | ||||||
| 	if (sck == MIO_SCKHND_INVALID)  | 	if (sck == MIO_SYSHND_INVALID)  | ||||||
| 	{ | 	{ | ||||||
| 	#if defined(SOCK_NONBLOCK) && defined(SOCK_CLOEXEC) | 	#if defined(SOCK_NONBLOCK) && defined(SOCK_CLOEXEC) | ||||||
| 		if (errno == EINVAL && (type & (SOCK_NONBLOCK | SOCK_CLOEXEC))) | 		if (errno == EINVAL && (type & (SOCK_NONBLOCK | SOCK_CLOEXEC))) | ||||||
| @ -117,23 +112,96 @@ open_socket: | |||||||
| 	#endif | 	#endif | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	flags = fcntl(sck, F_GETFD, 0); | 	if (mio_makesyshndasync(mio, sck) <= -1 || | ||||||
| 	if (flags == -1) goto oops; | 	    mio_makesyshndcloexec(mio, sck) <= -1) goto oops; | ||||||
| #if defined(FD_CLOEXEC) |  | ||||||
| 	flags |= FD_CLOEXEC; |  | ||||||
| #endif |  | ||||||
| #if defined(O_NONBLOCK) |  | ||||||
| 	flags |= O_NONBLOCK; |  | ||||||
| #endif |  | ||||||
| 	if (fcntl(sck, F_SETFD, flags) == -1) goto oops; |  | ||||||
|  |  | ||||||
| done: | done: | ||||||
| 	return sck; | 	return sck; | ||||||
|  |  | ||||||
| oops: | oops: | ||||||
| 	if (sck != MIO_SCKHND_INVALID) close (sck); | 	if (sck != MIO_SYSHND_INVALID) close (sck); | ||||||
| 	mio_seterrwithsyserr (mio, 0, errno); | 	mio_seterrwithsyserr (mio, 0, errno); | ||||||
| 	return MIO_SCKHND_INVALID; | 	return MIO_SYSHND_INVALID; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static mio_syshnd_t open_async_qx (mio_t* mio, mio_syshnd_t* side_chan) | ||||||
|  | { | ||||||
|  | 	int fd[2]; | ||||||
|  |  | ||||||
|  | #if 1 | ||||||
|  | 	int type = SOCK_DGRAM; | ||||||
|  |  | ||||||
|  | #if defined(SOCK_NONBLOCK) && defined(SOCK_CLOEXEC) | ||||||
|  | 	type |= SOCK_NONBLOCK | SOCK_CLOEXEC; | ||||||
|  | open_socket: | ||||||
|  | #endif | ||||||
|  | 	if (socketpair(AF_UNIX, type, 0, fd) <= -1) | ||||||
|  | 	{ | ||||||
|  | 	#if defined(SOCK_NONBLOCK) && defined(SOCK_CLOEXEC) | ||||||
|  | 		if (errno == EINVAL && (type & (SOCK_NONBLOCK | SOCK_CLOEXEC))) | ||||||
|  | 		{ | ||||||
|  | 			type &= ~(SOCK_NONBLOCK | SOCK_CLOEXEC); | ||||||
|  | 			goto open_socket; | ||||||
|  | 		} | ||||||
|  | 	#endif | ||||||
|  | 		return MIO_SYSHND_INVALID; | ||||||
|  | 	} | ||||||
|  | 	else | ||||||
|  | 	{ | ||||||
|  | 	#if defined(SOCK_NONBLOCK) && defined(SOCK_CLOEXEC) | ||||||
|  | 		if (type & (SOCK_NONBLOCK | SOCK_CLOEXEC)) goto done; | ||||||
|  | 	#endif | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	if (mio_makesyshndasync(mio, fd[0]) <= -1 || | ||||||
|  | 	    mio_makesyshndasync(mio, fd[1]) <= -1 || | ||||||
|  | 	    mio_makesyshndcloexec(mio, fd[0]) <= -1 || | ||||||
|  | 	    mio_makesyshndcloexec(mio, fd[1]) <= -1)  | ||||||
|  | 	{ | ||||||
|  | 		close (fd[0]); | ||||||
|  | 		close (fd[1]); | ||||||
|  | 		return MIO_SYSHND_INVALID; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | done: | ||||||
|  | 	*side_chan = fd[1]; /* write end of the pipe */ | ||||||
|  | 	return fd[0]; /* read end of the pipe */ | ||||||
|  | #else | ||||||
|  |  | ||||||
|  | #if defined(HAVE_PIPE2) | ||||||
|  | 	/* in linux 3.4 or higher, O_DIRECT can make the pipes work in the packet mode if the data size is <= PIPE_BUF */ | ||||||
|  | 	if (pipe2(fd, O_CLOEXEC | O_NONBLOCK) <= -1) | ||||||
|  | 	{ | ||||||
|  | 		if  (errno == ENOSYS) goto normal_pipe; | ||||||
|  | 		mio_seterrwithsyserr (mio, 0, errno); | ||||||
|  | 		return MIO_SYSHND_INVALID; | ||||||
|  | 	} | ||||||
|  | 	goto done; | ||||||
|  |  | ||||||
|  | normal_pipe: | ||||||
|  | #endif | ||||||
|  | 	if (pipe(fd) <= -1) | ||||||
|  | 	{ | ||||||
|  | 		mio_seterrwithsyserr (mio, 0, errno); | ||||||
|  | 		return MIO_SYSHND_INVALID; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	if (mio_makesyshndasync(mio, fd[0]) <= -1 || | ||||||
|  | 	    mio_makesyshndasync(mio, fd[1]) <= -1 || | ||||||
|  | 	    mio_makesyshndcloexec(mio, fd[0]) <= -1 || | ||||||
|  | 	    mio_makesyshndcloexec(mio, fd[1]) <= -1)  | ||||||
|  | 	{ | ||||||
|  | 		close (fd[0]); | ||||||
|  | 		close (fd[1]); | ||||||
|  | 		return MIO_SYSHND_INVALID; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | #if defined(HAVE_PIPE2) | ||||||
|  | done: | ||||||
|  | #endif | ||||||
|  | 	*side_chan = fd[1]; /* write end of the pipe */ | ||||||
|  | 	return fd[0]; /* read end of the pipe */ | ||||||
|  | #endif | ||||||
| } | } | ||||||
|  |  | ||||||
| /* ========================================================================= */ | /* ========================================================================= */ | ||||||
| @ -167,8 +235,13 @@ struct sck_type_map_t | |||||||
| 	int extra_dev_cap; | 	int extra_dev_cap; | ||||||
| }; | }; | ||||||
|  |  | ||||||
|  | #define __AF_QX 999999 | ||||||
|  |  | ||||||
| static struct sck_type_map_t sck_type_map[] = | static struct sck_type_map_t sck_type_map[] = | ||||||
| { | { | ||||||
|  | 	/* MIO_DEV_SCK_QX */ | ||||||
|  | 	{ __AF_QX,    0,              0,                         0 }, | ||||||
|  |  | ||||||
| 	/* MIO_DEV_SCK_TCP4 */ | 	/* MIO_DEV_SCK_TCP4 */ | ||||||
| 	{ AF_INET,    SOCK_STREAM,    0,                         MIO_DEV_CAP_STREAM }, | 	{ AF_INET,    SOCK_STREAM,    0,                         MIO_DEV_CAP_STREAM }, | ||||||
|  |  | ||||||
| @ -204,7 +277,18 @@ static struct sck_type_map_t sck_type_map[] = | |||||||
| 	{ AF_INET,    SOCK_RAW,       IPPROTO_ICMP,              0,                                             }, | 	{ AF_INET,    SOCK_RAW,       IPPROTO_ICMP,              0,                                             }, | ||||||
|  |  | ||||||
| 	/* MIO_DEV_SCK_ICMP6 - IP protocol field is 1 byte only. no byte order conversion is needed */ | 	/* MIO_DEV_SCK_ICMP6 - IP protocol field is 1 byte only. no byte order conversion is needed */ | ||||||
| 	{ AF_INET6,   SOCK_RAW,       IPPROTO_ICMP,              0,                                               } | 	{ AF_INET6,   SOCK_RAW,       IPPROTO_ICMP,              0,                                             }, | ||||||
|  |  | ||||||
|  |  | ||||||
|  | #if defined(AF_PACKET) && (MIO_SIZEOF_STRUCT_SOCKADDR_LL > 0) | ||||||
|  | 	/* MIO_DEV_SCK_PACKET */ | ||||||
|  | 	{ AF_PACKET,  SOCK_RAW,       MIO_CONST_HTON16(ETH_P_ALL),            0                                 }, | ||||||
|  | #elif defined(AF_LINK) && (MIO_SIZEOF_STRUCT_SOCKADDR_DL > 0) | ||||||
|  | 	/* MIO_DEV_SCK_PACKET */ | ||||||
|  | 	{ AF_PACKET,  SOCK_RAW,       MIO_CONST_HTON16(ETH_P_ALL),            0                                 }, | ||||||
|  | #else | ||||||
|  | 	{ -1,       0,                0,                         0                                              }, | ||||||
|  | #endif | ||||||
| }; | }; | ||||||
|  |  | ||||||
| /* ======================================================================== */ | /* ======================================================================== */ | ||||||
| @ -294,6 +378,8 @@ static int dev_sck_make (mio_dev_t* dev, void* ctx) | |||||||
| 	mio_t* mio = dev->mio; | 	mio_t* mio = dev->mio; | ||||||
| 	mio_dev_sck_t* rdev = (mio_dev_sck_t*)dev; | 	mio_dev_sck_t* rdev = (mio_dev_sck_t*)dev; | ||||||
| 	mio_dev_sck_make_t* arg = (mio_dev_sck_make_t*)ctx; | 	mio_dev_sck_make_t* arg = (mio_dev_sck_make_t*)ctx; | ||||||
|  | 	mio_syshnd_t hnd = MIO_SYSHND_INVALID; | ||||||
|  | 	mio_syshnd_t side_chan = MIO_SYSHND_INVALID; | ||||||
|  |  | ||||||
| 	MIO_ASSERT (mio, arg->type >= 0 && arg->type < MIO_COUNTOF(sck_type_map)); | 	MIO_ASSERT (mio, arg->type >= 0 && arg->type < MIO_COUNTOF(sck_type_map)); | ||||||
|  |  | ||||||
| @ -303,9 +389,38 @@ static int dev_sck_make (mio_dev_t* dev, void* ctx) | |||||||
| 		return -1; | 		return -1; | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	rdev->hnd = open_async_socket(mio, sck_type_map[arg->type].domain, sck_type_map[arg->type].type, sck_type_map[arg->type].proto); | 	if (arg->options & MIO_DEV_SCK_MAKE_IMPSYSHND) | ||||||
| 	if (rdev->hnd == MIO_SCKHND_INVALID) goto oops; | 	{ | ||||||
|  | 		/* Make sure to pass a proper type for a given socket handle when you use MIO_DEV_SCK_MAKE_IMPSYSHND. | ||||||
|  | 		 * Otherwise, some innerworking of the library may go wrong */ | ||||||
|  | 		if (sck_type_map[arg->type].domain == __AF_QX) | ||||||
|  | 		{ | ||||||
|  | 			/* can't import a handle of this type */ | ||||||
|  | 			mio_seterrnum (mio, MIO_EINVAL);  | ||||||
|  | 			goto oops; | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		hnd = arg->syshnd; | ||||||
|  | 		if (hnd == MIO_SYSHND_INVALID) | ||||||
|  | 		{ | ||||||
|  | 			mio_seterrnum (mio, MIO_EINVAL);  | ||||||
|  | 			goto oops; | ||||||
|  | 		} | ||||||
|  | 		if (mio_makesyshndasync(mio, hnd) <= -1) goto oops; | ||||||
|  | 	} | ||||||
|  | 	else if (sck_type_map[arg->type].domain == __AF_QX) | ||||||
|  | 	{ | ||||||
|  | 		hnd = open_async_qx(mio, &side_chan); | ||||||
|  | 		if (hnd == MIO_SYSHND_INVALID) goto oops; | ||||||
|  | 	} | ||||||
|  | 	else | ||||||
|  | 	{ | ||||||
|  | 		hnd = open_async_socket(mio, sck_type_map[arg->type].domain, sck_type_map[arg->type].type, sck_type_map[arg->type].proto); | ||||||
|  | 		if (hnd == MIO_SYSHND_INVALID) goto oops; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	rdev->hnd = hnd; | ||||||
|  | 	rdev->side_chan = side_chan; | ||||||
| 	rdev->dev_cap = MIO_DEV_CAP_IN | MIO_DEV_CAP_OUT | sck_type_map[arg->type].extra_dev_cap; | 	rdev->dev_cap = MIO_DEV_CAP_IN | MIO_DEV_CAP_OUT | sck_type_map[arg->type].extra_dev_cap; | ||||||
| 	rdev->on_write = arg->on_write; | 	rdev->on_write = arg->on_write; | ||||||
| 	rdev->on_read = arg->on_read; | 	rdev->on_read = arg->on_read; | ||||||
| @ -317,11 +432,8 @@ static int dev_sck_make (mio_dev_t* dev, void* ctx) | |||||||
| 	return 0; | 	return 0; | ||||||
|  |  | ||||||
| oops: | oops: | ||||||
| 	if (rdev->hnd != MIO_SCKHND_INVALID) | 	if (hnd != MIO_SYSHND_INVALID) close_async_socket (mio, hnd); | ||||||
| 	{ | 	if (side_chan != MIO_SYSHND_INVALID) close (rdev->side_chan); | ||||||
| 		close_async_socket (mio, rdev->hnd); |  | ||||||
| 		rdev->hnd = MIO_SCKHND_INVALID; |  | ||||||
| 	} |  | ||||||
| 	return -1; | 	return -1; | ||||||
| } | } | ||||||
|  |  | ||||||
| @ -340,18 +452,8 @@ static int dev_sck_make_client (mio_dev_t* dev, void* ctx) | |||||||
| 	rdev->hnd = *clisckhnd; | 	rdev->hnd = *clisckhnd; | ||||||
| 	rdev->tmrjob_index = MIO_TMRIDX_INVALID; | 	rdev->tmrjob_index = MIO_TMRIDX_INVALID; | ||||||
|  |  | ||||||
| 	if (mio_makesckasync(mio, rdev->hnd) <= -1) return -1; | 	if (mio_makesyshndasync(mio, rdev->hnd) <= -1 || | ||||||
| #if defined(FD_CLOEXEC) | 	    mio_makesyshndcloexec(mio, rdev->hnd) <= -1) return -1; | ||||||
| 	{ |  | ||||||
| 		int flags = fcntl(rdev->hnd, F_GETFD, 0); |  | ||||||
| 		if (fcntl(rdev->hnd, F_SETFD, flags | FD_CLOEXEC) == -1) |  | ||||||
| 		{ |  | ||||||
| 			mio_seterrbfmtwithsyserr (mio, 0, errno, "unable to set FD_CLOEXEC"); |  | ||||||
| 			return -1; |  | ||||||
| 		} |  | ||||||
| 	} |  | ||||||
| #endif |  | ||||||
|  |  | ||||||
| 	return 0; | 	return 0; | ||||||
| } | } | ||||||
|  |  | ||||||
| @ -398,12 +500,17 @@ static int dev_sck_kill (mio_dev_t* dev, int force) | |||||||
| 	} | 	} | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
| 	if (rdev->hnd != MIO_SCKHND_INVALID)  | 	if (rdev->hnd != MIO_SYSHND_INVALID)  | ||||||
| 	{ | 	{ | ||||||
| 		close_async_socket (mio, rdev->hnd); | 		close_async_socket (mio, rdev->hnd); | ||||||
| 		rdev->hnd = MIO_SCKHND_INVALID; | 		rdev->hnd = MIO_SYSHND_INVALID; | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | 	if (rdev->side_chan != MIO_SYSHND_INVALID) | ||||||
|  | 	{ | ||||||
|  | 		close (rdev->hnd); | ||||||
|  | 		rdev->hnd = MIO_SYSHND_INVALID; | ||||||
|  | 	} | ||||||
| 	return 0; | 	return 0; | ||||||
| } | } | ||||||
|  |  | ||||||
| @ -1255,6 +1362,7 @@ static mio_dev_mth_t dev_mth_clisck = | |||||||
| 	dev_sck_sendfile_stateful, | 	dev_sck_sendfile_stateful, | ||||||
| 	dev_sck_ioctl | 	dev_sck_ioctl | ||||||
| }; | }; | ||||||
|  |  | ||||||
| /* ========================================================================= */ | /* ========================================================================= */ | ||||||
|  |  | ||||||
| static int harvest_outgoing_connection (mio_dev_sck_t* rdev) | static int harvest_outgoing_connection (mio_dev_sck_t* rdev) | ||||||
| @ -1349,53 +1457,21 @@ static int harvest_outgoing_connection (mio_dev_sck_t* rdev) | |||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
| static int accept_incoming_connection (mio_dev_sck_t* rdev) | static int make_accepted_client_connection (mio_dev_sck_t* rdev, mio_syshnd_t clisck, mio_skad_t* remoteaddr) | ||||||
| { | { | ||||||
| 	mio_t* mio = rdev->mio; | 	mio_t* mio = rdev->mio; | ||||||
| 	mio_sckhnd_t clisck; |  | ||||||
| 	mio_skad_t remoteaddr; |  | ||||||
| 	mio_scklen_t addrlen; |  | ||||||
| 	mio_dev_sck_t* clidev; | 	mio_dev_sck_t* clidev; | ||||||
| 	int flags; | 	mio_scklen_t addrlen; | ||||||
|  |  | ||||||
| 	/* this is a server(lisening) socket */ | 	if (rdev->on_raw_accept) | ||||||
|  |  | ||||||
| #if defined(SOCK_NONBLOCK) && defined(SOCK_CLOEXEC) && defined(HAVE_ACCEPT4) |  | ||||||
| 	flags = SOCK_NONBLOCK | SOCK_CLOEXEC; |  | ||||||
|  |  | ||||||
| 	addrlen = MIO_SIZEOF(remoteaddr); |  | ||||||
| 	clisck = accept4(rdev->hnd, (struct sockaddr*)&remoteaddr, &addrlen, flags); |  | ||||||
| 	if (clisck == MIO_SCKHND_INVALID) |  | ||||||
| 	{ | 	{ | ||||||
| 		 if (errno != ENOSYS) | 		/* this is a special optional callback. If you don't want a client socket device  | ||||||
| 		 { | 		 * to be created upon accept, you may implement the on_raw_accept() handler.  | ||||||
| 			if (errno == EINPROGRESS || errno == EWOULDBLOCK || errno == EAGAIN) return 0; | 		 * the socket handle is delated to the callback. */ | ||||||
| 			if (errno == EINTR) return 0; /* if interrupted by a signal, treat it as if it's EINPROGRESS */ | 		rdev->on_raw_accept (rdev, clisck); | ||||||
|  | 		return 0; | ||||||
| 			mio_seterrwithsyserr (mio, 0, errno); |  | ||||||
| 			return -1; |  | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 		 // go on for the normal 3-parameter accept |  | ||||||
| 	} |  | ||||||
| 	else |  | ||||||
| 	{ |  | ||||||
| 		 goto accept_done; |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| #endif |  | ||||||
| 	addrlen = MIO_SIZEOF(remoteaddr); |  | ||||||
| 	clisck = accept(rdev->hnd, (struct sockaddr*)&remoteaddr, &addrlen); |  | ||||||
| 	if (clisck == MIO_SCKHND_INVALID) |  | ||||||
| 	{ |  | ||||||
| 		if (errno == EINPROGRESS || errno == EWOULDBLOCK || errno == EAGAIN) return 0; |  | ||||||
| 		if (errno == EINTR) return 0; /* if interrupted by a signal, treat it as if it's EINPROGRESS */ |  | ||||||
|  |  | ||||||
| 		mio_seterrwithsyserr (mio, 0, errno); |  | ||||||
| 		return -1; |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| accept_done: |  | ||||||
| 	/* use rdev->dev_size when instantiating a client sck device | 	/* use rdev->dev_size when instantiating a client sck device | ||||||
| 	 * instead of MIO_SIZEOF(mio_dev_sck_t). therefore, the   | 	 * instead of MIO_SIZEOF(mio_dev_sck_t). therefore, the   | ||||||
| 	 * extension area as big as that of the master sck device | 	 * extension area as big as that of the master sck device | ||||||
| @ -1407,10 +1483,14 @@ accept_done: | |||||||
| 		return -1; | 		return -1; | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | // TODO: | ||||||
|  | //if (clidev->type == MIO_DEV_SCK_QX) change it to the specified type.. | ||||||
|  | // TODO: | ||||||
|  |  | ||||||
| 	MIO_ASSERT (mio, clidev->hnd == clisck); | 	MIO_ASSERT (mio, clidev->hnd == clisck); | ||||||
|  |  | ||||||
| 	clidev->dev_cap |= MIO_DEV_CAP_IN | MIO_DEV_CAP_OUT | MIO_DEV_CAP_STREAM; | 	clidev->dev_cap |= MIO_DEV_CAP_IN | MIO_DEV_CAP_OUT | MIO_DEV_CAP_STREAM; | ||||||
| 	clidev->remoteaddr = remoteaddr; | 	clidev->remoteaddr = *remoteaddr; | ||||||
|  |  | ||||||
| 	addrlen = MIO_SIZEOF(clidev->localaddr); | 	addrlen = MIO_SIZEOF(clidev->localaddr); | ||||||
| 	if (getsockname(clisck, (struct sockaddr*)&clidev->localaddr, &addrlen) == -1) clidev->localaddr = rdev->localaddr; | 	if (getsockname(clisck, (struct sockaddr*)&clidev->localaddr, &addrlen) == -1) clidev->localaddr = rdev->localaddr; | ||||||
| @ -1491,6 +1571,55 @@ accept_done: | |||||||
| 	return 0; | 	return 0; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | static int accept_incoming_connection (mio_dev_sck_t* rdev) | ||||||
|  | { | ||||||
|  | 	mio_t* mio = rdev->mio; | ||||||
|  | 	mio_syshnd_t clisck; | ||||||
|  | 	mio_skad_t remoteaddr; | ||||||
|  | 	mio_scklen_t addrlen; | ||||||
|  | 	int flags; | ||||||
|  |  | ||||||
|  | 	/* this is a server(lisening) socket */ | ||||||
|  |  | ||||||
|  | #if defined(SOCK_NONBLOCK) && defined(SOCK_CLOEXEC) && defined(HAVE_ACCEPT4) | ||||||
|  | 	flags = SOCK_NONBLOCK | SOCK_CLOEXEC; | ||||||
|  |  | ||||||
|  | 	addrlen = MIO_SIZEOF(remoteaddr); | ||||||
|  | 	clisck = accept4(rdev->hnd, (struct sockaddr*)&remoteaddr, &addrlen, flags); | ||||||
|  | 	if (clisck <= -1) | ||||||
|  | 	{ | ||||||
|  | 		 if (errno != ENOSYS) | ||||||
|  | 		 { | ||||||
|  | 			if (errno == EINPROGRESS || errno == EWOULDBLOCK || errno == EAGAIN) return 0; | ||||||
|  | 			if (errno == EINTR) return 0; /* if interrupted by a signal, treat it as if it's EINPROGRESS */ | ||||||
|  |  | ||||||
|  | 			mio_seterrwithsyserr (mio, 0, errno); | ||||||
|  | 			return -1; | ||||||
|  | 		 } | ||||||
|  |  | ||||||
|  | 		 /* go on for the normal 3-parameter accept */ | ||||||
|  | 	} | ||||||
|  | 	else | ||||||
|  | 	{ | ||||||
|  | 		 goto accept_done; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | #endif | ||||||
|  | 	addrlen = MIO_SIZEOF(remoteaddr); | ||||||
|  | 	clisck = accept(rdev->hnd, (struct sockaddr*)&remoteaddr, &addrlen); | ||||||
|  | 	if (clisck <=  -1) | ||||||
|  | 	{ | ||||||
|  | 		if (errno == EINPROGRESS || errno == EWOULDBLOCK || errno == EAGAIN) return 0; | ||||||
|  | 		if (errno == EINTR) return 0; /* if interrupted by a signal, treat it as if it's EINPROGRESS */ | ||||||
|  |  | ||||||
|  | 		mio_seterrwithsyserr (mio, 0, errno); | ||||||
|  | 		return -1; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | accept_done: | ||||||
|  | 	return make_accepted_client_connection (rdev, clisck, &remoteaddr); | ||||||
|  | } | ||||||
|  |  | ||||||
| static int dev_evcb_sck_ready_stateful (mio_dev_t* dev, int events) | static int dev_evcb_sck_ready_stateful (mio_dev_t* dev, int events) | ||||||
| { | { | ||||||
| 	mio_t* mio = dev->mio; | 	mio_t* mio = dev->mio; | ||||||
| @ -1733,6 +1862,8 @@ static int dev_evcb_sck_on_write_stateless (mio_dev_t* dev, mio_iolen_t wrlen, v | |||||||
| 	return rdev->on_write(rdev, wrlen, wrctx, dstaddr->ptr); | 	return rdev->on_write(rdev, wrlen, wrctx, dstaddr->ptr); | ||||||
| } | } | ||||||
|  |  | ||||||
|  | /* ========================================================================= */ | ||||||
|  |  | ||||||
| static mio_dev_evcb_t dev_sck_event_callbacks_stateful = | static mio_dev_evcb_t dev_sck_event_callbacks_stateful = | ||||||
| { | { | ||||||
| 	dev_evcb_sck_ready_stateful, | 	dev_evcb_sck_ready_stateful, | ||||||
| @ -1746,6 +1877,86 @@ static mio_dev_evcb_t dev_sck_event_callbacks_stateless = | |||||||
| 	dev_evcb_sck_on_read_stateless, | 	dev_evcb_sck_on_read_stateless, | ||||||
| 	dev_evcb_sck_on_write_stateless | 	dev_evcb_sck_on_write_stateless | ||||||
| }; | }; | ||||||
|  | /* ========================================================================= */ | ||||||
|  |  | ||||||
|  | static int dev_evcb_sck_ready_qx (mio_dev_t* dev, int events) | ||||||
|  | { | ||||||
|  | 	mio_t* mio = dev->mio; | ||||||
|  | 	mio_dev_sck_t* rdev = (mio_dev_sck_t*)dev; | ||||||
|  |  | ||||||
|  | 	if (events & MIO_DEV_EVENT_ERR) | ||||||
|  | 	{ | ||||||
|  | 		int errcode; | ||||||
|  | 		mio_scklen_t len; | ||||||
|  |  | ||||||
|  | 		len = MIO_SIZEOF(errcode); | ||||||
|  | 		if (getsockopt(rdev->hnd, SOL_SOCKET, SO_ERROR, (char*)&errcode, &len) == -1) | ||||||
|  | 		{ | ||||||
|  | 			/* the error number is set to the socket error code. | ||||||
|  | 			 * errno resulting from getsockopt() doesn't reflect the actual | ||||||
|  | 			 * socket error. so errno is not used to set the error number. | ||||||
|  | 			 * instead, the generic device error MIO_EDEVERRR is used */ | ||||||
|  | 			mio_seterrbfmt (mio, MIO_EDEVERR, "device error - unable to get SO_ERROR"); | ||||||
|  | 		} | ||||||
|  | 		else | ||||||
|  | 		{ | ||||||
|  | 			mio_seterrwithsyserr (rdev->mio, 0, errcode); | ||||||
|  | 		} | ||||||
|  | 		return -1; | ||||||
|  | 	} | ||||||
|  | 	else if (events & MIO_DEV_EVENT_HUP) | ||||||
|  | 	{ | ||||||
|  | 		mio_seterrnum (mio, MIO_EDEVHUP); | ||||||
|  | 		return -1; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	return 1; /* the device is ok. carry on reading or writing */ | ||||||
|  | } | ||||||
|  |  | ||||||
|  |  | ||||||
|  | static int dev_evcb_sck_on_read_qx (mio_dev_t* dev, const void* data, mio_iolen_t dlen, const mio_devaddr_t* srcaddr) | ||||||
|  | { | ||||||
|  | 	mio_t* mio = dev->mio; | ||||||
|  | 	mio_dev_sck_t* rdev = (mio_dev_sck_t*)dev; | ||||||
|  | 	mio_dev_sck_qxmsg_t* qxmsg; | ||||||
|  |  | ||||||
|  | 	if (dlen != MIO_SIZEOF(*qxmsg)) | ||||||
|  | 	{ | ||||||
|  | 		mio_seterrbfmt (mio, MIO_EINVAL, "wrong qx packet size"); | ||||||
|  | 		return -1; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	qxmsg = (mio_dev_sck_qxmsg_t*)data; | ||||||
|  | 	if (qxmsg->cmd == MIO_DEV_SCK_QXMSG_NEWCONN) | ||||||
|  | 	{ | ||||||
|  | 		if (make_accepted_client_connection(rdev, qxmsg->syshnd, &qxmsg->remoteaddr) <= -1)  | ||||||
|  | 		{ | ||||||
|  | 			close (qxmsg->syshnd); | ||||||
|  | 			return -1; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	else | ||||||
|  | 	{ | ||||||
|  | 		mio_seterrbfmt (mio, MIO_EINVAL, "wrong qx command code"); | ||||||
|  | 		return -1; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	return 0; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static int dev_evcb_sck_on_write_qx (mio_dev_t* dev, mio_iolen_t wrlen, void* wrctx, const mio_devaddr_t* dstaddr) | ||||||
|  | { | ||||||
|  | 	/*mio_dev_sck_t* rdev = (mio_dev_sck_t*)dev;*/ | ||||||
|  | 	/* this should not be called */ | ||||||
|  | 	return 0; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static mio_dev_evcb_t dev_sck_event_callbacks_qx = | ||||||
|  | { | ||||||
|  | 	dev_evcb_sck_ready_qx, | ||||||
|  | 	dev_evcb_sck_on_read_qx, | ||||||
|  | 	dev_evcb_sck_on_write_qx | ||||||
|  | }; | ||||||
|  |  | ||||||
| /* ========================================================================= */ | /* ========================================================================= */ | ||||||
|  |  | ||||||
| @ -1759,7 +1970,13 @@ mio_dev_sck_t* mio_dev_sck_make (mio_t* mio, mio_oow_t xtnsize, const mio_dev_sc | |||||||
| 		return MIO_NULL; | 		return MIO_NULL; | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	if (sck_type_map[info->type].extra_dev_cap & MIO_DEV_CAP_STREAM) /* can't use the IS_STATEFUL() macro yet */ | 	if (info->type == MIO_DEV_SCK_QX) | ||||||
|  | 	{ | ||||||
|  | 		rdev = (mio_dev_sck_t*)mio_dev_make( | ||||||
|  | 			mio, MIO_SIZEOF(mio_dev_sck_t) + xtnsize, | ||||||
|  | 			&dev_sck_methods_stateless, &dev_sck_event_callbacks_qx, (void*)info); | ||||||
|  | 	} | ||||||
|  | 	else if (sck_type_map[info->type].extra_dev_cap & MIO_DEV_CAP_STREAM) /* can't use the IS_STATEFUL() macro yet */ | ||||||
| 	{ | 	{ | ||||||
| 		rdev = (mio_dev_sck_t*)mio_dev_make( | 		rdev = (mio_dev_sck_t*)mio_dev_make( | ||||||
| 			mio, MIO_SIZEOF(mio_dev_sck_t) + xtnsize, | 			mio, MIO_SIZEOF(mio_dev_sck_t) + xtnsize, | ||||||
| @ -1858,6 +2075,18 @@ int mio_dev_sck_sendfileok (mio_dev_sck_t* dev) | |||||||
| #endif | #endif | ||||||
| } | } | ||||||
|  |  | ||||||
|  | int mio_dev_sck_writetosidechan (mio_dev_sck_t* dev, const void* dptr, mio_oow_t dlen) | ||||||
|  | { | ||||||
|  | 	if (dev->side_chan == MIO_SYSHND_INVALID) | ||||||
|  | 	{ | ||||||
|  | 		mio_seterrnum (dev->mio, MIO_ENOCAPA); | ||||||
|  | 		return -1; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	write (dev->side_chan, dptr, dlen); | ||||||
|  | 	return 0; | ||||||
|  | } | ||||||
|  |  | ||||||
| /* ========================================================================= */ | /* ========================================================================= */ | ||||||
|  |  | ||||||
| mio_uint16_t mio_checksum_ip (const void* hdr, mio_oow_t len) | mio_uint16_t mio_checksum_ip (const void* hdr, mio_oow_t len) | ||||||
|  | |||||||
| @ -41,13 +41,36 @@ int mio_sys_initmux (mio_t* mio) | |||||||
| 	mio_sys_mux_t* mux = &mio->sysdep->mux; | 	mio_sys_mux_t* mux = &mio->sysdep->mux; | ||||||
|  |  | ||||||
| #if defined(USE_EPOLL) | #if defined(USE_EPOLL) | ||||||
| 	mux->hnd = epoll_create(1000); /* TODO: choose proper initial size? */ |  | ||||||
|  | #if defined(HAVE_EPOLL_CREATE1) | ||||||
|  | 	mux->hnd = epoll_create1(O_CLOEXEC); | ||||||
|  | 	if (mux->hnd == -1) | ||||||
|  | 	{ | ||||||
|  | 		if (errno == ENOSYS) goto normal_epoll_create; /* kernel doesn't support it */ | ||||||
|  | 		mio_seterrwithsyserr (mio, 0, errno); | ||||||
|  | 		return -1; | ||||||
|  | 	} | ||||||
|  | 	goto epoll_create_done; | ||||||
|  |  | ||||||
|  | normal_epoll_create: | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | 	mux->hnd = epoll_create(16384); /* TODO: choose proper initial size? */ | ||||||
| 	if (mux->hnd == -1) | 	if (mux->hnd == -1) | ||||||
| 	{ | 	{ | ||||||
| 		mio_seterrwithsyserr (mio, 0, errno); | 		mio_seterrwithsyserr (mio, 0, errno); | ||||||
| 		return -1; | 		return -1; | ||||||
| 	} | 	} | ||||||
| #endif |  | ||||||
|  | #if defined(FD_CLOEXEC) | ||||||
|  | 	{ | ||||||
|  | 		int flags = fcntl(mux->hnd, F_GETFD, 0); | ||||||
|  | 		if (flags >= 0) fcntl(mux->hnd, F_SETFD, flags | FD_CLOEXEC); | ||||||
|  | 	} | ||||||
|  | #endif /* FD_CLOEXEC */ | ||||||
|  |  | ||||||
|  | epoll_create_done: | ||||||
|  | #endif /* USE_EPOLL */ | ||||||
|  |  | ||||||
| 	return 0; | 	return 0; | ||||||
| } | } | ||||||
| @ -254,7 +277,7 @@ int mio_sys_ctrlmux (mio_t* mio, mio_sys_mux_cmd_t cmd, mio_dev_t* dev, int dev_ | |||||||
| 	} | 	} | ||||||
| 	if (dev_cap & MIO_DEV_CAP_OUT_WATCHED) events |= EPOLLOUT; | 	if (dev_cap & MIO_DEV_CAP_OUT_WATCHED) events |= EPOLLOUT; | ||||||
|  |  | ||||||
| 	ev.events = events | EPOLLHUP | EPOLLERR /*| EPOLLET*/; | 	ev.events = events | EPOLLHUP | EPOLLERR /*| EPOLLET*/; /* TODO: ready to support edge-trigger? */ | ||||||
| 	ev.data.ptr = dev; | 	ev.data.ptr = dev; | ||||||
|  |  | ||||||
| 	switch (cmd) | 	switch (cmd) | ||||||
|  | |||||||
| @ -68,7 +68,7 @@ struct mio_sys_mux_t | |||||||
| struct mio_sys_mux_t | struct mio_sys_mux_t | ||||||
| { | { | ||||||
| 	int hnd; | 	int hnd; | ||||||
| 	struct epoll_event revs[128]; /* TODO: is it a good size? */ | 	struct epoll_event revs[1024]; /* TODO: is it a good size? */ | ||||||
| }; | }; | ||||||
|  |  | ||||||
| #endif | #endif | ||||||
|  | |||||||
| @ -90,3 +90,22 @@ int mio_makesyshndasync (mio_t* mio, mio_syshnd_t hnd) | |||||||
| 	return -1; | 	return -1; | ||||||
| #endif | #endif | ||||||
| } | } | ||||||
|  |  | ||||||
|  | int mio_makesyshndcloexec (mio_t* mio, mio_syshnd_t hnd) | ||||||
|  | { | ||||||
|  | #if defined(F_GETFL) && defined(F_SETFL) && defined(FD_CLOEXEC) | ||||||
|  | 	int flags; | ||||||
|  |  | ||||||
|  | 	if ((flags = fcntl(hnd, F_GETFD)) <= -1 || | ||||||
|  | 	    (flags = fcntl(hnd, F_SETFD, flags | FD_CLOEXEC)) <= -1) | ||||||
|  | 	{ | ||||||
|  | 		mio_seterrwithsyserr (mio, 0, errno); | ||||||
|  | 		return -1; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	return 0; | ||||||
|  | #else | ||||||
|  | 	mio_seterrnum (mio, MIO_ENOIMPL); | ||||||
|  | 	return -1; | ||||||
|  | #endif | ||||||
|  | } | ||||||
|  | |||||||
		Reference in New Issue
	
	Block a user