diff --git a/mio/bin/Makefile.am b/mio/bin/Makefile.am index 95cd9f4..e15badb 100644 --- a/mio/bin/Makefile.am +++ b/mio/bin/Makefile.am @@ -52,3 +52,9 @@ mio_t05_SOURCES = t05.c mio_t05_CPPFLAGS = $(CPPFLAGS_LIB_COMMON) mio_t05_LDFLAGS = $(LDFLAGS_LIB_COMMON) 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) diff --git a/mio/bin/Makefile.in b/mio/bin/Makefile.in index c7a36eb..28696c6 100644 --- a/mio/bin/Makefile.in +++ b/mio/bin/Makefile.in @@ -89,7 +89,8 @@ POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ 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 ACLOCAL_M4 = $(top_srcdir)/aclocal.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) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(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_DEFAULT_V@) am__v_P_0 = false @@ -173,7 +181,7 @@ am__maybe_remake_depfiles = depfiles am__depfiles_remade = ./$(DEPDIR)/mio_execd-execd.Po \ ./$(DEPDIR)/mio_t01-t01.Po ./$(DEPDIR)/mio_t02-t02.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 COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(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_1 = 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) \ $(mio_t02_SOURCES) $(mio_t03_SOURCES) $(mio_t04_SOURCES) \ - $(mio_t05_SOURCES) + $(mio_t05_SOURCES) $(mio_t06_SOURCES) am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ @@ -411,6 +420,10 @@ mio_t05_SOURCES = t05.c mio_t05_CPPFLAGS = $(CPPFLAGS_LIB_COMMON) mio_t05_LDFLAGS = $(LDFLAGS_LIB_COMMON) 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 .SUFFIXES: @@ -518,6 +531,10 @@ mio-t05$(EXEEXT): $(mio_t05_OBJECTS) $(mio_t05_DEPENDENCIES) $(EXTRA_mio_t05_DEP @rm -f mio-t05$(EXEEXT) $(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: -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_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_t06-t06.Po@am__quote@ # am--include-marker $(am__depfiles_remade): @$(MKDIR_P) $(@D) @@ -645,6 +663,20 @@ mio_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) $(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: -rm -f *.lo @@ -784,6 +816,7 @@ distclean: distclean-am -rm -f ./$(DEPDIR)/mio_t03-t03.Po -rm -f ./$(DEPDIR)/mio_t04-t04.Po -rm -f ./$(DEPDIR)/mio_t05-t05.Po + -rm -f ./$(DEPDIR)/mio_t06-t06.Po -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags @@ -835,6 +868,7 @@ maintainer-clean: maintainer-clean-am -rm -f ./$(DEPDIR)/mio_t03-t03.Po -rm -f ./$(DEPDIR)/mio_t04-t04.Po -rm -f ./$(DEPDIR)/mio_t05-t05.Po + -rm -f ./$(DEPDIR)/mio_t06-t06.Po -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic diff --git a/mio/bin/t01.c b/mio/bin/t01.c index 7785b47..9f24d34 100644 --- a/mio/bin/t01.c +++ b/mio/bin/t01.c @@ -969,7 +969,7 @@ if (mio_htre_getcontentlen(req) > 0) else if (mio_comp_bcstr_limited(qpath, "/cgi/", 5, 1) == 0) x = mio_svc_htts_docgi(htts, csck, req, "", mio_htre_getqpath(req)); 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; return 0; diff --git a/mio/configure b/mio/configure index 2aa954b..a610b26 100755 --- a/mio/configure +++ b/mio/configure @@ -17924,7 +17924,7 @@ _ACEOF fi done -for ac_func in accept4 sendmsg recvmsg writev readv +for ac_func in pipe2 accept4 sendmsg recvmsg writev readv do : as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" diff --git a/mio/configure.ac b/mio/configure.ac index 3781d03..4145a14 100644 --- a/mio/configure.ac +++ b/mio/configure.ac @@ -160,7 +160,7 @@ AC_CHECK_FUNCS([backtrace backtrace_symbols]) AC_CHECK_FUNCS([fork vfork posix_spawn gettid nanosleep select]) AC_CHECK_FUNCS([makecontext swapcontext getcontext setcontext]) 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]) OLDLIBS="$LIBS" diff --git a/mio/lib/http-fil.c b/mio/lib/http-fil.c index 75e73d9..163326f 100644 --- a/mio/lib/http-fil.c +++ b/mio/lib/http-fil.c @@ -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_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; 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, status_code, mio_http_status_to_bcstr(status_code), 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 */ @@ -687,7 +687,7 @@ static MIO_INLINE void fadvise_on_peer (file_state_t* file_state) #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... */ @@ -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)); #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; } } else if (file_state->req_method == MIO_HTTP_HEAD) { - - if (file_state_send_header_to_client(file_state, 200, 0) <= -1) goto oops; + if (file_state_send_header_to_client(file_state, 200, 0, mime_type) <= -1) goto oops; file_state_mark_over (file_state, FILE_STATE_OVER_READ_FROM_PEER | FILE_STATE_OVER_WRITE_TO_PEER); } diff --git a/mio/lib/http-svr.c b/mio/lib/http-svr.c index 0a5e4e6..110d8f5 100644 --- a/mio/lib/http-svr.c +++ b/mio/lib/http-svr.c @@ -25,6 +25,7 @@ */ #include "http-prv.h" +#include /* ------------------------------------------------------------------------ */ 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; } +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); +} + + diff --git a/mio/lib/mio-cfg.h.in b/mio/lib/mio-cfg.h.in index 7d2f770..7684a8f 100644 --- a/mio/lib/mio-cfg.h.in +++ b/mio/lib/mio-cfg.h.in @@ -376,6 +376,9 @@ /* Define to 1 if you have the header file. */ #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. */ #undef HAVE_POSIX_FADVISE diff --git a/mio/lib/mio-http.h b/mio/lib/mio-http.h index 74e162a..7a23ea4 100644 --- a/mio/lib/mio-http.h +++ b/mio/lib/mio-http.h @@ -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) #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_svc_htts_t* htts, const mio_bch_t* server_name @@ -282,7 +288,8 @@ MIO_EXPORT int mio_svc_htts_dofile ( mio_dev_sck_t* csck, mio_htre_t* req, 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 ( diff --git a/mio/lib/mio-prv.h b/mio/lib/mio-prv.h index 3325cc0..1954b4d 100644 --- a/mio/lib/mio-prv.h +++ b/mio/lib/mio-prv.h @@ -114,6 +114,11 @@ int mio_makesyshndasync ( mio_syshnd_t hnd ); +int mio_makesyshndcloexec ( + mio_t* mio, + mio_syshnd_t hnd +); + void mio_cleartmrjobs ( mio_t* mio ); diff --git a/mio/lib/mio-sck.h b/mio/lib/mio-sck.h index 3d10fac..50c9f4d 100644 --- a/mio/lib/mio-sck.h +++ b/mio/lib/mio-sck.h @@ -186,23 +186,6 @@ typedef struct mio_icmphdr_t mio_icmphdr_t; typedef int mio_scklen_t; #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 ); +typedef void (*mio_dev_sck_on_raw_accept_t) ( + mio_dev_sck_t* dev, + mio_syshnd_t syshnd +); + enum mio_dev_sck_type_t { + MIO_DEV_SCK_QX, + + MIO_DEV_SCK_TCP4, MIO_DEV_SCK_TCP6, MIO_DEV_SCK_UDP4, @@ -285,22 +276,33 @@ enum mio_dev_sck_type_t MIO_DEV_SCK_ICMP4, /* ICMP at the IPv6 layer */ - MIO_DEV_SCK_ICMP6 + MIO_DEV_SCK_ICMP6, -#if 0 - MIO_DEV_SCK_RAW, /* raw L2-level packet */ -#endif + /* raw L2-level packet */ + MIO_DEV_SCK_PACKET }; 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; struct mio_dev_sck_make_t { mio_dev_sck_type_t type; + + int options; + mio_syshnd_t syshnd; + mio_dev_sck_on_write_t on_write; mio_dev_sck_on_read_t on_read; mio_dev_sck_on_connect_t on_connect; 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 @@ -362,7 +364,7 @@ struct mio_dev_sck_t MIO_DEV_HEADER; mio_dev_sck_type_t type; - mio_sckhnd_t hnd; + mio_syshnd_t hnd; int state; @@ -387,11 +389,11 @@ struct mio_dev_sck_t mio_dev_sck_on_write_t on_write; 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 */ mio_dev_sck_on_connect_t on_connect; mio_dev_sck_on_disconnect_t on_disconnect; + mio_dev_sck_on_raw_accept_t on_raw_accept; /* timer job index for handling * - connect() timeout for a connecting socket. @@ -406,6 +408,7 @@ struct mio_dev_sck_t void* ssl_ctx; void* ssl; + mio_syshnd_t side_chan; /* side-channel for MIO_DEV_SCK_QX */ }; 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; +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 extern "C" { #endif -MIO_EXPORT int mio_makesckasync ( - mio_t* mio, - mio_sckhnd_t sck -); - /* ========================================================================= */ 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) 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 # 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_gettype(sck) (((mio_dev_sck_t*)sck)->type) +# define mio_dev_sck_getsyshnd(sck) (((mio_dev_sck_t*)sck)->hnd) #endif MIO_EXPORT int mio_dev_sck_bind ( @@ -566,9 +580,16 @@ MIO_EXPORT int mio_dev_sck_sendfileok ( 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 ( const void* hdr, - mio_oow_t len + mio_oow_t len ); #ifdef __cplusplus diff --git a/mio/lib/sck.c b/mio/lib/sck.c index a67379d..75c24d7 100644 --- a/mio/lib/sck.c +++ b/mio/lib/sck.c @@ -35,6 +35,7 @@ #include #include +#include #if defined(HAVE_NETPACKET_PACKET_H) # include @@ -78,28 +79,22 @@ /* ========================================================================= */ -int mio_makesckasync (mio_t* mio, mio_sckhnd_t sck) -{ - return mio_makesyshndasync (mio, (mio_syshnd_t)sck); -} - -static void close_async_socket (mio_t* mio, mio_sckhnd_t sck) +static void close_async_socket (mio_t* mio, mio_syshnd_t 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; #if defined(SOCK_NONBLOCK) && defined(SOCK_CLOEXEC) - type |= SOCK_NONBLOCK; - type |= SOCK_CLOEXEC; + type |= SOCK_NONBLOCK | SOCK_CLOEXEC; open_socket: #endif sck = socket(domain, type, proto); - if (sck == MIO_SCKHND_INVALID) + if (sck == MIO_SYSHND_INVALID) { #if defined(SOCK_NONBLOCK) && defined(SOCK_CLOEXEC) if (errno == EINVAL && (type & (SOCK_NONBLOCK | SOCK_CLOEXEC))) @@ -117,23 +112,96 @@ open_socket: #endif } - flags = fcntl(sck, F_GETFD, 0); - if (flags == -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; + if (mio_makesyshndasync(mio, sck) <= -1 || + mio_makesyshndcloexec(mio, sck) <= -1) goto oops; done: return sck; oops: - if (sck != MIO_SCKHND_INVALID) close (sck); + if (sck != MIO_SYSHND_INVALID) close (sck); 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; }; +#define __AF_QX 999999 + static struct sck_type_map_t sck_type_map[] = { + /* MIO_DEV_SCK_QX */ + { __AF_QX, 0, 0, 0 }, + /* MIO_DEV_SCK_TCP4 */ { AF_INET, SOCK_STREAM, 0, MIO_DEV_CAP_STREAM }, @@ -176,10 +249,10 @@ static struct sck_type_map_t sck_type_map[] = { AF_INET6, SOCK_STREAM, 0, MIO_DEV_CAP_STREAM }, /* MIO_DEV_SCK_UPD4 */ - { AF_INET, SOCK_DGRAM, 0, 0 }, + { AF_INET, SOCK_DGRAM, 0, 0 }, /* MIO_DEV_SCK_UDP6 */ - { AF_INET6, SOCK_DGRAM, 0, 0 }, + { AF_INET6, SOCK_DGRAM, 0, 0 }, #if defined(AF_PACKET) && (MIO_SIZEOF_STRUCT_SOCKADDR_LL > 0) @@ -196,15 +269,26 @@ static struct sck_type_map_t sck_type_map[] = /* MIO_DEV_SCK_ARP_DGRAM */ { AF_LINK, SOCK_DGRAM, MIO_CONST_HTON16(MIO_ETHHDR_PROTO_ARP), 0 }, #else - { -1, 0, 0, 0 }, - { -1, 0, 0, 0 }, + { -1, 0, 0, 0 }, + { -1, 0, 0, 0 }, #endif /* MIO_DEV_SCK_ICMP4 - IP protocol field is 1 byte only. no byte order conversion is needed */ - { 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 */ - { 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_dev_sck_t* rdev = (mio_dev_sck_t*)dev; 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)); @@ -303,9 +389,38 @@ static int dev_sck_make (mio_dev_t* dev, void* ctx) 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 (rdev->hnd == MIO_SCKHND_INVALID) goto oops; + if (arg->options & MIO_DEV_SCK_MAKE_IMPSYSHND) + { + /* 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->on_write = arg->on_write; rdev->on_read = arg->on_read; @@ -317,11 +432,8 @@ static int dev_sck_make (mio_dev_t* dev, void* ctx) return 0; oops: - if (rdev->hnd != MIO_SCKHND_INVALID) - { - close_async_socket (mio, rdev->hnd); - 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); return -1; } @@ -340,18 +452,8 @@ static int dev_sck_make_client (mio_dev_t* dev, void* ctx) rdev->hnd = *clisckhnd; rdev->tmrjob_index = MIO_TMRIDX_INVALID; - if (mio_makesckasync(mio, rdev->hnd) <= -1) return -1; -#if defined(FD_CLOEXEC) - { - 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 - + if (mio_makesyshndasync(mio, rdev->hnd) <= -1 || + mio_makesyshndcloexec(mio, rdev->hnd) <= -1) return -1; return 0; } @@ -398,12 +500,17 @@ static int dev_sck_kill (mio_dev_t* dev, int force) } #endif - if (rdev->hnd != MIO_SCKHND_INVALID) + if (rdev->hnd != MIO_SYSHND_INVALID) { 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; } @@ -1255,6 +1362,7 @@ static mio_dev_mth_t dev_mth_clisck = dev_sck_sendfile_stateful, dev_sck_ioctl }; + /* ========================================================================= */ static int harvest_outgoing_connection (mio_dev_sck_t* rdev) @@ -1349,55 +1457,23 @@ 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_sckhnd_t clisck; - mio_skad_t remoteaddr; - mio_scklen_t addrlen; mio_dev_sck_t* clidev; - int flags; + mio_scklen_t addrlen; - /* 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 == MIO_SCKHND_INVALID) + if (rdev->on_raw_accept) { - 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; + /* 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. + * the socket handle is delated to the callback. */ + rdev->on_raw_accept (rdev, clisck); + return 0; } -#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 - * 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 * is created in the client sck device */ clidev = (mio_dev_sck_t*)mio_dev_make(mio, rdev->dev_size, &dev_mth_clisck, rdev->dev_evcb, &clisck); @@ -1407,10 +1483,14 @@ accept_done: return -1; } +// TODO: +//if (clidev->type == MIO_DEV_SCK_QX) change it to the specified type.. +// TODO: + MIO_ASSERT (mio, clidev->hnd == clisck); 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); if (getsockname(clisck, (struct sockaddr*)&clidev->localaddr, &addrlen) == -1) clidev->localaddr = rdev->localaddr; @@ -1491,6 +1571,55 @@ accept_done: 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) { mio_t* mio = dev->mio; @@ -1686,7 +1815,7 @@ static int dev_evcb_sck_ready_stateless (mio_dev_t* dev, int events) mio_scklen_t len; len = MIO_SIZEOF(errcode); - if (getsockopt (rdev->hnd, SOL_SOCKET, SO_ERROR, (char*)&errcode, &len) == -1) + 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 @@ -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); } +/* ========================================================================= */ + static mio_dev_evcb_t dev_sck_event_callbacks_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_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; } - 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( mio, MIO_SIZEOF(mio_dev_sck_t) + xtnsize, @@ -1858,6 +2075,18 @@ int mio_dev_sck_sendfileok (mio_dev_sck_t* dev) #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) diff --git a/mio/lib/sys-mux.c b/mio/lib/sys-mux.c index 6f78744..0430272 100644 --- a/mio/lib/sys-mux.c +++ b/mio/lib/sys-mux.c @@ -41,13 +41,36 @@ int mio_sys_initmux (mio_t* mio) mio_sys_mux_t* mux = &mio->sysdep->mux; #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) { mio_seterrwithsyserr (mio, 0, errno); 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; } @@ -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; - ev.events = events | EPOLLHUP | EPOLLERR /*| EPOLLET*/; + ev.events = events | EPOLLHUP | EPOLLERR /*| EPOLLET*/; /* TODO: ready to support edge-trigger? */ ev.data.ptr = dev; switch (cmd) diff --git a/mio/lib/sys-prv.h b/mio/lib/sys-prv.h index 93f71e3..d9c2ca0 100644 --- a/mio/lib/sys-prv.h +++ b/mio/lib/sys-prv.h @@ -68,7 +68,7 @@ struct mio_sys_mux_t struct mio_sys_mux_t { 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 diff --git a/mio/lib/sys.c b/mio/lib/sys.c index 159758b..6dcb734 100644 --- a/mio/lib/sys.c +++ b/mio/lib/sys.c @@ -90,3 +90,22 @@ int mio_makesyshndasync (mio_t* mio, mio_syshnd_t hnd) return -1; #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 +}