Compare commits

..
3 Commits
22 changed files with 2068 additions and 194 deletions
+15 -4
View File
@@ -19,9 +19,20 @@ rpm: dist-gzip
cp @PACKAGE_NAME@-@PACKAGE_VERSION@.tar.gz "@abs_builddir@/pkgs/RPM/SOURCES" cp @PACKAGE_NAME@-@PACKAGE_VERSION@.tar.gz "@abs_builddir@/pkgs/RPM/SOURCES"
rpmbuild --define "_topdir @abs_builddir@/pkgs/RPM" -ba @abs_builddir@/pkgs/hio.spec --target=@build_cpu@ rpmbuild --define "_topdir @abs_builddir@/pkgs/RPM" -ba @abs_builddir@/pkgs/hio.spec --target=@build_cpu@
## assumes --enable-static --disable-shared, so bin/hio-webs is the program
## itself and libhio is linked into it. what is still missing from a FROM scratch
## image is the system libraries it links against and the dynamic loader, so each
## goes in at the path it is loaded from - there is no /etc/ld.so.cache in the
## image to redirect the search.
docker: all docker: all
mkdir -p data rm -rf hio-webs-root hio-webs.tar
rm -rf data/* mkdir -p hio-webs-root/bin hio-webs-root/data
tar -cvf hio-webs.tar bin/hio-webs data cp bin/hio-webs hio-webs-root/bin/hio-webs
ldd bin/hio-webs | $(AWK) '$$2 == "=>" { print $$3 } $$1 ~ /^\// { print $$1 }' | \
while read -r so; do \
mkdir -p "hio-webs-root$${so%/*}"; \
cp -L "$$so" "hio-webs-root$$so" || exit 1; \
done
tar -C hio-webs-root -cvf hio-webs.tar .
docker build -t hio:webs -f Dockerfile . docker build -t hio:webs -f Dockerfile .
rm -f hio-webs.tar rm -rf hio-webs-root hio-webs.tar
+12 -4
View File
@@ -295,6 +295,8 @@ PTHREAD_LIBS = @PTHREAD_LIBS@
QUADMATH_LIBS = @QUADMATH_LIBS@ QUADMATH_LIBS = @QUADMATH_LIBS@
RANLIB = @RANLIB@ RANLIB = @RANLIB@
SCTP_ENABLED = @SCTP_ENABLED@ SCTP_ENABLED = @SCTP_ENABLED@
SCTP_MULTIHOMING_ENABLED = @SCTP_MULTIHOMING_ENABLED@
SCTP_PEELOFF_ENABLED = @SCTP_PEELOFF_ENABLED@
SED = @SED@ SED = @SED@
SENDFILE_LIBS = @SENDFILE_LIBS@ SENDFILE_LIBS = @SENDFILE_LIBS@
SET_MAKE = @SET_MAKE@ SET_MAKE = @SET_MAKE@
@@ -865,11 +867,17 @@ rpm: dist-gzip
rpmbuild --define "_topdir @abs_builddir@/pkgs/RPM" -ba @abs_builddir@/pkgs/hio.spec --target=@build_cpu@ rpmbuild --define "_topdir @abs_builddir@/pkgs/RPM" -ba @abs_builddir@/pkgs/hio.spec --target=@build_cpu@
docker: all docker: all
mkdir -p data rm -rf hio-webs-root hio-webs.tar
rm -rf data/* mkdir -p hio-webs-root/bin hio-webs-root/data
tar -cvf hio-webs.tar bin/hio-webs data cp bin/hio-webs hio-webs-root/bin/hio-webs
ldd bin/hio-webs | $(AWK) '$$2 == "=>" { print $$3 } $$1 ~ /^\// { print $$1 }' | \
while read -r so; do \
mkdir -p "hio-webs-root$${so%/*}"; \
cp -L "$$so" "hio-webs-root$$so" || exit 1; \
done
tar -C hio-webs-root -cvf hio-webs.tar .
docker build -t hio:webs -f Dockerfile . docker build -t hio:webs -f Dockerfile .
rm -f hio-webs.tar rm -rf hio-webs-root hio-webs.tar
# Tell versions [3.59,3.63) of GNU make to not export all variables. # Tell versions [3.59,3.63) of GNU make to not export all variables.
# Otherwise a system limit (for SysV at least) may be exceeded. # Otherwise a system limit (for SysV at least) may be exceeded.
+2
View File
@@ -329,6 +329,8 @@ PTHREAD_LIBS = @PTHREAD_LIBS@
QUADMATH_LIBS = @QUADMATH_LIBS@ QUADMATH_LIBS = @QUADMATH_LIBS@
RANLIB = @RANLIB@ RANLIB = @RANLIB@
SCTP_ENABLED = @SCTP_ENABLED@ SCTP_ENABLED = @SCTP_ENABLED@
SCTP_MULTIHOMING_ENABLED = @SCTP_MULTIHOMING_ENABLED@
SCTP_PEELOFF_ENABLED = @SCTP_PEELOFF_ENABLED@
SED = @SED@ SED = @SED@
SENDFILE_LIBS = @SENDFILE_LIBS@ SENDFILE_LIBS = @SENDFILE_LIBS@
SET_MAKE = @SET_MAKE@ SET_MAKE = @SET_MAKE@
Vendored
+215 -59
View File
@@ -689,6 +689,8 @@ ax_pthread_config
CPP CPP
SENDFILE_LIBS SENDFILE_LIBS
SOCKET_LIBS SOCKET_LIBS
SCTP_MULTIHOMING_ENABLED
SCTP_PEELOFF_ENABLED
SCTP_ENABLED SCTP_ENABLED
LIBM LIBM
MACOSX_FALSE MACOSX_FALSE
@@ -1860,6 +1862,65 @@ printf "%s\n" "$ac_res" >&6; }
} # ac_fn_check_decl } # ac_fn_check_decl
# ac_fn_c_check_type LINENO TYPE VAR INCLUDES
# -------------------------------------------
# Tests whether TYPE exists after having included INCLUDES, setting cache
# variable VAR accordingly.
ac_fn_c_check_type ()
{
as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
printf %s "checking for $2... " >&6; }
if eval test \${$3+y}
then :
printf %s "(cached) " >&6
else case e in #(
e) eval "$3=no"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
$4
int
main (void)
{
if (sizeof ($2))
return 0;
;
return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"
then :
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
$4
int
main (void)
{
if (sizeof (($2)))
return 0;
;
return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"
then :
else case e in #(
e) eval "$3=yes" ;;
esac
fi
rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
fi
rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext ;;
esac
fi
eval ac_res=\$$3
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
printf "%s\n" "$ac_res" >&6; }
eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
} # ac_fn_c_check_type
# ac_fn_c_try_cpp LINENO # ac_fn_c_try_cpp LINENO
# ---------------------- # ----------------------
# Try to preprocess conftest.$ac_ext, and return whether this succeeded. # Try to preprocess conftest.$ac_ext, and return whether this succeeded.
@@ -1962,65 +2023,6 @@ printf "%s\n" "$ac_res" >&6; }
} # ac_fn_c_check_member } # ac_fn_c_check_member
# ac_fn_c_check_type LINENO TYPE VAR INCLUDES
# -------------------------------------------
# Tests whether TYPE exists after having included INCLUDES, setting cache
# variable VAR accordingly.
ac_fn_c_check_type ()
{
as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
printf %s "checking for $2... " >&6; }
if eval test \${$3+y}
then :
printf %s "(cached) " >&6
else case e in #(
e) eval "$3=no"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
$4
int
main (void)
{
if (sizeof ($2))
return 0;
;
return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"
then :
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
$4
int
main (void)
{
if (sizeof (($2)))
return 0;
;
return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"
then :
else case e in #(
e) eval "$3=yes" ;;
esac
fi
rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
fi
rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext ;;
esac
fi
eval ac_res=\$$3
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
printf "%s\n" "$ac_res" >&6; }
eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
} # ac_fn_c_check_type
# ac_fn_c_try_run LINENO # ac_fn_c_try_run LINENO
# ---------------------- # ----------------------
# Try to run conftest.$ac_ext, and return whether this succeeded. Assumes that # Try to run conftest.$ac_ext, and return whether this succeeded. Assumes that
@@ -16298,7 +16300,159 @@ printf "%s\n" "#define HIO_ENABLE_SCTP 1" >>confdefs.h
fi fi
fi fi
if test "x$SCTP_ENABLED" = "xyes"
then
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for library containing sctp_bindx" >&5
printf %s "checking for library containing sctp_bindx... " >&6; }
if test ${ac_cv_search_sctp_bindx+y}
then :
printf %s "(cached) " >&6
else case e in #(
e) ac_func_search_save_LIBS=$LIBS
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
/* Override any GCC internal prototype to avoid an error.
Use char because int might match the return type of a GCC
builtin and then its argument prototype would still apply.
The 'extern "C"' is for builds by C++ compilers;
although this is not generally supported in C code supporting it here
has little cost and some practical benefit (sr 110532). */
#ifdef __cplusplus
extern "C"
#endif
char sctp_bindx (void);
int
main (void)
{
return sctp_bindx ();
;
return 0;
}
_ACEOF
for ac_lib in '' sctp
do
if test -z "$ac_lib"; then
ac_res="none required"
else
ac_res=-l$ac_lib
LIBS="-l$ac_lib $ac_func_search_save_LIBS"
fi
if ac_fn_c_try_link "$LINENO"
then :
ac_cv_search_sctp_bindx=$ac_res
fi fi
rm -f core conftest.err conftest.$ac_objext conftest.beam \
conftest$ac_exeext
if test ${ac_cv_search_sctp_bindx+y}
then :
break
fi
done
if test ${ac_cv_search_sctp_bindx+y}
then :
else case e in #(
e) ac_cv_search_sctp_bindx=no ;;
esac
fi
rm conftest.$ac_ext
LIBS=$ac_func_search_save_LIBS ;;
esac
fi
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_sctp_bindx" >&5
printf "%s\n" "$ac_cv_search_sctp_bindx" >&6; }
ac_res=$ac_cv_search_sctp_bindx
if test "$ac_res" != no
then :
test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
fi
ac_fn_c_check_func "$LINENO" "sctp_bindx" "ac_cv_func_sctp_bindx"
if test "x$ac_cv_func_sctp_bindx" = xyes
then :
printf "%s\n" "#define HAVE_SCTP_BINDX 1" >>confdefs.h
fi
ac_fn_c_check_func "$LINENO" "sctp_peeloff" "ac_cv_func_sctp_peeloff"
if test "x$ac_cv_func_sctp_peeloff" = xyes
then :
printf "%s\n" "#define HAVE_SCTP_PEELOFF 1" >>confdefs.h
fi
ac_fn_c_check_func "$LINENO" "sctp_getpaddrs" "ac_cv_func_sctp_getpaddrs"
if test "x$ac_cv_func_sctp_getpaddrs" = xyes
then :
printf "%s\n" "#define HAVE_SCTP_GETPADDRS 1" >>confdefs.h
fi
ac_fn_c_check_func "$LINENO" "sctp_getladdrs" "ac_cv_func_sctp_getladdrs"
if test "x$ac_cv_func_sctp_getladdrs" = xyes
then :
printf "%s\n" "#define HAVE_SCTP_GETLADDRS 1" >>confdefs.h
fi
ac_fn_c_check_func "$LINENO" "sctp_freepaddrs" "ac_cv_func_sctp_freepaddrs"
if test "x$ac_cv_func_sctp_freepaddrs" = xyes
then :
printf "%s\n" "#define HAVE_SCTP_FREEPADDRS 1" >>confdefs.h
fi
ac_fn_c_check_func "$LINENO" "sctp_freeladdrs" "ac_cv_func_sctp_freeladdrs"
if test "x$ac_cv_func_sctp_freeladdrs" = xyes
then :
printf "%s\n" "#define HAVE_SCTP_FREELADDRS 1" >>confdefs.h
fi
if test "x$ac_cv_func_sctp_peeloff" = "xyes"
then
SCTP_PEELOFF_ENABLED="yes"
fi
if test "x$ac_cv_func_sctp_bindx" = "xyes" -a \
"x$ac_cv_func_sctp_getpaddrs" = "xyes" -a \
"x$ac_cv_func_sctp_getladdrs" = "xyes"
then
SCTP_MULTIHOMING_ENABLED="yes"
fi
ac_fn_c_check_type "$LINENO" "struct sctp_prim" "ac_cv_type_struct_sctp_prim" "
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/sctp.h>
"
if test "x$ac_cv_type_struct_sctp_prim" = xyes
then :
printf "%s\n" "#define HAVE_STRUCT_SCTP_PRIM 1" >>confdefs.h
fi
ac_fn_c_check_type "$LINENO" "struct sctp_setprim" "ac_cv_type_struct_sctp_setprim" "
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/sctp.h>
"
if test "x$ac_cv_type_struct_sctp_setprim" = xyes
then :
printf "%s\n" "#define HAVE_STRUCT_SCTP_SETPRIM 1" >>confdefs.h
fi
fi
fi
test -z "$SCTP_PEELOFF_ENABLED" && SCTP_PEELOFF_ENABLED="no"
test -z "$SCTP_MULTIHOMING_ENABLED" && SCTP_MULTIHOMING_ENABLED="no"
ac_fn_c_check_header_compile "$LINENO" "net/if.h" "ac_cv_header_net_if_h" " ac_fn_c_check_header_compile "$LINENO" "net/if.h" "ac_cv_header_net_if_h" "
#include <sys/types.h> #include <sys/types.h>
@@ -24904,6 +25058,8 @@ echo " Socket library: ${SOCKET_LIBS}"
echo " Sendfile library: ${SENDFILE_LIBS}" echo " Sendfile library: ${SENDFILE_LIBS}"
echo " SSL library: ${SSL_LIBS}" echo " SSL library: ${SSL_LIBS}"
echo " SCTP support: ${SCTP_ENABLED}" echo " SCTP support: ${SCTP_ENABLED}"
echo " SCTP peel-off: ${SCTP_PEELOFF_ENABLED}"
echo " SCTP multi-homing: ${SCTP_MULTIHOMING_ENABLED}"
echo "-------------------------------------------------------------------------" echo "-------------------------------------------------------------------------"
+42
View File
@@ -142,8 +142,48 @@ then
#include <netinet/in.h> #include <netinet/in.h>
]]) ]])
fi fi
if test "x$SCTP_ENABLED" = "xyes"
then
dnl these library calls are a separate matter from the socket type. on
dnl the bsds they are in libc; on linux they live in libsctp
dnl (lksctp-tools), which may well be absent on a machine whose kernel
dnl and headers have sctp. so they are probed on their own and the basic
dnl one-to-one and one-to-many support stands either way.
dnl
dnl peel-off and multi-homing are reported apart because they are
dnl separate features sharing nothing but the library they come from:
dnl peel-off needs sctp_peeloff() and multi-homing needs the address
dnl calls. a system missing one must not lose both.
AC_SEARCH_LIBS([sctp_bindx], [sctp])
AC_CHECK_FUNCS([sctp_bindx sctp_peeloff sctp_getpaddrs sctp_getladdrs sctp_freepaddrs sctp_freeladdrs])
if test "x$ac_cv_func_sctp_peeloff" = "xyes"
then
SCTP_PEELOFF_ENABLED="yes"
fi
if test "x$ac_cv_func_sctp_bindx" = "xyes" -a \
"x$ac_cv_func_sctp_getpaddrs" = "xyes" -a \
"x$ac_cv_func_sctp_getladdrs" = "xyes"
then
SCTP_MULTIHOMING_ENABLED="yes"
fi
dnl SCTP_PRIMARY_ADDR takes a structure the two families spell
dnl differently - struct sctp_prim on linux, struct sctp_setprim on
dnl the bsds - with identical members.
AC_CHECK_TYPES([struct sctp_prim, struct sctp_setprim], [], [], [[
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/sctp.h>
]])
fi
fi fi
AC_SUBST(SCTP_ENABLED) AC_SUBST(SCTP_ENABLED)
test -z "$SCTP_PEELOFF_ENABLED" && SCTP_PEELOFF_ENABLED="no"
AC_SUBST(SCTP_PEELOFF_ENABLED)
test -z "$SCTP_MULTIHOMING_ENABLED" && SCTP_MULTIHOMING_ENABLED="no"
AC_SUBST(SCTP_MULTIHOMING_ENABLED)
AC_CHECK_HEADERS([net/if.h net/if_dl.h netinet/if_ether.h netpacket/packet.h net/bpf.h], [], [], [ AC_CHECK_HEADERS([net/if.h net/if_dl.h netinet/if_ether.h netpacket/packet.h net/bpf.h], [], [], [
#include <sys/types.h> #include <sys/types.h>
#include <sys/socket.h>]) #include <sys/socket.h>])
@@ -947,5 +987,7 @@ echo " Socket library: ${SOCKET_LIBS}"
echo " Sendfile library: ${SENDFILE_LIBS}" echo " Sendfile library: ${SENDFILE_LIBS}"
echo " SSL library: ${SSL_LIBS}" echo " SSL library: ${SSL_LIBS}"
echo " SCTP support: ${SCTP_ENABLED}" echo " SCTP support: ${SCTP_ENABLED}"
echo " SCTP peel-off: ${SCTP_PEELOFF_ENABLED}"
echo " SCTP multi-homing: ${SCTP_MULTIHOMING_ENABLED}"
echo "-------------------------------------------------------------------------" echo "-------------------------------------------------------------------------"
] ]
+2
View File
@@ -374,6 +374,8 @@ PTHREAD_LIBS = @PTHREAD_LIBS@
QUADMATH_LIBS = @QUADMATH_LIBS@ QUADMATH_LIBS = @QUADMATH_LIBS@
RANLIB = @RANLIB@ RANLIB = @RANLIB@
SCTP_ENABLED = @SCTP_ENABLED@ SCTP_ENABLED = @SCTP_ENABLED@
SCTP_MULTIHOMING_ENABLED = @SCTP_MULTIHOMING_ENABLED@
SCTP_PEELOFF_ENABLED = @SCTP_PEELOFF_ENABLED@
SED = @SED@ SED = @SED@
SENDFILE_LIBS = @SENDFILE_LIBS@ SENDFILE_LIBS = @SENDFILE_LIBS@
SET_MAKE = @SET_MAKE@ SET_MAKE = @SET_MAKE@
+2 -2
View File
@@ -161,7 +161,7 @@ HIO_DEBUG1 (hio, "DNC - releasing dns message - msgid:%d\n", (int)hio_ntoh16(hio
if (msgxtn->rtmridx != HIO_TMRIDX_INVALID) if (msgxtn->rtmridx != HIO_TMRIDX_INVALID)
{ {
hio_deltmrjob (hio, msgxtn->rtmridx); hio_deltmrjob(hio, msgxtn->rtmridx);
HIO_ASSERT(hio, msgxtn->rtmridx == HIO_TMRIDX_INVALID); HIO_ASSERT(hio, msgxtn->rtmridx == HIO_TMRIDX_INVALID);
} }
@@ -574,7 +574,7 @@ static int on_udp_read (hio_dev_sck_t* dev, const void* data, hio_iolen_t dlen,
if (reqmsgxtn->rtmridx != HIO_TMRIDX_INVALID) if (reqmsgxtn->rtmridx != HIO_TMRIDX_INVALID)
{ {
/* unschedule a timer job if any */ /* unschedule a timer job if any */
hio_deltmrjob (hio, reqmsgxtn->rtmridx); hio_deltmrjob(hio, reqmsgxtn->rtmridx);
HIO_ASSERT(hio, reqmsgxtn->rtmridx == HIO_TMRIDX_INVALID); HIO_ASSERT(hio, reqmsgxtn->rtmridx == HIO_TMRIDX_INVALID);
} }
+24
View File
@@ -295,6 +295,24 @@
/* Define to 1 if you have the 'recvmsg' function. */ /* Define to 1 if you have the 'recvmsg' function. */
#undef HAVE_RECVMSG #undef HAVE_RECVMSG
/* Define to 1 if you have the 'sctp_bindx' function. */
#undef HAVE_SCTP_BINDX
/* Define to 1 if you have the 'sctp_freeladdrs' function. */
#undef HAVE_SCTP_FREELADDRS
/* Define to 1 if you have the 'sctp_freepaddrs' function. */
#undef HAVE_SCTP_FREEPADDRS
/* Define to 1 if you have the 'sctp_getladdrs' function. */
#undef HAVE_SCTP_GETLADDRS
/* Define to 1 if you have the 'sctp_getpaddrs' function. */
#undef HAVE_SCTP_GETPADDRS
/* Define to 1 if you have the 'sctp_peeloff' function. */
#undef HAVE_SCTP_PEELOFF
/* Define to 1 if you have the 'select' function. */ /* Define to 1 if you have the 'select' function. */
#undef HAVE_SELECT #undef HAVE_SELECT
@@ -382,6 +400,12 @@
/* Define to 1 if the system has the type 'struct lifreq'. */ /* Define to 1 if the system has the type 'struct lifreq'. */
#undef HAVE_STRUCT_LIFREQ #undef HAVE_STRUCT_LIFREQ
/* Define to 1 if the system has the type 'struct sctp_prim'. */
#undef HAVE_STRUCT_SCTP_PRIM
/* Define to 1 if the system has the type 'struct sctp_setprim'. */
#undef HAVE_STRUCT_SCTP_SETPRIM
/* Define to 1 if 'sin6_scope_id' is a member of 'struct sockaddr_in6'. */ /* Define to 1 if 'sin6_scope_id' is a member of 'struct sockaddr_in6'. */
#undef HAVE_STRUCT_SOCKADDR_IN6_SIN6_SCOPE_ID #undef HAVE_STRUCT_SOCKADDR_IN6_SIN6_SCOPE_ID
+141 -6
View File
@@ -262,6 +262,38 @@ typedef void (*hio_dev_sck_on_connect_t) (
* *
* Leave it unset to have notifications discarded. * Leave it unset to have notifications discarded.
*/ */
/**
* A decoded SCTP_ASSOC_CHANGE notification, as filled in by
* hio_dev_sck_parse_assoc_event(). The negotiated stream counts are worth
* having on their own: they are the outcome of the SCTP_INITMSG request from
* both ends, and are not knowable any other way.
*/
typedef struct hio_sctp_assoc_event_t hio_sctp_assoc_event_t;
struct hio_sctp_assoc_event_t
{
int state; /**< #hio_sctp_assoc_state_t */
int error; /**< the notification's error field, 0 if none */
hio_int32_t assoc_id; /**< pass this to hio_dev_sck_peeloff() */
hio_uint16_t ostreams; /**< outbound streams negotiated */
hio_uint16_t instreams; /**< inbound streams negotiated */
};
/**
* The states an association can report. The names mirror the SCTP_COMM_UP
* family so a reader of RFC 6458 recognises them, without the header's types
* appearing in this interface.
*/
enum hio_sctp_assoc_state_t
{
HIO_SCTP_ASSOC_COMM_UP = 0, /**< a new association is usable */
HIO_SCTP_ASSOC_COMM_LOST, /**< it failed */
HIO_SCTP_ASSOC_RESTART, /**< the peer restarted it */
HIO_SCTP_ASSOC_SHUTDOWN_COMP, /**< it closed in an orderly way */
HIO_SCTP_ASSOC_CANT_STR_ASSOC, /**< setup never completed */
HIO_SCTP_ASSOC_STATE_UNKNOWN /**< something this build does not name */
};
typedef enum hio_sctp_assoc_state_t hio_sctp_assoc_state_t;
typedef void (*hio_dev_sck_on_notification_t) ( typedef void (*hio_dev_sck_on_notification_t) (
hio_dev_sck_t* dev, hio_dev_sck_t* dev,
const void* data, const void* data,
@@ -297,8 +329,8 @@ enum hio_dev_sck_type_t
HIO_DEV_SCK_SCTP4, /* one-to-one sctp stream */ HIO_DEV_SCK_SCTP4, /* one-to-one sctp stream */
HIO_DEV_SCK_SCTP6, /* one-to-one sctp stream */ HIO_DEV_SCK_SCTP6, /* one-to-one sctp stream */
HIO_DEV_SCK_SCTP4_SP, /* one-to-one sctp seqpacket */ HIO_DEV_SCK_SCTP4_SEQPKT, /* one-to-one sctp seqpacket */
HIO_DEV_SCK_SCTP6_SP, /* one-to-one sctp seqpacket */ HIO_DEV_SCK_SCTP6_SEQPKT, /* one-to-one sctp seqpacket */
/* ICMP at the IPv4 layer */ /* ICMP at the IPv4 layer */
HIO_DEV_SCK_ICMP4, HIO_DEV_SCK_ICMP4,
@@ -388,12 +420,13 @@ struct hio_dev_sck_connect_t
hio_ntime_t connect_tmout; hio_ntime_t connect_tmout;
}; };
#if 0 /** flags for hio_dev_sck_bindx() */
enum hio_dev_sck_listen_option_t enum hio_dev_sck_bindx_flag_t
{ {
HIO_DEV_SCK_BINDX_ADD = 0, /**< add the addresses to the endpoint */
HIO_DEV_SCK_BINDX_REM = 1 /**< take them away from it */
}; };
typedef enum hio_dev_sck_listen_option_t hio_dev_sck_listen_option_t; typedef enum hio_dev_sck_bindx_flag_t hio_dev_sck_bindx_flag_t;
#endif
typedef struct hio_dev_sck_listen_t hio_dev_sck_listen_t; typedef struct hio_dev_sck_listen_t hio_dev_sck_listen_t;
struct hio_dev_sck_listen_t struct hio_dev_sck_listen_t
@@ -647,6 +680,108 @@ HIO_EXPORT int hio_dev_sck_shutdown (
int how /* bitwise-ORed of hio_dev_sck_shutdown_how_t enumerators */ int how /* bitwise-ORed of hio_dev_sck_shutdown_how_t enumerators */
); );
/**
* The hio_dev_sck_peeloff() function takes one association off a one-to-many
* SCTP socket and gives it a socket, and a device, of its own. The new device
* arrives through on_connect() in the #HIO_DEV_SCK_ACCEPTED state carrying the
* one-to-one methods - a write queue of its own, a read-enable bit of its own,
* and addresses of its own, which is what per-association multi-homing needs.
* It is the same door an accepted tcp connection comes through.
*
* It may be called at any point in an association's life, and where it is
* called from is the whole point:
*
* - from on_notification(), on an SCTP_COMM_UP whose peer address you like -
* use hio_dev_sck_parse_assoc_event() to get the association id;
* - from on_read(), when a message tells you this peer deserves a session -
* the association id is already there, on the source address, via
* hio_skad_get_assoc().
*
* Peeling mid-stream leaves a clean seam: messages already handed to on_read()
* are yours, whatever is still queued in the kernel moves to the new socket,
* and everything after arrives on the new device. Nothing is lost or
* duplicated. Call it synchronously from inside the callback though - defer it
* and this socket may read another message for that association first, which
* widens the seam by however long you waited.
*
* Only for the one-to-many SCTP types; anything else fails with #HIO_EINVAL.
* A build whose system lacks sctp_peeloff() fails with #HIO_ENOIMPL.
*/
HIO_EXPORT int hio_dev_sck_peeloff (
hio_dev_sck_t* dev,
hio_int32_t assoc_id
);
/**
* The hio_dev_sck_parse_assoc_event() function decodes what on_notification()
* hands over, when what it hands over is an association change. It exists so
* that deciding what to do about a new association does not require picking
* apart a kernel structure by hand.
*
* Returns 0 and fills 'ev' if the notification is an association change, or -1
* if it is not - some other kind of event, or a buffer too short to be one.
*
* -1 is an answer, not a failure: no error number is set, and none can be, as
* this is a pure decoder with no hio_t to set one on. A caller walking
* notifications simply ignores the ones it gets -1 for.
*/
HIO_EXPORT int hio_dev_sck_parse_assoc_event (
const void* data,
hio_iolen_t dlen,
hio_sctp_assoc_event_t* ev
);
/**
* The hio_dev_sck_bindx() function adds or removes local addresses on an
* already bound SCTP endpoint - which is what local multi-homing is. The
* addresses belong to the endpoint rather than to any one association, so this
* is a socket operation and works the same whether associations are peeled off
* or kept on the one socket.
*
* hio_dev_sck_bind() must have been called first: sctp_bindx() adds to an
* existing binding, it does not replace it.
*
* Available only for the SCTP socket types; anything else fails with
* #HIO_ENOIMPL.
*/
HIO_EXPORT int hio_dev_sck_bindx (
hio_dev_sck_t* dev,
const hio_skad_t* addrs,
hio_oow_t naddrs,
hio_dev_sck_bindx_flag_t flags
);
/**
* The hio_dev_sck_getladdrs() function reports the local addresses of the
* endpoint, and hio_dev_sck_getpaddrs() the peer addresses of the association -
* the two halves of what multi-homing established.
*
* On entry *naddrs is the room available in 'addrs'; on return it is how many
* were written. #HIO_EBUFFULL is reported if there were more, with *naddrs set
* to the number needed.
*/
HIO_EXPORT int hio_dev_sck_getladdrs (
hio_dev_sck_t* dev,
hio_skad_t* addrs,
hio_oow_t* naddrs
);
HIO_EXPORT int hio_dev_sck_getpaddrs (
hio_dev_sck_t* dev,
hio_skad_t* addrs,
hio_oow_t* naddrs
);
/**
* The hio_dev_sck_setprimaryaddr() function asks the peer to prefer one of its
* addresses as the primary path. It must be one of the addresses
* hio_dev_sck_getpaddrs() reports.
*/
HIO_EXPORT int hio_dev_sck_setprimaryaddr (
hio_dev_sck_t* dev,
const hio_skad_t* addr
);
HIO_EXPORT int hio_dev_sck_sendfileok ( HIO_EXPORT int hio_dev_sck_sendfileok (
hio_dev_sck_t* dev hio_dev_sck_t* dev
); );
+2 -2
View File
@@ -850,7 +850,7 @@ static HIO_INLINE void handle_event (hio_t* hio, hio_dev_t* dev, int events, int
tmrjob.handler = on_read_timeout; tmrjob.handler = on_read_timeout;
tmrjob.idxptr = &dev->rtmridx; tmrjob.idxptr = &dev->rtmridx;
hio_updtmrjob (hio, dev->rtmridx, &tmrjob); hio_updtmrjob(hio, dev->rtmridx, &tmrjob);
/*hio_deltmrjob(hio, dev->rtmridx); /*hio_deltmrjob(hio, dev->rtmridx);
dev->rtmridx = HIO_TMRIDX_INVALID;*/ dev->rtmridx = HIO_TMRIDX_INVALID;*/
@@ -1427,7 +1427,7 @@ kill_device:
if (kill_and_free_device(dev, 0) <= -1) if (kill_and_free_device(dev, 0) <= -1)
{ {
HIO_ASSERT(hio, dev->dev_cap & HIO_DEV_CAP_ZOMBIE); HIO_ASSERT(hio, dev->dev_cap & HIO_DEV_CAP_ZOMBIE);
if (schedule_kill_zombie_job (dev) <= -1) if (schedule_kill_zombie_job(dev) <= -1)
{ {
/* i have no choice but to free up the devide by force */ /* i have no choice but to free up the devide by force */
while (kill_and_free_device(dev, 1) <= -1) while (kill_and_free_device(dev, 1) <= -1)
+1 -1
View File
@@ -710,7 +710,7 @@ static void unbind_task_from_peer (file_t* file, int rcdown)
if (file->peer_tmridx != HIO_TMRIDX_INVALID) if (file->peer_tmridx != HIO_TMRIDX_INVALID)
{ {
hio_deltmrjob (hio, file->peer_tmridx); hio_deltmrjob(hio, file->peer_tmridx);
HIO_ASSERT(hio, file->peer_tmridx == HIO_TMRIDX_INVALID); HIO_ASSERT(hio, file->peer_tmridx == HIO_TMRIDX_INVALID);
} }
+19 -19
View File
@@ -97,13 +97,13 @@ static int get_sco_ifconf (hio_t* hio, struct ifconf* ifc)
hio_seterrwithsyserr(hio, 0, errno); hio_seterrwithsyserr(hio, 0, errno);
goto oops; goto oops;
} }
close (h); h = -1; close(h); h = -1;
return 0; return 0;
oops: oops:
if (ifc->ifc_buf) hio_freemem(hio, ifc->ifc_buf); if (ifc->ifc_buf) hio_freemem(hio, ifc->ifc_buf);
if (h >= 0) close (h); if (h >= 0) close(h);
return -1; return -1;
} }
@@ -188,13 +188,13 @@ int hio_bcstrtoifindex (hio_t* hio, const hio_bch_t* ptr, unsigned int* index)
{ {
if (hio_comp_bcstr(ptr, ifc.ifc_req[i].ifr_name, 0) == 0) if (hio_comp_bcstr(ptr, ifc.ifc_req[i].ifr_name, 0) == 0)
{ {
free_sco_ifconf (hio, &ifc); free_sco_ifconf(hio, &ifc);
*index = i + 1; *index = i + 1;
return 0; return 0;
} }
} }
free_sco_ifconf (hio, &ifc); free_sco_ifconf(hio, &ifc);
return -1; return -1;
#else #else
@@ -232,7 +232,7 @@ int hio_bcharstoifindex (hio_t* hio, const hio_bch_t* ptr, hio_oow_t len, unsign
if (hio_copy_bchars_to_bcstr(ifr.ifr_name, HIO_COUNTOF(ifr.ifr_name), ptr, len) < len) return -1; /* name too long */ if (hio_copy_bchars_to_bcstr(ifr.ifr_name, HIO_COUNTOF(ifr.ifr_name), ptr, len) < len) return -1; /* name too long */
x = ioctl(h, SIOCGIFINDEX, &ifr); x = ioctl(h, SIOCGIFINDEX, &ifr);
close (h); close(h);
if (x >= 0) if (x >= 0)
{ {
@@ -271,13 +271,13 @@ int hio_bcharstoifindex (hio_t* hio, const hio_bch_t* ptr, hio_oow_t len, unsign
{ {
if (hio_comp_bchars_bcstr(ptr, len, ifc.ifc_req[i].ifr_name) == 0) if (hio_comp_bchars_bcstr(ptr, len, ifc.ifc_req[i].ifr_name) == 0)
{ {
free_sco_ifconf (hio, &ifc); free_sco_ifconf(hio, &ifc);
*index = i + 1; *index = i + 1;
return 0; return 0;
} }
} }
free_sco_ifconf (hio, &ifc); free_sco_ifconf(hio, &ifc);
return -1; return -1;
#else #else
@@ -316,7 +316,7 @@ int hio_ucstrtoifindex (hio_t* hio, const hio_uch_t* ptr, unsigned int* index)
if (hio_convutobcstr(hio, ptr, &wl, ifr.ifr_name, &ml) <= -1) return -1; if (hio_convutobcstr(hio, ptr, &wl, ifr.ifr_name, &ml) <= -1) return -1;
x = ioctl(h, SIOCGIFINDEX, &ifr); x = ioctl(h, SIOCGIFINDEX, &ifr);
close (h); close(h);
if (x >= 0) if (x >= 0)
{ {
@@ -363,13 +363,13 @@ int hio_ucstrtoifindex (hio_t* hio, const hio_uch_t* ptr, unsigned int* index)
{ {
if (hio_comp_bcstr(tmp, ifc.ifc_req[i].ifr_name, 0) == 0) if (hio_comp_bcstr(tmp, ifc.ifc_req[i].ifr_name, 0) == 0)
{ {
free_sco_ifconf (hio, &ifc); free_sco_ifconf(hio, &ifc);
*index = i + 1; *index = i + 1;
return 0; return 0;
} }
} }
free_sco_ifconf (hio, &ifc); free_sco_ifconf(hio, &ifc);
return -1; return -1;
#else #else
@@ -409,7 +409,7 @@ int hio_ucharstoifindex (hio_t* hio, const hio_uch_t* ptr, hio_oow_t len, unsign
ifr.ifr_name[ml] = '\0'; ifr.ifr_name[ml] = '\0';
x = ioctl(h, SIOCGIFINDEX, &ifr); x = ioctl(h, SIOCGIFINDEX, &ifr);
close (h); close(h);
if (x >= 0) if (x >= 0)
{ {
@@ -457,13 +457,13 @@ int hio_ucharstoifindex (hio_t* hio, const hio_uch_t* ptr, hio_oow_t len, unsign
{ {
if (hio_comp_bcstr(tmp, ifc.ifc_req[i].ifr_name, 0) == 0) if (hio_comp_bcstr(tmp, ifc.ifc_req[i].ifr_name, 0) == 0)
{ {
free_sco_ifconf (hio, &ifc); free_sco_ifconf(hio, &ifc);
*index = i + 1; *index = i + 1;
return 0; return 0;
} }
} }
free_sco_ifconf (hio, &ifc); free_sco_ifconf(hio, &ifc);
return -1; return -1;
#else #else
return -1; return -1;
@@ -519,7 +519,7 @@ int hio_ifindextobcstr (hio_t* hio, unsigned int index, hio_bch_t* buf, hio_oow_
#elif defined(HAVE_IF_INDEXTONAME) #elif defined(HAVE_IF_INDEXTONAME)
hio_bch_t tmp[IF_NAMESIZE + 1]; hio_bch_t tmp[IF_NAMESIZE + 1];
if (if_indextoname (index, tmp) == HIO_NULL) if (if_indextoname(index, tmp) == HIO_NULL)
{ {
hio_seterrwithsyserr(hio, 0, errno); hio_seterrwithsyserr(hio, 0, errno);
return -1; return -1;
@@ -539,12 +539,12 @@ int hio_ifindextobcstr (hio_t* hio, unsigned int index, hio_bch_t* buf, hio_oow_
if (index > num) if (index > num)
{ {
hio_seterrnum(hio, HIO_ENOENT); hio_seterrnum(hio, HIO_ENOENT);
free_sco_ifconf (hio, &ifc); free_sco_ifconf(hio, &ifc);
return -1; return -1;
} }
ml = hio_copy_bcstr(buf, len, ifc.ifc_req[index - 1].ifr_name); ml = hio_copy_bcstr(buf, len, ifc.ifc_req[index - 1].ifr_name);
free_sco_ifconf (hio, &ifc); free_sco_ifconf(hio, &ifc);
return ml; return ml;
#else #else
@@ -588,7 +588,7 @@ int hio_ifindextoucstr (hio_t* hio, unsigned int index, hio_uch_t* buf, hio_oow_
#endif #endif
x = ioctl(h, SIOCGIFNAME, &ifr); x = ioctl(h, SIOCGIFNAME, &ifr);
close (h); close(h);
if (x <= -1) if (x <= -1)
{ {
@@ -630,13 +630,13 @@ int hio_ifindextoucstr (hio_t* hio, unsigned int index, hio_uch_t* buf, hio_oow_
num = ifc.ifc_len / HIO_SIZEOF(struct ifreq); num = ifc.ifc_len / HIO_SIZEOF(struct ifreq);
if (index > num) if (index > num)
{ {
free_sco_ifconf (hio, &ifc); free_sco_ifconf(hio, &ifc);
return -1; return -1;
} }
wl = len; wl = len;
x = hio_convbtoucstr(ifc.ifc_req[index - 1].ifr_name, &ml, buf, &wl, 0); x = hio_convbtoucstr(ifc.ifc_req[index - 1].ifr_name, &ml, buf, &wl, 0);
free_sco_ifconf (hio, &ifc); free_sco_ifconf(hio, &ifc);
if (x == -2 && wl > 1) buf[wl - 1] = '\0'; if (x == -2 && wl > 1) buf[wl - 1] = '\0';
else if (x != 0) return -1; else if (x != 0) return -1;
+34 -31
View File
@@ -160,20 +160,20 @@ static pid_t standard_fork_and_exec (hio_dev_pro_t* dev, int pfds[], hio_dev_pro
if (mi->flags & HIO_DEV_PRO_WRITEIN) if (mi->flags & HIO_DEV_PRO_WRITEIN)
{ {
/* slave should read */ /* slave should read */
close (pfds[1]); close(pfds[1]);
pfds[1] = HIO_SYSHND_INVALID; pfds[1] = HIO_SYSHND_INVALID;
/* let the pipe be standard input */ /* let the pipe be standard input */
if (dup2(pfds[0], 0) <= -1) goto slave_oops; if (dup2(pfds[0], 0) <= -1) goto slave_oops;
close (pfds[0]); close(pfds[0]);
pfds[0] = HIO_SYSHND_INVALID; pfds[0] = HIO_SYSHND_INVALID;
} }
if (mi->flags & HIO_DEV_PRO_READOUT) if (mi->flags & HIO_DEV_PRO_READOUT)
{ {
/* slave should write */ /* slave should write */
close (pfds[2]); close(pfds[2]);
pfds[2] = HIO_SYSHND_INVALID; pfds[2] = HIO_SYSHND_INVALID;
if (dup2(pfds[3], 1) == -1) goto slave_oops; if (dup2(pfds[3], 1) == -1) goto slave_oops;
@@ -183,13 +183,13 @@ static pid_t standard_fork_and_exec (hio_dev_pro_t* dev, int pfds[], hio_dev_pro
if (dup2(pfds[3], 2) == -1) goto slave_oops; if (dup2(pfds[3], 2) == -1) goto slave_oops;
} }
close (pfds[3]); close(pfds[3]);
pfds[3] = HIO_SYSHND_INVALID; pfds[3] = HIO_SYSHND_INVALID;
} }
if (mi->flags & HIO_DEV_PRO_READERR) if (mi->flags & HIO_DEV_PRO_READERR)
{ {
close (pfds[4]); close(pfds[4]);
pfds[4] = HIO_SYSHND_INVALID; pfds[4] = HIO_SYSHND_INVALID;
if (dup2(pfds[5], 2) == -1) goto slave_oops; if (dup2(pfds[5], 2) == -1) goto slave_oops;
@@ -199,7 +199,7 @@ static pid_t standard_fork_and_exec (hio_dev_pro_t* dev, int pfds[], hio_dev_pro
if (dup2(pfds[5], 1) == -1) goto slave_oops; if (dup2(pfds[5], 1) == -1) goto slave_oops;
} }
close (pfds[5]); close(pfds[5]);
pfds[5] = HIO_SYSHND_INVALID; pfds[5] = HIO_SYSHND_INVALID;
} }
@@ -218,18 +218,18 @@ static pid_t standard_fork_and_exec (hio_dev_pro_t* dev, int pfds[], hio_dev_pro
if ((mi->flags & HIO_DEV_PRO_OUTTONUL) && dup2(devnull, 1) == -1) goto slave_oops; if ((mi->flags & HIO_DEV_PRO_OUTTONUL) && dup2(devnull, 1) == -1) goto slave_oops;
if ((mi->flags & HIO_DEV_PRO_ERRTONUL) && dup2(devnull, 2) == -1) goto slave_oops; if ((mi->flags & HIO_DEV_PRO_ERRTONUL) && dup2(devnull, 2) == -1) goto slave_oops;
close (devnull); close(devnull);
devnull = HIO_SYSHND_INVALID; devnull = HIO_SYSHND_INVALID;
} }
if (mi->flags & HIO_DEV_PRO_DROPIN) close (0); if (mi->flags & HIO_DEV_PRO_DROPIN) close(0);
if (mi->flags & HIO_DEV_PRO_DROPOUT) close (1); if (mi->flags & HIO_DEV_PRO_DROPOUT) close(1);
if (mi->flags & HIO_DEV_PRO_DROPERR) close (2); if (mi->flags & HIO_DEV_PRO_DROPERR) close(2);
execv (param->argv[0], param->argv); execv (param->argv[0], param->argv);
/* if exec fails, free 'param' parameter which is an inherited pointer */ /* if exec fails, free 'param' parameter which is an inherited pointer */
free_param (hio, param); free_param(hio, param);
slave_oops: slave_oops:
if (devnull != HIO_SYSHND_INVALID) close(devnull); if (devnull != HIO_SYSHND_INVALID) close(devnull);
@@ -291,7 +291,7 @@ static int dev_pro_make_master (hio_dev_t* dev, void* ctx)
if (make_param(hio, info->cmd, info->flags, &param) <= -1) goto oops; if (make_param(hio, info->cmd, info->flags, &param) <= -1) goto oops;
/* TODO: more advanced fork and exec .. */ /* TODO: more advanced fork and exec .. */
pid = standard_fork_and_exec(rdev, pfds, info, &param); pid = standard_fork_and_exec(rdev, pfds, info, &param);
free_param (hio, &param); free_param(hio, &param);
if (pid <= -1) goto oops; if (pid <= -1) goto oops;
rdev->child_pid = pid; rdev->child_pid = pid;
@@ -305,7 +305,7 @@ static int dev_pro_make_master (hio_dev_t* dev, void* ctx)
* X * X
* WRITE => 1 * WRITE => 1
*/ */
close (pfds[0]); close(pfds[0]);
pfds[0] = HIO_SYSHND_INVALID; pfds[0] = HIO_SYSHND_INVALID;
if (hio_makesyshndasync(hio, pfds[1]) <= -1) goto oops; if (hio_makesyshndasync(hio, pfds[1]) <= -1) goto oops;
@@ -319,7 +319,7 @@ static int dev_pro_make_master (hio_dev_t* dev, void* ctx)
* X * X
* READ => 2 * READ => 2
*/ */
close (pfds[3]); close(pfds[3]);
pfds[3] = HIO_SYSHND_INVALID; pfds[3] = HIO_SYSHND_INVALID;
if (hio_makesyshndasync(hio, pfds[2]) <= -1) goto oops; if (hio_makesyshndasync(hio, pfds[2]) <= -1) goto oops;
@@ -333,7 +333,7 @@ static int dev_pro_make_master (hio_dev_t* dev, void* ctx)
* X * X
* READ => 4 * READ => 4
*/ */
close (pfds[5]); close(pfds[5]);
pfds[5] = HIO_SYSHND_INVALID; pfds[5] = HIO_SYSHND_INVALID;
if (hio_makesyshndasync(hio, pfds[4]) <= -1) goto oops; if (hio_makesyshndasync(hio, pfds[4]) <= -1) goto oops;
@@ -401,22 +401,25 @@ static int dev_pro_make_master (hio_dev_t* dev, void* ctx)
rdev->on_write = info->on_write; rdev->on_write = info->on_write;
rdev->on_close = info->on_close; rdev->on_close = info->on_close;
HIO_DEBUG7 (hio, "PRO(%p) - slave[%d] %p slave[%d] %p slave[%d] %p\n", dev, HIO_DEBUG7(hio, "PRO(%p) - slave[%d] %p slave[%d] %p slave[%d] %p\n", dev,
HIO_DEV_PRO_IN, rdev->slave[HIO_DEV_PRO_IN], HIO_DEV_PRO_IN, rdev->slave[HIO_DEV_PRO_IN],
HIO_DEV_PRO_OUT, rdev->slave[HIO_DEV_PRO_OUT], HIO_DEV_PRO_OUT, rdev->slave[HIO_DEV_PRO_OUT],
HIO_DEV_PRO_ERR, rdev->slave[HIO_DEV_PRO_ERR]); HIO_DEV_PRO_ERR, rdev->slave[HIO_DEV_PRO_ERR]);
return 0; return 0;
oops: oops:
for (i = minidx; i <= maxidx; i++) if (minidx >= 0 && maxidx >= 0)
{ {
if (pfds[i] != HIO_SYSHND_INVALID) close (pfds[i]); for (i = minidx; i <= maxidx; i++)
{
if (pfds[i] != HIO_SYSHND_INVALID) close(pfds[i]);
}
} }
if (rdev->mcmd) if (rdev->mcmd)
{ {
hio_freemem(hio, rdev->mcmd); hio_freemem(hio, rdev->mcmd);
free_param (hio, &param); free_param(hio, &param);
} }
for (i = HIO_COUNTOF(rdev->slave); i > 0; ) for (i = HIO_COUNTOF(rdev->slave); i > 0; )
@@ -424,7 +427,7 @@ oops:
i--; i--;
if (rdev->slave[i]) if (rdev->slave[i])
{ {
hio_dev_kill ((hio_dev_t*)rdev->slave[i]); hio_dev_kill((hio_dev_t*)rdev->slave[i]);
rdev->slave[i] = HIO_NULL; rdev->slave[i] = HIO_NULL;
} }
} }
@@ -454,7 +457,7 @@ static int dev_pro_kill_master (hio_dev_t* dev, int force)
* self-initiated termination or master-driven termination */ * self-initiated termination or master-driven termination */
rdev->slave[i] = HIO_NULL; rdev->slave[i] = HIO_NULL;
hio_dev_kill ((hio_dev_t*)sdev); hio_dev_kill((hio_dev_t*)sdev);
} }
} }
} }
@@ -475,7 +478,7 @@ static int dev_pro_kill_master (hio_dev_t* dev, int force)
{ {
if (!(rdev->flags & HIO_DEV_PRO_FORGET_DIEHARD_CHILD)) if (!(rdev->flags & HIO_DEV_PRO_FORGET_DIEHARD_CHILD))
{ {
kill (rdev->child_pid, SIGKILL); kill(rdev->child_pid, SIGKILL);
killed = 1; killed = 1;
goto await_child; goto await_child;
} }
@@ -495,11 +498,11 @@ static int dev_pro_kill_master (hio_dev_t* dev, int force)
*/ */
} }
HIO_DEBUG2 (hio, "PRO(%p) - REAPED CHILD %d\n", dev, (int)rdev->child_pid); HIO_DEBUG2(hio, "PRO(%p) - REAPED CHILD %d\n", dev, (int)rdev->child_pid);
rdev->child_pid = -1; rdev->child_pid = -1;
} }
if (rdev->on_close) rdev->on_close (rdev, HIO_DEV_PRO_MASTER); if (rdev->on_close) rdev->on_close(rdev, HIO_DEV_PRO_MASTER);
return 0; return 0;
} }
@@ -530,7 +533,7 @@ static int dev_pro_kill_slave (hio_dev_t* dev, int force)
rdev->master = HIO_NULL; rdev->master = HIO_NULL;
/* indicate EOF */ /* indicate EOF */
if (master->on_close) master->on_close (master, rdev->id); if (master->on_close) master->on_close(master, rdev->id);
HIO_ASSERT(hio, master->slave_count > 0); HIO_ASSERT(hio, master->slave_count > 0);
master->slave_count--; master->slave_count--;
@@ -541,7 +544,7 @@ static int dev_pro_kill_slave (hio_dev_t* dev, int force)
if (master->slave_count <= 0) if (master->slave_count <= 0)
{ {
/* if this is the last slave, kill the master also */ /* if this is the last slave, kill the master also */
hio_dev_kill ((hio_dev_t*)master); hio_dev_kill((hio_dev_t*)master);
/* the master pointer is not valid from this point onwards /* the master pointer is not valid from this point onwards
* as the actual master device object is freed in hio_dev_kill() */ * as the actual master device object is freed in hio_dev_kill() */
} }
@@ -557,7 +560,7 @@ static int dev_pro_kill_slave (hio_dev_t* dev, int force)
if (rdev->pfd != HIO_SYSHND_INVALID) if (rdev->pfd != HIO_SYSHND_INVALID)
{ {
close (rdev->pfd); close(rdev->pfd);
rdev->pfd = HIO_SYSHND_INVALID; rdev->pfd = HIO_SYSHND_INVALID;
} }
@@ -567,7 +570,7 @@ static int dev_pro_kill_slave (hio_dev_t* dev, int force)
static void dev_pro_fail_before_make_slave (void* ctx) static void dev_pro_fail_before_make_slave (void* ctx)
{ {
slave_info_t* si = (slave_info_t*)ctx; slave_info_t* si = (slave_info_t*)ctx;
close (si->pfd); close(si->pfd);
} }
static int dev_pro_read_slave (hio_dev_t* dev, void* buf, hio_iolen_t* len, hio_devaddr_t* srcaddr) static int dev_pro_read_slave (hio_dev_t* dev, void* buf, hio_iolen_t* len, hio_devaddr_t* srcaddr)
@@ -620,7 +623,7 @@ static int dev_pro_write_slave (hio_dev_t* dev, const void* data, hio_iolen_t* l
if (HIO_LIKELY(pro->pfd != HIO_SYSHND_INVALID)) if (HIO_LIKELY(pro->pfd != HIO_SYSHND_INVALID))
{ {
hio_dev_watch (dev, HIO_DEV_WATCH_STOP, 0); hio_dev_watch (dev, HIO_DEV_WATCH_STOP, 0);
close (pro->pfd); close(pro->pfd);
pro->pfd = HIO_SYSHND_INVALID; pro->pfd = HIO_SYSHND_INVALID;
} }
return 1; /* indicate that the operation got successful. the core will execute on_write() with the write length of 0. */ return 1; /* indicate that the operation got successful. the core will execute on_write() with the write length of 0. */
@@ -662,7 +665,7 @@ static int dev_pro_writev_slave (hio_dev_t* dev, const hio_iovec_t* iov, hio_iol
if (HIO_LIKELY(pro->pfd != HIO_SYSHND_INVALID)) if (HIO_LIKELY(pro->pfd != HIO_SYSHND_INVALID))
{ {
hio_dev_watch (dev, HIO_DEV_WATCH_STOP, 0); hio_dev_watch (dev, HIO_DEV_WATCH_STOP, 0);
close (pro->pfd); close(pro->pfd);
pro->pfd = HIO_SYSHND_INVALID; pro->pfd = HIO_SYSHND_INVALID;
} }
return 1; /* indicate that the operation got successful. the core will execute on_write() with 0. */ return 1; /* indicate that the operation got successful. the core will execute on_write() with 0. */
@@ -714,7 +717,7 @@ static int dev_pro_ioctl (hio_dev_t* dev, int cmd, void* arg)
/* unlike dev_pro_kill_master(), i don't nullify rdev->slave[sid]. /* unlike dev_pro_kill_master(), i don't nullify rdev->slave[sid].
* so i treat the closing ioctl as if it's a kill request * so i treat the closing ioctl as if it's a kill request
* initiated by the slave device itself. */ * initiated by the slave device itself. */
hio_dev_kill ((hio_dev_t*)rdev->slave[sid]); hio_dev_kill((hio_dev_t*)rdev->slave[sid]);
/* if this is the last slave, the master is destroyed as well. /* if this is the last slave, the master is destroyed as well.
* therefore, using rdev is unsafe in the assertion below is unsafe. * therefore, using rdev is unsafe in the assertion below is unsafe.
+11 -11
View File
@@ -158,7 +158,7 @@ static pid_t standard_fork_and_exec (hio_dev_pty_t* dev, int pfds[], hio_dev_pty
{ {
/* slave process */ /* slave process */
/* child */ /* child */
close (pfds[0]); /* close the pty master */ close(pfds[0]); /* close the pty master */
pfds[0] = HIO_SYSHND_INVALID; pfds[0] = HIO_SYSHND_INVALID;
/*TODO: close all open file descriptors */ /*TODO: close all open file descriptors */
@@ -170,13 +170,13 @@ static pid_t standard_fork_and_exec (hio_dev_pty_t* dev, int pfds[], hio_dev_pty
if (dup2(pfds[1], 0) == -1 || dup2(pfds[1], 1) == -1 || dup2(pfds[1], 2) == -1) goto slave_oops; if (dup2(pfds[1], 0) == -1 || dup2(pfds[1], 1) == -1 || dup2(pfds[1], 2) == -1) goto slave_oops;
close (pfds[1]); close(pfds[1]);
pfds[1] = HIO_SYSHND_INVALID; pfds[1] = HIO_SYSHND_INVALID;
execve (param->argv[0], param->argv, param->fixed_env); execve (param->argv[0], param->argv, param->fixed_env);
/* if exec fails, free 'param' parameter which is an inherited pointer */ /* if exec fails, free 'param' parameter which is an inherited pointer */
free_param (hio, param); free_param(hio, param);
slave_oops: slave_oops:
if (pfds[1] != HIO_SYSHND_INVALID) close(pfds[1]); if (pfds[1] != HIO_SYSHND_INVALID) close(pfds[1]);
@@ -276,10 +276,10 @@ static int dev_pty_make (hio_dev_t* dev, void* ctx)
if (make_param(hio, info->cmd, info->flags, &param) <= -1) goto oops; if (make_param(hio, info->cmd, info->flags, &param) <= -1) goto oops;
pid = standard_fork_and_exec(rdev, pfds, info, &param); pid = standard_fork_and_exec(rdev, pfds, info, &param);
free_param (hio, &param); free_param(hio, &param);
if (pid <= -1) goto oops; if (pid <= -1) goto oops;
close (pfds[1]); /* close the pty slave */ close(pfds[1]); /* close the pty slave */
pfds[1] = HIO_SYSHND_INVALID; pfds[1] = HIO_SYSHND_INVALID;
if (hio_makesyshndasync(hio, pfds[0]) <= -1) goto oops; if (hio_makesyshndasync(hio, pfds[0]) <= -1) goto oops;
@@ -294,8 +294,8 @@ static int dev_pty_make (hio_dev_t* dev, void* ctx)
return 0; return 0;
oops: oops:
if (pfds[0] != HIO_SYSHND_INVALID) close (pfds[0]); if (pfds[0] != HIO_SYSHND_INVALID) close(pfds[0]);
if (pfds[1] != HIO_SYSHND_INVALID) close (pfds[1]); if (pfds[1] != HIO_SYSHND_INVALID) close(pfds[1]);
return -1; return -1;
} }
@@ -344,11 +344,11 @@ static int dev_pty_kill (hio_dev_t* dev, int force)
rdev->child_pid = -1; rdev->child_pid = -1;
} }
if (rdev->on_close) rdev->on_close (rdev); if (rdev->on_close) rdev->on_close(rdev);
if (rdev->hnd != HIO_SYSHND_INVALID) if (rdev->hnd != HIO_SYSHND_INVALID)
{ {
close (rdev->hnd); close(rdev->hnd);
rdev->hnd = HIO_SYSHND_INVALID; rdev->hnd = HIO_SYSHND_INVALID;
} }
return 0; return 0;
@@ -396,7 +396,7 @@ static int dev_pty_write (hio_dev_t* dev, const void* data, hio_iolen_t* len, co
if (HIO_LIKELY(pty->hnd != HIO_SYSHND_INVALID)) /* halt() doesn't close the pty immediately. so close the underlying pty */ if (HIO_LIKELY(pty->hnd != HIO_SYSHND_INVALID)) /* halt() doesn't close the pty immediately. so close the underlying pty */
{ {
hio_dev_watch (dev, HIO_DEV_WATCH_STOP, 0); hio_dev_watch (dev, HIO_DEV_WATCH_STOP, 0);
close (pty->hnd); close(pty->hnd);
pty->hnd = HIO_SYSHND_INVALID; pty->hnd = HIO_SYSHND_INVALID;
} }
return 1; /* indicate that the operation got successful. the core will execute on_write() with 0. */ return 1; /* indicate that the operation got successful. the core will execute on_write() with 0. */
@@ -433,7 +433,7 @@ static int dev_pty_writev (hio_dev_t* dev, const hio_iovec_t* iov, hio_iolen_t*
if (HIO_LIKELY(pty->hnd != HIO_SYSHND_INVALID)) /* halt() doesn't close the pty immediately. so close the underlying pty */ if (HIO_LIKELY(pty->hnd != HIO_SYSHND_INVALID)) /* halt() doesn't close the pty immediately. so close the underlying pty */
{ {
hio_dev_watch (dev, HIO_DEV_WATCH_STOP, 0); hio_dev_watch (dev, HIO_DEV_WATCH_STOP, 0);
close (pty->hnd); close(pty->hnd);
pty->hnd = HIO_SYSHND_INVALID; pty->hnd = HIO_SYSHND_INVALID;
} }
return 1; /* indicate that the operation got successful. the core will execute on_write() with 0. */ return 1; /* indicate that the operation got successful. the core will execute on_write() with 0. */
+469 -35
View File
@@ -51,6 +51,24 @@
# include <netinet/sctp.h> # include <netinet/sctp.h>
# if defined(IPPROTO_SCTP) # if defined(IPPROTO_SCTP)
# define ENABLE_SCTP # define ENABLE_SCTP
/* these library calls are a separate question from the socket type. on
* linux they live in libsctp, which a machine with sctp headers and an
* sctp kernel may not have installed. the basic one-to-one and
* one-to-many transports need none of them, so they stand either way.
*
* peel-off and multi-homing are probed apart because they are separate
* features that share nothing but the library they come from: peel-off
* needs sctp_peeloff() and multi-homing needs the address calls, and
* neither calls into the other. bundling them would mean a system
* missing one silently loses both - the same "they always come
* together" assumption that let the old header-derived ENABLE_SCTP
* stay wrong for so long. */
# if defined(HAVE_SCTP_PEELOFF)
# define ENABLE_SCTP_PEELOFF
# endif
# if defined(HAVE_SCTP_BINDX) && defined(HAVE_SCTP_GETPADDRS) && defined(HAVE_SCTP_GETLADDRS)
# define ENABLE_SCTP_MH
# endif
# endif # endif
#endif #endif
@@ -322,13 +340,23 @@ static struct sck_type_map_t sck_type_map[] =
/* HIO_DEV_SCK_SCTP6 */ /* HIO_DEV_SCK_SCTP6 */
{ AF_INET6, SOCK_STREAM, IPPROTO_SCTP, 1, 1, HIO_DEV_CAP_STREAM }, { AF_INET6, SOCK_STREAM, IPPROTO_SCTP, 1, 1, HIO_DEV_CAP_STREAM },
/* HIO_DEV_SCK_SCTP4_SP - one-to-many. listen() is called but hio never /* HIO_DEV_SCK_SCTP4_SEQPKT - one-to-many. listen() is called but hio never
* accepts: associations are not devices in this model, they are told apart * accepts: associations are not devices in this model, they are told apart
* by the source address on each message. */ * by the source address on each message.
{ AF_INET, SOCK_SEQPACKET, IPPROTO_SCTP, 1, 1, 0 }, *
* marked unconnectable, as udp is. the socket api does allow connect() on a
* one-to-many socket - it forms an association and makes it the default
* destination - but nothing here can finish the job: a device with no
* HIO_DEV_CAP_STREAM gets dev_evcb_sck_ready_stateless(), which looks only
* at ERR and HUP and never at the progress bits, so on_connect() would
* never fire. the device would sit in HIO_DEV_SCK_CONNECTING for good -
* writes failing, a second connect() refused as already in progress, and
* with a connect timeout set, silently halted a few seconds later.
* refusing outright beats handing back a bricked device. */
{ AF_INET, SOCK_SEQPACKET, IPPROTO_SCTP, 0, 1, 0 },
/* HIO_DEV_SCK_SCTP6_SP */ /* HIO_DEV_SCK_SCTP6_SEQPKT */
{ AF_INET6, SOCK_SEQPACKET, IPPROTO_SCTP, 1, 1, 0 }, { AF_INET6, SOCK_SEQPACKET, IPPROTO_SCTP, 0, 1, 0 },
#else #else
{ -1, 0, 0, 0, 0, 0 }, { -1, 0, 0, 0, 0, 0 },
{ -1, 0, 0, 0, 0, 0 }, { -1, 0, 0, 0, 0, 0 },
@@ -605,10 +633,18 @@ oops:
return -1; return -1;
} }
/* hio_dev_make() hands this back exactly what was passed to it, for the case
* where it fails before the make() method could take ownership of the handle.
*
* [NOTE] the ctx used to be a bare hio_syshnd_t and is now a struct whose first
* member is one. the old cast still read the right value - a pointer to a
* struct points to its first member - but only by accident of layout: put any
* field ahead of 'hnd' and this would close (int)type instead, which is a small
* integer, which is to say some other part of the program's descriptor. */
static void dev_sck_fail_before_make_client (void* ctx) static void dev_sck_fail_before_make_client (void* ctx)
{ {
hio_syshnd_t* clisckhnd = (hio_syshnd_t*)ctx; sck_make_client_ctx_t* mc = (sck_make_client_ctx_t*)ctx;
close(*clisckhnd); close(mc->hnd);
} }
static int dev_sck_kill (hio_dev_t* dev, int force) static int dev_sck_kill (hio_dev_t* dev, int force)
@@ -884,7 +920,14 @@ static int sendmsg_sctp(
* addressing by msg_name. it is ignored on a one-to-one socket. */ * addressing by msg_name. it is ignored on a one-to-one socket. */
sinfo->sinfo_assoc_id = (sctp_assoc_t)assoc_id; sinfo->sinfo_assoc_id = (sctp_assoc_t)assoc_id;
/* the plain stream and stateless send paths all ask for this; without it a
* failing sctp write raises SIGPIPE and kills the process where the
* equivalent tcp write merely returns EPIPE. */
#if defined(MSG_NOSIGNAL)
return sendmsg(s, &msg, MSG_NOSIGNAL);
#else
return sendmsg(s, &msg, 0); return sendmsg(s, &msg, 0);
#endif
} }
/* the core passes no destination for a connected socket - hio_dev_sck_write() /* the core passes no destination for a connected socket - hio_dev_sck_write()
@@ -915,9 +958,8 @@ static HIO_INLINE hio_int32_t dstaddr_assoc (const hio_devaddr_t* dstaddr)
return (dstaddr && dstaddr->ptr)? hio_skad_get_assoc((const hio_skad_t*)dstaddr->ptr): 0; return (dstaddr && dstaddr->ptr)? hio_skad_get_assoc((const hio_skad_t*)dstaddr->ptr): 0;
} }
static int dev_sck_read_sctp_sp (hio_dev_t* dev, void* buf, hio_iolen_t* len, hio_devaddr_t* srcaddr) static int dev_sck_read_sctp_seqpkt (hio_dev_t* dev, void* buf, hio_iolen_t* len, hio_devaddr_t* srcaddr)
{ {
/* NOTE: sctp support is far away from complete */
hio_t* hio = dev->hio; hio_t* hio = dev->hio;
hio_dev_sck_t* rdev = (hio_dev_sck_t*)dev; hio_dev_sck_t* rdev = (hio_dev_sck_t*)dev;
hio_scklen_t srcaddrlen; hio_scklen_t srcaddrlen;
@@ -944,7 +986,12 @@ static int dev_sck_read_sctp_sp (hio_dev_t* dev, void* buf, hio_iolen_t* len, hi
if (msg_flags & MSG_NOTIFICATION) if (msg_flags & MSG_NOTIFICATION)
{ {
/* an association or path event, not payload. handing this to /* an association or path event, not payload. handing this to
* on_read() would splice an event record into the data stream. */ * on_read() would splice an event record into the data stream.
*
* every one of these is passed on, association changes included. this
* socket takes no view on which associations deserve a device of their
* own - hio_dev_sck_peeloff() is a call the application makes, from
* here or from on_read() later, for the associations it picks. */
if (rdev->on_notification) rdev->on_notification(rdev, buf, x); if (rdev->on_notification) rdev->on_notification(rdev, buf, x);
return 0; /* nothing readable for the caller this time round */ return 0; /* nothing readable for the caller this time round */
} }
@@ -970,7 +1017,7 @@ static int dev_sck_read_sctp_sp (hio_dev_t* dev, void* buf, hio_iolen_t* len, hi
if (!rdev->sctp_discarding) if (!rdev->sctp_discarding)
{ {
rdev->sctp_discarding = 1; rdev->sctp_discarding = 1;
HIO_INFO2 (hio, "SCK(%p) - discarding an sctp message too large for the read buffer of %zu octets\n", rdev, hio->bigbuf.capa); HIO_INFO2(hio, "SCK(%p) - discarding an sctp message too large for the read buffer of %zu octets\n", rdev, hio->bigbuf.capa);
} }
/* keep swallowing fragments until the one that ends the message */ /* keep swallowing fragments until the one that ends the message */
if (msg_flags & MSG_EOR) rdev->sctp_discarding = 0; if (msg_flags & MSG_EOR) rdev->sctp_discarding = 0;
@@ -1260,9 +1307,8 @@ static int dev_sck_writev_bpf (hio_dev_t* dev, const hio_iovec_t* iov, hio_iolen
/* ------------------------------------------------------------------------------ */ /* ------------------------------------------------------------------------------ */
#if defined(ENABLE_SCTP) #if defined(ENABLE_SCTP)
static int dev_sck_write_sctp_sp (hio_dev_t* dev, const void* data, hio_iolen_t* len, const hio_devaddr_t* dstaddr) static int dev_sck_write_sctp_seqpkt (hio_dev_t* dev, const void* data, hio_iolen_t* len, const hio_devaddr_t* dstaddr)
{ {
/* NOTE: sctp support is far away from complete */
hio_t* hio = dev->hio; hio_t* hio = dev->hio;
hio_dev_sck_t* rdev = (hio_dev_sck_t*)dev; hio_dev_sck_t* rdev = (hio_dev_sck_t*)dev;
ssize_t x; ssize_t x;
@@ -1292,7 +1338,7 @@ static int dev_sck_write_sctp_sp (hio_dev_t* dev, const void* data, hio_iolen_t*
/* the one-to-one sctp types carry HIO_DEV_CAP_STREAM, so the core treats them /* the one-to-one sctp types carry HIO_DEV_CAP_STREAM, so the core treats them
* like a tcp socket: a zero-length write is the writing-end shutdown, and a * like a tcp socket: a zero-length write is the writing-end shutdown, and a
* zero-length read is EOF. the seqpacket methods above answer neither of those * zero-length read is EOF. the seqpkt methods above answer neither of those
* conventions - a zero-length sendmsg() puts an empty message on the wire * conventions - a zero-length sendmsg() puts an empty message on the wire
* rather than closing anything - so the stream variants need their own pair. * rather than closing anything - so the stream variants need their own pair.
* *
@@ -1329,9 +1375,9 @@ static int dev_sck_read_sctp_stream (hio_dev_t* dev, void* buf, hio_iolen_t* len
/* x of 0 falls through as a zero length, which is what the core reads as /* x of 0 falls through as a zero length, which is what the core reads as
* EOF on a stream device */ * EOF on a stream device */
hio_skad_set_chan (&rdev->remoteaddr, sri.sinfo_stream); hio_skad_set_chan(&rdev->remoteaddr, sri.sinfo_stream);
hio_skad_set_ppid (&rdev->remoteaddr, sri.sinfo_ppid); hio_skad_set_ppid(&rdev->remoteaddr, sri.sinfo_ppid);
hio_skad_set_assoc (&rdev->remoteaddr, (hio_int32_t)sri.sinfo_assoc_id); hio_skad_set_assoc(&rdev->remoteaddr, (hio_int32_t)sri.sinfo_assoc_id);
*len = x; *len = x;
return 1; return 1;
@@ -1403,7 +1449,7 @@ static int dev_sck_writev_sctp_stream (hio_dev_t* dev, const hio_iovec_t* iov, h
return 1; return 1;
} }
static int dev_sck_writev_sctp_sp (hio_dev_t* dev, const hio_iovec_t* iov, hio_iolen_t* iovcnt, const hio_devaddr_t* dstaddr) static int dev_sck_writev_sctp_seqpkt (hio_dev_t* dev, const hio_iovec_t* iov, hio_iolen_t* iovcnt, const hio_devaddr_t* dstaddr)
{ {
hio_t* hio = dev->hio; hio_t* hio = dev->hio;
hio_dev_sck_t* rdev = (hio_dev_sck_t*)dev; hio_dev_sck_t* rdev = (hio_dev_sck_t*)dev;
@@ -2118,7 +2164,7 @@ static hio_dev_mth_t dev_mth_clisck_sctp_stream =
{ {
dev_sck_make_client, dev_sck_make_client,
dev_sck_kill, dev_sck_kill,
HIO_NULL, dev_sck_fail_before_make_client,
dev_sck_getsyshnd, dev_sck_getsyshnd,
HIO_NULL, HIO_NULL,
dev_sck_ioctl, dev_sck_ioctl,
@@ -2153,7 +2199,7 @@ static hio_dev_mth_t dev_mth_sck_stream =
}; };
#if defined(ENABLE_SCTP) #if defined(ENABLE_SCTP)
static hio_dev_mth_t dev_mth_sck_sctp_sp = static hio_dev_mth_t dev_mth_sck_sctp_seqpkt =
{ {
dev_sck_make, dev_sck_make,
dev_sck_kill, dev_sck_kill,
@@ -2162,9 +2208,9 @@ static hio_dev_mth_t dev_mth_sck_sctp_sp =
HIO_NULL, HIO_NULL,
dev_sck_ioctl, /* ioctl */ dev_sck_ioctl, /* ioctl */
dev_sck_read_sctp_sp, dev_sck_read_sctp_seqpkt,
dev_sck_write_sctp_sp, dev_sck_write_sctp_seqpkt,
dev_sck_writev_sctp_sp, dev_sck_writev_sctp_seqpkt,
HIO_NULL, /* sendfile */ HIO_NULL, /* sendfile */
HIO_NULL, /* readpending */ HIO_NULL, /* readpending */
@@ -2210,7 +2256,7 @@ static hio_dev_mth_t dev_mth_clisck_stream =
}; };
#if defined(ENABLE_SCTP) #if defined(ENABLE_SCTP)
static hio_dev_mth_t dev_mth_clisck_sctp_sp = static hio_dev_mth_t dev_mth_clisck_sctp_seqpkt =
{ {
dev_sck_make_client, dev_sck_make_client,
dev_sck_kill, dev_sck_kill,
@@ -2219,12 +2265,12 @@ static hio_dev_mth_t dev_mth_clisck_sctp_sp =
HIO_NULL, HIO_NULL,
dev_sck_ioctl, dev_sck_ioctl,
dev_sck_read_sctp_sp, dev_sck_read_sctp_seqpkt,
dev_sck_write_sctp_sp, dev_sck_write_sctp_seqpkt,
dev_sck_writev_sctp_sp, dev_sck_writev_sctp_seqpkt,
HIO_NULL, /* sendfile */ HIO_NULL, /* sendfile */
HIO_NULL /* readpending - no ssl on a seqpacket socket */ HIO_NULL /* readpending - no ssl on a seqpkt socket */
}; };
#endif #endif
@@ -2344,11 +2390,11 @@ static int harvest_outgoing_connection (hio_dev_sck_t* rdev)
static int make_accepted_client_connection (hio_dev_sck_t* rdev, hio_syshnd_t clisck, hio_skad_t* remoteaddr, hio_dev_sck_type_t clisck_type) static int make_accepted_client_connection (hio_dev_sck_t* rdev, hio_syshnd_t clisck, hio_skad_t* remoteaddr, hio_dev_sck_type_t clisck_type)
{ {
sck_make_client_ctx_t mc;
hio_t* hio = rdev->hio; hio_t* hio = rdev->hio;
hio_dev_sck_t* clidev; hio_dev_sck_t* clidev;
hio_scklen_t addrlen; hio_scklen_t addrlen;
hio_dev_mth_t* dev_mth; hio_dev_mth_t* dev_mth;
sck_make_client_ctx_t mc;
if (rdev->on_raw_accept) if (rdev->on_raw_accept)
{ {
@@ -2370,8 +2416,8 @@ static int make_accepted_client_connection (hio_dev_sck_t* rdev, hio_syshnd_t cl
*/ */
#if defined(ENABLE_SCTP) #if defined(ENABLE_SCTP)
dev_mth = (sck_type_map[clisck_type].extra_dev_cap & HIO_DEV_CAP_STREAM)? dev_mth = (sck_type_map[clisck_type].extra_dev_cap & HIO_DEV_CAP_STREAM)?
((sck_type_map[clisck_type].proto == IPPROTO_SCTP)? &dev_mth_clisck_sctp_stream: &dev_mth_clisck_stream): ((sck_type_map[clisck_type].proto == IPPROTO_SCTP)? &dev_mth_clisck_sctp_stream: &dev_mth_clisck_stream):
(sck_type_map[clisck_type].proto == IPPROTO_SCTP)? &dev_mth_clisck_sctp_sp: &dev_mth_clisck_stateless; ((sck_type_map[clisck_type].proto == IPPROTO_SCTP)? &dev_mth_clisck_sctp_seqpkt: &dev_mth_clisck_stateless);
#else #else
dev_mth = (sck_type_map[clisck_type].extra_dev_cap & HIO_DEV_CAP_STREAM)? &dev_mth_clisck_stream: &dev_mth_clisck_stateless; dev_mth = (sck_type_map[clisck_type].extra_dev_cap & HIO_DEV_CAP_STREAM)? &dev_mth_clisck_stream: &dev_mth_clisck_stateless;
#endif #endif
@@ -2380,7 +2426,7 @@ static int make_accepted_client_connection (hio_dev_sck_t* rdev, hio_syshnd_t cl
clidev = (hio_dev_sck_t*)hio_dev_make(hio, rdev->dev_size, dev_mth, rdev->dev_evcb, &mc); clidev = (hio_dev_sck_t*)hio_dev_make(hio, rdev->dev_size, dev_mth, rdev->dev_evcb, &mc);
if (HIO_UNLIKELY(!clidev)) if (HIO_UNLIKELY(!clidev))
{ {
/* [NOTE] 'clisck' is closed by callback methods called by hio_dev_make() upon failure */ /* [NOTE] 'clisck' is closed by callback(fail_before_make) methods called by hio_dev_make() upon failure */
HIO_DEBUG3(hio, "SCK(%p) - unable to make a new accepted device for %d - %js\n", rdev, (int)clisck, hio_geterrmsg(hio)); HIO_DEBUG3(hio, "SCK(%p) - unable to make a new accepted device for %d - %js\n", rdev, (int)clisck, hio_geterrmsg(hio));
return -1; return -1;
} }
@@ -2529,6 +2575,10 @@ static int accept_incoming_connection (hio_dev_sck_t* rdev)
#if defined(SOCK_NONBLOCK) && defined(SOCK_CLOEXEC) && defined(HAVE_ACCEPT4) #if defined(SOCK_NONBLOCK) && defined(SOCK_CLOEXEC) && defined(HAVE_ACCEPT4)
accept_done: accept_done:
#endif #endif
/* no separate error handling to close clisck becuase it's supposed to be
* handled by hio_dev_make() via the fail_before_make callback inside
* make_accepted_client_connection(). if it fails even before hio_dev_make()
* inside make_accepted_client_connection(), it should close the socket explicitly */
return make_accepted_client_connection(rdev, clisck, &remoteaddr, rdev->type); return make_accepted_client_connection(rdev, clisck, &remoteaddr, rdev->type);
} }
@@ -2634,7 +2684,6 @@ static int dev_evcb_sck_ready_stream (hio_dev_t* dev, int events)
#endif #endif
case HIO_DEV_SCK_LISTENING: case HIO_DEV_SCK_LISTENING:
if (events & HIO_DEV_EVENT_HUP) if (events & HIO_DEV_EVENT_HUP)
{ {
/* device hang-up */ /* device hang-up */
@@ -2798,7 +2847,7 @@ static hio_dev_evcb_t dev_sck_event_callbacks_stateless =
dev_evcb_sck_on_write_stateless dev_evcb_sck_on_write_stateless
}; };
static hio_dev_evcb_t dev_sck_event_callbacks_sctp_sp = static hio_dev_evcb_t dev_sck_event_callbacks_sctp_seqpkt =
{ {
dev_evcb_sck_ready_stateless, dev_evcb_sck_ready_stateless,
dev_evcb_sck_on_read_stateless, dev_evcb_sck_on_read_stateless,
@@ -2972,7 +3021,7 @@ hio_dev_sck_t* hio_dev_sck_make (hio_t* hio, hio_oow_t xtnsize, const hio_dev_sc
{ {
rdev = (hio_dev_sck_t*)hio_dev_make( rdev = (hio_dev_sck_t*)hio_dev_make(
hio, HIO_SIZEOF(hio_dev_sck_t) + xtnsize, hio, HIO_SIZEOF(hio_dev_sck_t) + xtnsize,
&dev_mth_sck_sctp_sp, &dev_sck_event_callbacks_sctp_sp, (void*)info); &dev_mth_sck_sctp_seqpkt, &dev_sck_event_callbacks_sctp_seqpkt, (void*)info);
} }
#endif #endif
else else
@@ -3161,6 +3210,391 @@ int hio_dev_sck_shutdown (hio_dev_sck_t* dev, int how)
return 0; return 0;
} }
/* ------------------------------------------------------------------------- */
/* sctp peel-off */
/* ------------------------------------------------------------------------- */
#if defined(ENABLE_SCTP_PEELOFF)
/* the one-to-one type a peeled-off association becomes. sctp_peeloff() hands
* back a SOCK_STREAM socket carrying one association, which is precisely what
* the one-to-one types already describe - so the peeled device gets the
* existing one-to-one methods, write queue and all. */
static int sctp_one_to_one_type (hio_dev_sck_type_t sp_type, hio_dev_sck_type_t* one_to_one)
{
switch (sp_type)
{
case HIO_DEV_SCK_SCTP4_SEQPKT:
*one_to_one = HIO_DEV_SCK_SCTP4;
return 0;
case HIO_DEV_SCK_SCTP6_SEQPKT:
*one_to_one = HIO_DEV_SCK_SCTP6;
return 0;
default:
return -1;
}
}
int hio_dev_sck_peeloff (hio_dev_sck_t* rdev, hio_int32_t assoc_id)
{
hio_t* hio = rdev->hio;
hio_dev_sck_type_t clitype;
hio_syshnd_t clisck;
hio_skad_t remoteaddr;
hio_scklen_t addrlen;
if (sctp_one_to_one_type(rdev->type, &clitype) <= -1)
{
hio_seterrbfmt(hio, HIO_EINVAL, "not a one-to-many sctp socket");
return -1;
}
/* move the association onto a socket of its own. anything still queued for
* it in the kernel moves with it, which is what makes a mid-stream peel
* safe: messages already handed to on_read() are the caller's, the rest
* arrive on the new device, and none are lost or seen twice. */
clisck = sctp_peeloff(rdev->hnd, (sctp_assoc_t)assoc_id);
if (clisck <= -1)
{
hio_seterrwithsyserr(hio, 0, errno);
return -1;
}
/* the extra area past the sockaddr is not written by getpeername(), so it
* is cleared here rather than left holding the stream and ppid of whatever
* message last used this device's remoteaddr. */
HIO_MEMSET(&remoteaddr, 0, HIO_SIZEOF(remoteaddr));
addrlen = HIO_SIZEOF(remoteaddr);
if (getpeername(clisck, (struct sockaddr*)&remoteaddr, &addrlen) <= -1)
{
/* fall back on the address the notification came from - the primary
* path of the same association. the remaining addresses of a
* multi-homed peer are reachable with hio_dev_sck_getpaddrs(). */
remoteaddr = rdev->remoteaddr;
hio_skad_set_chan(&remoteaddr, 0);
hio_skad_set_ppid(&remoteaddr, 0);
hio_skad_set_assoc(&remoteaddr, 0);
}
/* no separate error handling to close clisck becuase it's supposed to be
* handled by hio_dev_make() via the fail_before_make callback inside
* make_accepted_client_connection(). if it fails even before hio_dev_make()
* inside make_accepted_client_connection(), it should close the socket explicitly */
return make_accepted_client_connection(rdev, clisck, &remoteaddr, clitype);
}
#else /* ENABLE_SCTP_PEELOFF */
int hio_dev_sck_peeloff (hio_dev_sck_t* rdev, hio_int32_t assoc_id)
{
hio_seterrbfmt(rdev->hio, HIO_ENOIMPL, "sctp peel-off not supported");
return -1;
}
#endif /* ENABLE_SCTP_PEELOFF */
/* ------------------------------------------------------------------------- */
#if defined(ENABLE_SCTP)
int hio_dev_sck_parse_assoc_event (const void* data, hio_iolen_t dlen, hio_sctp_assoc_event_t* ev)
{
struct sctp_assoc_change ac;
/* copied out rather than read in place: a caller may hand over a buffer
* whose alignment is not this structure's to assume. */
if (dlen < (hio_iolen_t)HIO_SIZEOF(ac)) return -1; /* too short to be one */
HIO_MEMCPY(&ac, data, HIO_SIZEOF(ac));
if (ac.sac_type != SCTP_ASSOC_CHANGE) return -1; /* a different event, not an error */
switch (ac.sac_state)
{
case SCTP_COMM_UP: ev->state = HIO_SCTP_ASSOC_COMM_UP; break;
case SCTP_COMM_LOST: ev->state = HIO_SCTP_ASSOC_COMM_LOST; break;
case SCTP_RESTART: ev->state = HIO_SCTP_ASSOC_RESTART; break;
case SCTP_SHUTDOWN_COMP: ev->state = HIO_SCTP_ASSOC_SHUTDOWN_COMP; break;
case SCTP_CANT_STR_ASSOC: ev->state = HIO_SCTP_ASSOC_CANT_STR_ASSOC; break;
default: ev->state = HIO_SCTP_ASSOC_STATE_UNKNOWN; break;
}
ev->error = ac.sac_error;
ev->assoc_id = (hio_int32_t)ac.sac_assoc_id;
/* the negotiated counts - the outcome of both ends' SCTP_INITMSG requests,
* and not reachable any other way */
ev->ostreams = ac.sac_outbound_streams;
ev->instreams = ac.sac_inbound_streams;
return 0;
}
#else
int hio_dev_sck_parse_assoc_event (const void* data, hio_iolen_t dlen, hio_sctp_assoc_event_t* ev)
{
return -1;
}
#endif
/* ------------------------------------------------------------------------- */
/* sctp multi-homing */
/* ------------------------------------------------------------------------- */
#if defined(ENABLE_SCTP_MH)
static HIO_INLINE int is_sctp_sck (hio_dev_sck_t* dev)
{
return sck_type_map[dev->type].proto == IPPROTO_SCTP;
}
/* the sctp calls take addresses as a packed run of sockaddrs of mixed length,
* not an array of a fixed-size type. these two convert between that and
* hio_skad_t, which is fixed-size and carries an extra area the kernel neither
* writes nor reads. */
static int pack_skads (hio_t* hio, const hio_skad_t* addrs, hio_oow_t naddrs, hio_uint8_t** buf)
{
hio_uint8_t* b, * p;
hio_oow_t total = 0, i;
for (i = 0; i < naddrs; i++)
{
int len = hio_skad_get_size(&addrs[i]);
if (len <= 0)
{
hio_seterrbfmt(hio, HIO_EINVAL, "address #%zu is not of a supported family", i);
return -1;
}
total += len;
}
b = (hio_uint8_t*)hio_allocmem(hio, total);
if (HIO_UNLIKELY(!b)) return -1;
for (i = 0, p = b; i < naddrs; i++)
{
int len = hio_skad_get_size(&addrs[i]);
HIO_MEMCPY(p, &addrs[i], len);
p += len;
}
*buf = b;
return 0;
}
static int unpack_skads (hio_t* hio, const struct sockaddr* packed, int count, hio_skad_t* addrs, hio_oow_t* naddrs)
{
hio_oow_t room = *naddrs, i;
const hio_uint8_t* p = (const hio_uint8_t*)packed;
/* every address is reported, so the caller learns how much room it needed
* even when it did not have enough. what does not fit is not written. */
for (i = 0; i < (hio_oow_t)count; i++)
{
hio_oow_t len;
switch (((const struct sockaddr*)p)->sa_family)
{
case AF_INET:
len = HIO_SIZEOF(struct sockaddr_in);
break;
#if defined(AF_INET6)
case AF_INET6:
len = HIO_SIZEOF(struct sockaddr_in6);
break;
#endif
default:
/* the run cannot be walked past an address of unknown length */
hio_seterrbfmt(hio, HIO_EINVAL, "unsupported address family %d in the sctp address list", (int)((const struct sockaddr*)p)->sa_family);
*naddrs = i;
return -1;
}
if (i < room)
{
/* the extra area past the sockaddr belongs to hio, not the kernel */
HIO_MEMSET(&addrs[i], 0, HIO_SIZEOF(addrs[i]));
HIO_MEMCPY(&addrs[i], p, len);
}
p += len;
}
*naddrs = (hio_oow_t)count;
if ((hio_oow_t)count > room)
{
hio_seterrbfmt(hio, HIO_EBUFFULL, "%d addresses do not fit in %zu slot(s)", count, room);
return -1;
}
return 0;
}
int hio_dev_sck_bindx (hio_dev_sck_t* dev, const hio_skad_t* addrs, hio_oow_t naddrs, hio_dev_sck_bindx_flag_t flags)
{
hio_t* hio = dev->hio;
hio_uint8_t* buf;
int x;
if (!is_sctp_sck(dev))
{
hio_seterrbfmt(hio, HIO_ENOIMPL, "not an sctp socket device");
return -1;
}
if (naddrs <= 0)
{
hio_seterrbfmt(hio, HIO_EINVAL, "no address given");
return -1;
}
if (pack_skads(hio, addrs, naddrs, &buf) <= -1) return -1;
x = sctp_bindx(dev->hnd, (struct sockaddr*)buf, (int)naddrs,
(flags == HIO_DEV_SCK_BINDX_REM)? SCTP_BINDX_REM_ADDR: SCTP_BINDX_ADD_ADDR);
if (x <= -1) hio_seterrwithsyserr(hio, 0, errno);
hio_freemem (hio, buf);
return (x <= -1)? -1: 0;
}
int hio_dev_sck_getladdrs (hio_dev_sck_t* dev, hio_skad_t* addrs, hio_oow_t* naddrs)
{
hio_t* hio = dev->hio;
struct sockaddr* packed = HIO_NULL;
int count, x;
if (!is_sctp_sck(dev))
{
hio_seterrbfmt(hio, HIO_ENOIMPL, "not an sctp socket device");
return -1;
}
/* association 0 asks about the endpoint, which is what local multi-homing
* is about - the addresses belong to the socket, not to one association. */
count = sctp_getladdrs(dev->hnd, 0, &packed);
if (count <= -1)
{
hio_seterrwithsyserr(hio, 0, errno);
return -1;
}
x = unpack_skads(hio, packed, count, addrs, naddrs);
sctp_freeladdrs(packed);
return x;
}
int hio_dev_sck_getpaddrs (hio_dev_sck_t* dev, hio_skad_t* addrs, hio_oow_t* naddrs)
{
hio_t* hio = dev->hio;
struct sockaddr* packed = HIO_NULL;
int count, x;
if (!is_sctp_sck(dev))
{
hio_seterrbfmt(hio, HIO_ENOIMPL, "not an sctp socket device");
return -1;
}
/* peer addresses belong to an association, and only a one-to-one socket has
* exactly one. that is what a peeled-off or connected device is; a
* one-to-many socket holds many and cannot answer the question. */
if (sck_type_map[dev->type].type == SOCK_SEQPACKET)
{
hio_seterrbfmt(hio, HIO_EPERM, "peer addresses are per-association - peel the association off first");
return -1;
}
count = sctp_getpaddrs(dev->hnd, 0, &packed);
if (count <= -1)
{
hio_seterrwithsyserr(hio, 0, errno);
return -1;
}
x = unpack_skads(hio, packed, count, addrs, naddrs);
sctp_freepaddrs(packed);
return x;
}
/* SCTP_PRIMARY_ADDR takes the same two members under two names: struct
* sctp_prim on linux, struct sctp_setprim on the bsds. */
#if defined(HAVE_STRUCT_SCTP_PRIM)
# define sctp_prim_t struct sctp_prim
#elif defined(HAVE_STRUCT_SCTP_SETPRIM)
# define sctp_prim_t struct sctp_setprim
#endif
int hio_dev_sck_setprimaryaddr (hio_dev_sck_t* dev, const hio_skad_t* addr)
{
hio_t* hio = dev->hio;
#if defined(sctp_prim_t)
sctp_prim_t prim;
int len;
if (!is_sctp_sck(dev))
{
hio_seterrbfmt(hio, HIO_ENOIMPL, "not an sctp socket device");
return -1;
}
len = hio_skad_get_size(addr);
if (len <= 0 || (hio_oow_t)len > HIO_SIZEOF(prim.ssp_addr))
{
hio_seterrbfmt(hio, HIO_EINVAL, "address is not of a supported family");
return -1;
}
HIO_MEMSET(&prim, 0, HIO_SIZEOF(prim));
prim.ssp_assoc_id = 0; /* the only association, on a one-to-one socket */
HIO_MEMCPY(&prim.ssp_addr, addr, len);
if (setsockopt(dev->hnd, IPPROTO_SCTP, SCTP_PRIMARY_ADDR, &prim, HIO_SIZEOF(prim)) <= -1)
{
hio_seterrwithsyserr(hio, 0, errno);
return -1;
}
return 0;
#else
hio_seterrbfmt(hio, HIO_ENOIMPL, "no structure for SCTP_PRIMARY_ADDR on this system");
return -1;
#endif
}
#else /* ENABLE_SCTP_MH */
/* the declarations are unconditional, so the symbols have to exist. they say
* so rather than being absent at link time. */
int hio_dev_sck_bindx (hio_dev_sck_t* dev, const hio_skad_t* addrs, hio_oow_t naddrs, hio_dev_sck_bindx_flag_t flags)
{
hio_seterrbfmt(dev->hio, HIO_ENOIMPL, "sctp multi-homing not supported");
return -1;
}
int hio_dev_sck_getladdrs (hio_dev_sck_t* dev, hio_skad_t* addrs, hio_oow_t* naddrs)
{
hio_seterrbfmt(dev->hio, HIO_ENOIMPL, "sctp multi-homing not supported");
return -1;
}
int hio_dev_sck_getpaddrs (hio_dev_sck_t* dev, hio_skad_t* addrs, hio_oow_t* naddrs)
{
hio_seterrbfmt(dev->hio, HIO_ENOIMPL, "sctp multi-homing not supported");
return -1;
}
int hio_dev_sck_setprimaryaddr (hio_dev_sck_t* dev, const hio_skad_t* addr)
{
hio_seterrbfmt(dev->hio, HIO_ENOIMPL, "sctp multi-homing not supported");
return -1;
}
#endif /* ENABLE_SCTP_MH */
int hio_dev_sck_sendfileok (hio_dev_sck_t* dev) int hio_dev_sck_sendfileok (hio_dev_sck_t* dev)
{ {
/* the transport has to actually implement it. the sctp methods deliberately /* the transport has to actually implement it. the sctp methods deliberately
+1 -1
View File
@@ -252,7 +252,7 @@ void hio_sys_intrmux (hio_t* hio)
{ {
/* for now, thie only use of the control pipe is to interrupt the multiplexer */ /* for now, thie only use of the control pipe is to interrupt the multiplexer */
hio_sys_mux_t* mux = &hio->sysdep->mux; hio_sys_mux_t* mux = &hio->sysdep->mux;
if (mux->ctrlp[1] != HIO_SYSHND_INVALID) write (mux->ctrlp[1], "Q", 1); if (mux->ctrlp[1] != HIO_SYSHND_INVALID) write(mux->ctrlp[1], "Q", 1);
} }
#if defined(USE_POLL) #if defined(USE_POLL)
+1 -1
View File
@@ -215,7 +215,7 @@ static int x_process_content (hio_tar_t* tar)
chunksize = tar->x.hi.filesize < tar->x.blk.len? tar->x.hi.filesize: tar->x.blk.len; chunksize = tar->x.hi.filesize < tar->x.blk.len? tar->x.hi.filesize: tar->x.blk.len;
/* TODO: error check */ /* TODO: error check */
fwrite (tar->x.blk.buf, 1, chunksize, tar->x.hi.fp); fwrite(tar->x.blk.buf, 1, chunksize, tar->x.hi.fp);
tar->x.hi.filesize -= chunksize; tar->x.hi.filesize -= chunksize;
if (tar->x.hi.filesize <= 0) if (tar->x.hi.filesize <= 0)
+11 -11
View File
@@ -89,14 +89,14 @@ static int ready_to_free_thr_info (hio_t* hio, hio_cfmb_t* cfmb)
if (HIO_UNLIKELY(hio->_fini_in_progress)) if (HIO_UNLIKELY(hio->_fini_in_progress))
{ {
pthread_join (ti->thr_hnd, HIO_NULL); /* BAD. blocking call in a non-blocking library. not useful to call pthread_tryjoin_np() here. */ pthread_join (ti->thr_hnd, HIO_NULL); /* BAD. blocking call in a non-blocking library. not useful to call pthread_tryjoin_np() here. */
free_thr_info_resources (hio, ti); free_thr_info_resources(hio, ti);
return 1; /* free me */ return 1; /* free me */
} }
#endif #endif
if (ti->thr_done) if (ti->thr_done)
{ {
free_thr_info_resources (hio, ti); free_thr_info_resources(hio, ti);
#if defined(HAVE_PTHREAD_TRYJOIN_NP) #if defined(HAVE_PTHREAD_TRYJOIN_NP)
if (pthread_tryjoin_np(ti->thr_hnd) != 0) /* not terminated yet - however, this isn't necessary. z*/ if (pthread_tryjoin_np(ti->thr_hnd) != 0) /* not terminated yet - however, this isn't necessary. z*/
#endif #endif
@@ -126,7 +126,7 @@ static void* run_thr_func (void* ctx)
ti->thr_func (ti->hio, &ti->thr_iop, ti->thr_ctx); ti->thr_func (ti->hio, &ti->thr_iop, ti->thr_ctx);
free_thr_info_resources (ti->hio, ti); free_thr_info_resources(ti->hio, ti);
pthread_cleanup_pop (1); pthread_cleanup_pop (1);
pthread_exit (HIO_NULL); pthread_exit (HIO_NULL);
@@ -301,7 +301,7 @@ static int dev_thr_kill_master (hio_dev_t* dev, int force)
* self-initiated termination or master-driven termination */ * self-initiated termination or master-driven termination */
rdev->slave[i] = HIO_NULL; rdev->slave[i] = HIO_NULL;
hio_dev_kill ((hio_dev_t*)sdev); hio_dev_kill((hio_dev_t*)sdev);
} }
} }
} }
@@ -310,7 +310,7 @@ static int dev_thr_kill_master (hio_dev_t* dev, int force)
if (ti->thr_done) if (ti->thr_done)
{ {
pthread_detach (ti->thr_hnd); /* pthread_join() may be blocking. detach the thread instead */ pthread_detach (ti->thr_hnd); /* pthread_join() may be blocking. detach the thread instead */
free_thr_info_resources (hio, ti); free_thr_info_resources(hio, ti);
hio_freemem(hio, ti); hio_freemem(hio, ti);
} }
else else
@@ -319,15 +319,15 @@ static int dev_thr_kill_master (hio_dev_t* dev, int force)
/* since pthread_join can be blocking, i'd schedule a resource destroyer with hio_addcfmb(). /* since pthread_join can be blocking, i'd schedule a resource destroyer with hio_addcfmb().
* see after #else */ * see after #else */
pthread_join (ti->thr_hnd, HIO_NULL); pthread_join (ti->thr_hnd, HIO_NULL);
free_thr_info_resources (hio, ti); free_thr_info_resources(hio, ti);
hio_freemem(hio, ti); hio_freemem(hio, ti);
#else #else
/* schedule a resource destroyer */ /* schedule a resource destroyer */
hio_addcfmb (hio, (hio_cfmb_t*)ti, ready_to_free_thr_info, HIO_NULL); hio_addcfmb(hio, (hio_cfmb_t*)ti, ready_to_free_thr_info, HIO_NULL);
#endif #endif
} }
if (rdev->on_close) rdev->on_close (rdev, HIO_DEV_THR_MASTER); if (rdev->on_close) rdev->on_close(rdev, HIO_DEV_THR_MASTER);
return 0; return 0;
} }
@@ -344,7 +344,7 @@ static int dev_thr_kill_slave (hio_dev_t* dev, int force)
rdev->master = HIO_NULL; rdev->master = HIO_NULL;
/* indicate EOF */ /* indicate EOF */
if (master->on_close) master->on_close (master, rdev->id); if (master->on_close) master->on_close(master, rdev->id);
HIO_ASSERT(hio, master->slave_count > 0); HIO_ASSERT(hio, master->slave_count > 0);
master->slave_count--; master->slave_count--;
@@ -355,7 +355,7 @@ static int dev_thr_kill_slave (hio_dev_t* dev, int force)
if (master->slave_count <= 0) if (master->slave_count <= 0)
{ {
/* if this is the last slave, kill the master also */ /* if this is the last slave, kill the master also */
hio_dev_kill ((hio_dev_t*)master); hio_dev_kill((hio_dev_t*)master);
/* the master pointer is not valid from this point onwards /* the master pointer is not valid from this point onwards
* as the actual master device object is freed in hio_dev_kill() */ * as the actual master device object is freed in hio_dev_kill() */
} }
@@ -530,7 +530,7 @@ static int dev_thr_ioctl (hio_dev_t* dev, int cmd, void* arg)
/* unlike dev_thr_kill_master(), i don't nullify rdev->slave[sid]. /* unlike dev_thr_kill_master(), i don't nullify rdev->slave[sid].
* so i treat the closing ioctl as if it's a kill request * so i treat the closing ioctl as if it's a kill request
* initiated by the slave device itself. */ * initiated by the slave device itself. */
hio_dev_kill ((hio_dev_t*)rdev->slave[sid]); hio_dev_kill((hio_dev_t*)rdev->slave[sid]);
/* if this is the last slave, the master is destroyed as well. /* if this is the last slave, the master is destroyed as well.
* therefore, using rdev is unsafe in the assertion below is unsafe. * therefore, using rdev is unsafe in the assertion below is unsafe.
+3 -3
View File
@@ -33,7 +33,7 @@
void hio_cleartmrjobs (hio_t* hio) void hio_cleartmrjobs (hio_t* hio)
{ {
while (hio->tmr.size > 0) hio_deltmrjob (hio, 0); while (hio->tmr.size > 0) hio_deltmrjob(hio, 0);
} }
static hio_tmridx_t sift_up (hio_t* hio, hio_tmridx_t index) static hio_tmridx_t sift_up (hio_t* hio, hio_tmridx_t index)
@@ -174,10 +174,10 @@ void hio_firetmrjobs (hio_t* hio, const hio_ntime_t* tm, hio_oow_t* firecnt)
if (HIO_CMP_NTIME(&hio->tmr.jobs[0].when, &now) > 0) break; if (HIO_CMP_NTIME(&hio->tmr.jobs[0].when, &now) > 0) break;
tmrjob = hio->tmr.jobs[0]; /* copy the scheduled job */ tmrjob = hio->tmr.jobs[0]; /* copy the scheduled job */
hio_deltmrjob (hio, 0); /* deschedule the job */ hio_deltmrjob(hio, 0); /* deschedule the job */
count++; count++;
tmrjob.handler (hio, &now, &tmrjob); /* then fire the job */ tmrjob.handler(hio, &now, &tmrjob); /* then fire the job */
} }
if (firecnt) *firecnt = count; if (firecnt) *firecnt = count;
+2
View File
@@ -588,6 +588,8 @@ PTHREAD_LIBS = @PTHREAD_LIBS@
QUADMATH_LIBS = @QUADMATH_LIBS@ QUADMATH_LIBS = @QUADMATH_LIBS@
RANLIB = @RANLIB@ RANLIB = @RANLIB@
SCTP_ENABLED = @SCTP_ENABLED@ SCTP_ENABLED = @SCTP_ENABLED@
SCTP_MULTIHOMING_ENABLED = @SCTP_MULTIHOMING_ENABLED@
SCTP_PEELOFF_ENABLED = @SCTP_PEELOFF_ENABLED@
SED = @SED@ SED = @SED@
SENDFILE_LIBS = @SENDFILE_LIBS@ SENDFILE_LIBS = @SENDFILE_LIBS@
SET_MAKE = @SET_MAKE@ SET_MAKE = @SET_MAKE@
+2 -2
View File
@@ -654,8 +654,8 @@ int main (int argc, char* argv[])
else if (strcmp(argv[i], "-ss") == 0) else if (strcmp(argv[i], "-ss") == 0)
{ {
i++; i++;
g_dev_type4 = HIO_DEV_SCK_SCTP4_SP; g_dev_type4 = HIO_DEV_SCK_SCTP4_SEQPKT;
g_dev_type6 = HIO_DEV_SCK_SCTP6_SP; g_dev_type6 = HIO_DEV_SCK_SCTP6_SEQPKT;
} }
else if (strcmp(argv[i], "-t") == 0) else if (strcmp(argv[i], "-t") == 0)
{ {
+1057 -2
View File
File diff suppressed because it is too large Load Diff