Compare commits
3
Commits
bdc03c3982
...
84eecea31c
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
84eecea31c | ||
|
|
b5fc81ef2d | ||
|
|
00d5056e60 |
+15
-4
@@ -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
@@ -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.
|
||||||
|
|||||||
@@ -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@
|
||||||
|
|||||||
@@ -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
|
fi
|
||||||
|
if ac_fn_c_try_link "$LINENO"
|
||||||
|
then :
|
||||||
|
ac_cv_search_sctp_bindx=$ac_res
|
||||||
|
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 "-------------------------------------------------------------------------"
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -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 "-------------------------------------------------------------------------"
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -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@
|
||||||
|
|||||||
@@ -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
@@ -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
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -408,10 +408,13 @@ static int dev_pro_make_master (hio_dev_t* dev, void* ctx)
|
|||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
oops:
|
oops:
|
||||||
|
if (minidx >= 0 && maxidx >= 0)
|
||||||
|
{
|
||||||
for (i = minidx; i <= maxidx; i++)
|
for (i = minidx; i <= maxidx; i++)
|
||||||
{
|
{
|
||||||
if (pfds[i] != HIO_SYSHND_INVALID) close(pfds[i]);
|
if (pfds[i] != HIO_SYSHND_INVALID) close(pfds[i]);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (rdev->mcmd)
|
if (rdev->mcmd)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -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 */
|
||||||
}
|
}
|
||||||
@@ -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.
|
||||||
*
|
*
|
||||||
@@ -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)
|
||||||
{
|
{
|
||||||
@@ -2371,7 +2417,7 @@ 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
|
||||||
|
|||||||
@@ -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
@@ -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)
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in New Issue
Block a user