aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--erts/configure.in46
-rw-r--r--erts/doc/src/erl.xml5
-rw-r--r--erts/doc/src/erl_dist_protocol.xml13
-rw-r--r--erts/doc/src/erl_ext_dist.xml492
-rw-r--r--erts/emulator/Makefile.in34
-rw-r--r--erts/emulator/beam/dist.c50
-rw-r--r--erts/emulator/beam/erl_alloc_util.h4
-rw-r--r--erts/emulator/beam/io.c63
-rw-r--r--erts/emulator/beam/time.c9
-rw-r--r--erts/emulator/nifs/common/net_nif.c30
-rw-r--r--erts/emulator/nifs/common/socket_int.h4
-rw-r--r--erts/emulator/nifs/common/socket_nif.c6011
-rw-r--r--erts/emulator/nifs/common/socket_util.c16
-rw-r--r--erts/emulator/nifs/common/socket_util.h18
-rw-r--r--erts/emulator/sys/common/erl_check_io.c1
-rw-r--r--erts/emulator/sys/common/erl_poll.c31
-rw-r--r--erts/emulator/test/driver_SUITE.erl78
-rw-r--r--erts/emulator/test/net_SUITE.erl17
-rw-r--r--erts/emulator/test/socket_SUITE.erl233
-rw-r--r--erts/emulator/test/socket_test_evaluator.erl165
-rw-r--r--erts/etc/common/erlexec.c15
-rw-r--r--erts/etc/unix/etp-commands.in60
-rw-r--r--erts/preloaded/ebin/erl_init.beambin1820 -> 2312 bytes
-rw-r--r--erts/preloaded/ebin/net.beambin5940 -> 6140 bytes
-rw-r--r--erts/preloaded/ebin/socket.beambin70312 -> 70300 bytes
-rw-r--r--erts/preloaded/src/Makefile21
-rw-r--r--erts/preloaded/src/erl_init.erl26
-rw-r--r--erts/preloaded/src/erts.app.src3
-rw-r--r--erts/preloaded/src/net.erl21
-rw-r--r--erts/preloaded/src/socket.erl209
-rw-r--r--lib/compiler/src/beam_ssa_pre_codegen.erl141
-rw-r--r--lib/compiler/test/bs_match_SUITE.erl35
-rw-r--r--lib/crypto/doc/src/crypto.xml56
-rw-r--r--lib/crypto/doc/src/new_api.xml89
-rw-r--r--lib/crypto/src/crypto.erl21
-rw-r--r--lib/erl_interface/doc/src/ei.xml60
-rw-r--r--lib/erl_interface/include/ei.h8
-rw-r--r--lib/erl_interface/src/decode/decode_binary.c61
-rw-r--r--lib/erl_interface/src/decode/decode_skip.c10
-rw-r--r--lib/erl_interface/src/encode/encode_binary.c101
-rw-r--r--lib/erl_interface/src/misc/ei_printterm.c14
-rw-r--r--lib/erl_interface/src/misc/ei_x_encode.c6
-rw-r--r--lib/erl_interface/src/misc/show_msg.c9
-rw-r--r--lib/erl_interface/test/ei_connect_SUITE_data/ei_connect_test.c7
-rw-r--r--lib/erl_interface/test/ei_decode_SUITE_data/ei_decode_test.c15
-rw-r--r--lib/erl_interface/test/ei_decode_encode_SUITE.erl20
-rw-r--r--lib/erl_interface/test/ei_decode_encode_SUITE_data/ei_decode_encode_test.c79
-rw-r--r--lib/kernel/src/erl_distribution.erl6
-rw-r--r--lib/kernel/src/user_drv.erl8
-rw-r--r--lib/kernel/test/erl_distribution_SUITE.erl8
-rw-r--r--lib/sasl/src/Makefile4
-rw-r--r--lib/sasl/src/systools_make.erl10
-rw-r--r--lib/ssh/doc/src/notes.xml22
-rw-r--r--lib/ssh/src/ssh.app.src10
-rw-r--r--lib/ssh/vsn.mk2
-rw-r--r--lib/ssl/doc/src/standards_compliance.xml15
-rw-r--r--lib/ssl/src/ssl_cipher.hrl4
-rw-r--r--lib/ssl/src/ssl_cipher_format.erl24
-rw-r--r--lib/ssl/src/tls_v1.erl8
-rw-r--r--lib/ssl/test/Makefile1
-rw-r--r--lib/ssl/test/openssl_server_cipher_suite_SUITE.erl768
-rw-r--r--lib/ssl/test/ssl_ECC_SUITE.erl59
-rw-r--r--lib/ssl/test/ssl_ECC_openssl_SUITE.erl96
-rw-r--r--lib/ssl/test/ssl_cipher_suite_SUITE.erl55
-rw-r--r--lib/ssl/test/ssl_test_lib.erl89
-rw-r--r--lib/stdlib/doc/src/gb_trees.xml7
-rw-r--r--lib/stdlib/doc/src/queue.xml2
-rw-r--r--lib/tools/doc/src/make.xml5
-rw-r--r--make/configure.in6
-rw-r--r--make/otp.mk.in4
-rw-r--r--otp_versions.table1
-rwxr-xr-xscripts/run-dialyzer50
72 files changed, 5884 insertions, 3787 deletions
diff --git a/erts/configure.in b/erts/configure.in
index 5f969a0a8b..506ce0d0fb 100644
--- a/erts/configure.in
+++ b/erts/configure.in
@@ -2,7 +2,7 @@ dnl Process this file with autoconf to produce a configure script. -*-m4-*-
dnl %CopyrightBegin%
dnl
-dnl Copyright Ericsson AB 1997-2018. All Rights Reserved.
+dnl Copyright Ericsson AB 1997-2019. All Rights Reserved.
dnl
dnl Licensed under the Apache License, Version 2.0 (the "License");
dnl you may not use this file except in compliance with the License.
@@ -590,6 +590,22 @@ AC_SUBST(WERRORFLAGS)
## Check if we can do profile guided optimization of beam_emu
LM_CHECK_ENABLE_CFLAG([-fprofile-generate -Werror],[PROFILE_GENERATE])
LM_CHECK_ENABLE_CFLAG([-fprofile-use -Werror],[PROFILE_USE])
+LM_CHECK_ENABLE_CFLAG([-fprofile-use -fprofile-correction -Werror],[PROFILE_CORRECTION])
+
+if test "X$PROFILE_CORRECTION" = "Xtrue"; then
+ saved_CFLAGS=$CFLAGS
+ saved_LDFLAGS=$LDFLAGS
+ CFLAGS="-fprofile-generate $saved_CFLAGS"
+ LDFLAGS="-fprofile-generate $saved_LDFLAGS"
+ AC_MSG_CHECKING([whether $CC links with -fprofile-generate])
+ AC_LINK_IFELSE([AC_LANG_PROGRAM([],[return 0;])],
+ [AC_MSG_RESULT([yes])
+ PROFILE_GENERATE=true],
+ [AC_MSG_RESULT([no])
+ PROFILE_GENERATE=false])
+ CFLAGS=$saved_CFLAGS
+ LDFLAGS=$saved_LDFLAGS
+fi
## Check if this is clang
LM_CHECK_ENABLE_CFLAG([-fprofile-instr-generate -Werror],[PROFILE_INSTR_GENERATE])
@@ -614,8 +630,8 @@ if test "X$PROFILE_INSTR_GENERATE" = "Xtrue"; then
if test "X$LLVM_PROFDATA" != "X"; then
CFLAGS="-fprofile-instr-use=default.profdata -Werror $saved_CFLAGS";
$LLVM_PROFDATA merge -output=default.profdata *.profraw;
- AC_MSG_CHECKING([whether gcc accepts -fprofile-instr-use=default.profdata -Werror])
- AC_COMPILE_IFELSE([],
+ AC_MSG_CHECKING([whether $CC accepts -fprofile-instr-use=default.profdata -Werror])
+ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([],[return 0;])],
[AC_MSG_RESULT([yes])
PROFILE_INSTR_USE=true],
[AC_MSG_RESULT([no])
@@ -637,8 +653,6 @@ AS_HELP_STRING([--enable-pgo],
esac
],enable_pgo=default)
-LM_CHECK_ENABLE_CFLAG([-fprofile-use -fprofile-correction -Werror],[PROFILE_CORRECTION])
-
USE_PGO=false
AC_MSG_CHECKING([whether to do PGO of erts])
if test $enable_pgo = no; then
@@ -1329,6 +1343,28 @@ LIBS=$zlib_save_LIBS
fi
AC_SUBST(Z_LIB)
+
+dnl -------------
+dnl esock
+dnl -------------
+
+AC_ARG_ENABLE(esock,
+AS_HELP_STRING([--enable-esock], [enable builtin experimental socket (as a nif) support (default)])
+AS_HELP_STRING([--disable-esock], [disable builtin experimental socket (as a nif) support]))
+
+dnl Default value
+USE_ESOCK=yes
+
+if test "x$enable_esock" = "xyes"; then
+ USE_ESOCK=yes
+else
+ if test "x$enable_esock" = "xno"; then
+ USE_ESOCK=no
+ fi
+fi
+AC_SUBST(USE_ESOCK)
+
+
dnl
dnl This test kindly borrowed from Tcl
dnl
diff --git a/erts/doc/src/erl.xml b/erts/doc/src/erl.xml
index 471d7caa5a..ed1b0880b4 100644
--- a/erts/doc/src/erl.xml
+++ b/erts/doc/src/erl.xml
@@ -460,7 +460,10 @@
<tag><c><![CDATA[-remsh Node]]></c></tag>
<item>
<p>Starts Erlang with a remote shell connected to
- <c><![CDATA[Node]]></c>.</p>
+ <c><![CDATA[Node]]></c>. Requires either <c><![CDATA[-name]]></c>
+ or <c><![CDATA[-sname]]></c> to be given. If <c><![CDATA[Node]]></c>
+ does not contain a hostname, one is automatically taken from
+ <c><![CDATA[-name]]></c> or <c><![CDATA[-sname]]></c></p>
</item>
<tag><c><![CDATA[-rsh Program]]></c></tag>
<item>
diff --git a/erts/doc/src/erl_dist_protocol.xml b/erts/doc/src/erl_dist_protocol.xml
index 185c75fe84..f924c8a70b 100644
--- a/erts/doc/src/erl_dist_protocol.xml
+++ b/erts/doc/src/erl_dist_protocol.xml
@@ -850,10 +850,15 @@ DiB == gen_digest(ChA, ICA)?
<tag><c>-define(DFLAG_EXIT_PAYLOAD, 16#400000).</c></tag>
<item>
<p>Use the <c>PAYLOAD_EXIT</c>, <c>PAYLOAD_EXIT_TT</c>,
- <c>PAYLOAD_EXIT2</c>, <c>PAYLOAD_EXIT2_TT</c>
- and <c>PAYLOAD_MONITOR_P_EXIT</c>
- <seealso marker="#control_message">control message</seealso>s
- instead of the non-PAYLOAD variants.</p>
+ <c>PAYLOAD_EXIT2</c>, <c>PAYLOAD_EXIT2_TT</c>
+ and <c>PAYLOAD_MONITOR_P_EXIT</c>
+ <seealso marker="#control_message">control message</seealso>s
+ instead of the non-PAYLOAD variants.</p>
+ </item>
+ <tag><c>-define(DFLAG_FRAGMENTS, 16#800000).</c></tag>
+ <item>
+ <p>Use <seealso marker="erl_ext_dist#fragments">fragmented</seealso>
+ distribution messages to send large messages.</p>
</item>
</taglist>
<p>
diff --git a/erts/doc/src/erl_ext_dist.xml b/erts/doc/src/erl_ext_dist.xml
index a6bc44b8c8..3730f0e8ac 100644
--- a/erts/doc/src/erl_ext_dist.xml
+++ b/erts/doc/src/erl_ext_dist.xml
@@ -140,162 +140,366 @@
<marker id="distribution_header"/>
<title>Distribution Header</title>
<p>
- The distribution header only contains an atom cache
- reference section, but can in the future contain more
- information. The distribution header precedes one or more Erlang
- terms on the external format. For more information, see the
- documentation of the
+ The distribution header is sent by the erlang distribution to
+ carry metadata about the coming
+ <seealso marker="erl_dist_protocol#control_message">control message</seealso>
+ and potential payload. It is primarily used to handle the atom cache
+ in the Erlang distribution. Since OTP-22 it is also used to fragment
+ large distribution messages into multiple smaller fragments.
+ For more information about how the distribution uses the distribution header,
+ see the documentation of the
<seealso marker="erl_dist_protocol#connected_nodes">protocol between
connected nodes</seealso> in the
<seealso marker="erl_dist_protocol">distribution protocol</seealso>
documentation.
</p>
<p>
- <seealso marker="#ATOM_CACHE_REF">ATOM_CACHE_REF</seealso>
+ Any <seealso marker="#ATOM_CACHE_REF">ATOM_CACHE_REF</seealso>
entries with corresponding <c>AtomCacheReferenceIndex</c> in terms
encoded on the external format following a distribution header refer
to the atom cache references made in the distribution header. The range
is 0 &lt;= <c>AtomCacheReferenceIndex</c> &lt; 255, that is, at most 255
different atom cache references from the following terms can be made.
</p>
- <p>
- The distribution header format is as follows:
- </p>
- <table align="left">
- <row>
- <cell align="center">1</cell>
- <cell align="center">1</cell>
- <cell align="center">1</cell>
- <cell align="center">NumberOfAtomCacheRefs/2+1 | 0</cell>
- <cell align="center">N | 0</cell>
- </row>
- <row>
- <cell align="center"><c>131</c></cell>
- <cell align="center"><c>68</c></cell>
- <cell align="center"><c>NumberOfAtomCacheRefs</c></cell>
- <cell align="center"><c>Flags</c></cell>
- <cell align="center"><c>AtomCacheRefs</c></cell>
- </row>
- <tcaption>Distribution Header Format</tcaption></table>
- <p>
- <c>Flags</c> consist of <c>NumberOfAtomCacheRefs/2+1</c> bytes,
- unless <c>NumberOfAtomCacheRefs</c> is <c>0</c>. If
- <c>NumberOfAtomCacheRefs</c> is <c>0</c>, <c>Flags</c> and
- <c>AtomCacheRefs</c> are omitted. Each atom cache reference has
- a half byte flag field. Flags corresponding to a specific
- <c>AtomCacheReferenceIndex</c> are located in flag byte number
- <c>AtomCacheReferenceIndex/2</c>. Flag byte 0 is the first byte
- after the <c>NumberOfAtomCacheRefs</c> byte. Flags for an even
- <c>AtomCacheReferenceIndex</c> are located in the least significant
- half byte and flags for an odd <c>AtomCacheReferenceIndex</c> are
- located in the most significant half byte.
- </p>
- <p>
- The flag field of an atom cache reference has the following
- format:
- </p>
- <table align="left">
- <row>
- <cell align="center">1 bit</cell>
- <cell align="center">3 bits</cell>
- </row>
- <row>
- <cell align="center"><c>NewCacheEntryFlag</c></cell>
- <cell align="center"><c>SegmentIndex</c></cell>
- </row>
- <tcaption></tcaption></table>
- <p>
- The most significant bit is the <c>NewCacheEntryFlag</c>. If set,
- the corresponding cache reference is new. The three least
- significant bits are the <c>SegmentIndex</c> of the corresponding
- atom cache entry. An atom cache consists of 8 segments, each of size
- 256, that is, an atom cache can contain 2048 entries.
- </p>
- <p>
- After flag fields for atom cache references, another half byte flag
- field is located with the following format:
- </p>
- <table align="left">
- <row>
- <cell align="center">3 bits</cell>
- <cell align="center">1 bit</cell>
- </row>
- <row>
- <cell align="center"><c>CurrentlyUnused</c></cell>
- <cell align="center"><c>LongAtoms</c></cell>
- </row>
- <tcaption></tcaption></table>
- <p>
- The least significant bit in that half byte is flag <c>LongAtoms</c>.
- If it is set, 2 bytes are used for atom lengths instead of
- 1 byte in the distribution header.
- </p>
- <p>
- After the <c>Flags</c> field follow the <c>AtomCacheRefs</c>. The
- first <c>AtomCacheRef</c> is the one corresponding to
- <c>AtomCacheReferenceIndex</c> 0. Higher indices follow
- in sequence up to index <c>NumberOfAtomCacheRefs - 1</c>.
- </p>
- <p>
- If the <c>NewCacheEntryFlag</c> for the next <c>AtomCacheRef</c> has
- been set, a <c>NewAtomCacheRef</c> on the following format follows:
- </p>
- <table align="left">
- <row>
- <cell align="center">1</cell>
- <cell align="center">1 | 2</cell>
- <cell align="center">Length</cell>
- </row>
- <row>
- <cell align="center"><c>InternalSegmentIndex</c></cell>
- <cell align="center"><c>Length</c></cell>
- <cell align="center"><c>AtomText</c></cell>
- </row>
- <tcaption></tcaption></table>
- <p>
- <c>InternalSegmentIndex</c> together with the <c>SegmentIndex</c>
- completely identify the location of an atom cache entry in the
- atom cache. <c>Length</c> is the number of bytes that <c>AtomText</c>
- consists of. Length is a 2 byte big-endian integer
- if flag <c>LongAtoms</c> has been set, otherwise a 1 byte
- integer. When distribution flag
- <seealso marker="erl_dist_protocol#dflags">
- <c>DFLAG_UTF8_ATOMS</c></seealso>
- has been exchanged between both nodes in the
- <seealso marker="erl_dist_protocol#distribution_handshake">
- distribution handshake</seealso>,
- characters in <c>AtomText</c> are encoded in UTF-8, otherwise
- in Latin-1. The following <c>CachedAtomRef</c>s with the same
- <c>SegmentIndex</c> and <c>InternalSegmentIndex</c> as this
- <c>NewAtomCacheRef</c> refer to this atom until a new
- <c>NewAtomCacheRef</c> with the same <c>SegmentIndex</c>
- and <c>InternalSegmentIndex</c> appear.
- </p>
- <p>
- For more information on encoding of atoms, see the
- <seealso marker="#utf8_atoms">note on UTF-8 encoded atoms</seealso>
- in the beginning of this section.
- </p>
- <p>
- If the <c>NewCacheEntryFlag</c> for the next <c>AtomCacheRef</c>
- has not been set, a <c>CachedAtomRef</c> on the following format
- follows:
- </p>
- <table align="left">
- <row>
- <cell align="center">1</cell>
- </row>
- <row>
- <cell align="center"><c>InternalSegmentIndex</c></cell>
- </row>
- <tcaption></tcaption></table>
- <p>
- <c>InternalSegmentIndex</c> together with the <c>SegmentIndex</c>
- identify the location of the atom cache entry in the atom cache.
- The atom corresponding to this <c>CachedAtomRef</c> is the
- latest <c>NewAtomCacheRef</c> preceding this <c>CachedAtomRef</c>
- in another previously passed distribution header.
- </p>
+ <section>
+ <title>Normal Distribution Header</title>
+ <p>
+ The non-fragmented distribution header format is as follows:
+ </p>
+ <table align="left">
+ <row>
+ <cell align="center">1</cell>
+ <cell align="center">1</cell>
+ <cell align="center">1</cell>
+ <cell align="center">NumberOfAtomCacheRefs/2+1 | 0</cell>
+ <cell align="center">N | 0</cell>
+ </row>
+ <row>
+ <cell align="center"><c>131</c></cell>
+ <cell align="center"><c>68</c></cell>
+ <cell align="center"><c>NumberOfAtomCacheRefs</c></cell>
+ <cell align="center"><c>Flags</c></cell>
+ <cell align="center"><c>AtomCacheRefs</c></cell>
+ </row>
+ <tcaption>Normal Distribution Header Format</tcaption></table>
+ <p>
+ <c>Flags</c> consist of <c>NumberOfAtomCacheRefs/2+1</c> bytes,
+ unless <c>NumberOfAtomCacheRefs</c> is <c>0</c>. If
+ <c>NumberOfAtomCacheRefs</c> is <c>0</c>, <c>Flags</c> and
+ <c>AtomCacheRefs</c> are omitted. Each atom cache reference has
+ a half byte flag field. Flags corresponding to a specific
+ <c>AtomCacheReferenceIndex</c> are located in flag byte number
+ <c>AtomCacheReferenceIndex/2</c>. Flag byte 0 is the first byte
+ after the <c>NumberOfAtomCacheRefs</c> byte. Flags for an even
+ <c>AtomCacheReferenceIndex</c> are located in the least significant
+ half byte and flags for an odd <c>AtomCacheReferenceIndex</c> are
+ located in the most significant half byte.
+ </p>
+ <p>
+ The flag field of an atom cache reference has the following
+ format:
+ </p>
+ <table align="left">
+ <row>
+ <cell align="center">1 bit</cell>
+ <cell align="center">3 bits</cell>
+ </row>
+ <row>
+ <cell align="center"><c>NewCacheEntryFlag</c></cell>
+ <cell align="center"><c>SegmentIndex</c></cell>
+ </row>
+ <tcaption></tcaption></table>
+ <p>
+ The most significant bit is the <c>NewCacheEntryFlag</c>. If set,
+ the corresponding cache reference is new. The three least
+ significant bits are the <c>SegmentIndex</c> of the corresponding
+ atom cache entry. An atom cache consists of 8 segments, each of size
+ 256, that is, an atom cache can contain 2048 entries.
+ </p>
+ <p>
+ After flag fields for atom cache references, another half byte flag
+ field is located with the following format:
+ </p>
+ <table align="left">
+ <row>
+ <cell align="center">3 bits</cell>
+ <cell align="center">1 bit</cell>
+ </row>
+ <row>
+ <cell align="center"><c>CurrentlyUnused</c></cell>
+ <cell align="center"><c>LongAtoms</c></cell>
+ </row>
+ <tcaption></tcaption></table>
+ <p>
+ The least significant bit in that half byte is flag <c>LongAtoms</c>.
+ If it is set, 2 bytes are used for atom lengths instead of
+ 1 byte in the distribution header.
+ </p>
+ <p>
+ After the <c>Flags</c> field follow the <c>AtomCacheRefs</c>. The
+ first <c>AtomCacheRef</c> is the one corresponding to
+ <c>AtomCacheReferenceIndex</c> 0. Higher indices follow
+ in sequence up to index <c>NumberOfAtomCacheRefs - 1</c>.
+ </p>
+ <p>
+ If the <c>NewCacheEntryFlag</c> for the next <c>AtomCacheRef</c> has
+ been set, a <c>NewAtomCacheRef</c> on the following format follows:
+ </p>
+ <table align="left">
+ <row>
+ <cell align="center">1</cell>
+ <cell align="center">1 | 2</cell>
+ <cell align="center">Length</cell>
+ </row>
+ <row>
+ <cell align="center"><c>InternalSegmentIndex</c></cell>
+ <cell align="center"><c>Length</c></cell>
+ <cell align="center"><c>AtomText</c></cell>
+ </row>
+ <tcaption></tcaption></table>
+ <p>
+ <c>InternalSegmentIndex</c> together with the <c>SegmentIndex</c>
+ completely identify the location of an atom cache entry in the
+ atom cache. <c>Length</c> is the number of bytes that <c>AtomText</c>
+ consists of. Length is a 2 byte big-endian integer
+ if flag <c>LongAtoms</c> has been set, otherwise a 1 byte
+ integer. When distribution flag
+ <seealso marker="erl_dist_protocol#dflags">
+ <c>DFLAG_UTF8_ATOMS</c></seealso>
+ has been exchanged between both nodes in the
+ <seealso marker="erl_dist_protocol#distribution_handshake">
+ distribution handshake</seealso>,
+ characters in <c>AtomText</c> are encoded in UTF-8, otherwise
+ in Latin-1. The following <c>CachedAtomRef</c>s with the same
+ <c>SegmentIndex</c> and <c>InternalSegmentIndex</c> as this
+ <c>NewAtomCacheRef</c> refer to this atom until a new
+ <c>NewAtomCacheRef</c> with the same <c>SegmentIndex</c>
+ and <c>InternalSegmentIndex</c> appear.
+ </p>
+ <p>
+ For more information on encoding of atoms, see the
+ <seealso marker="#utf8_atoms">note on UTF-8 encoded atoms</seealso>
+ in the beginning of this section.
+ </p>
+ <p>
+ If the <c>NewCacheEntryFlag</c> for the next <c>AtomCacheRef</c>
+ has not been set, a <c>CachedAtomRef</c> on the following format
+ follows:
+ </p>
+ <table align="left">
+ <row>
+ <cell align="center">1</cell>
+ </row>
+ <row>
+ <cell align="center"><c>InternalSegmentIndex</c></cell>
+ </row>
+ <tcaption></tcaption></table>
+ <p>
+ <c>InternalSegmentIndex</c> together with the <c>SegmentIndex</c>
+ identify the location of the atom cache entry in the atom cache.
+ The atom corresponding to this <c>CachedAtomRef</c> is the
+ latest <c>NewAtomCacheRef</c> preceding this <c>CachedAtomRef</c>
+ in another previously passed distribution header.
+ </p>
+ </section>
+ <section>
+ <marker id="fragments"/>
+ <title>Distribution Header for fragmented messages</title>
+ <p>Messages sent between Erlang nodes can sometimes be
+ quite large. Since OTP-22 it is possible to split large messages
+ into smaller fragments in order to allow smaller messages to be interleaved
+ between larges messages. It is only the <c>message</c> part of each
+ <seealso marker="erl_dist_protocol#connected_nodes">distributed message</seealso>
+ that may be split using fragmentation. Therefore it is recommended to use the
+ <seealso marker="erl_dist_protocol#new-ctrlmessages-for-erlang-otp-22">
+ PAYLOAD control messages</seealso> introduced in OTP-22.
+ </p>
+ <p>Fragmented distribution messages are only used if the receiving node
+ signals that it supports them via the
+ <seealso marker="erl_dist_protocol#dflags">DFLAG_FRAGMENTS</seealso> distribution
+ flag.</p>
+ <p>A process must complete the sending of a fragmented message before it
+ can start sending any other message on the same distribution channel.</p>
+
+ <p>The start of a sequence of fragmented messages looks like this:</p>
+ <table align="left">
+ <row>
+ <cell align="center">1</cell>
+ <cell align="center">1</cell>
+ <cell align="center">8</cell>
+ <cell align="center">8</cell>
+ <cell align="center">1</cell>
+ <cell align="center">NumberOfAtomCacheRefs/2+1 | 0</cell>
+ <cell align="center">N | 0</cell>
+ </row>
+ <row>
+ <cell align="center"><c>131</c></cell>
+ <cell align="center"><c>69</c></cell>
+ <cell align="center"><c>SequenceId</c></cell>
+ <cell align="center"><c>FragmentId</c></cell>
+ <cell align="center"><c>NumberOfAtomCacheRefs</c></cell>
+ <cell align="center"><c>Flags</c></cell>
+ <cell align="center"><c>AtomCacheRefs</c></cell>
+ </row>
+ <tcaption>Starting Fragmented Distribution Header Format</tcaption>
+ </table>
+
+ <p>The continuation of a sequence of fragmented messages looks like this:</p>
+ <table align="left">
+ <row>
+ <cell align="center">1</cell>
+ <cell align="center">1</cell>
+ <cell align="center">8</cell>
+ <cell align="center">8</cell>
+ </row>
+ <row>
+ <cell align="center"><c>131</c></cell>
+ <cell align="center"><c>70</c></cell>
+ <cell align="center"><c>SequenceId</c></cell>
+ <cell align="center"><c>FragmentId</c></cell>
+ </row>
+ <tcaption>Continuing Fragmented Distribution Header Format</tcaption>
+ </table>
+
+ <p>
+ The starting distribution header is very similar to a non-fragmented distribution
+ header. The atom cache works the same as for normal distribution header and
+ is the same for the entire sequence. The additional fields added are the
+ sequence id and fragment id.
+ </p>
+
+ <taglist>
+ <tag>Sequence ID</tag>
+ <item>
+ <p>
+ The sequence id is used to uniquely identify a fragmented message sent
+ from one process to another on the same distributed connection. This is used
+ to identify which sequence a fragment is a part of as the same process can
+ be in the process of receiving multiple sequences at the same time.
+ </p>
+ <p>
+ As one process can only be sending one fragmented message at once,
+ it can be convenient to use the local PID as the sequence id.
+ </p>
+ </item>
+ <tag>Fragments ID</tag>
+ <item>
+ <p>
+ The Fragment ID is used to number the fragments in a sequence.
+ The id starts at the total number of fragments and then decrements to 1
+ (which is the final fragment). So if a sequence consists of 3 fragments
+ the fragment id in the starting header will be 3, and then fragments 2 and 1
+ are sent.
+ </p>
+ <p>
+ The fragments must be delivered in the correct order, so if an unordered
+ distribution carrier is used, they must be ordered before delivered to the
+ Erlang run-time.
+ </p>
+ </item>
+ </taglist>
+
+ <section>
+ <title>Example:</title>
+ <p>
+ As an example, let say that we want to send
+ <c>{call, &lt;0.245.2>, {set_get_state, &lt;&lt;0:1024>>}}</c> to
+ registered process <c>reg</c> using a fragment size of 128. To send
+ this message we need a distribution header, atom cache updates,
+ the control message (which would be <c>{6, &lt;0.245.2>, [], reg}</c> in this case)
+ and finally the actual message. This would all be encoded into:
+ </p>
+
+ <code>
+131,69,0,0,2,168,0,0,5,83,0,0,0,0,0,0,0,2, %% Header with seq and frag id
+5,4,137,9,10,5,236,3,114,101,103,9,4,99,97,108,108, %% Atom cache updates
+238,13,115,101,116,95,103,101,116,95,115,116,97,116,101,
+104,4,97,6,103,82,0,0,0,0,85,0,0,0,0,2,82,1,82,2, %% Control message
+104,3,82,3,103,82,0,0,0,0,245,0,0,0,2,2, %% Actual message using cached atoms
+104,2,82,4,109,0,0,0,128,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
+
+131,70,0,0,2,168,0,0,5,83,0,0,0,0,0,0,0,1, %% Cont Header with seq and frag id
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, %% Rest of payload
+0,0,0,0</code>
+
+ <p>
+ Let us break that apart into its components. First we have the
+ distribution header tags together with the sequence id and
+ a fragment id of 2.
+ </p>
+ <code>
+131,69, %% Start fragment header
+0,0,2,168,0,0,5,83, %% The sequence ID
+0,0,0,0,0,0,0,2, %% The fragment ID
+</code>
+ <p>Then we have the updates to the atom cache:</p>
+ <code>
+5,4,137,9, %% 5 atoms and their flags
+10,5, %% The already cached atom ids
+236,3,114,101,103, %% The atom 'reg'
+9,4,99,97,108,108, %% The atom 'call'
+238,13,115,101,116,95,103,101,116,95,115,116,97,116,101, %% The atom 'set_get_state'
+ </code>
+ <p>
+ The first byte says that we have 5 atoms that are part
+ of the cache. Then follows three bytes that are the
+ atom cache ref flags. Each of the flags uses 4 bits so
+ they are a bit hard to read in decimal byte form. In
+ binary half-byte form they look like this:
+ </p>
+ <code>0000, 0100, 1000, 1001, 1001</code>
+ <p>
+ As the high bit of the first two atoms in the
+ cache are not set we know that they are already in the cache,
+ so they do not have to be sent again (this is the node name of the
+ receiving and sending node). Then follows the atoms that have to be sent,
+ together with their segment ids.
+ </p>
+ <p>
+ Then the listing of the atoms comes, starting with 10 and 5
+ which are the atom refs of the already cached atoms. Then the
+ new atoms are sent.
+ </p>
+ <p>
+ When the atom cache is setup correctly the control message is sent.
+ </p>
+ <code>104,4,97,6,103,82,0,0,0,0,85,0,0,0,0,2,82,1,82,2,</code>
+ <p>
+ Note that up until here it is not allowed to fragments the message.
+ The entire atom cache and control message has to be part of the
+ starting fragment. After the control message the payload of the message
+ is sent using 128 bytes:
+ </p>
+ <code>
+104,3,82,3,103,82,0,0,0,0,245,0,0,0,2,2,
+104,2,82,4,109,0,0,0,128,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
+ </code>
+ <p>
+ Since the payload is larger than 128-bytes it is split into two
+ fragments. The second fragment does not have any atom cache update
+ instructions so it is a lot simpler:
+ </p>
+ <code>
+131,70,0,0,2,168,0,0,5,83,0,0,0,0,0,0,0,1, %% Continuation dist header 70 with seq and frag id
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, %% remaining payload
+0,0,0,0
+ </code>
+ <note>
+ <p>
+ The fragment size of 128 is only used as an example.
+ Any fragments size may be used when sending fragmented messages.
+ </p>
+ </note>
+ </section>
+ </section>
</section>
<section>
diff --git a/erts/emulator/Makefile.in b/erts/emulator/Makefile.in
index 448f41b523..a9f3bb8e89 100644
--- a/erts/emulator/Makefile.in
+++ b/erts/emulator/Makefile.in
@@ -633,6 +633,15 @@ GENERATE += $(TTF_DIR)/driver_tab.c
# This list must be consistent with PRE_LOADED_MODULES in
# erts/preloaded/src/Makefile.
+ifeq ($(USE_ESOCK), yes)
+ESOCK_PRELOAD_BEAM = \
+ $(ERL_TOP)/erts/preloaded/ebin/socket.beam \
+ $(ERL_TOP)/erts/preloaded/ebin/net.beam
+else
+ESOCK_PRELOAD_BEAM = \
+ $(ERL_TOP)/erts/preloaded/ebin/net.beam
+endif
+
PRELOAD_BEAM = $(ERL_TOP)/erts/preloaded/ebin/erts_code_purger.beam \
$(ERL_TOP)/erts/preloaded/ebin/erl_init.beam \
$(ERL_TOP)/erts/preloaded/ebin/init.beam \
@@ -641,8 +650,7 @@ PRELOAD_BEAM = $(ERL_TOP)/erts/preloaded/ebin/erts_code_purger.beam \
$(ERL_TOP)/erts/preloaded/ebin/prim_inet.beam \
$(ERL_TOP)/erts/preloaded/ebin/prim_file.beam \
$(ERL_TOP)/erts/preloaded/ebin/zlib.beam \
- $(ERL_TOP)/erts/preloaded/ebin/socket.beam \
- $(ERL_TOP)/erts/preloaded/ebin/net.beam \
+ $(ESOCK_PRELOAD_BEAM) \
$(ERL_TOP)/erts/preloaded/ebin/prim_zip.beam \
$(ERL_TOP)/erts/preloaded/ebin/erl_prim_loader.beam \
$(ERL_TOP)/erts/preloaded/ebin/erlang.beam \
@@ -835,6 +843,15 @@ EMU_OBJS = \
$(OBJDIR)/beam_catches.o $(OBJDIR)/code_ix.o \
$(OBJDIR)/beam_ranges.o
+
+ifeq ($(USE_ESOCK), yes)
+
+# WE ARE USING ESOCK
+
+ESOCK_NIF_OBJS = \
+ $(OBJDIR)/socket_nif.o \
+ $(OBJDIR)/net_nif.o
+
ifneq ($(TARGET), win32)
# These are *currently* only needed for non-win32,
# since the nif-functions for socket and net are basically
@@ -847,6 +864,16 @@ else
ESOCK_RUN_OBJS =
endif
+else
+
+# WE ARE *NOT* USING ESOCK
+
+ESOCK_NIF_OBJS =
+ESOCK_RUN_OBJS =
+
+endif
+
+
RUN_OBJS += \
$(OBJDIR)/erl_alloc.o $(OBJDIR)/erl_mtrace.o \
$(OBJDIR)/erl_alloc_util.o $(OBJDIR)/erl_goodfit_alloc.o \
@@ -903,8 +930,7 @@ NIF_OBJS = \
$(OBJDIR)/prim_buffer_nif.o \
$(OBJDIR)/prim_file_nif.o \
$(OBJDIR)/zlib_nif.o \
- $(OBJDIR)/socket_nif.o \
- $(OBJDIR)/net_nif.o
+ $(ESOCK_NIF_OBJS)
ifeq ($(TARGET),win32)
DRV_OBJS = \
diff --git a/erts/emulator/beam/dist.c b/erts/emulator/beam/dist.c
index 27599f38e0..ff19ef018e 100644
--- a/erts/emulator/beam/dist.c
+++ b/erts/emulator/beam/dist.c
@@ -55,7 +55,6 @@
*/
#if 0
#define ERTS_DIST_MSG_DBG
-FILE *dbg_file;
#endif
#if 0
/* Enable this to print the dist debug messages to a file instead */
@@ -67,6 +66,7 @@ FILE *dbg_file;
#endif
#if defined(ERTS_DIST_MSG_DBG) || defined(ERTS_RAW_DIST_MSG_DBG)
+FILE *dbg_file;
static void bw(byte *buf, ErlDrvSizeT sz)
{
bin_write(ERTS_PRINT_FILE, dbg_file, buf, sz);
@@ -743,7 +743,7 @@ void init_dist(void)
sprintf(buff, ERTS_DIST_MSG_DBG_FILE, getpid());
dbg_file = fopen(buff,"w+");
}
-#elif defined (ERTS_DIST_MSG_DBG)
+#elif defined(ERTS_DIST_MSG_DBG) || defined(ERTS_RAW_DIST_MSG_DBG)
dbg_file = stderr;
#endif
@@ -1844,7 +1844,7 @@ int erts_net_message(Port *prt,
if (locks)
erts_proc_unlock(rp, locks);
- } else if (ede_hfrag) {
+ } else if (ede_hfrag != NULL) {
erts_free_dist_ext_copy(erts_get_dist_ext(ede_hfrag));
free_message_buffer(ede_hfrag);
}
@@ -1886,16 +1886,18 @@ int erts_net_message(Port *prt,
goto invalid_message;
}
rp = erts_proc_lookup(to);
+
if (rp) {
ErtsProcLocks locks = 0;
erts_queue_dist_message(rp, locks, edep, ede_hfrag, token, am_Empty);
if (locks)
erts_proc_unlock(rp, locks);
- } else if (ede_hfrag) {
+ } else if (ede_hfrag != NULL) {
erts_free_dist_ext_copy(erts_get_dist_ext(ede_hfrag));
free_message_buffer(ede_hfrag);
}
+
break;
}
@@ -1936,15 +1938,19 @@ int erts_net_message(Port *prt,
goto invalid_message;
}
- if (!erts_proc_lookup(watcher)) break; /* Process not alive */
-
- if (reason == THE_NON_VALUE) {
+ if (!erts_proc_lookup(watcher)) {
+ if (ede_hfrag != NULL) {
+ erts_free_dist_ext_copy(erts_get_dist_ext(ede_hfrag));
+ free_message_buffer(ede_hfrag);
+ }
+ break; /* Process not alive */
+ }
#ifdef ERTS_DIST_MSG_DBG
+ if (reason == THE_NON_VALUE) {
dist_msg_dbg(edep, "MSG", buf, orig_len);
-#endif
-
}
+#endif
erts_proc_sig_send_dist_monitor_down(
dep, ref, watched, watcher, edep, ede_hfrag, reason);
@@ -1993,13 +1999,19 @@ int erts_net_message(Port *prt,
goto invalid_message;
}
- if (!erts_proc_lookup(to)) break; /* Process not alive */
+ if (!erts_proc_lookup(to)) {
+ if (ede_hfrag != NULL) {
+ erts_free_dist_ext_copy(erts_get_dist_ext(ede_hfrag));
+ free_message_buffer(ede_hfrag);
+ }
+ break; /* Process not alive */
+ }
- if (reason == THE_NON_VALUE) {
#ifdef ERTS_DIST_MSG_DBG
+ if (reason == THE_NON_VALUE) {
dist_msg_dbg(edep, "MSG", buf, orig_len);
-#endif
}
+#endif
erts_proc_sig_send_dist_link_exit(dep,
from, to, edep, ede_hfrag,
@@ -2048,13 +2060,19 @@ int erts_net_message(Port *prt,
goto invalid_message;
}
- if (!erts_proc_lookup(to)) break; /* Process not alive */
+ if (!erts_proc_lookup(to)) {
+ if (ede_hfrag != NULL) {
+ erts_free_dist_ext_copy(erts_get_dist_ext(ede_hfrag));
+ free_message_buffer(ede_hfrag);
+ }
+ break; /* Process not alive */
+ }
- if (reason == THE_NON_VALUE) {
#ifdef ERTS_DIST_MSG_DBG
+ if (reason == THE_NON_VALUE) {
dist_msg_dbg(edep, "MSG", buf, orig_len);
-#endif
}
+#endif
erts_proc_sig_send_dist_exit(dep, from, to, edep, ede_hfrag, reason, token);
break;
@@ -3455,6 +3473,8 @@ dist_ctrl_get_data_1(BIF_ALIST_1)
obufsize -= size_obuf(obuf);
if (reds < 0) {
erts_de_runlock(dep);
+ if (obufsize)
+ erts_atomic_add_nob(&dep->qsize, (erts_aint_t) -obufsize);
ERTS_BIF_YIELD1(bif_export[BIF_dist_ctrl_get_data_1],
BIF_P, BIF_ARG_1);
}
diff --git a/erts/emulator/beam/erl_alloc_util.h b/erts/emulator/beam/erl_alloc_util.h
index b34916271e..b46b311c59 100644
--- a/erts/emulator/beam/erl_alloc_util.h
+++ b/erts/emulator/beam/erl_alloc_util.h
@@ -336,7 +336,9 @@ void erts_alcu_sched_spec_data_init(struct ErtsSchedulerData_ *esdp);
#if MBC_ABLK_OFFSET_BITS
/* The shift is reduced by 1 since the highest bit is used for a flag. */
# define MBC_ABLK_OFFSET_SHIFT (sizeof(UWord)*8 - 1 - MBC_ABLK_OFFSET_BITS)
-# define MBC_ABLK_OFFSET_MASK (((1ul << MBC_ABLK_OFFSET_BITS) - 1ul) << MBC_ABLK_OFFSET_SHIFT)
+# define MBC_ABLK_OFFSET_MASK \
+ (((UWORD_CONSTANT(1) << MBC_ABLK_OFFSET_BITS) - UWORD_CONSTANT(1)) \
+ << MBC_ABLK_OFFSET_SHIFT)
# define MBC_ABLK_SZ_MASK (~MBC_ABLK_OFFSET_MASK & ~BLK_FLG_MASK)
#else
# define MBC_ABLK_SZ_MASK (~BLK_FLG_MASK)
diff --git a/erts/emulator/beam/io.c b/erts/emulator/beam/io.c
index 31c941337f..45fef0c0e5 100644
--- a/erts/emulator/beam/io.c
+++ b/erts/emulator/beam/io.c
@@ -5298,44 +5298,31 @@ erts_get_port_names(Eterm id, ErlDrvPort drv_port)
pnp->driver_name = NULL;
}
else {
- int do_realloc = 1;
- int len = -1;
- size_t pnp_len = sizeof(ErtsPortNames);
-#ifndef DEBUG
- pnp_len += 100; /* In most cases 100 characters will be enough... */
- ASSERT(prt->common.id == id);
-#endif
- pnp = erts_alloc(ERTS_ALC_T_PORT_NAMES, pnp_len);
- do {
- int nlen;
- char *name, *driver_name;
- if (len > 0) {
- erts_free(ERTS_ALC_T_PORT_NAMES, pnp);
- pnp_len = sizeof(ErtsPortNames) + len;
- pnp = erts_alloc(ERTS_ALC_T_PORT_NAMES, pnp_len);
- }
- name = prt->name;
- len = nlen = name ? sys_strlen(name) + 1 : 0;
- driver_name = (prt->drv_ptr ? prt->drv_ptr->name : NULL);
- len += driver_name ? sys_strlen(driver_name) + 1 : 0;
- if (len <= pnp_len - sizeof(ErtsPortNames)) {
- if (!name)
- pnp->name = NULL;
- else {
- pnp->name = ((char *) pnp) + sizeof(ErtsPortNames);
- sys_strcpy(pnp->name, name);
- }
- if (!driver_name)
- pnp->driver_name = NULL;
- else {
- pnp->driver_name = (((char *) pnp)
- + sizeof(ErtsPortNames)
- + nlen);
- sys_strcpy(pnp->driver_name, driver_name);
- }
- do_realloc = 0;
- }
- } while (do_realloc);
+ int len;
+ int nlen;
+ char *driver_name;
+
+ len = nlen = prt->name ? sys_strlen(prt->name) + 1 : 0;
+ driver_name = (prt->drv_ptr ? prt->drv_ptr->name : NULL);
+ len += driver_name ? sys_strlen(driver_name) + 1 : 0;
+
+ pnp = erts_alloc(ERTS_ALC_T_PORT_NAMES,
+ sizeof(ErtsPortNames) + len);
+
+ if (!prt->name)
+ pnp->name = NULL;
+ else {
+ pnp->name = ((char *) pnp) + sizeof(ErtsPortNames);
+ sys_strcpy(pnp->name, prt->name);
+ }
+ if (!driver_name)
+ pnp->driver_name = NULL;
+ else {
+ pnp->driver_name = (((char *) pnp)
+ + sizeof(ErtsPortNames)
+ + nlen);
+ sys_strcpy(pnp->driver_name, driver_name);
+ }
}
return pnp;
}
diff --git a/erts/emulator/beam/time.c b/erts/emulator/beam/time.c
index a3069e419a..9eb020d070 100644
--- a/erts/emulator/beam/time.c
+++ b/erts/emulator/beam/time.c
@@ -316,7 +316,7 @@ struct ErtsTimerWheel_ {
#define ERTS_TW_SLOT_AT_ONCE (-1)
#define ERTS_TW_BUMP_LATER_WHEEL(TIW) \
- ((tiw)->pos + ERTS_TW_LATER_WHEEL_SLOT_SIZE >= (TIW)->later.pos)
+ ((TIW)->pos + ERTS_TW_LATER_WHEEL_SLOT_SIZE >= (TIW)->later.pos)
static int bump_later_wheel(ErtsTimerWheel *tiw, int *yield_count_p);
@@ -701,7 +701,8 @@ remove_timer(ErtsTimerWheel *tiw, ErtsTWheelTimer *p)
if (slot < ERTS_TW_SOON_WHEEL_END_SLOT) {
if (empty_slot
&& tiw->true_next_timeout_time
- && p->timeout_pos == tiw->next_timeout_pos) {
+ && p->timeout_pos == tiw->next_timeout_pos
+ && tiw->yield_slot == ERTS_TW_SLOT_INACTIVE) {
tiw->true_next_timeout_time = 0;
}
if (--tiw->soon.nto == 0)
@@ -714,7 +715,8 @@ remove_timer(ErtsTimerWheel *tiw, ErtsTWheelTimer *p)
ErtsMonotonicTime tpos = tiw->later.min_tpos;
tpos &= ERTS_TW_LATER_WHEEL_POS_MASK;
tpos -= ERTS_TW_LATER_WHEEL_SLOT_SIZE;
- if (tpos == tiw->next_timeout_pos)
+ if (tpos == tiw->next_timeout_pos
+ && tiw->yield_slot == ERTS_TW_SLOT_INACTIVE)
tiw->true_next_timeout_time = 0;
}
if (--tiw->later.nto == 0) {
@@ -908,7 +910,6 @@ erts_bump_timers(ErtsTimerWheel *tiw, ErtsMonotonicTime curr_time)
{
ErtsMonotonicTime tmp_slots = bump_to - tiw->pos;
- tmp_slots = (bump_to - tiw->pos);
if (tmp_slots < ERTS_TW_SOON_WHEEL_SIZE)
slots = (int) tmp_slots;
else
diff --git a/erts/emulator/nifs/common/net_nif.c b/erts/emulator/nifs/common/net_nif.c
index 252aa3c835..8a69052935 100644
--- a/erts/emulator/nifs/common/net_nif.c
+++ b/erts/emulator/nifs/common/net_nif.c
@@ -274,10 +274,10 @@ ENET_NIF_FUNCS
static ERL_NIF_TERM ncommand(ErlNifEnv* env,
ERL_NIF_TERM cmd);
static ERL_NIF_TERM ngethostname(ErlNifEnv* env);
-static ERL_NIF_TERM ngetnameinfo(ErlNifEnv* env,
- const SocketAddress* saP,
- SOCKLEN_T saLen,
- int flags);
+static ERL_NIF_TERM ngetnameinfo(ErlNifEnv* env,
+ const ESockAddress* saP,
+ SOCKLEN_T saLen,
+ int flags);
static ERL_NIF_TERM ngetaddrinfo(ErlNifEnv* env,
char* host,
char* serv);
@@ -627,12 +627,12 @@ ERL_NIF_TERM nif_getnameinfo(ErlNifEnv* env,
#if defined(__WIN32__)
return enif_raise_exception(env, MKA(env, "notsup"));
#else
- ERL_NIF_TERM result;
- ERL_NIF_TERM eSockAddr, eFlags;
- int flags = 0; // Just in case...
- SocketAddress sa;
- SOCKLEN_T saLen = 0; // Just in case...
- char* xres;
+ ERL_NIF_TERM result;
+ ERL_NIF_TERM eSockAddr, eFlags;
+ int flags = 0; // Just in case...
+ ESockAddress sa;
+ SOCKLEN_T saLen = 0; // Just in case...
+ char* xres;
NDBG( ("NET", "nif_getnameinfo -> entry (%d)\r\n", argc) );
@@ -674,10 +674,10 @@ ERL_NIF_TERM nif_getnameinfo(ErlNifEnv* env,
*/
#if !defined(__WIN32__)
static
-ERL_NIF_TERM ngetnameinfo(ErlNifEnv* env,
- const SocketAddress* saP,
- SOCKLEN_T saLen,
- int flags)
+ERL_NIF_TERM ngetnameinfo(ErlNifEnv* env,
+ const ESockAddress* saP,
+ SOCKLEN_T saLen,
+ int flags)
{
ERL_NIF_TERM result;
char host[HOSTNAME_LEN];
@@ -1429,7 +1429,7 @@ ERL_NIF_TERM encode_address_info(ErlNifEnv* env,
type = encode_address_info_type(env, addrInfoP->ai_socktype);
proto = encode_address_info_proto(env, addrInfoP->ai_protocol);
esock_encode_sockaddr(env,
- (SocketAddress*) addrInfoP->ai_addr,
+ (ESockAddress*) addrInfoP->ai_addr,
addrInfoP->ai_addrlen,
&addr);
diff --git a/erts/emulator/nifs/common/socket_int.h b/erts/emulator/nifs/common/socket_int.h
index 043303a60d..38c28a6de5 100644
--- a/erts/emulator/nifs/common/socket_int.h
+++ b/erts/emulator/nifs/common/socket_int.h
@@ -82,7 +82,7 @@ typedef union {
struct sockaddr_un un;
#endif
-} SocketAddress;
+} ESockAddress;
/* *** Boolean *type* stuff... *** */
@@ -388,5 +388,7 @@ GLOBAL_ERROR_REASON_ATOM_DEFS
#define REALLOC_BIN(SZ, BP) enif_realloc_binary((SZ), (BP))
#define FREE_BIN(BP) enif_release_binary((BP))
+/* Copy term T into environment E */
+#define CP_TERM(E, T) enif_make_copy((E), (T))
#endif // SOCKET_INT_H__
diff --git a/erts/emulator/nifs/common/socket_nif.c b/erts/emulator/nifs/common/socket_nif.c
index 870ab63bdf..ee3b9f2a98 100644
--- a/erts/emulator/nifs/common/socket_nif.c
+++ b/erts/emulator/nifs/common/socket_nif.c
@@ -32,7 +32,7 @@
*
* esock_dbg_printf("DEMONP", "[%d] %s: %T\r\n",
* descP->sock, slogan,
- * MON2T(env, &monP->mon));
+ * esock_make_monitor_term(env, &mon));
*
*/
@@ -119,7 +119,6 @@
-
/* AND HERE WE MAY HAVE A BUNCH OF DEFINES....SEE INET DRIVER.... */
@@ -332,6 +331,20 @@ static void (*esock_sctp_freepaddrs)(struct sockaddr *addrs) = NULL;
#include "socket_int.h"
#include "socket_util.h"
+
+#if defined(ERTS_INLINE)
+# define ESOCK_INLINE ERTS_INLINE
+#else
+# if defined(__GNUC__)
+# define ESOCK_INLINE __inline__
+# elif defined(__WIN32__)
+# define ESOCK_INLINE __inline
+# else
+# define ESOCK_INLINE
+# endif
+#endif
+
+
#if defined(SOL_IPV6) || defined(IPPROTO_IPV6)
#define HAVE_IPV6
#endif
@@ -654,7 +667,9 @@ typedef union {
* *
* =================================================================== */
+/* Global socket debug */
#define SGDBG( proto ) ESOCK_DBG_PRINTF( data.dbg , proto )
+/* Socket specific debug */
#define SSDBG( __D__ , proto ) ESOCK_DBG_PRINTF( (__D__)->dbg , proto )
@@ -759,25 +774,32 @@ static unsigned long one_value = 1;
typedef struct {
- int is_active;
ErlNifMonitor mon;
+ BOOLEAN_T isActive;
} ESockMonitor;
typedef struct {
- ErlNifPid pid; // PID of the requesting process
- ESockMonitor mon; // Monitor to the requesting process
- ERL_NIF_TERM ref; // The (unique) reference (ID) of the request
-} SocketRequestor;
+ ErlNifPid pid; // PID of the requesting process
+ ESockMonitor mon; // Monitor to the requesting process
-typedef struct socket_request_queue_element {
- struct socket_request_queue_element* nextP;
- SocketRequestor data;
-} SocketRequestQueueElement;
+ /* We need an environment for the copy of the ref we store here.
+ * We will also use this environment for any messages we send
+ * (with the ref in it). Such as the select message (used in the
+ * select call) or the abort message.
+ */
+ ErlNifEnv* env;
+ ERL_NIF_TERM ref; // The (unique) reference (ID) of the request
+} ESockRequestor;
+
+typedef struct esock_request_queue_element {
+ struct esock_request_queue_element* nextP;
+ ESockRequestor data;
+} ESockRequestQueueElement;
typedef struct {
- SocketRequestQueueElement* first;
- SocketRequestQueueElement* last;
-} SocketRequestQueue;
+ ESockRequestQueueElement* first;
+ ESockRequestQueueElement* last;
+} ESockRequestQueue;
typedef struct {
@@ -791,21 +813,18 @@ typedef struct {
int protocol;
unsigned int state;
- SocketAddress remote;
+ ESockAddress remote;
unsigned int addrLen;
- ErlNifEnv* env;
-
/* +++ Controller (owner) process +++ */
ErlNifPid ctrlPid;
- // ErlNifMonitor ctrlMon;
ESockMonitor ctrlMon;
/* +++ Write stuff +++ */
ErlNifMutex* writeMtx;
- SocketRequestor currentWriter;
- SocketRequestor* currentWriterP; // NULL or points to currentWriter
- SocketRequestQueue writersQ;
+ ESockRequestor currentWriter;
+ ESockRequestor* currentWriterP; // NULL or points to currentWriter
+ ESockRequestQueue writersQ;
BOOLEAN_T isWritable;
Uint32 writePkgCnt;
Uint32 writeByteCnt;
@@ -815,9 +834,9 @@ typedef struct {
/* +++ Read stuff +++ */
ErlNifMutex* readMtx;
- SocketRequestor currentReader;
- SocketRequestor* currentReaderP; // NULL or points to currentReader
- SocketRequestQueue readersQ;
+ ESockRequestor currentReader;
+ ESockRequestor* currentReaderP; // NULL or points to currentReader
+ ESockRequestQueue readersQ;
BOOLEAN_T isReadable;
ErlNifBinary rbuffer; // DO WE NEED THIS
Uint32 readCapacity; // DO WE NEED THIS
@@ -828,11 +847,12 @@ typedef struct {
/* +++ Accept stuff +++ */
ErlNifMutex* accMtx;
- SocketRequestor currentAcceptor;
- SocketRequestor* currentAcceptorP; // NULL or points to currentAcceptor
- SocketRequestQueue acceptorsQ;
+ ESockRequestor currentAcceptor;
+ ESockRequestor* currentAcceptorP; // NULL or points to currentAcceptor
+ ESockRequestQueue acceptorsQ;
/* +++ Config & Misc stuff +++ */
+ ErlNifMutex* cfgMtx;
size_t rBufSz; // Read buffer size (when data length = 0)
/* rNum and rNumCnt are used (together with rBufSz) when calling the recv
* function with the Length argument set to 0 (zero).
@@ -856,7 +876,7 @@ typedef struct {
ERL_NIF_TERM closeRef;
BOOLEAN_T closeLocal;
-} SocketDescriptor;
+} ESockDescriptor;
/* Global stuff.
@@ -880,7 +900,7 @@ typedef struct {
Uint32 numProtoTCP;
Uint32 numProtoUDP;
Uint32 numProtoSCTP;
-} SocketData;
+} ESockData;
/* ----------------------------------------------------------------------
@@ -980,122 +1000,131 @@ static ERL_NIF_TERM nopen(ErlNifEnv* env,
int type,
int protocol,
char* netns);
-static ERL_NIF_TERM nbind(ErlNifEnv* env,
- SocketDescriptor* descP,
- SocketAddress* sockAddrP,
- unsigned int addrLen);
-static ERL_NIF_TERM nconnect(ErlNifEnv* env,
- SocketDescriptor* descP);
-static ERL_NIF_TERM nlisten(ErlNifEnv* env,
- SocketDescriptor* descP,
- int backlog);
-static ERL_NIF_TERM naccept(ErlNifEnv* env,
- SocketDescriptor* descP,
- ERL_NIF_TERM sockRef,
- ERL_NIF_TERM ref);
-static ERL_NIF_TERM naccept_listening(ErlNifEnv* env,
- SocketDescriptor* descP,
- ERL_NIF_TERM ref);
-static ERL_NIF_TERM naccept_listening_error(ErlNifEnv* env,
- SocketDescriptor* descP,
- ERL_NIF_TERM ref,
- ErlNifPid caller,
- int save_errno);
-static ERL_NIF_TERM naccept_listening_accept(ErlNifEnv* env,
- SocketDescriptor* descP,
- SOCKET accSock,
- ErlNifPid caller,
- SocketAddress* remote);
-static ERL_NIF_TERM naccept_accepting(ErlNifEnv* env,
- SocketDescriptor* descP,
- ERL_NIF_TERM sockRef,
- ERL_NIF_TERM ref);
-static ERL_NIF_TERM naccept_accepting_current(ErlNifEnv* env,
- SocketDescriptor* descP,
- ERL_NIF_TERM sockRef,
- ERL_NIF_TERM ref);
-static ERL_NIF_TERM naccept_accepting_current_accept(ErlNifEnv* env,
- SocketDescriptor* descP,
- ERL_NIF_TERM sockRef,
- SOCKET accSock,
- SocketAddress* remote);
-static ERL_NIF_TERM naccept_accepting_current_error(ErlNifEnv* env,
- SocketDescriptor* descP,
- ERL_NIF_TERM sockRef,
- ERL_NIF_TERM opRef,
- int save_errno);
-static ERL_NIF_TERM naccept_accepting_other(ErlNifEnv* env,
- SocketDescriptor* descP,
- ERL_NIF_TERM ref,
- ErlNifPid caller);
-static ERL_NIF_TERM naccept_busy_retry(ErlNifEnv* env,
- SocketDescriptor* descP,
- ERL_NIF_TERM ref,
- ErlNifPid* pid,
- unsigned int nextState);
-static BOOLEAN_T naccept_accepted(ErlNifEnv* env,
- SocketDescriptor* descP,
- SOCKET accSock,
- ErlNifPid pid,
- SocketAddress* remote,
- ERL_NIF_TERM* result);
-static ERL_NIF_TERM nsend(ErlNifEnv* env,
- SocketDescriptor* descP,
- ERL_NIF_TERM sockRef,
- ERL_NIF_TERM sendRef,
- ErlNifBinary* dataP,
- int flags);
-static ERL_NIF_TERM nsendto(ErlNifEnv* env,
- SocketDescriptor* descP,
- ERL_NIF_TERM sockRef,
- ERL_NIF_TERM sendRef,
- ErlNifBinary* dataP,
- int flags,
- SocketAddress* toAddrP,
- unsigned int toAddrLen);
-static ERL_NIF_TERM nsendmsg(ErlNifEnv* env,
- SocketDescriptor* descP,
- ERL_NIF_TERM sockRef,
- ERL_NIF_TERM sendRef,
- ERL_NIF_TERM eMsgHdr,
- int flags);
-static ERL_NIF_TERM nrecv(ErlNifEnv* env,
- SocketDescriptor* descP,
- ERL_NIF_TERM sendRef,
- ERL_NIF_TERM recvRef,
- int len,
- int flags);
-static ERL_NIF_TERM nrecvfrom(ErlNifEnv* env,
- SocketDescriptor* descP,
- ERL_NIF_TERM sockRef,
- ERL_NIF_TERM recvRef,
- Uint16 bufSz,
- int flags);
-static ERL_NIF_TERM nrecvmsg(ErlNifEnv* env,
- SocketDescriptor* descP,
- ERL_NIF_TERM sockRef,
- ERL_NIF_TERM recvRef,
- Uint16 bufLen,
- Uint16 ctrlLen,
- int flags);
-static ERL_NIF_TERM nclose(ErlNifEnv* env,
- SocketDescriptor* descP);
-static ERL_NIF_TERM nshutdown(ErlNifEnv* env,
- SocketDescriptor* descP,
- int how);
-static ERL_NIF_TERM nsetopt(ErlNifEnv* env,
- SocketDescriptor* descP,
- BOOLEAN_T isEncoded,
- BOOLEAN_T isOTP,
- int level,
- int eOpt,
- ERL_NIF_TERM eVal);
+static ERL_NIF_TERM nbind(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ESockAddress* sockAddrP,
+ unsigned int addrLen);
+static ERL_NIF_TERM nconnect(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM sockRef);
+static ERL_NIF_TERM nlisten(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ int backlog);
+static ERL_NIF_TERM naccept(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM sockRef,
+ ERL_NIF_TERM ref);
+static ERL_NIF_TERM naccept_listening(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM sockRef,
+ ERL_NIF_TERM ref);
+static ERL_NIF_TERM naccept_listening_error(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM sockRef,
+ ERL_NIF_TERM accRef,
+ ErlNifPid caller,
+ int save_errno);
+static ERL_NIF_TERM naccept_listening_accept(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ SOCKET accSock,
+ ErlNifPid caller,
+ ESockAddress* remote);
+static ERL_NIF_TERM naccept_accepting(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM sockRef,
+ ERL_NIF_TERM ref);
+static ERL_NIF_TERM naccept_accepting_current(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM sockRef,
+ ERL_NIF_TERM ref);
+static ERL_NIF_TERM naccept_accepting_current_accept(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM sockRef,
+ SOCKET accSock,
+ ESockAddress* remote);
+static ERL_NIF_TERM naccept_accepting_current_error(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM sockRef,
+ ERL_NIF_TERM opRef,
+ int save_errno);
+static ERL_NIF_TERM naccept_accepting_other(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM ref,
+ ErlNifPid caller);
+static ERL_NIF_TERM naccept_busy_retry(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM sockRef,
+ ERL_NIF_TERM accRef,
+ ErlNifPid* pid,
+ unsigned int nextState);
+static BOOLEAN_T naccept_accepted(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ SOCKET accSock,
+ ErlNifPid pid,
+ ESockAddress* remote,
+ ERL_NIF_TERM* result);
+static ERL_NIF_TERM nsend(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM sockRef,
+ ERL_NIF_TERM sendRef,
+ ErlNifBinary* dataP,
+ int flags);
+static ERL_NIF_TERM nsendto(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM sockRef,
+ ERL_NIF_TERM sendRef,
+ ErlNifBinary* dataP,
+ int flags,
+ ESockAddress* toAddrP,
+ unsigned int toAddrLen);
+static ERL_NIF_TERM nsendmsg(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM sockRef,
+ ERL_NIF_TERM sendRef,
+ ERL_NIF_TERM eMsgHdr,
+ int flags);
+static ERL_NIF_TERM nrecv(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM sendRef,
+ ERL_NIF_TERM recvRef,
+ int len,
+ int flags);
+static ERL_NIF_TERM nrecvfrom(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM sockRef,
+ ERL_NIF_TERM recvRef,
+ Uint16 bufSz,
+ int flags);
+static ERL_NIF_TERM nrecvmsg(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM sockRef,
+ ERL_NIF_TERM recvRef,
+ Uint16 bufLen,
+ Uint16 ctrlLen,
+ int flags);
+static ERL_NIF_TERM nclose(ErlNifEnv* env,
+ ESockDescriptor* descP);
+static BOOLEAN_T nclose_check(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM* reason);
+static ERL_NIF_TERM nclose_do(ErlNifEnv* env,
+ ESockDescriptor* descP);
+static ERL_NIF_TERM nshutdown(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ int how);
+static ERL_NIF_TERM nsetopt(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ BOOLEAN_T isEncoded,
+ BOOLEAN_T isOTP,
+ int level,
+ int eOpt,
+ ERL_NIF_TERM eVal);
/* Set OTP level options */
-static ERL_NIF_TERM nsetopt_otp(ErlNifEnv* env,
- SocketDescriptor* descP,
- int eOpt,
- ERL_NIF_TERM eVal);
+static ERL_NIF_TERM nsetopt_otp(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ int eOpt,
+ ERL_NIF_TERM eVal);
/* *** nsetopt_otp_debug ***
* *** nsetopt_otp_iow ***
* *** nsetopt_otp_ctrl_proc ***
@@ -1111,171 +1140,171 @@ static ERL_NIF_TERM nsetopt_otp(ErlNifEnv* env,
NSETOPT_OTP_FUNC_DEF(rcvctrlbuf); \
NSETOPT_OTP_FUNC_DEF(sndctrlbuf);
#define NSETOPT_OTP_FUNC_DEF(F) \
- static ERL_NIF_TERM nsetopt_otp_##F(ErlNifEnv* env, \
- SocketDescriptor* descP, \
- ERL_NIF_TERM eVal)
+ static ERL_NIF_TERM nsetopt_otp_##F(ErlNifEnv* env, \
+ ESockDescriptor* descP, \
+ ERL_NIF_TERM eVal)
NSETOPT_OTP_FUNCS
#undef NSETOPT_OTP_FUNC_DEF
/* Set native options */
-static ERL_NIF_TERM nsetopt_native(ErlNifEnv* env,
- SocketDescriptor* descP,
- int level,
- int eOpt,
- ERL_NIF_TERM eVal);
-static ERL_NIF_TERM nsetopt_level(ErlNifEnv* env,
- SocketDescriptor* descP,
- int level,
- int eOpt,
- ERL_NIF_TERM eVal);
-static ERL_NIF_TERM nsetopt_lvl_socket(ErlNifEnv* env,
- SocketDescriptor* descP,
- int eOpt,
- ERL_NIF_TERM eVal);
+static ERL_NIF_TERM nsetopt_native(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ int level,
+ int eOpt,
+ ERL_NIF_TERM eVal);
+static ERL_NIF_TERM nsetopt_level(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ int level,
+ int eOpt,
+ ERL_NIF_TERM eVal);
+static ERL_NIF_TERM nsetopt_lvl_socket(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ int eOpt,
+ ERL_NIF_TERM eVal);
/* *** Handling set of socket options for level = socket *** */
#if defined(SO_BINDTODEVICE)
-static ERL_NIF_TERM nsetopt_lvl_sock_bindtodevice(ErlNifEnv* env,
- SocketDescriptor* descP,
- ERL_NIF_TERM eVal);
+static ERL_NIF_TERM nsetopt_lvl_sock_bindtodevice(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal);
#endif
#if defined(SO_BROADCAST)
-static ERL_NIF_TERM nsetopt_lvl_sock_broadcast(ErlNifEnv* env,
- SocketDescriptor* descP,
- ERL_NIF_TERM eVal);
+static ERL_NIF_TERM nsetopt_lvl_sock_broadcast(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal);
#endif
#if defined(SO_DEBUG)
-static ERL_NIF_TERM nsetopt_lvl_sock_debug(ErlNifEnv* env,
- SocketDescriptor* descP,
- ERL_NIF_TERM eVal);
+static ERL_NIF_TERM nsetopt_lvl_sock_debug(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal);
#endif
#if defined(SO_DONTROUTE)
-static ERL_NIF_TERM nsetopt_lvl_sock_dontroute(ErlNifEnv* env,
- SocketDescriptor* descP,
- ERL_NIF_TERM eVal);
+static ERL_NIF_TERM nsetopt_lvl_sock_dontroute(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal);
#endif
#if defined(SO_KEEPALIVE)
-static ERL_NIF_TERM nsetopt_lvl_sock_keepalive(ErlNifEnv* env,
- SocketDescriptor* descP,
- ERL_NIF_TERM eVal);
+static ERL_NIF_TERM nsetopt_lvl_sock_keepalive(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal);
#endif
#if defined(SO_LINGER)
-static ERL_NIF_TERM nsetopt_lvl_sock_linger(ErlNifEnv* env,
- SocketDescriptor* descP,
- ERL_NIF_TERM eVal);
+static ERL_NIF_TERM nsetopt_lvl_sock_linger(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal);
#endif
#if defined(SO_OOBINLINE)
-static ERL_NIF_TERM nsetopt_lvl_sock_oobinline(ErlNifEnv* env,
- SocketDescriptor* descP,
- ERL_NIF_TERM eVal);
+static ERL_NIF_TERM nsetopt_lvl_sock_oobinline(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal);
#endif
#if defined(SO_PEEK_OFF)
-static ERL_NIF_TERM nsetopt_lvl_sock_peek_off(ErlNifEnv* env,
- SocketDescriptor* descP,
- ERL_NIF_TERM eVal);
+static ERL_NIF_TERM nsetopt_lvl_sock_peek_off(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal);
#endif
#if defined(SO_PRIORITY)
-static ERL_NIF_TERM nsetopt_lvl_sock_priority(ErlNifEnv* env,
- SocketDescriptor* descP,
- ERL_NIF_TERM eVal);
+static ERL_NIF_TERM nsetopt_lvl_sock_priority(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal);
#endif
#if defined(SO_RCVBUF)
-static ERL_NIF_TERM nsetopt_lvl_sock_rcvbuf(ErlNifEnv* env,
- SocketDescriptor* descP,
- ERL_NIF_TERM eVal);
+static ERL_NIF_TERM nsetopt_lvl_sock_rcvbuf(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal);
#endif
#if defined(SO_RCVLOWAT)
-static ERL_NIF_TERM nsetopt_lvl_sock_rcvlowat(ErlNifEnv* env,
- SocketDescriptor* descP,
- ERL_NIF_TERM eVal);
+static ERL_NIF_TERM nsetopt_lvl_sock_rcvlowat(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal);
#endif
#if defined(SO_RCVTIMEO)
-static ERL_NIF_TERM nsetopt_lvl_sock_rcvtimeo(ErlNifEnv* env,
- SocketDescriptor* descP,
- ERL_NIF_TERM eVal);
+static ERL_NIF_TERM nsetopt_lvl_sock_rcvtimeo(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal);
#endif
#if defined(SO_REUSEADDR)
-static ERL_NIF_TERM nsetopt_lvl_sock_reuseaddr(ErlNifEnv* env,
- SocketDescriptor* descP,
- ERL_NIF_TERM eVal);
+static ERL_NIF_TERM nsetopt_lvl_sock_reuseaddr(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal);
#endif
#if defined(SO_REUSEPORT)
-static ERL_NIF_TERM nsetopt_lvl_sock_reuseport(ErlNifEnv* env,
- SocketDescriptor* descP,
- ERL_NIF_TERM eVal);
+static ERL_NIF_TERM nsetopt_lvl_sock_reuseport(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal);
#endif
#if defined(SO_SNDBUF)
-static ERL_NIF_TERM nsetopt_lvl_sock_sndbuf(ErlNifEnv* env,
- SocketDescriptor* descP,
- ERL_NIF_TERM eVal);
+static ERL_NIF_TERM nsetopt_lvl_sock_sndbuf(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal);
#endif
#if defined(SO_SNDLOWAT)
-static ERL_NIF_TERM nsetopt_lvl_sock_sndlowat(ErlNifEnv* env,
- SocketDescriptor* descP,
- ERL_NIF_TERM eVal);
+static ERL_NIF_TERM nsetopt_lvl_sock_sndlowat(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal);
#endif
#if defined(SO_SNDTIMEO)
-static ERL_NIF_TERM nsetopt_lvl_sock_sndtimeo(ErlNifEnv* env,
- SocketDescriptor* descP,
- ERL_NIF_TERM eVal);
+static ERL_NIF_TERM nsetopt_lvl_sock_sndtimeo(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal);
#endif
#if defined(SO_TIMESTAMP)
-static ERL_NIF_TERM nsetopt_lvl_sock_timestamp(ErlNifEnv* env,
- SocketDescriptor* descP,
- ERL_NIF_TERM eVal);
+static ERL_NIF_TERM nsetopt_lvl_sock_timestamp(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal);
#endif
-static ERL_NIF_TERM nsetopt_lvl_ip(ErlNifEnv* env,
- SocketDescriptor* descP,
- int eOpt,
- ERL_NIF_TERM eVal);
+static ERL_NIF_TERM nsetopt_lvl_ip(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ int eOpt,
+ ERL_NIF_TERM eVal);
/* *** Handling set of socket options for level = ip *** */
#if defined(IP_ADD_MEMBERSHIP)
-static ERL_NIF_TERM nsetopt_lvl_ip_add_membership(ErlNifEnv* env,
- SocketDescriptor* descP,
- ERL_NIF_TERM eVal);
+static ERL_NIF_TERM nsetopt_lvl_ip_add_membership(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal);
#endif
#if defined(IP_ADD_SOURCE_MEMBERSHIP)
-static ERL_NIF_TERM nsetopt_lvl_ip_add_source_membership(ErlNifEnv* env,
- SocketDescriptor* descP,
- ERL_NIF_TERM eVal);
+static ERL_NIF_TERM nsetopt_lvl_ip_add_source_membership(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal);
#endif
#if defined(IP_BLOCK_SOURCE)
-static ERL_NIF_TERM nsetopt_lvl_ip_block_source(ErlNifEnv* env,
- SocketDescriptor* descP,
- ERL_NIF_TERM eVal);
+static ERL_NIF_TERM nsetopt_lvl_ip_block_source(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal);
#endif
#if defined(IP_DROP_MEMBERSHIP)
-static ERL_NIF_TERM nsetopt_lvl_ip_drop_membership(ErlNifEnv* env,
- SocketDescriptor* descP,
- ERL_NIF_TERM eVal);
+static ERL_NIF_TERM nsetopt_lvl_ip_drop_membership(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal);
#endif
#if defined(IP_DROP_SOURCE_MEMBERSHIP)
-static ERL_NIF_TERM nsetopt_lvl_ip_drop_source_membership(ErlNifEnv* env,
- SocketDescriptor* descP,
- ERL_NIF_TERM eVal);
+static ERL_NIF_TERM nsetopt_lvl_ip_drop_source_membership(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal);
#endif
#if defined(IP_FREEBIND)
-static ERL_NIF_TERM nsetopt_lvl_ip_freebind(ErlNifEnv* env,
- SocketDescriptor* descP,
- ERL_NIF_TERM eVal);
+static ERL_NIF_TERM nsetopt_lvl_ip_freebind(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal);
#endif
#if defined(IP_HDRINCL)
-static ERL_NIF_TERM nsetopt_lvl_ip_hdrincl(ErlNifEnv* env,
- SocketDescriptor* descP,
- ERL_NIF_TERM eVal);
+static ERL_NIF_TERM nsetopt_lvl_ip_hdrincl(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal);
#endif
#if defined(IP_MINTTL)
-static ERL_NIF_TERM nsetopt_lvl_ip_minttl(ErlNifEnv* env,
- SocketDescriptor* descP,
- ERL_NIF_TERM eVal);
+static ERL_NIF_TERM nsetopt_lvl_ip_minttl(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal);
#endif
#if defined(IP_MSFILTER) && defined(IP_MSFILTER_SIZE)
-static ERL_NIF_TERM nsetopt_lvl_ip_msfilter(ErlNifEnv* env,
- SocketDescriptor* descP,
- ERL_NIF_TERM eVal);
+static ERL_NIF_TERM nsetopt_lvl_ip_msfilter(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal);
static BOOLEAN_T decode_ip_msfilter_mode(ErlNifEnv* env,
ERL_NIF_TERM eVal,
Uint32* mode);
@@ -1285,322 +1314,322 @@ static ERL_NIF_TERM nsetopt_lvl_ip_msfilter_set(ErlNifEnv* env,
SOCKLEN_T optLen);
#endif
#if defined(IP_MTU_DISCOVER)
-static ERL_NIF_TERM nsetopt_lvl_ip_mtu_discover(ErlNifEnv* env,
- SocketDescriptor* descP,
- ERL_NIF_TERM eVal);
+static ERL_NIF_TERM nsetopt_lvl_ip_mtu_discover(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal);
#endif
#if defined(IP_MULTICAST_ALL)
-static ERL_NIF_TERM nsetopt_lvl_ip_multicast_all(ErlNifEnv* env,
- SocketDescriptor* descP,
- ERL_NIF_TERM eVal);
+static ERL_NIF_TERM nsetopt_lvl_ip_multicast_all(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal);
#endif
#if defined(IP_MULTICAST_IF)
-static ERL_NIF_TERM nsetopt_lvl_ip_multicast_if(ErlNifEnv* env,
- SocketDescriptor* descP,
- ERL_NIF_TERM eVal);
+static ERL_NIF_TERM nsetopt_lvl_ip_multicast_if(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal);
#endif
#if defined(IP_MULTICAST_LOOP)
-static ERL_NIF_TERM nsetopt_lvl_ip_multicast_loop(ErlNifEnv* env,
- SocketDescriptor* descP,
- ERL_NIF_TERM eVal);
+static ERL_NIF_TERM nsetopt_lvl_ip_multicast_loop(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal);
#endif
#if defined(IP_MULTICAST_TTL)
-static ERL_NIF_TERM nsetopt_lvl_ip_multicast_ttl(ErlNifEnv* env,
- SocketDescriptor* descP,
- ERL_NIF_TERM eVal);
+static ERL_NIF_TERM nsetopt_lvl_ip_multicast_ttl(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal);
#endif
#if defined(IP_NODEFRAG)
-static ERL_NIF_TERM nsetopt_lvl_ip_nodefrag(ErlNifEnv* env,
- SocketDescriptor* descP,
- ERL_NIF_TERM eVal);
+static ERL_NIF_TERM nsetopt_lvl_ip_nodefrag(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal);
#endif
#if defined(IP_PKTINFO)
-static ERL_NIF_TERM nsetopt_lvl_ip_pktinfo(ErlNifEnv* env,
- SocketDescriptor* descP,
- ERL_NIF_TERM eVal);
+static ERL_NIF_TERM nsetopt_lvl_ip_pktinfo(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal);
#endif
#if defined(IP_RECVDSTADDR)
-static ERL_NIF_TERM nsetopt_lvl_ip_recvdstaddr(ErlNifEnv* env,
- SocketDescriptor* descP,
- ERL_NIF_TERM eVal);
+static ERL_NIF_TERM nsetopt_lvl_ip_recvdstaddr(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal);
#endif
#if defined(IP_RECVERR)
-static ERL_NIF_TERM nsetopt_lvl_ip_recverr(ErlNifEnv* env,
- SocketDescriptor* descP,
- ERL_NIF_TERM eVal);
+static ERL_NIF_TERM nsetopt_lvl_ip_recverr(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal);
#endif
#if defined(IP_RECVIF)
-static ERL_NIF_TERM nsetopt_lvl_ip_recvif(ErlNifEnv* env,
- SocketDescriptor* descP,
- ERL_NIF_TERM eVal);
+static ERL_NIF_TERM nsetopt_lvl_ip_recvif(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal);
#endif
#if defined(IP_RECVOPTS)
-static ERL_NIF_TERM nsetopt_lvl_ip_recvopts(ErlNifEnv* env,
- SocketDescriptor* descP,
- ERL_NIF_TERM eVal);
+static ERL_NIF_TERM nsetopt_lvl_ip_recvopts(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal);
#endif
#if defined(IP_RECVORIGDSTADDR)
-static ERL_NIF_TERM nsetopt_lvl_ip_recvorigdstaddr(ErlNifEnv* env,
- SocketDescriptor* descP,
- ERL_NIF_TERM eVal);
+static ERL_NIF_TERM nsetopt_lvl_ip_recvorigdstaddr(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal);
#endif
#if defined(IP_RECVTOS)
-static ERL_NIF_TERM nsetopt_lvl_ip_recvtos(ErlNifEnv* env,
- SocketDescriptor* descP,
- ERL_NIF_TERM eVal);
+static ERL_NIF_TERM nsetopt_lvl_ip_recvtos(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal);
#endif
#if defined(IP_RECVTTL)
-static ERL_NIF_TERM nsetopt_lvl_ip_recvttl(ErlNifEnv* env,
- SocketDescriptor* descP,
- ERL_NIF_TERM eVal);
+static ERL_NIF_TERM nsetopt_lvl_ip_recvttl(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal);
#endif
#if defined(IP_RETOPTS)
-static ERL_NIF_TERM nsetopt_lvl_ip_retopts(ErlNifEnv* env,
- SocketDescriptor* descP,
- ERL_NIF_TERM eVal);
+static ERL_NIF_TERM nsetopt_lvl_ip_retopts(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal);
#endif
#if defined(IP_ROUTER_ALERT)
-static ERL_NIF_TERM nsetopt_lvl_ip_router_alert(ErlNifEnv* env,
- SocketDescriptor* descP,
- ERL_NIF_TERM eVal);
+static ERL_NIF_TERM nsetopt_lvl_ip_router_alert(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal);
#endif
#if defined(IP_SENDSRCADDR)
-static ERL_NIF_TERM nsetopt_lvl_ip_sendsrcaddr(ErlNifEnv* env,
- SocketDescriptor* descP,
- ERL_NIF_TERM eVal);
+static ERL_NIF_TERM nsetopt_lvl_ip_sendsrcaddr(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal);
#endif
#if defined(IP_TOS)
-static ERL_NIF_TERM nsetopt_lvl_ip_tos(ErlNifEnv* env,
- SocketDescriptor* descP,
- ERL_NIF_TERM eVal);
+static ERL_NIF_TERM nsetopt_lvl_ip_tos(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal);
#endif
#if defined(IP_TRANSPARENT)
-static ERL_NIF_TERM nsetopt_lvl_ip_transparent(ErlNifEnv* env,
- SocketDescriptor* descP,
- ERL_NIF_TERM eVal);
+static ERL_NIF_TERM nsetopt_lvl_ip_transparent(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal);
#endif
#if defined(IP_TTL)
-static ERL_NIF_TERM nsetopt_lvl_ip_ttl(ErlNifEnv* env,
- SocketDescriptor* descP,
- ERL_NIF_TERM eVal);
+static ERL_NIF_TERM nsetopt_lvl_ip_ttl(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal);
#endif
#if defined(IP_UNBLOCK_SOURCE)
-static ERL_NIF_TERM nsetopt_lvl_ip_unblock_source(ErlNifEnv* env,
- SocketDescriptor* descP,
- ERL_NIF_TERM eVal);
+static ERL_NIF_TERM nsetopt_lvl_ip_unblock_source(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal);
#endif
#if defined(IP_DROP_MEMBERSHIP) || defined(IP_ADD_MEMBERSHIP)
static
-ERL_NIF_TERM nsetopt_lvl_ip_update_membership(ErlNifEnv* env,
- SocketDescriptor* descP,
- ERL_NIF_TERM eVal,
- int opt);
+ERL_NIF_TERM nsetopt_lvl_ip_update_membership(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal,
+ int opt);
#endif
#if defined(IP_ADD_SOURCE_MEMBERSHIP) || defined(IP_DROP_SOURCE_MEMBERSHIP) || defined(IP_BLOCK_SOURCE) || defined(IP_UNBLOCK_SOURCE)
static
-ERL_NIF_TERM nsetopt_lvl_ip_update_source(ErlNifEnv* env,
- SocketDescriptor* descP,
- ERL_NIF_TERM eVal,
- int opt);
+ERL_NIF_TERM nsetopt_lvl_ip_update_source(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal,
+ int opt);
#endif
/* *** Handling set of socket options for level = ipv6 *** */
#if defined(HAVE_IPV6)
-static ERL_NIF_TERM nsetopt_lvl_ipv6(ErlNifEnv* env,
- SocketDescriptor* descP,
- int eOpt,
- ERL_NIF_TERM eVal);
+static ERL_NIF_TERM nsetopt_lvl_ipv6(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ int eOpt,
+ ERL_NIF_TERM eVal);
#if defined(IPV6_ADDRFORM)
-static ERL_NIF_TERM nsetopt_lvl_ipv6_addrform(ErlNifEnv* env,
- SocketDescriptor* descP,
- ERL_NIF_TERM eVal);
+static ERL_NIF_TERM nsetopt_lvl_ipv6_addrform(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal);
#endif
#if defined(IPV6_ADD_MEMBERSHIP)
-static ERL_NIF_TERM nsetopt_lvl_ipv6_add_membership(ErlNifEnv* env,
- SocketDescriptor* descP,
- ERL_NIF_TERM eVal);
+static ERL_NIF_TERM nsetopt_lvl_ipv6_add_membership(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal);
#endif
#if defined(IPV6_AUTHHDR)
-static ERL_NIF_TERM nsetopt_lvl_ipv6_authhdr(ErlNifEnv* env,
- SocketDescriptor* descP,
- ERL_NIF_TERM eVal);
+static ERL_NIF_TERM nsetopt_lvl_ipv6_authhdr(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal);
#endif
#if defined(IPV6_DROP_MEMBERSHIP)
-static ERL_NIF_TERM nsetopt_lvl_ipv6_drop_membership(ErlNifEnv* env,
- SocketDescriptor* descP,
- ERL_NIF_TERM eVal);
+static ERL_NIF_TERM nsetopt_lvl_ipv6_drop_membership(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal);
#endif
#if defined(IPV6_DSTOPTS)
-static ERL_NIF_TERM nsetopt_lvl_ipv6_dstopts(ErlNifEnv* env,
- SocketDescriptor* descP,
- ERL_NIF_TERM eVal);
+static ERL_NIF_TERM nsetopt_lvl_ipv6_dstopts(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal);
#endif
#if defined(IPV6_FLOWINFO)
-static ERL_NIF_TERM nsetopt_lvl_ipv6_flowinfo(ErlNifEnv* env,
- SocketDescriptor* descP,
- ERL_NIF_TERM eVal);
+static ERL_NIF_TERM nsetopt_lvl_ipv6_flowinfo(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal);
#endif
#if defined(IPV6_HOPLIMIT)
-static ERL_NIF_TERM nsetopt_lvl_ipv6_hoplimit(ErlNifEnv* env,
- SocketDescriptor* descP,
- ERL_NIF_TERM eVal);
+static ERL_NIF_TERM nsetopt_lvl_ipv6_hoplimit(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal);
#endif
#if defined(IPV6_HOPOPTS)
-static ERL_NIF_TERM nsetopt_lvl_ipv6_hopopts(ErlNifEnv* env,
- SocketDescriptor* descP,
- ERL_NIF_TERM eVal);
+static ERL_NIF_TERM nsetopt_lvl_ipv6_hopopts(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal);
#endif
#if defined(IPV6_MTU)
-static ERL_NIF_TERM nsetopt_lvl_ipv6_mtu(ErlNifEnv* env,
- SocketDescriptor* descP,
- ERL_NIF_TERM eVal);
+static ERL_NIF_TERM nsetopt_lvl_ipv6_mtu(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal);
#endif
#if defined(IPV6_MTU_DISCOVER)
-static ERL_NIF_TERM nsetopt_lvl_ipv6_mtu_discover(ErlNifEnv* env,
- SocketDescriptor* descP,
- ERL_NIF_TERM eVal);
+static ERL_NIF_TERM nsetopt_lvl_ipv6_mtu_discover(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal);
#endif
#if defined(IPV6_MULTICAST_HOPS)
-static ERL_NIF_TERM nsetopt_lvl_ipv6_multicast_hops(ErlNifEnv* env,
- SocketDescriptor* descP,
- ERL_NIF_TERM eVal);
+static ERL_NIF_TERM nsetopt_lvl_ipv6_multicast_hops(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal);
#endif
#if defined(IPV6_MULTICAST_IF)
-static ERL_NIF_TERM nsetopt_lvl_ipv6_multicast_if(ErlNifEnv* env,
- SocketDescriptor* descP,
- ERL_NIF_TERM eVal);
+static ERL_NIF_TERM nsetopt_lvl_ipv6_multicast_if(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal);
#endif
#if defined(IPV6_MULTICAST_LOOP)
-static ERL_NIF_TERM nsetopt_lvl_ipv6_multicast_loop(ErlNifEnv* env,
- SocketDescriptor* descP,
- ERL_NIF_TERM eVal);
+static ERL_NIF_TERM nsetopt_lvl_ipv6_multicast_loop(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal);
#endif
#if defined(IPV6_RECVERR)
-static ERL_NIF_TERM nsetopt_lvl_ipv6_recverr(ErlNifEnv* env,
- SocketDescriptor* descP,
- ERL_NIF_TERM eVal);
+static ERL_NIF_TERM nsetopt_lvl_ipv6_recverr(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal);
#endif
#if defined(IPV6_RECVPKTINFO) || defined(IPV6_PKTINFO)
-static ERL_NIF_TERM nsetopt_lvl_ipv6_recvpktinfo(ErlNifEnv* env,
- SocketDescriptor* descP,
- ERL_NIF_TERM eVal);
+static ERL_NIF_TERM nsetopt_lvl_ipv6_recvpktinfo(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal);
#endif
#if defined(IPV6_ROUTER_ALERT)
-static ERL_NIF_TERM nsetopt_lvl_ipv6_router_alert(ErlNifEnv* env,
- SocketDescriptor* descP,
- ERL_NIF_TERM eVal);
+static ERL_NIF_TERM nsetopt_lvl_ipv6_router_alert(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal);
#endif
#if defined(IPV6_RTHDR)
-static ERL_NIF_TERM nsetopt_lvl_ipv6_rthdr(ErlNifEnv* env,
- SocketDescriptor* descP,
- ERL_NIF_TERM eVal);
+static ERL_NIF_TERM nsetopt_lvl_ipv6_rthdr(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal);
#endif
#if defined(IPV6_UNICAST_HOPS)
-static ERL_NIF_TERM nsetopt_lvl_ipv6_unicast_hops(ErlNifEnv* env,
- SocketDescriptor* descP,
- ERL_NIF_TERM eVal);
+static ERL_NIF_TERM nsetopt_lvl_ipv6_unicast_hops(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal);
#endif
#if defined(IPV6_V6ONLY)
-static ERL_NIF_TERM nsetopt_lvl_ipv6_v6only(ErlNifEnv* env,
- SocketDescriptor* descP,
- ERL_NIF_TERM eVal);
+static ERL_NIF_TERM nsetopt_lvl_ipv6_v6only(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal);
#endif
#if defined(IPV6_ADD_MEMBERSHIP) || defined(IPV6_DROP_MEMBERSHIP)
-static ERL_NIF_TERM nsetopt_lvl_ipv6_update_membership(ErlNifEnv* env,
- SocketDescriptor* descP,
- ERL_NIF_TERM eVal,
- int opt);
+static ERL_NIF_TERM nsetopt_lvl_ipv6_update_membership(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal,
+ int opt);
#endif
#endif // defined(HAVE_IPV6)
-static ERL_NIF_TERM nsetopt_lvl_tcp(ErlNifEnv* env,
- SocketDescriptor* descP,
- int eOpt,
- ERL_NIF_TERM eVal);
+static ERL_NIF_TERM nsetopt_lvl_tcp(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ int eOpt,
+ ERL_NIF_TERM eVal);
#if defined(TCP_CONGESTION)
-static ERL_NIF_TERM nsetopt_lvl_tcp_congestion(ErlNifEnv* env,
- SocketDescriptor* descP,
- ERL_NIF_TERM eVal);
+static ERL_NIF_TERM nsetopt_lvl_tcp_congestion(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal);
#endif
#if defined(TCP_MAXSEG)
-static ERL_NIF_TERM nsetopt_lvl_tcp_maxseg(ErlNifEnv* env,
- SocketDescriptor* descP,
- ERL_NIF_TERM eVal);
+static ERL_NIF_TERM nsetopt_lvl_tcp_maxseg(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal);
#endif
#if defined(TCP_NODELAY)
-static ERL_NIF_TERM nsetopt_lvl_tcp_nodelay(ErlNifEnv* env,
- SocketDescriptor* descP,
- ERL_NIF_TERM eVal);
-#endif
-static ERL_NIF_TERM nsetopt_lvl_udp(ErlNifEnv* env,
- SocketDescriptor* descP,
- int eOpt,
- ERL_NIF_TERM eVal);
+static ERL_NIF_TERM nsetopt_lvl_tcp_nodelay(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal);
+#endif
+static ERL_NIF_TERM nsetopt_lvl_udp(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ int eOpt,
+ ERL_NIF_TERM eVal);
#if defined(UDP_CORK)
-static ERL_NIF_TERM nsetopt_lvl_udp_cork(ErlNifEnv* env,
- SocketDescriptor* descP,
- ERL_NIF_TERM eVal);
+static ERL_NIF_TERM nsetopt_lvl_udp_cork(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal);
#endif
#if defined(HAVE_SCTP)
-static ERL_NIF_TERM nsetopt_lvl_sctp(ErlNifEnv* env,
- SocketDescriptor* descP,
- int eOpt,
- ERL_NIF_TERM eVal);
+static ERL_NIF_TERM nsetopt_lvl_sctp(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ int eOpt,
+ ERL_NIF_TERM eVal);
#if defined(SCTP_ASSOCINFO)
-static ERL_NIF_TERM nsetopt_lvl_sctp_associnfo(ErlNifEnv* env,
- SocketDescriptor* descP,
- ERL_NIF_TERM eVal);
+static ERL_NIF_TERM nsetopt_lvl_sctp_associnfo(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal);
#endif
#if defined(SCTP_AUTOCLOSE)
-static ERL_NIF_TERM nsetopt_lvl_sctp_autoclose(ErlNifEnv* env,
- SocketDescriptor* descP,
- ERL_NIF_TERM eVal);
+static ERL_NIF_TERM nsetopt_lvl_sctp_autoclose(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal);
#endif
#if defined(SCTP_DISABLE_FRAGMENTS)
-static ERL_NIF_TERM nsetopt_lvl_sctp_disable_fragments(ErlNifEnv* env,
- SocketDescriptor* descP,
- ERL_NIF_TERM eVal);
+static ERL_NIF_TERM nsetopt_lvl_sctp_disable_fragments(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal);
#endif
#if defined(SCTP_EVENTS)
-static ERL_NIF_TERM nsetopt_lvl_sctp_events(ErlNifEnv* env,
- SocketDescriptor* descP,
- ERL_NIF_TERM eVal);
+static ERL_NIF_TERM nsetopt_lvl_sctp_events(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal);
#endif
#if defined(SCTP_INITMSG)
-static ERL_NIF_TERM nsetopt_lvl_sctp_initmsg(ErlNifEnv* env,
- SocketDescriptor* descP,
- ERL_NIF_TERM eVal);
+static ERL_NIF_TERM nsetopt_lvl_sctp_initmsg(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal);
#endif
#if defined(SCTP_MAXSEG)
-static ERL_NIF_TERM nsetopt_lvl_sctp_maxseg(ErlNifEnv* env,
- SocketDescriptor* descP,
- ERL_NIF_TERM eVal);
+static ERL_NIF_TERM nsetopt_lvl_sctp_maxseg(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal);
#endif
#if defined(SCTP_NODELAY)
-static ERL_NIF_TERM nsetopt_lvl_sctp_nodelay(ErlNifEnv* env,
- SocketDescriptor* descP,
- ERL_NIF_TERM eVal);
+static ERL_NIF_TERM nsetopt_lvl_sctp_nodelay(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal);
#endif
#if defined(SCTP_RTOINFO)
-static ERL_NIF_TERM nsetopt_lvl_sctp_rtoinfo(ErlNifEnv* env,
- SocketDescriptor* descP,
- ERL_NIF_TERM eVal);
+static ERL_NIF_TERM nsetopt_lvl_sctp_rtoinfo(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal);
#endif
#endif // defined(HAVE_SCTP)
-static ERL_NIF_TERM ngetopt(ErlNifEnv* env,
- SocketDescriptor* descP,
- BOOLEAN_T isEncoded,
- BOOLEAN_T isOTP,
- int level,
- ERL_NIF_TERM eOpt);
+static ERL_NIF_TERM ngetopt(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ BOOLEAN_T isEncoded,
+ BOOLEAN_T isOTP,
+ int level,
+ ERL_NIF_TERM eOpt);
-static ERL_NIF_TERM ngetopt_otp(ErlNifEnv* env,
- SocketDescriptor* descP,
- int eOpt);
+static ERL_NIF_TERM ngetopt_otp(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ int eOpt);
/* *** ngetopt_otp_debug ***
* *** ngetopt_otp_iow ***
* *** ngetopt_otp_ctrl_proc ***
@@ -1625,518 +1654,595 @@ static ERL_NIF_TERM ngetopt_otp(ErlNifEnv* env,
NGETOPT_OTP_FUNC_DEF(protocol);
#define NGETOPT_OTP_FUNC_DEF(F) \
static ERL_NIF_TERM ngetopt_otp_##F(ErlNifEnv* env, \
- SocketDescriptor* descP)
+ ESockDescriptor* descP)
NGETOPT_OTP_FUNCS
#undef NGETOPT_OTP_FUNC_DEF
-static ERL_NIF_TERM ngetopt_native(ErlNifEnv* env,
- SocketDescriptor* descP,
- int level,
- ERL_NIF_TERM eOpt);
-static ERL_NIF_TERM ngetopt_native_unspec(ErlNifEnv* env,
- SocketDescriptor* descP,
- int level,
- int opt,
- SOCKOPTLEN_T valueSz);
-static ERL_NIF_TERM ngetopt_level(ErlNifEnv* env,
- SocketDescriptor* descP,
- int level,
- int eOpt);
-static ERL_NIF_TERM ngetopt_lvl_socket(ErlNifEnv* env,
- SocketDescriptor* descP,
- int eOpt);
+static ERL_NIF_TERM ngetopt_native(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ int level,
+ ERL_NIF_TERM eOpt);
+static ERL_NIF_TERM ngetopt_native_unspec(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ int level,
+ int opt,
+ SOCKOPTLEN_T valueSz);
+static ERL_NIF_TERM ngetopt_level(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ int level,
+ int eOpt);
+static ERL_NIF_TERM ngetopt_lvl_socket(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ int eOpt);
#if defined(SO_ACCEPTCONN)
-static ERL_NIF_TERM ngetopt_lvl_sock_acceptconn(ErlNifEnv* env,
- SocketDescriptor* descP);
+static ERL_NIF_TERM ngetopt_lvl_sock_acceptconn(ErlNifEnv* env,
+ ESockDescriptor* descP);
#endif
#if defined(SO_BINDTODEVICE)
-static ERL_NIF_TERM ngetopt_lvl_sock_bindtodevice(ErlNifEnv* env,
- SocketDescriptor* descP);
+static ERL_NIF_TERM ngetopt_lvl_sock_bindtodevice(ErlNifEnv* env,
+ ESockDescriptor* descP);
#endif
#if defined(SO_BROADCAST)
-static ERL_NIF_TERM ngetopt_lvl_sock_broadcast(ErlNifEnv* env,
- SocketDescriptor* descP);
+static ERL_NIF_TERM ngetopt_lvl_sock_broadcast(ErlNifEnv* env,
+ ESockDescriptor* descP);
#endif
#if defined(SO_DEBUG)
-static ERL_NIF_TERM ngetopt_lvl_sock_debug(ErlNifEnv* env,
- SocketDescriptor* descP);
+static ERL_NIF_TERM ngetopt_lvl_sock_debug(ErlNifEnv* env,
+ ESockDescriptor* descP);
#endif
#if defined(SO_DOMAIN)
-static ERL_NIF_TERM ngetopt_lvl_sock_domain(ErlNifEnv* env,
- SocketDescriptor* descP);
+static ERL_NIF_TERM ngetopt_lvl_sock_domain(ErlNifEnv* env,
+ ESockDescriptor* descP);
#endif
#if defined(SO_DONTROUTE)
-static ERL_NIF_TERM ngetopt_lvl_sock_dontroute(ErlNifEnv* env,
- SocketDescriptor* descP);
+static ERL_NIF_TERM ngetopt_lvl_sock_dontroute(ErlNifEnv* env,
+ ESockDescriptor* descP);
#endif
#if defined(SO_KEEPALIVE)
-static ERL_NIF_TERM ngetopt_lvl_sock_keepalive(ErlNifEnv* env,
- SocketDescriptor* descP);
+static ERL_NIF_TERM ngetopt_lvl_sock_keepalive(ErlNifEnv* env,
+ ESockDescriptor* descP);
#endif
#if defined(SO_LINGER)
-static ERL_NIF_TERM ngetopt_lvl_sock_linger(ErlNifEnv* env,
- SocketDescriptor* descP);
+static ERL_NIF_TERM ngetopt_lvl_sock_linger(ErlNifEnv* env,
+ ESockDescriptor* descP);
#endif
#if defined(SO_OOBINLINE)
-static ERL_NIF_TERM ngetopt_lvl_sock_oobinline(ErlNifEnv* env,
- SocketDescriptor* descP);
+static ERL_NIF_TERM ngetopt_lvl_sock_oobinline(ErlNifEnv* env,
+ ESockDescriptor* descP);
#endif
#if defined(SO_PEEK_OFF)
-static ERL_NIF_TERM ngetopt_lvl_sock_peek_off(ErlNifEnv* env,
- SocketDescriptor* descP);
+static ERL_NIF_TERM ngetopt_lvl_sock_peek_off(ErlNifEnv* env,
+ ESockDescriptor* descP);
#endif
#if defined(SO_PRIORITY)
-static ERL_NIF_TERM ngetopt_lvl_sock_priority(ErlNifEnv* env,
- SocketDescriptor* descP);
+static ERL_NIF_TERM ngetopt_lvl_sock_priority(ErlNifEnv* env,
+ ESockDescriptor* descP);
#endif
#if defined(SO_PROTOCOL)
-static ERL_NIF_TERM ngetopt_lvl_sock_protocol(ErlNifEnv* env,
- SocketDescriptor* descP);
+static ERL_NIF_TERM ngetopt_lvl_sock_protocol(ErlNifEnv* env,
+ ESockDescriptor* descP);
#endif
#if defined(SO_RCVBUF)
-static ERL_NIF_TERM ngetopt_lvl_sock_rcvbuf(ErlNifEnv* env,
- SocketDescriptor* descP);
+static ERL_NIF_TERM ngetopt_lvl_sock_rcvbuf(ErlNifEnv* env,
+ ESockDescriptor* descP);
#endif
#if defined(SO_RCVLOWAT)
-static ERL_NIF_TERM ngetopt_lvl_sock_rcvlowat(ErlNifEnv* env,
- SocketDescriptor* descP);
+static ERL_NIF_TERM ngetopt_lvl_sock_rcvlowat(ErlNifEnv* env,
+ ESockDescriptor* descP);
#endif
#if defined(SO_RCVTIMEO)
-static ERL_NIF_TERM ngetopt_lvl_sock_rcvtimeo(ErlNifEnv* env,
- SocketDescriptor* descP);
+static ERL_NIF_TERM ngetopt_lvl_sock_rcvtimeo(ErlNifEnv* env,
+ ESockDescriptor* descP);
#endif
#if defined(SO_REUSEADDR)
-static ERL_NIF_TERM ngetopt_lvl_sock_reuseaddr(ErlNifEnv* env,
- SocketDescriptor* descP);
+static ERL_NIF_TERM ngetopt_lvl_sock_reuseaddr(ErlNifEnv* env,
+ ESockDescriptor* descP);
#endif
#if defined(SO_REUSEPORT)
-static ERL_NIF_TERM ngetopt_lvl_sock_reuseport(ErlNifEnv* env,
- SocketDescriptor* descP);
+static ERL_NIF_TERM ngetopt_lvl_sock_reuseport(ErlNifEnv* env,
+ ESockDescriptor* descP);
#endif
#if defined(SO_SNDBUF)
-static ERL_NIF_TERM ngetopt_lvl_sock_sndbuf(ErlNifEnv* env,
- SocketDescriptor* descP);
+static ERL_NIF_TERM ngetopt_lvl_sock_sndbuf(ErlNifEnv* env,
+ ESockDescriptor* descP);
#endif
#if defined(SO_SNDLOWAT)
-static ERL_NIF_TERM ngetopt_lvl_sock_sndlowat(ErlNifEnv* env,
- SocketDescriptor* descP);
+static ERL_NIF_TERM ngetopt_lvl_sock_sndlowat(ErlNifEnv* env,
+ ESockDescriptor* descP);
#endif
#if defined(SO_SNDTIMEO)
-static ERL_NIF_TERM ngetopt_lvl_sock_sndtimeo(ErlNifEnv* env,
- SocketDescriptor* descP);
+static ERL_NIF_TERM ngetopt_lvl_sock_sndtimeo(ErlNifEnv* env,
+ ESockDescriptor* descP);
#endif
#if defined(SO_TIMESTAMP)
-static ERL_NIF_TERM ngetopt_lvl_sock_timestamp(ErlNifEnv* env,
- SocketDescriptor* descP);
+static ERL_NIF_TERM ngetopt_lvl_sock_timestamp(ErlNifEnv* env,
+ ESockDescriptor* descP);
#endif
#if defined(SO_TYPE)
-static ERL_NIF_TERM ngetopt_lvl_sock_type(ErlNifEnv* env,
- SocketDescriptor* descP);
+static ERL_NIF_TERM ngetopt_lvl_sock_type(ErlNifEnv* env,
+ ESockDescriptor* descP);
#endif
-static ERL_NIF_TERM ngetopt_lvl_ip(ErlNifEnv* env,
- SocketDescriptor* descP,
- int eOpt);
+static ERL_NIF_TERM ngetopt_lvl_ip(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ int eOpt);
#if defined(IP_FREEBIND)
-static ERL_NIF_TERM ngetopt_lvl_ip_freebind(ErlNifEnv* env,
- SocketDescriptor* descP);
+static ERL_NIF_TERM ngetopt_lvl_ip_freebind(ErlNifEnv* env,
+ ESockDescriptor* descP);
#endif
#if defined(IP_HDRINCL)
-static ERL_NIF_TERM ngetopt_lvl_ip_hdrincl(ErlNifEnv* env,
- SocketDescriptor* descP);
+static ERL_NIF_TERM ngetopt_lvl_ip_hdrincl(ErlNifEnv* env,
+ ESockDescriptor* descP);
#endif
#if defined(IP_MINTTL)
-static ERL_NIF_TERM ngetopt_lvl_ip_minttl(ErlNifEnv* env,
- SocketDescriptor* descP);
+static ERL_NIF_TERM ngetopt_lvl_ip_minttl(ErlNifEnv* env,
+ ESockDescriptor* descP);
#endif
#if defined(IP_MTU)
-static ERL_NIF_TERM ngetopt_lvl_ip_mtu(ErlNifEnv* env,
- SocketDescriptor* descP);
+static ERL_NIF_TERM ngetopt_lvl_ip_mtu(ErlNifEnv* env,
+ ESockDescriptor* descP);
#endif
#if defined(IP_MTU_DISCOVER)
-static ERL_NIF_TERM ngetopt_lvl_ip_mtu_discover(ErlNifEnv* env,
- SocketDescriptor* descP);
+static ERL_NIF_TERM ngetopt_lvl_ip_mtu_discover(ErlNifEnv* env,
+ ESockDescriptor* descP);
#endif
#if defined(IP_MULTICAST_ALL)
-static ERL_NIF_TERM ngetopt_lvl_ip_multicast_all(ErlNifEnv* env,
- SocketDescriptor* descP);
+static ERL_NIF_TERM ngetopt_lvl_ip_multicast_all(ErlNifEnv* env,
+ ESockDescriptor* descP);
#endif
#if defined(IP_MULTICAST_IF)
-static ERL_NIF_TERM ngetopt_lvl_ip_multicast_if(ErlNifEnv* env,
- SocketDescriptor* descP);
+static ERL_NIF_TERM ngetopt_lvl_ip_multicast_if(ErlNifEnv* env,
+ ESockDescriptor* descP);
#endif
#if defined(IP_MULTICAST_LOOP)
-static ERL_NIF_TERM ngetopt_lvl_ip_multicast_loop(ErlNifEnv* env,
- SocketDescriptor* descP);
+static ERL_NIF_TERM ngetopt_lvl_ip_multicast_loop(ErlNifEnv* env,
+ ESockDescriptor* descP);
#endif
#if defined(IP_MULTICAST_TTL)
-static ERL_NIF_TERM ngetopt_lvl_ip_multicast_ttl(ErlNifEnv* env,
- SocketDescriptor* descP);
+static ERL_NIF_TERM ngetopt_lvl_ip_multicast_ttl(ErlNifEnv* env,
+ ESockDescriptor* descP);
#endif
#if defined(IP_NODEFRAG)
-static ERL_NIF_TERM ngetopt_lvl_ip_nodefrag(ErlNifEnv* env,
- SocketDescriptor* descP);
+static ERL_NIF_TERM ngetopt_lvl_ip_nodefrag(ErlNifEnv* env,
+ ESockDescriptor* descP);
#endif
#if defined(IP_PKTINFO)
-static ERL_NIF_TERM ngetopt_lvl_ip_pktinfo(ErlNifEnv* env,
- SocketDescriptor* descP);
+static ERL_NIF_TERM ngetopt_lvl_ip_pktinfo(ErlNifEnv* env,
+ ESockDescriptor* descP);
#endif
#if defined(IP_RECVDSTADDR)
-static ERL_NIF_TERM ngetopt_lvl_ip_recvdstaddr(ErlNifEnv* env,
- SocketDescriptor* descP);
+static ERL_NIF_TERM ngetopt_lvl_ip_recvdstaddr(ErlNifEnv* env,
+ ESockDescriptor* descP);
#endif
#if defined(IP_RECVERR)
-static ERL_NIF_TERM ngetopt_lvl_ip_recverr(ErlNifEnv* env,
- SocketDescriptor* descP);
+static ERL_NIF_TERM ngetopt_lvl_ip_recverr(ErlNifEnv* env,
+ ESockDescriptor* descP);
#endif
#if defined(IP_RECVIF)
-static ERL_NIF_TERM ngetopt_lvl_ip_recvif(ErlNifEnv* env,
- SocketDescriptor* descP);
+static ERL_NIF_TERM ngetopt_lvl_ip_recvif(ErlNifEnv* env,
+ ESockDescriptor* descP);
#endif
#if defined(IP_RECVOPTS)
-static ERL_NIF_TERM ngetopt_lvl_ip_recvopts(ErlNifEnv* env,
- SocketDescriptor* descP);
+static ERL_NIF_TERM ngetopt_lvl_ip_recvopts(ErlNifEnv* env,
+ ESockDescriptor* descP);
#endif
#if defined(IP_RECVORIGDSTADDR)
-static ERL_NIF_TERM ngetopt_lvl_ip_recvorigdstaddr(ErlNifEnv* env,
- SocketDescriptor* descP);
+static ERL_NIF_TERM ngetopt_lvl_ip_recvorigdstaddr(ErlNifEnv* env,
+ ESockDescriptor* descP);
#endif
#if defined(IP_RECVTOS)
-static ERL_NIF_TERM ngetopt_lvl_ip_recvtos(ErlNifEnv* env,
- SocketDescriptor* descP);
+static ERL_NIF_TERM ngetopt_lvl_ip_recvtos(ErlNifEnv* env,
+ ESockDescriptor* descP);
#endif
#if defined(IP_RECVTTL)
-static ERL_NIF_TERM ngetopt_lvl_ip_recvttl(ErlNifEnv* env,
- SocketDescriptor* descP);
+static ERL_NIF_TERM ngetopt_lvl_ip_recvttl(ErlNifEnv* env,
+ ESockDescriptor* descP);
#endif
#if defined(IP_RETOPTS)
-static ERL_NIF_TERM ngetopt_lvl_ip_retopts(ErlNifEnv* env,
- SocketDescriptor* descP);
+static ERL_NIF_TERM ngetopt_lvl_ip_retopts(ErlNifEnv* env,
+ ESockDescriptor* descP);
#endif
#if defined(IP_ROUTER_ALERT)
-static ERL_NIF_TERM ngetopt_lvl_ip_router_alert(ErlNifEnv* env,
- SocketDescriptor* descP);
+static ERL_NIF_TERM ngetopt_lvl_ip_router_alert(ErlNifEnv* env,
+ ESockDescriptor* descP);
#endif
#if defined(IP_SENDSRCADDR)
-static ERL_NIF_TERM ngetopt_lvl_ip_sendsrcaddr(ErlNifEnv* env,
- SocketDescriptor* descP);
+static ERL_NIF_TERM ngetopt_lvl_ip_sendsrcaddr(ErlNifEnv* env,
+ ESockDescriptor* descP);
#endif
#if defined(IP_TOS)
-static ERL_NIF_TERM ngetopt_lvl_ip_tos(ErlNifEnv* env,
- SocketDescriptor* descP);
+static ERL_NIF_TERM ngetopt_lvl_ip_tos(ErlNifEnv* env,
+ ESockDescriptor* descP);
#endif
#if defined(IP_TRANSPARENT)
-static ERL_NIF_TERM ngetopt_lvl_ip_transparent(ErlNifEnv* env,
- SocketDescriptor* descP);
+static ERL_NIF_TERM ngetopt_lvl_ip_transparent(ErlNifEnv* env,
+ ESockDescriptor* descP);
#endif
#if defined(IP_TTL)
-static ERL_NIF_TERM ngetopt_lvl_ip_ttl(ErlNifEnv* env,
- SocketDescriptor* descP);
+static ERL_NIF_TERM ngetopt_lvl_ip_ttl(ErlNifEnv* env,
+ ESockDescriptor* descP);
#endif
#if defined(HAVE_IPV6)
-static ERL_NIF_TERM ngetopt_lvl_ipv6(ErlNifEnv* env,
- SocketDescriptor* descP,
- int eOpt);
+static ERL_NIF_TERM ngetopt_lvl_ipv6(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ int eOpt);
#if defined(IPV6_AUTHHDR)
-static ERL_NIF_TERM ngetopt_lvl_ipv6_authhdr(ErlNifEnv* env,
- SocketDescriptor* descP);
+static ERL_NIF_TERM ngetopt_lvl_ipv6_authhdr(ErlNifEnv* env,
+ ESockDescriptor* descP);
#endif
#if defined(IPV6_DSTOPTS)
-static ERL_NIF_TERM ngetopt_lvl_ipv6_dstopts(ErlNifEnv* env,
- SocketDescriptor* descP);
+static ERL_NIF_TERM ngetopt_lvl_ipv6_dstopts(ErlNifEnv* env,
+ ESockDescriptor* descP);
#endif
#if defined(IPV6_FLOWINFO)
-static ERL_NIF_TERM ngetopt_lvl_ipv6_flowinfo(ErlNifEnv* env,
- SocketDescriptor* descP);
+static ERL_NIF_TERM ngetopt_lvl_ipv6_flowinfo(ErlNifEnv* env,
+ ESockDescriptor* descP);
#endif
#if defined(IPV6_HOPLIMIT)
-static ERL_NIF_TERM ngetopt_lvl_ipv6_hoplimit(ErlNifEnv* env,
- SocketDescriptor* descP);
+static ERL_NIF_TERM ngetopt_lvl_ipv6_hoplimit(ErlNifEnv* env,
+ ESockDescriptor* descP);
#endif
#if defined(IPV6_HOPOPTS)
-static ERL_NIF_TERM ngetopt_lvl_ipv6_hopopts(ErlNifEnv* env,
- SocketDescriptor* descP);
+static ERL_NIF_TERM ngetopt_lvl_ipv6_hopopts(ErlNifEnv* env,
+ ESockDescriptor* descP);
#endif
#if defined(IPV6_MTU)
-static ERL_NIF_TERM ngetopt_lvl_ipv6_mtu(ErlNifEnv* env,
- SocketDescriptor* descP);
+static ERL_NIF_TERM ngetopt_lvl_ipv6_mtu(ErlNifEnv* env,
+ ESockDescriptor* descP);
#endif
#if defined(IPV6_MTU_DISCOVER)
-static ERL_NIF_TERM ngetopt_lvl_ipv6_mtu_discover(ErlNifEnv* env,
- SocketDescriptor* descP);
+static ERL_NIF_TERM ngetopt_lvl_ipv6_mtu_discover(ErlNifEnv* env,
+ ESockDescriptor* descP);
#endif
#if defined(IPV6_MULTICAST_HOPS)
-static ERL_NIF_TERM ngetopt_lvl_ipv6_multicast_hops(ErlNifEnv* env,
- SocketDescriptor* descP);
+static ERL_NIF_TERM ngetopt_lvl_ipv6_multicast_hops(ErlNifEnv* env,
+ ESockDescriptor* descP);
#endif
#if defined(IPV6_MULTICAST_IF)
-static ERL_NIF_TERM ngetopt_lvl_ipv6_multicast_if(ErlNifEnv* env,
- SocketDescriptor* descP);
+static ERL_NIF_TERM ngetopt_lvl_ipv6_multicast_if(ErlNifEnv* env,
+ ESockDescriptor* descP);
#endif
#if defined(IPV6_MULTICAST_LOOP)
-static ERL_NIF_TERM ngetopt_lvl_ipv6_multicast_loop(ErlNifEnv* env,
- SocketDescriptor* descP);
+static ERL_NIF_TERM ngetopt_lvl_ipv6_multicast_loop(ErlNifEnv* env,
+ ESockDescriptor* descP);
#endif
#if defined(IPV6_RECVERR)
-static ERL_NIF_TERM ngetopt_lvl_ipv6_recverr(ErlNifEnv* env,
- SocketDescriptor* descP);
+static ERL_NIF_TERM ngetopt_lvl_ipv6_recverr(ErlNifEnv* env,
+ ESockDescriptor* descP);
#endif
#if defined(IPV6_RECVPKTINFO) || defined(IPV6_PKTINFO)
-static ERL_NIF_TERM ngetopt_lvl_ipv6_recvpktinfo(ErlNifEnv* env,
- SocketDescriptor* descP);
+static ERL_NIF_TERM ngetopt_lvl_ipv6_recvpktinfo(ErlNifEnv* env,
+ ESockDescriptor* descP);
#endif
#if defined(IPV6_ROUTER_ALERT)
-static ERL_NIF_TERM ngetopt_lvl_ipv6_router_alert(ErlNifEnv* env,
- SocketDescriptor* descP);
+static ERL_NIF_TERM ngetopt_lvl_ipv6_router_alert(ErlNifEnv* env,
+ ESockDescriptor* descP);
#endif
#if defined(IPV6_RTHDR)
-static ERL_NIF_TERM ngetopt_lvl_ipv6_rthdr(ErlNifEnv* env,
- SocketDescriptor* descP);
+static ERL_NIF_TERM ngetopt_lvl_ipv6_rthdr(ErlNifEnv* env,
+ ESockDescriptor* descP);
#endif
#if defined(IPV6_UNICAST_HOPS)
-static ERL_NIF_TERM ngetopt_lvl_ipv6_unicast_hops(ErlNifEnv* env,
- SocketDescriptor* descP);
+static ERL_NIF_TERM ngetopt_lvl_ipv6_unicast_hops(ErlNifEnv* env,
+ ESockDescriptor* descP);
#endif
#if defined(IPV6_V6ONLY)
-static ERL_NIF_TERM ngetopt_lvl_ipv6_v6only(ErlNifEnv* env,
- SocketDescriptor* descP);
+static ERL_NIF_TERM ngetopt_lvl_ipv6_v6only(ErlNifEnv* env,
+ ESockDescriptor* descP);
#endif
#endif // defined(HAVE_IPV6)
-static ERL_NIF_TERM ngetopt_lvl_tcp(ErlNifEnv* env,
- SocketDescriptor* descP,
- int eOpt);
+static ERL_NIF_TERM ngetopt_lvl_tcp(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ int eOpt);
#if defined(TCP_CONGESTION)
-static ERL_NIF_TERM ngetopt_lvl_tcp_congestion(ErlNifEnv* env,
- SocketDescriptor* descP);
+static ERL_NIF_TERM ngetopt_lvl_tcp_congestion(ErlNifEnv* env,
+ ESockDescriptor* descP);
#endif
#if defined(TCP_MAXSEG)
-static ERL_NIF_TERM ngetopt_lvl_tcp_maxseg(ErlNifEnv* env,
- SocketDescriptor* descP);
+static ERL_NIF_TERM ngetopt_lvl_tcp_maxseg(ErlNifEnv* env,
+ ESockDescriptor* descP);
#endif
#if defined(TCP_NODELAY)
-static ERL_NIF_TERM ngetopt_lvl_tcp_nodelay(ErlNifEnv* env,
- SocketDescriptor* descP);
+static ERL_NIF_TERM ngetopt_lvl_tcp_nodelay(ErlNifEnv* env,
+ ESockDescriptor* descP);
#endif
-static ERL_NIF_TERM ngetopt_lvl_udp(ErlNifEnv* env,
- SocketDescriptor* descP,
- int eOpt);
+static ERL_NIF_TERM ngetopt_lvl_udp(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ int eOpt);
#if defined(UDP_CORK)
-static ERL_NIF_TERM ngetopt_lvl_udp_cork(ErlNifEnv* env,
- SocketDescriptor* descP);
+static ERL_NIF_TERM ngetopt_lvl_udp_cork(ErlNifEnv* env,
+ ESockDescriptor* descP);
#endif
#if defined(HAVE_SCTP)
-static ERL_NIF_TERM ngetopt_lvl_sctp(ErlNifEnv* env,
- SocketDescriptor* descP,
- int eOpt);
+static ERL_NIF_TERM ngetopt_lvl_sctp(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ int eOpt);
#if defined(SCTP_ASSOCINFO)
-static ERL_NIF_TERM ngetopt_lvl_sctp_associnfo(ErlNifEnv* env,
- SocketDescriptor* descP);
+static ERL_NIF_TERM ngetopt_lvl_sctp_associnfo(ErlNifEnv* env,
+ ESockDescriptor* descP);
#endif
#if defined(SCTP_AUTOCLOSE)
-static ERL_NIF_TERM ngetopt_lvl_sctp_autoclose(ErlNifEnv* env,
- SocketDescriptor* descP);
+static ERL_NIF_TERM ngetopt_lvl_sctp_autoclose(ErlNifEnv* env,
+ ESockDescriptor* descP);
#endif
#if defined(SCTP_DISABLE_FRAGMENTS)
-static ERL_NIF_TERM ngetopt_lvl_sctp_disable_fragments(ErlNifEnv* env,
- SocketDescriptor* descP);
+static ERL_NIF_TERM ngetopt_lvl_sctp_disable_fragments(ErlNifEnv* env,
+ ESockDescriptor* descP);
#endif
#if defined(SCTP_MAXSEG)
-static ERL_NIF_TERM ngetopt_lvl_sctp_maxseg(ErlNifEnv* env,
- SocketDescriptor* descP);
+static ERL_NIF_TERM ngetopt_lvl_sctp_maxseg(ErlNifEnv* env,
+ ESockDescriptor* descP);
#endif
#if defined(SCTP_INITMSG)
-static ERL_NIF_TERM ngetopt_lvl_sctp_initmsg(ErlNifEnv* env,
- SocketDescriptor* descP);
+static ERL_NIF_TERM ngetopt_lvl_sctp_initmsg(ErlNifEnv* env,
+ ESockDescriptor* descP);
#endif
#if defined(SCTP_NODELAY)
-static ERL_NIF_TERM ngetopt_lvl_sctp_nodelay(ErlNifEnv* env,
- SocketDescriptor* descP);
+static ERL_NIF_TERM ngetopt_lvl_sctp_nodelay(ErlNifEnv* env,
+ ESockDescriptor* descP);
#endif
#if defined(SCTP_RTOINFO)
-static ERL_NIF_TERM ngetopt_lvl_sctp_rtoinfo(ErlNifEnv* env,
- SocketDescriptor* descP);
+static ERL_NIF_TERM ngetopt_lvl_sctp_rtoinfo(ErlNifEnv* env,
+ ESockDescriptor* descP);
#endif
#endif // defined(HAVE_SCTP)
-static ERL_NIF_TERM nsockname(ErlNifEnv* env,
- SocketDescriptor* descP);
-static ERL_NIF_TERM npeername(ErlNifEnv* env,
- SocketDescriptor* descP);
-static ERL_NIF_TERM ncancel(ErlNifEnv* env,
- SocketDescriptor* descP,
- ERL_NIF_TERM op,
- ERL_NIF_TERM sockRef,
- ERL_NIF_TERM opRef);
-static ERL_NIF_TERM ncancel_connect(ErlNifEnv* env,
- SocketDescriptor* descP,
- ERL_NIF_TERM opRef);
-static ERL_NIF_TERM ncancel_accept(ErlNifEnv* env,
- SocketDescriptor* descP,
- ERL_NIF_TERM sockRef,
- ERL_NIF_TERM opRef);
-static ERL_NIF_TERM ncancel_accept_current(ErlNifEnv* env,
- SocketDescriptor* descP,
- ERL_NIF_TERM sockRef);
-static ERL_NIF_TERM ncancel_accept_waiting(ErlNifEnv* env,
- SocketDescriptor* descP,
- ERL_NIF_TERM opRef);
-static ERL_NIF_TERM ncancel_send(ErlNifEnv* env,
- SocketDescriptor* descP,
- ERL_NIF_TERM sockRef,
- ERL_NIF_TERM opRef);
-static ERL_NIF_TERM ncancel_send_current(ErlNifEnv* env,
- SocketDescriptor* descP,
- ERL_NIF_TERM sockRef);
-static ERL_NIF_TERM ncancel_send_waiting(ErlNifEnv* env,
- SocketDescriptor* descP,
- ERL_NIF_TERM opRef);
-static ERL_NIF_TERM ncancel_recv(ErlNifEnv* env,
- SocketDescriptor* descP,
- ERL_NIF_TERM sockRef,
- ERL_NIF_TERM opRef);
-static ERL_NIF_TERM ncancel_recv_current(ErlNifEnv* env,
- SocketDescriptor* descP,
- ERL_NIF_TERM sockRef);
-static ERL_NIF_TERM ncancel_recv_waiting(ErlNifEnv* env,
- SocketDescriptor* descP,
- ERL_NIF_TERM opRef);
-static ERL_NIF_TERM ncancel_read_select(ErlNifEnv* env,
- SocketDescriptor* descP,
- ERL_NIF_TERM opRef);
-static ERL_NIF_TERM ncancel_write_select(ErlNifEnv* env,
- SocketDescriptor* descP,
- ERL_NIF_TERM opRef);
-static ERL_NIF_TERM ncancel_mode_select(ErlNifEnv* env,
- SocketDescriptor* descP,
- ERL_NIF_TERM opRef,
- int smode,
- int rmode);
+static ERL_NIF_TERM nsockname(ErlNifEnv* env,
+ ESockDescriptor* descP);
+static ERL_NIF_TERM npeername(ErlNifEnv* env,
+ ESockDescriptor* descP);
+static ERL_NIF_TERM ncancel(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM op,
+ ERL_NIF_TERM sockRef,
+ ERL_NIF_TERM opRef);
+static ERL_NIF_TERM ncancel_connect(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM opRef);
+static ERL_NIF_TERM ncancel_accept(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM sockRef,
+ ERL_NIF_TERM opRef);
+static ERL_NIF_TERM ncancel_accept_current(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM sockRef);
+static ERL_NIF_TERM ncancel_accept_waiting(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM opRef);
+static ERL_NIF_TERM ncancel_send(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM sockRef,
+ ERL_NIF_TERM opRef);
+static ERL_NIF_TERM ncancel_send_current(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM sockRef);
+static ERL_NIF_TERM ncancel_send_waiting(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM opRef);
+static ERL_NIF_TERM ncancel_recv(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM sockRef,
+ ERL_NIF_TERM opRef);
+static ERL_NIF_TERM ncancel_recv_current(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM sockRef);
+static ERL_NIF_TERM ncancel_recv_waiting(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM opRef);
+static ERL_NIF_TERM ncancel_read_select(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM opRef);
+static ERL_NIF_TERM ncancel_write_select(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM opRef);
+static ERL_NIF_TERM ncancel_mode_select(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM opRef,
+ int smode,
+ int rmode);
#if defined(USE_SETOPT_STR_OPT)
-static ERL_NIF_TERM nsetopt_str_opt(ErlNifEnv* env,
- SocketDescriptor* descP,
- int level,
- int opt,
- int max,
- ERL_NIF_TERM eVal);
-#endif
-static ERL_NIF_TERM nsetopt_bool_opt(ErlNifEnv* env,
- SocketDescriptor* descP,
- int level,
- int opt,
- ERL_NIF_TERM eVal);
-static ERL_NIF_TERM nsetopt_int_opt(ErlNifEnv* env,
- SocketDescriptor* descP,
- int level,
- int opt,
- ERL_NIF_TERM eVal);
-static ERL_NIF_TERM nsetopt_timeval_opt(ErlNifEnv* env,
- SocketDescriptor* descP,
- int level,
- int opt,
- ERL_NIF_TERM eVal);
+static ERL_NIF_TERM nsetopt_str_opt(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ int level,
+ int opt,
+ int max,
+ ERL_NIF_TERM eVal);
+#endif
+static ERL_NIF_TERM nsetopt_bool_opt(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ int level,
+ int opt,
+ ERL_NIF_TERM eVal);
+static ERL_NIF_TERM nsetopt_int_opt(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ int level,
+ int opt,
+ ERL_NIF_TERM eVal);
+static ERL_NIF_TERM nsetopt_timeval_opt(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ int level,
+ int opt,
+ ERL_NIF_TERM eVal);
#if defined(USE_GETOPT_STR_OPT)
-static ERL_NIF_TERM ngetopt_str_opt(ErlNifEnv* env,
- SocketDescriptor* descP,
- int level,
- int opt,
- int max);
-#endif
-static ERL_NIF_TERM ngetopt_bool_opt(ErlNifEnv* env,
- SocketDescriptor* descP,
- int level,
- int opt);
-static ERL_NIF_TERM ngetopt_int_opt(ErlNifEnv* env,
- SocketDescriptor* descP,
- int level,
- int opt);
-static ERL_NIF_TERM ngetopt_timeval_opt(ErlNifEnv* env,
- SocketDescriptor* descP,
- int level,
- int opt);
-
-static BOOLEAN_T send_check_writer(ErlNifEnv* env,
- SocketDescriptor* descP,
- ERL_NIF_TERM ref,
- ERL_NIF_TERM* checkResult);
-static ERL_NIF_TERM send_check_result(ErlNifEnv* env,
- SocketDescriptor* descP,
- ssize_t written,
- ssize_t dataSize,
- int saveErrno,
- ERL_NIF_TERM sockRef,
- ERL_NIF_TERM sendRef);
-static BOOLEAN_T recv_check_reader(ErlNifEnv* env,
- SocketDescriptor* descP,
- ERL_NIF_TERM ref,
- ERL_NIF_TERM* checkResult);
-static char* recv_init_current_reader(ErlNifEnv* env,
- SocketDescriptor* descP,
- ERL_NIF_TERM ref);
-static ERL_NIF_TERM recv_update_current_reader(ErlNifEnv* env,
- SocketDescriptor* descP,
- ERL_NIF_TERM sockRef);
-static void recv_error_current_reader(ErlNifEnv* env,
- SocketDescriptor* descP,
- ERL_NIF_TERM sockRef,
- ERL_NIF_TERM reason);
-static ERL_NIF_TERM recv_check_result(ErlNifEnv* env,
- SocketDescriptor* descP,
- int read,
- int toRead,
- int saveErrno,
- ErlNifBinary* bufP,
- ERL_NIF_TERM sockRef,
- ERL_NIF_TERM recvRef);
-static ERL_NIF_TERM recvfrom_check_result(ErlNifEnv* env,
- SocketDescriptor* descP,
- int read,
- int saveErrno,
- ErlNifBinary* bufP,
- SocketAddress* fromAddrP,
- unsigned int fromAddrLen,
- ERL_NIF_TERM sockRef,
- ERL_NIF_TERM recvRef);
-static ERL_NIF_TERM recvmsg_check_result(ErlNifEnv* env,
- SocketDescriptor* descP,
- int read,
- int saveErrno,
- struct msghdr* msgHdrP,
- ErlNifBinary* dataBufP,
- ErlNifBinary* ctrlBufP,
- ERL_NIF_TERM sockRef,
- ERL_NIF_TERM recvRef);
-
-static ERL_NIF_TERM nfinalize_connection(ErlNifEnv* env,
- SocketDescriptor* descP);
-static ERL_NIF_TERM nfinalize_close(ErlNifEnv* env,
- SocketDescriptor* descP);
-
-extern char* encode_msghdr(ErlNifEnv* env,
- SocketDescriptor* descP,
- int read,
- struct msghdr* msgHdrP,
- ErlNifBinary* dataBufP,
- ErlNifBinary* ctrlBufP,
- ERL_NIF_TERM* eSockAddr);
-extern char* encode_cmsghdrs(ErlNifEnv* env,
- SocketDescriptor* descP,
- ErlNifBinary* cmsgBinP,
- struct msghdr* msgHdrP,
- ERL_NIF_TERM* eCMsgHdr);
-extern char* decode_cmsghdrs(ErlNifEnv* env,
- SocketDescriptor* descP,
- ERL_NIF_TERM eCMsgHdr,
- char* cmsgHdrBufP,
- size_t cmsgHdrBufLen,
- size_t* cmsgHdrBufUsed);
-extern char* decode_cmsghdr(ErlNifEnv* env,
- SocketDescriptor* descP,
- ERL_NIF_TERM eCMsgHdr,
- char* bufP,
- size_t rem,
- size_t* used);
+static ERL_NIF_TERM ngetopt_str_opt(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ int level,
+ int opt,
+ int max);
+#endif
+static ERL_NIF_TERM ngetopt_bool_opt(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ int level,
+ int opt);
+static ERL_NIF_TERM ngetopt_int_opt(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ int level,
+ int opt);
+static ERL_NIF_TERM ngetopt_timeval_opt(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ int level,
+ int opt);
+
+static BOOLEAN_T send_check_writer(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM ref,
+ ERL_NIF_TERM* checkResult);
+static ERL_NIF_TERM send_check_result(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ssize_t written,
+ ssize_t dataSize,
+ int saveErrno,
+ ERL_NIF_TERM sockRef,
+ ERL_NIF_TERM sendRef);
+static ERL_NIF_TERM send_check_ok(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ssize_t written,
+ ssize_t dataSize,
+ ERL_NIF_TERM sockRef);
+static ERL_NIF_TERM send_check_fail(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ int saveErrno,
+ ERL_NIF_TERM sockRef);
+static ERL_NIF_TERM send_check_retry(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ssize_t written,
+ ERL_NIF_TERM sockRef,
+ ERL_NIF_TERM sendRef);
+static BOOLEAN_T recv_check_reader(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM ref,
+ ERL_NIF_TERM* checkResult);
+static char* recv_init_current_reader(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM ref);
+static ERL_NIF_TERM recv_update_current_reader(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM sockRef);
+static void recv_error_current_reader(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM sockRef,
+ ERL_NIF_TERM reason);
+static ERL_NIF_TERM recv_check_result(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ int read,
+ int toRead,
+ int saveErrno,
+ ErlNifBinary* bufP,
+ ERL_NIF_TERM sockRef,
+ ERL_NIF_TERM recvRef);
+static ERL_NIF_TERM recv_check_full(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ int read,
+ int toRead,
+ ErlNifBinary* bufP,
+ ERL_NIF_TERM sockRef,
+ ERL_NIF_TERM recvRef);
+static ERL_NIF_TERM recv_check_full_maybe_done(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ int read,
+ int toRead,
+ ErlNifBinary* bufP,
+ ERL_NIF_TERM sockRef,
+ ERL_NIF_TERM recvRef);
+static ERL_NIF_TERM recv_check_full_done(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ int read,
+ ErlNifBinary* bufP,
+ ERL_NIF_TERM sockRef);
+static ERL_NIF_TERM recv_check_fail(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ int saveErrno,
+ ErlNifBinary* buf1P,
+ ErlNifBinary* buf2P,
+ ERL_NIF_TERM sockRef,
+ ERL_NIF_TERM recvRef);
+static ERL_NIF_TERM recv_check_fail_closed(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM sockRef,
+ ERL_NIF_TERM recvRef);
+static ERL_NIF_TERM recv_check_partial(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ int read,
+ int toRead,
+ ErlNifBinary* bufP,
+ ERL_NIF_TERM sockRef,
+ ERL_NIF_TERM recvRef);
+static ERL_NIF_TERM recv_check_partial_done(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ int read,
+ ErlNifBinary* bufP,
+ ERL_NIF_TERM sockRef);
+static ERL_NIF_TERM recv_check_partial_part(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ int read,
+ ErlNifBinary* bufP,
+ ERL_NIF_TERM sockRef,
+ ERL_NIF_TERM recvRef);
+static ERL_NIF_TERM recv_check_retry(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM sockRef,
+ ERL_NIF_TERM recvRef);
+static ERL_NIF_TERM recv_check_fail_gen(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ int saveErrno,
+ ERL_NIF_TERM sockRef);
+static ERL_NIF_TERM recvfrom_check_result(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ int read,
+ int saveErrno,
+ ErlNifBinary* bufP,
+ ESockAddress* fromAddrP,
+ unsigned int fromAddrLen,
+ ERL_NIF_TERM sockRef,
+ ERL_NIF_TERM recvRef);
+static ERL_NIF_TERM recvmsg_check_result(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ int read,
+ int saveErrno,
+ struct msghdr* msgHdrP,
+ ErlNifBinary* dataBufP,
+ ErlNifBinary* ctrlBufP,
+ ERL_NIF_TERM sockRef,
+ ERL_NIF_TERM recvRef);
+static ERL_NIF_TERM recvmsg_check_msg(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ int read,
+ struct msghdr* msgHdrP,
+ ErlNifBinary* dataBufP,
+ ErlNifBinary* ctrlBufP,
+ ERL_NIF_TERM sockRef);
+
+static ERL_NIF_TERM nfinalize_connection(ErlNifEnv* env,
+ ESockDescriptor* descP);
+static ERL_NIF_TERM nfinalize_close(ErlNifEnv* env,
+ ESockDescriptor* descP);
+
+extern char* encode_msghdr(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ int read,
+ struct msghdr* msgHdrP,
+ ErlNifBinary* dataBufP,
+ ErlNifBinary* ctrlBufP,
+ ERL_NIF_TERM* eSockAddr);
+extern char* encode_cmsghdrs(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ErlNifBinary* cmsgBinP,
+ struct msghdr* msgHdrP,
+ ERL_NIF_TERM* eCMsgHdr);
+extern char* decode_cmsghdrs(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eCMsgHdr,
+ char* cmsgHdrBufP,
+ size_t cmsgHdrBufLen,
+ size_t* cmsgHdrBufUsed);
+extern char* decode_cmsghdr(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eCMsgHdr,
+ char* bufP,
+ size_t rem,
+ size_t* used);
static char* encode_cmsghdr_level(ErlNifEnv* env,
int level,
ERL_NIF_TERM* eLevel);
@@ -2182,26 +2288,26 @@ static char* encode_cmsghdr_data_ipv6(ErlNifEnv* env,
size_t dataLen,
ERL_NIF_TERM* eCMsgHdrData);
#endif
-extern char* encode_msghdr_flags(ErlNifEnv* env,
- SocketDescriptor* descP,
- int msgFlags,
- ERL_NIF_TERM* flags);
-static char* decode_cmsghdr_data(ErlNifEnv* env,
- SocketDescriptor* descP,
- char* bufP,
- size_t rem,
- int level,
- int type,
- ERL_NIF_TERM eData,
- size_t* used);
-static char* decode_cmsghdr_final(SocketDescriptor* descP,
- char* bufP,
- size_t rem,
- int level,
- int type,
- char* data,
- int sz,
- size_t* used);
+extern char* encode_msghdr_flags(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ int msgFlags,
+ ERL_NIF_TERM* flags);
+static char* decode_cmsghdr_data(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ char* bufP,
+ size_t rem,
+ int level,
+ int type,
+ ERL_NIF_TERM eData,
+ size_t* used);
+static char* decode_cmsghdr_final(ESockDescriptor* descP,
+ char* bufP,
+ size_t rem,
+ int level,
+ int type,
+ char* data,
+ int sz,
+ size_t* used);
static BOOLEAN_T decode_sock_linger(ErlNifEnv* env,
ERL_NIF_TERM eVal,
struct linger* valP);
@@ -2244,12 +2350,18 @@ static BOOLEAN_T decode_native_get_opt(ErlNifEnv* env,
// static void encode_bool(BOOLEAN_T val, ERL_NIF_TERM* eVal);
static ERL_NIF_TERM encode_ip_tos(ErlNifEnv* env, int val);
-static void inform_waiting_procs(ErlNifEnv* env,
- char* role,
- SocketDescriptor* descP,
- SocketRequestQueue* q,
- BOOLEAN_T free,
- ERL_NIF_TERM reason);
+static void socket_stop_handle_current(ErlNifEnv* env,
+ const char* role,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM sockRef,
+ ESockRequestor* reqP);
+static void inform_waiting_procs(ErlNifEnv* env,
+ const char* role,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM sockRef,
+ ESockRequestQueue* q,
+ BOOLEAN_T free,
+ ERL_NIF_TERM reason);
static int socket_setopt(int sock,
int level,
@@ -2257,9 +2369,9 @@ static int socket_setopt(int sock,
const void* optVal,
const socklen_t optLen);
-static BOOLEAN_T verify_is_connected(SocketDescriptor* descP, int* err);
+static BOOLEAN_T verify_is_connected(ESockDescriptor* descP, int* err);
-static SocketDescriptor* alloc_descriptor(SOCKET sock, HANDLE event);
+static ESockDescriptor* alloc_descriptor(SOCKET sock, HANDLE event);
static BOOLEAN_T edomain2domain(int edomain, int* domain);
@@ -2303,21 +2415,13 @@ static void dec_socket(int domain, int type, int protocol);
ACTIVATE_NEXT_FUNC_DEF(writer) \
ACTIVATE_NEXT_FUNC_DEF(reader)
-#define ACTIVATE_NEXT_FUNC_DEF(F) \
- static BOOLEAN_T activate_next_##F(ErlNifEnv* env, \
- SocketDescriptor* descP, \
- ERL_NIF_TERM sockRef);
+#define ACTIVATE_NEXT_FUNC_DEF(F) \
+ static BOOLEAN_T activate_next_##F(ErlNifEnv* env, \
+ ESockDescriptor* descP, \
+ ERL_NIF_TERM sockRef);
ACTIVATE_NEXT_FUNCS_DEFS
#undef ACTIVATE_NEXT_FUNC_DEF
-
-/*
-static BOOLEAN_T activate_next(ErlNifEnv* env,
- SocketDescriptor* descP,
- SocketRequestor* reqP,
- SocketRequestQueue* q,
- ERL_NIF_TERM sockRef);
-*/
-
+
/* *** acceptor_search4pid | writer_search4pid | reader_search4pid ***
* *** acceptor_push | writer_push | reader_push ***
* *** acceptor_pop | writer_pop | reader_pop ***
@@ -2333,48 +2437,51 @@ static BOOLEAN_T activate_next(ErlNifEnv* env,
ESOCK_OPERATOR_FUNCS_DEF(writer) \
ESOCK_OPERATOR_FUNCS_DEF(reader)
-#define ESOCK_OPERATOR_FUNCS_DEF(O) \
- static BOOLEAN_T O##_search4pid(ErlNifEnv* env, \
- SocketDescriptor* descP, \
- ErlNifPid* pid); \
- static ERL_NIF_TERM O##_push(ErlNifEnv* env, \
- SocketDescriptor* descP, \
- ErlNifPid pid, \
- ERL_NIF_TERM ref); \
- static BOOLEAN_T O##_pop(ErlNifEnv* env, \
- SocketDescriptor* descP, \
- SocketRequestor* reqP); \
- static BOOLEAN_T O##_unqueue(ErlNifEnv* env, \
- SocketDescriptor* descP, \
- const ErlNifPid* pid);
+#define ESOCK_OPERATOR_FUNCS_DEF(O) \
+ static BOOLEAN_T O##_search4pid(ErlNifEnv* env, \
+ ESockDescriptor* descP, \
+ ErlNifPid* pid); \
+ static ERL_NIF_TERM O##_push(ErlNifEnv* env, \
+ ESockDescriptor* descP, \
+ ErlNifPid pid, \
+ ERL_NIF_TERM ref); \
+ static BOOLEAN_T O##_pop(ErlNifEnv* env, \
+ ESockDescriptor* descP, \
+ ESockRequestor* reqP); \
+ static BOOLEAN_T O##_unqueue(ErlNifEnv* env, \
+ ESockDescriptor* descP, \
+ const ErlNifPid* pid);
ESOCK_OPERATOR_FUNCS_DEFS
#undef ESOCK_OPERATOR_FUNCS_DEF
-static BOOLEAN_T requestor_pop(SocketRequestQueue* q,
- SocketRequestor* reqP);
-
-static BOOLEAN_T qsearch4pid(ErlNifEnv* env,
- SocketRequestQueue* q,
- ErlNifPid* pid);
-static void qpush(SocketRequestQueue* q,
- SocketRequestQueueElement* e);
-static SocketRequestQueueElement* qpop(SocketRequestQueue* q);
-static BOOLEAN_T qunqueue(ErlNifEnv* env,
- SocketDescriptor* descP,
- const char* slogan,
- SocketRequestQueue* q,
- const ErlNifPid* pid);
-
-static int esock_monitor(const char* slogan,
- ErlNifEnv* env,
- SocketDescriptor* descP,
- const ErlNifPid* pid,
- ESockMonitor* mon);
-static int esock_demonitor(const char* slogan,
- ErlNifEnv* env,
- SocketDescriptor* descP,
- ESockMonitor* monP);
+static BOOLEAN_T requestor_pop(ESockRequestQueue* q,
+ ESockRequestor* reqP);
+
+static BOOLEAN_T qsearch4pid(ErlNifEnv* env,
+ ESockRequestQueue* q,
+ ErlNifPid* pid);
+static void qpush(ESockRequestQueue* q,
+ ESockRequestQueueElement* e);
+static ESockRequestQueueElement* qpop(ESockRequestQueue* q);
+static BOOLEAN_T qunqueue(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ const char* slogan,
+ ESockRequestQueue* q,
+ const ErlNifPid* pid);
+
+static int esock_monitor(const char* slogan,
+ ErlNifEnv* env,
+ ESockDescriptor* descP,
+ const ErlNifPid* pid,
+ ESockMonitor* mon);
+static int esock_demonitor(const char* slogan,
+ ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ESockMonitor* monP);
static void esock_monitor_init(ESockMonitor* mon);
+static ERL_NIF_TERM esock_make_monitor_term(ErlNifEnv* env,
+ const ESockMonitor* monP);
+
#endif // if defined(__WIN32__)
@@ -2396,48 +2503,62 @@ static void socket_down(ErlNifEnv* env,
#if !defined(__WIN32__)
-static void socket_down_acceptor(ErlNifEnv* env,
- SocketDescriptor* descP,
- ERL_NIF_TERM sockRef,
- const ErlNifPid* pid);
-static void socket_down_writer(ErlNifEnv* env,
- SocketDescriptor* descP,
- ERL_NIF_TERM sockRef,
- const ErlNifPid* pid);
-static void socket_down_reader(ErlNifEnv* env,
- SocketDescriptor* descP,
- ERL_NIF_TERM sockRef,
- const ErlNifPid* pid);
-
-static char* esock_send_close_msg(ErlNifEnv* env,
- SocketDescriptor* descP,
- ERL_NIF_TERM sockRef);
+static void socket_down_acceptor(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM sockRef,
+ const ErlNifPid* pid);
+static void socket_down_writer(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM sockRef,
+ const ErlNifPid* pid);
+static void socket_down_reader(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM sockRef,
+ const ErlNifPid* pid);
+
+static char* esock_send_close_msg(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ErlNifPid* pid);
static char* esock_send_abort_msg(ErlNifEnv* env,
ERL_NIF_TERM sockRef,
ERL_NIF_TERM recvRef,
+ ErlNifEnv* msgEnv,
ERL_NIF_TERM reason,
ErlNifPid* pid);
-static char* esock_send_socket_msg(ErlNifEnv* env,
- ERL_NIF_TERM sockRef,
- ERL_NIF_TERM tag,
- ERL_NIF_TERM info,
- ErlNifPid* pid,
- ErlNifEnv* msg_env);
static char* esock_send_msg(ErlNifEnv* env,
- ERL_NIF_TERM msg,
ErlNifPid* pid,
- ErlNifEnv* msg_env);
+ ERL_NIF_TERM msg,
+ ErlNifEnv* msgEnv);
+
+static ERL_NIF_TERM mk_abort_msg(ErlNifEnv* env,
+ ERL_NIF_TERM sockRef,
+ ERL_NIF_TERM opRef,
+ ERL_NIF_TERM reason);
+static ERL_NIF_TERM mk_close_msg(ErlNifEnv* env,
+ ERL_NIF_TERM sockRef,
+ ERL_NIF_TERM closeRef);
+static ERL_NIF_TERM mk_select_msg(ErlNifEnv* env,
+ ERL_NIF_TERM sockRef,
+ ERL_NIF_TERM selectRef);
+static ERL_NIF_TERM mk_socket_msg(ErlNifEnv* env,
+ ERL_NIF_TERM sockRef,
+ ERL_NIF_TERM tag,
+ ERL_NIF_TERM info);
+static ERL_NIF_TERM mk_socket(ErlNifEnv* env,
+ ERL_NIF_TERM sockRef);
static int esock_select_read(ErlNifEnv* env,
ErlNifEvent event,
void* obj,
const ErlNifPid* pid,
- ERL_NIF_TERM ref);
+ ERL_NIF_TERM sockRef,
+ ERL_NIF_TERM selectRef);
static int esock_select_write(ErlNifEnv* env,
ErlNifEvent event,
void* obj,
const ErlNifPid* pid,
- ERL_NIF_TERM ref);
+ ERL_NIF_TERM sockRef,
+ ERL_NIF_TERM selectRef);
static int esock_select_stop(ErlNifEnv* env,
ErlNifEvent event,
void* obj);
@@ -2786,7 +2907,30 @@ static ErlNifResourceTypeInit socketInit = {
};
// Initiated when the nif is loaded
-static SocketData data;
+static ESockData data;
+
+
+/* These two (inline) functions are primarily intended for debugging,
+ * that is, to make it easy to add debug printouts.
+ */
+static ESOCK_INLINE void esock_free_env(const char* slogan, ErlNifEnv* env)
+{
+ SGDBG( ("SOCKET", "env free - %s: 0x%lX\r\n", slogan, env) );
+ // esock_dbg_printf("SOCK ENV", "free - %s: 0x%lX\r\n", slogan, env);
+
+ if (env != NULL) enif_free_env(env);
+}
+
+
+static ESOCK_INLINE ErlNifEnv* esock_alloc_env(const char* slogan)
+{
+ ErlNifEnv* env = enif_alloc_env();
+
+ SGDBG( ("SOCKET", "env alloc - %s: 0x%lX\r\n", slogan, env) );
+ // esock_dbg_printf("SOCK ENV", "alloc - %s: 0x%lX\r\n", slogan, env);
+
+ return env;
+}
/* ----------------------------------------------------------------------
@@ -4282,13 +4426,13 @@ ERL_NIF_TERM nopen(ErlNifEnv* env,
int domain, int type, int protocol,
char* netns)
{
- SocketDescriptor* descP;
- ERL_NIF_TERM res;
- int save_errno = 0;
- SOCKET sock;
- HANDLE event;
+ ESockDescriptor* descP;
+ ERL_NIF_TERM res;
+ int save_errno = 0;
+ SOCKET sock;
+ HANDLE event;
#ifdef HAVE_SETNS
- int current_ns = 0;
+ int current_ns = 0;
#endif
SGDBG( ("SOCKET", "nopen -> entry with"
@@ -4502,11 +4646,11 @@ ERL_NIF_TERM nif_bind(ErlNifEnv* env,
#if defined(__WIN32__)
return enif_raise_exception(env, MKA(env, "notsup"));
#else
- SocketDescriptor* descP;
- ERL_NIF_TERM eSockAddr;
- SocketAddress sockAddr;
- unsigned int addrLen;
- char* xres;
+ ESockDescriptor* descP;
+ ERL_NIF_TERM eSockAddr;
+ ESockAddress sockAddr;
+ unsigned int addrLen;
+ char* xres;
SGDBG( ("SOCKET", "nif_bind -> entry with argc: %d\r\n", argc) );
@@ -4544,10 +4688,10 @@ ERL_NIF_TERM nif_bind(ErlNifEnv* env,
#if !defined(__WIN32__)
static
-ERL_NIF_TERM nbind(ErlNifEnv* env,
- SocketDescriptor* descP,
- SocketAddress* sockAddrP,
- unsigned int addrLen)
+ERL_NIF_TERM nbind(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ESockAddress* sockAddrP,
+ unsigned int addrLen)
{
int port, ntohs_port;
@@ -4563,7 +4707,7 @@ ERL_NIF_TERM nbind(ErlNifEnv* env,
port = which_address_port(sockAddrP);
SSDBG( descP, ("SOCKET", "nbind -> port: %d\r\n", port) );
if (port == 0) {
- SOCKLEN_T len = sizeof(SocketAddress);
+ SOCKLEN_T len = sizeof(ESockAddress);
sys_memzero((char *) sockAddrP, len);
sock_name(descP->sock, &sockAddrP->sa, &len);
port = which_address_port(sockAddrP);
@@ -4603,16 +4747,17 @@ ERL_NIF_TERM nif_connect(ErlNifEnv* env,
#if defined(__WIN32__)
return enif_raise_exception(env, MKA(env, "notsup"));
#else
- SocketDescriptor* descP;
- ERL_NIF_TERM res, eSockAddr;
- char* xres;
+ ESockDescriptor* descP;
+ ERL_NIF_TERM res, eSockAddr, sockRef;
+ char* xres;
SGDBG( ("SOCKET", "nif_connect -> entry with argc: %d\r\n", argc) );
/* Extract arguments and perform preliminary validation */
+ sockRef = argv[0];
if ((argc != 2) ||
- !enif_get_resource(env, argv[0], sockets, (void**) &descP)) {
+ !enif_get_resource(env, sockRef, sockets, (void**) &descP)) {
return enif_make_badarg(env);
}
eSockAddr = argv[1];
@@ -4624,16 +4769,24 @@ ERL_NIF_TERM nif_connect(ErlNifEnv* env,
"\r\n", descP->sock, argv[0], eSockAddr) );
if ((xres = esock_decode_sockaddr(env, eSockAddr,
- &descP->remote, &descP->addrLen)) != NULL) {
+ &descP->remote,
+ &descP->addrLen)) != NULL) {
return esock_make_error_str(env, xres);
}
+ /* Only a *!%&$*# would send an opened but non-connected socket
+ * somewhere (before its actually usable), but just to be on the
+ * safe side we do the best we can to avoid complications...
+ */
+
MLOCK(descP->readMtx);
MLOCK(descP->writeMtx);
+ MLOCK(descP->cfgMtx);
- res = nconnect(env, descP);
+ res = nconnect(env, descP, sockRef);
+ MUNLOCK(descP->cfgMtx);
MUNLOCK(descP->writeMtx);
MUNLOCK(descP->readMtx);
@@ -4645,8 +4798,9 @@ ERL_NIF_TERM nif_connect(ErlNifEnv* env,
#if !defined(__WIN32__)
static
-ERL_NIF_TERM nconnect(ErlNifEnv* env,
- SocketDescriptor* descP)
+ERL_NIF_TERM nconnect(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM sockRef)
{
ERL_NIF_TERM res, ref;
int code, sres, save_errno = 0;
@@ -4691,7 +4845,8 @@ ERL_NIF_TERM nconnect(ErlNifEnv* env,
(save_errno == EINPROGRESS))) { /* Unix & OSE!! */
ref = MKREF(env);
descP->state = SOCKET_STATE_CONNECTING;
- if ((sres = esock_select_write(env, descP->sock, descP, NULL, ref)) < 0) {
+ if ((sres = esock_select_write(env, descP->sock, descP, NULL,
+ sockRef, ref)) < 0) {
res = esock_make_error(env,
MKT2(env,
esock_atom_select_failed,
@@ -4721,6 +4876,9 @@ ERL_NIF_TERM nconnect(ErlNifEnv* env,
*
* Description:
* Make socket ready for input and output.
+ * This function is called if we where made to wait when we called the
+ * nif_connect function (we made a select, and the select message has
+ * now been received).
*
* Arguments:
* Socket (ref) - Points to the socket descriptor.
@@ -4733,7 +4891,7 @@ ERL_NIF_TERM nif_finalize_connection(ErlNifEnv* env,
#if defined(__WIN32__)
return enif_raise_exception(env, MKA(env, "notsup"));
#else
- SocketDescriptor* descP;
+ ESockDescriptor* descP;
/* Extract arguments and perform preliminary validation */
@@ -4753,8 +4911,8 @@ ERL_NIF_TERM nif_finalize_connection(ErlNifEnv* env,
*/
#if !defined(__WIN32__)
static
-ERL_NIF_TERM nfinalize_connection(ErlNifEnv* env,
- SocketDescriptor* descP)
+ERL_NIF_TERM nfinalize_connection(ErlNifEnv* env,
+ ESockDescriptor* descP)
{
int error;
@@ -4780,7 +4938,7 @@ ERL_NIF_TERM nfinalize_connection(ErlNifEnv* env,
*/
#if !defined(__WIN32__)
static
-BOOLEAN_T verify_is_connected(SocketDescriptor* descP, int* err)
+BOOLEAN_T verify_is_connected(ESockDescriptor* descP, int* err)
{
/*
* *** This is strange ***
@@ -4848,8 +5006,8 @@ ERL_NIF_TERM nif_listen(ErlNifEnv* env,
#if defined(__WIN32__)
return enif_raise_exception(env, MKA(env, "notsup"));
#else
- SocketDescriptor* descP;
- int backlog;
+ ESockDescriptor* descP;
+ int backlog;
SGDBG( ("SOCKET", "nif_listen -> entry with argc: %d\r\n", argc) );
@@ -4876,9 +5034,9 @@ ERL_NIF_TERM nif_listen(ErlNifEnv* env,
#if !defined(__WIN32__)
static
-ERL_NIF_TERM nlisten(ErlNifEnv* env,
- SocketDescriptor* descP,
- int backlog)
+ERL_NIF_TERM nlisten(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ int backlog)
{
/*
@@ -4930,8 +5088,8 @@ ERL_NIF_TERM nif_accept(ErlNifEnv* env,
#if defined(__WIN32__)
return enif_raise_exception(env, MKA(env, "notsup"));
#else
- SocketDescriptor* descP;
- ERL_NIF_TERM sockRef, ref, res;
+ ESockDescriptor* descP;
+ ERL_NIF_TERM sockRef, ref, res;
SGDBG( ("SOCKET", "nif_accept -> entry with argc: %d\r\n", argc) );
@@ -4944,13 +5102,29 @@ ERL_NIF_TERM nif_accept(ErlNifEnv* env,
}
ref = argv[1];
+ MLOCK(descP->accMtx);
+
SSDBG( descP,
("SOCKET", "nif_accept -> args when sock = %d:"
- "\r\n Socket: %T"
- "\r\n ReqRef: %T"
- "\r\n", descP->sock, argv[0], ref) );
-
- MLOCK(descP->accMtx);
+ "\r\n Socket: %T"
+ "\r\n ReqRef: %T"
+ "\r\nwhen"
+ "\r\n State: %s"
+ "\r\n Current Acceptor Addr: 0x%lX"
+ "\r\n Current Acceptor pid: %T"
+ "\r\n Current Acceptor mon: %T"
+ "\r\n Current Acceptor env: 0x%lX"
+ "\r\n Current Acceptor ref: %T"
+ "\r\n",
+ descP->sock,
+ sockRef, ref,
+ ((descP->state == SOCKET_STATE_LISTENING) ? "listening" :
+ ((descP->state == SOCKET_STATE_ACCEPTING) ? "accepting" : "other")),
+ descP->currentAcceptorP,
+ descP->currentAcceptor.pid,
+ esock_make_monitor_term(env, &descP->currentAcceptor.mon),
+ descP->currentAcceptor.env,
+ descP->currentAcceptor.ref) );
res = naccept(env, descP, sockRef, ref);
@@ -4964,10 +5138,10 @@ ERL_NIF_TERM nif_accept(ErlNifEnv* env,
#if !defined(__WIN32__)
static
-ERL_NIF_TERM naccept(ErlNifEnv* env,
- SocketDescriptor* descP,
- ERL_NIF_TERM sockRef,
- ERL_NIF_TERM ref)
+ERL_NIF_TERM naccept(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM sockRef,
+ ERL_NIF_TERM ref)
{
ERL_NIF_TERM res;
@@ -4976,7 +5150,7 @@ ERL_NIF_TERM naccept(ErlNifEnv* env,
switch (descP->state) {
case SOCKET_STATE_LISTENING:
- res = naccept_listening(env, descP, ref);
+ res = naccept_listening(env, descP, sockRef, ref);
break;
case SOCKET_STATE_ACCEPTING:
@@ -4994,15 +5168,17 @@ ERL_NIF_TERM naccept(ErlNifEnv* env,
/* *** naccept_listening ***
- * We have no active acceptor (and no acceptors in queue).
+ *
+ * We have no active acceptor (and therefor no acceptors in queue).
*/
#if !defined(__WIN32__)
static
-ERL_NIF_TERM naccept_listening(ErlNifEnv* env,
- SocketDescriptor* descP,
- ERL_NIF_TERM ref)
+ERL_NIF_TERM naccept_listening(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM sockRef,
+ ERL_NIF_TERM accRef)
{
- SocketAddress remote;
+ ESockAddress remote;
unsigned int n;
SOCKET accSock;
int save_errno;
@@ -5026,7 +5202,8 @@ ERL_NIF_TERM naccept_listening(ErlNifEnv* env,
("SOCKET",
"naccept_listening -> accept failed (%d)\r\n", save_errno) );
- res = naccept_listening_error(env, descP, ref, caller, save_errno);
+ res = naccept_listening_error(env, descP, sockRef, accRef,
+ caller, save_errno);
} else {
@@ -5045,38 +5222,45 @@ ERL_NIF_TERM naccept_listening(ErlNifEnv* env,
/* *** naccept_listening_error ***
+ *
* The accept call resultet in an error - handle it.
* There are only two cases:
* 1) BLOCK => Attempt a "retry"
* 2) Other => Return the value (converted to an atom)
*/
static
-ERL_NIF_TERM naccept_listening_error(ErlNifEnv* env,
- SocketDescriptor* descP,
- ERL_NIF_TERM ref,
- ErlNifPid caller,
- int save_errno)
+ERL_NIF_TERM naccept_listening_error(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM sockRef,
+ ERL_NIF_TERM accRef,
+ ErlNifPid caller,
+ int save_errno)
{
ERL_NIF_TERM res;
if (save_errno == ERRNO_BLOCK) {
/* *** Try again later *** */
- SSDBG( descP, ("SOCKET", "naccept_listening_error -> would block\r\n") );
+
+ SSDBG( descP,
+ ("SOCKET", "naccept_listening_error -> would block\r\n") );
descP->currentAcceptor.pid = caller;
if (MONP("naccept_listening -> current acceptor",
env, descP,
&descP->currentAcceptor.pid,
- &descP->currentAcceptor.mon) != 0)
- return esock_make_error(env, atom_exmon);
-
- descP->currentAcceptor.ref = enif_make_copy(descP->env, ref);
- descP->currentAcceptorP = &descP->currentAcceptor;
-
- res = naccept_busy_retry(env, descP, ref, NULL, SOCKET_STATE_ACCEPTING);
-
-
+ &descP->currentAcceptor.mon) != 0) {
+ enif_set_pid_undefined(&descP->currentAcceptor.pid);
+ res = esock_make_error(env, atom_exmon);
+ } else {
+ descP->currentAcceptor.env = esock_alloc_env("current acceptor");
+ descP->currentAcceptor.ref = CP_TERM(descP->currentAcceptor.env,
+ accRef);
+ descP->currentAcceptorP = &descP->currentAcceptor;
+ res = naccept_busy_retry(env, descP,
+ sockRef, accRef,
+ NULL, SOCKET_STATE_ACCEPTING);
+ }
} else {
SSDBG( descP,
("SOCKET",
@@ -5089,14 +5273,15 @@ ERL_NIF_TERM naccept_listening_error(ErlNifEnv* env,
/* *** naccept_listening_accept ***
+ *
* The accept call was successful (accepted) - handle the new connection.
*/
static
-ERL_NIF_TERM naccept_listening_accept(ErlNifEnv* env,
- SocketDescriptor* descP,
- SOCKET accSock,
- ErlNifPid caller,
- SocketAddress* remote)
+ERL_NIF_TERM naccept_listening_accept(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ SOCKET accSock,
+ ErlNifPid caller,
+ ESockAddress* remote)
{
ERL_NIF_TERM res;
@@ -5109,16 +5294,17 @@ ERL_NIF_TERM naccept_listening_accept(ErlNifEnv* env,
/* *** naccept_accepting ***
+ *
* We have an active acceptor and possibly acceptors waiting in queue.
* If the pid of the calling process is not the pid of the "current process",
* push the requester onto the (acceptor) queue.
*/
#if !defined(__WIN32__)
static
-ERL_NIF_TERM naccept_accepting(ErlNifEnv* env,
- SocketDescriptor* descP,
- ERL_NIF_TERM sockRef,
- ERL_NIF_TERM ref)
+ERL_NIF_TERM naccept_accepting(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM sockRef,
+ ERL_NIF_TERM ref)
{
ErlNifPid caller;
ERL_NIF_TERM res;
@@ -5162,12 +5348,12 @@ ERL_NIF_TERM naccept_accepting(ErlNifEnv* env,
* Handles when the current acceptor makes another attempt.
*/
static
-ERL_NIF_TERM naccept_accepting_current(ErlNifEnv* env,
- SocketDescriptor* descP,
- ERL_NIF_TERM sockRef,
- ERL_NIF_TERM accRef)
+ERL_NIF_TERM naccept_accepting_current(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM sockRef,
+ ERL_NIF_TERM accRef)
{
- SocketAddress remote;
+ ESockAddress remote;
unsigned int n;
SOCKET accSock;
int save_errno;
@@ -5207,24 +5393,24 @@ ERL_NIF_TERM naccept_accepting_current(ErlNifEnv* env,
* handle the new connection.
*/
static
-ERL_NIF_TERM naccept_accepting_current_accept(ErlNifEnv* env,
- SocketDescriptor* descP,
- ERL_NIF_TERM sockRef,
- SOCKET accSock,
- SocketAddress* remote)
+ERL_NIF_TERM naccept_accepting_current_accept(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM sockRef,
+ SOCKET accSock,
+ ESockAddress* remote)
{
ERL_NIF_TERM res;
if (naccept_accepted(env, descP, accSock,
descP->currentAcceptor.pid, remote, &res)) {
- /* We should really go through the queue until we succeed to activate
- * a waiting acceptor. For now we just pop once and hope for the best...
- * This will leave any remaining acceptors *hanging*...
- *
- * We need a "activate-next" function.
- *
- */
+ /* Clean out the old cobweb's before trying to invite a new spider */
+
+ descP->currentAcceptor.ref = esock_atom_undefined;
+ enif_set_pid_undefined(&descP->currentAcceptor.pid);
+ esock_free_env("naccept_accepting_current_accept - "
+ "current-accept-env",
+ descP->currentAcceptor.env);
if (!activate_next_acceptor(env, descP, sockRef)) {
@@ -5236,9 +5422,8 @@ ERL_NIF_TERM naccept_accepting_current_accept(ErlNifEnv* env,
descP->state = SOCKET_STATE_LISTENING;
descP->currentAcceptorP = NULL;
- descP->currentAcceptor.ref = esock_atom_undefined;
- enif_set_pid_undefined(&descP->currentAcceptor.pid);
- esock_monitor_init(&descP->currentAcceptor.mon);
+ descP->currentAcceptor.env = NULL;
+ MON_INIT(&descP->currentAcceptor.mon);
}
}
@@ -5254,14 +5439,14 @@ ERL_NIF_TERM naccept_accepting_current_accept(ErlNifEnv* env,
* 2) Other => Return the value (converted to an atom)
*/
static
-ERL_NIF_TERM naccept_accepting_current_error(ErlNifEnv* env,
- SocketDescriptor* descP,
- ERL_NIF_TERM sockRef,
- ERL_NIF_TERM opRef,
- int save_errno)
+ERL_NIF_TERM naccept_accepting_current_error(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM sockRef,
+ ERL_NIF_TERM opRef,
+ int save_errno)
{
- SocketRequestor req;
- ERL_NIF_TERM res, reason;
+ ESockRequestor req;
+ ERL_NIF_TERM res, reason;
if (save_errno == ERRNO_BLOCK) {
@@ -5274,7 +5459,8 @@ ERL_NIF_TERM naccept_accepting_current_error(ErlNifEnv* env,
"naccept_accepting_current_error -> "
"would block: try again\r\n") );
- res = naccept_busy_retry(env, descP, opRef, &descP->currentAcceptor.pid,
+ res = naccept_busy_retry(env, descP, sockRef, opRef,
+ &descP->currentAcceptor.pid,
/* No state change */
descP->state);
@@ -5287,7 +5473,8 @@ ERL_NIF_TERM naccept_accepting_current_error(ErlNifEnv* env,
SSDBG( descP,
("SOCKET", "naccept_accepting_current_error -> abort %T\r\n",
req.pid) );
- esock_send_abort_msg(env, sockRef, req.ref, reason, &req.pid);
+ esock_send_abort_msg(env, sockRef, req.ref, req.env,
+ reason, &req.pid);
DEMONP("naccept_accepting_current_error -> pop'ed writer",
env, descP, &req.mon);
}
@@ -5304,10 +5491,10 @@ ERL_NIF_TERM naccept_accepting_current_error(ErlNifEnv* env,
* acceptor queue.
*/
static
-ERL_NIF_TERM naccept_accepting_other(ErlNifEnv* env,
- SocketDescriptor* descP,
- ERL_NIF_TERM ref,
- ErlNifPid caller)
+ERL_NIF_TERM naccept_accepting_other(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM ref,
+ ErlNifPid caller)
{
ERL_NIF_TERM result;
@@ -5323,25 +5510,28 @@ ERL_NIF_TERM naccept_accepting_other(ErlNifEnv* env,
/* *** naccept_busy_retry ***
+ *
* Perform a retry select. If successful, set nextState.
*/
#if !defined(__WIN32__)
static
-ERL_NIF_TERM naccept_busy_retry(ErlNifEnv* env,
- SocketDescriptor* descP,
- ERL_NIF_TERM ref,
- ErlNifPid* pid,
- unsigned int nextState)
+ERL_NIF_TERM naccept_busy_retry(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM sockRef,
+ ERL_NIF_TERM accRef,
+ ErlNifPid* pid,
+ unsigned int nextState)
{
int sres;
ERL_NIF_TERM res, reason;
- if ((sres = esock_select_read(env, descP->sock, descP, pid, ref)) < 0) {
+ if ((sres = esock_select_read(env, descP->sock, descP, pid,
+ sockRef, accRef)) < 0) {
reason = MKT2(env, esock_atom_select_failed, MKI(env, sres));
res = esock_make_error(env, reason);
} else {
descP->state = nextState;
- res = esock_make_error(env, esock_atom_eagain);
+ res = esock_make_error(env, esock_atom_eagain); // OK!!
}
return res;
@@ -5350,20 +5540,21 @@ ERL_NIF_TERM naccept_busy_retry(ErlNifEnv* env,
/* *** naccept_accepted ***
+ *
* Generic function handling a successful accept.
*/
static
-BOOLEAN_T naccept_accepted(ErlNifEnv* env,
- SocketDescriptor* descP,
- SOCKET accSock,
- ErlNifPid pid,
- SocketAddress* remote,
- ERL_NIF_TERM* result)
+BOOLEAN_T naccept_accepted(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ SOCKET accSock,
+ ErlNifPid pid,
+ ESockAddress* remote,
+ ERL_NIF_TERM* result)
{
- SocketDescriptor* accDescP;
- HANDLE accEvent;
- ERL_NIF_TERM accRef;
- int save_errno;
+ ESockDescriptor* accDescP;
+ HANDLE accEvent;
+ ERL_NIF_TERM accRef;
+ int save_errno;
/*
* We got one
@@ -5389,7 +5580,7 @@ BOOLEAN_T naccept_accepted(ErlNifEnv* env,
accDescP->rBufSz = descP->rBufSz; // Inherit buffer size
accDescP->rNum = descP->rNum; // Inherit buffer uses
accDescP->rNumCnt = 0;
- accDescP->rCtrlSz = descP->rCtrlSz; // Inherit buffer siez
+ accDescP->rCtrlSz = descP->rCtrlSz; // Inherit buffer size
accDescP->wCtrlSz = descP->wCtrlSz; // Inherit buffer size
accRef = enif_make_resource(env, accDescP);
@@ -5401,6 +5592,7 @@ BOOLEAN_T naccept_accepted(ErlNifEnv* env,
&accDescP->ctrlPid,
&accDescP->ctrlMon) != 0) {
sock_close(accSock);
+ enif_set_pid_undefined(&descP->ctrlPid);
*result = esock_make_error(env, atom_exmon);
return FALSE;
}
@@ -5442,12 +5634,12 @@ ERL_NIF_TERM nif_send(ErlNifEnv* env,
#if defined(__WIN32__)
return enif_raise_exception(env, MKA(env, "notsup"));
#else
- SocketDescriptor* descP;
- ERL_NIF_TERM sockRef, sendRef;
- ErlNifBinary sndData;
- unsigned int eflags;
- int flags;
- ERL_NIF_TERM res;
+ ESockDescriptor* descP;
+ ERL_NIF_TERM sockRef, sendRef;
+ ErlNifBinary sndData;
+ unsigned int eflags;
+ int flags;
+ ERL_NIF_TERM res;
SGDBG( ("SOCKET", "nif_send -> entry with argc: %d\r\n", argc) );
@@ -5484,11 +5676,6 @@ ERL_NIF_TERM nif_send(ErlNifEnv* env,
* this time (resulting in an select). The write of the
* other process must be made to wait until current
* is done!
- * Basically, we need a write queue!
- *
- * A 'writing' field (boolean), which is set if we did
- * not manage to write the entire message and reset every
- * time we do.
*/
res = nsend(env, descP, sockRef, sendRef, &sndData, flags);
@@ -5496,6 +5683,7 @@ ERL_NIF_TERM nif_send(ErlNifEnv* env,
MUNLOCK(descP->writeMtx);
return res;
+
#endif // if defined(__WIN32__)
}
@@ -5510,12 +5698,12 @@ ERL_NIF_TERM nif_send(ErlNifEnv* env,
*/
#if !defined(__WIN32__)
static
-ERL_NIF_TERM nsend(ErlNifEnv* env,
- SocketDescriptor* descP,
- ERL_NIF_TERM sockRef,
- ERL_NIF_TERM sendRef,
- ErlNifBinary* sndDataP,
- int flags)
+ERL_NIF_TERM nsend(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM sockRef,
+ ERL_NIF_TERM sendRef,
+ ErlNifBinary* sndDataP,
+ int flags)
{
int save_errno;
ssize_t written;
@@ -5570,16 +5758,16 @@ ERL_NIF_TERM nif_sendto(ErlNifEnv* env,
#if defined(__WIN32__)
return enif_raise_exception(env, MKA(env, "notsup"));
#else
- SocketDescriptor* descP;
- ERL_NIF_TERM sockRef, sendRef;
- ErlNifBinary sndData;
- unsigned int eflags;
- int flags;
- ERL_NIF_TERM eSockAddr;
- SocketAddress remoteAddr;
- unsigned int remoteAddrLen;
- char* xres;
- ERL_NIF_TERM res;
+ ESockDescriptor* descP;
+ ERL_NIF_TERM sockRef, sendRef;
+ ErlNifBinary sndData;
+ unsigned int eflags;
+ int flags;
+ ERL_NIF_TERM eSockAddr;
+ ESockAddress remoteAddr;
+ unsigned int remoteAddrLen;
+ char* xres;
+ ERL_NIF_TERM res;
SGDBG( ("SOCKET", "nif_sendto -> entry with argc: %d\r\n", argc) );
@@ -5617,7 +5805,8 @@ ERL_NIF_TERM nif_sendto(ErlNifEnv* env,
if ((xres = esock_decode_sockaddr(env, eSockAddr,
&remoteAddr,
&remoteAddrLen)) != NULL) {
- SSDBG( descP, ("SOCKET", "nif_sendto -> sockaddr decode: %s\r\n", xres) );
+ SSDBG( descP,
+ ("SOCKET", "nif_sendto -> sockaddr decode: %s\r\n", xres) );
return esock_make_error_str(env, xres);
}
@@ -5633,20 +5822,21 @@ ERL_NIF_TERM nif_sendto(ErlNifEnv* env,
"\r\n", res) );
return res;
+
#endif // if defined(__WIN32__)
}
#if !defined(__WIN32__)
static
-ERL_NIF_TERM nsendto(ErlNifEnv* env,
- SocketDescriptor* descP,
- ERL_NIF_TERM sockRef,
- ERL_NIF_TERM sendRef,
- ErlNifBinary* dataP,
- int flags,
- SocketAddress* toAddrP,
- unsigned int toAddrLen)
+ERL_NIF_TERM nsendto(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM sockRef,
+ ERL_NIF_TERM sendRef,
+ ErlNifBinary* dataP,
+ int flags,
+ ESockAddress* toAddrP,
+ unsigned int toAddrLen)
{
int save_errno;
ssize_t written;
@@ -5706,10 +5896,10 @@ ERL_NIF_TERM nif_sendmsg(ErlNifEnv* env,
#if defined(__WIN32__)
return enif_raise_exception(env, MKA(env, "notsup"));
#else
- ERL_NIF_TERM res, sockRef, sendRef, eMsgHdr;
- SocketDescriptor* descP;
- unsigned int eflags;
- int flags;
+ ERL_NIF_TERM res, sockRef, sendRef, eMsgHdr;
+ ESockDescriptor* descP;
+ unsigned int eflags;
+ int flags;
SGDBG( ("SOCKET", "nif_sendmsg -> entry with argc: %d\r\n", argc) );
@@ -5751,21 +5941,22 @@ ERL_NIF_TERM nif_sendmsg(ErlNifEnv* env,
"\r\n", res) );
return res;
+
#endif // if defined(__WIN32__)
}
#if !defined(__WIN32__)
static
-ERL_NIF_TERM nsendmsg(ErlNifEnv* env,
- SocketDescriptor* descP,
- ERL_NIF_TERM sockRef,
- ERL_NIF_TERM sendRef,
- ERL_NIF_TERM eMsgHdr,
- int flags)
+ERL_NIF_TERM nsendmsg(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM sockRef,
+ ERL_NIF_TERM sendRef,
+ ERL_NIF_TERM eMsgHdr,
+ int flags)
{
ERL_NIF_TERM res, eAddr, eIOV, eCtrl;
- SocketAddress addr;
+ ESockAddress addr;
struct msghdr msgHdr;
ErlNifBinary* iovBins;
struct iovec* iov;
@@ -5908,6 +6099,7 @@ ERL_NIF_TERM nsendmsg(ErlNifEnv* env,
if (ctrlBuf != NULL) FREE(ctrlBuf);
return res;
+
}
#endif // if !defined(__WIN32__)
@@ -5928,10 +6120,10 @@ ERL_NIF_TERM nsendmsg(ErlNifEnv* env,
#ifdef FOBAR
static
-ERL_NIF_TERM nwritev(ErlNifEnv* env,
- SocketDescriptor* descP,
- ERL_NIF_TERM sendRef,
- ERL_NIF_TERM data)
+ERL_NIF_TERM nwritev(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM sendRef,
+ ERL_NIF_TERM data)
{
ERL_NIF_TERM tail;
ErlNifIOVec vec;
@@ -6006,12 +6198,12 @@ ERL_NIF_TERM nif_recv(ErlNifEnv* env,
#if defined(__WIN32__)
return enif_raise_exception(env, MKA(env, "notsup"));
#else
- SocketDescriptor* descP;
- ERL_NIF_TERM sockRef, recvRef;
- int len;
- unsigned int eflags;
- int flags;
- ERL_NIF_TERM res;
+ ESockDescriptor* descP;
+ ERL_NIF_TERM sockRef, recvRef;
+ int len;
+ unsigned int eflags;
+ int flags;
+ ERL_NIF_TERM res;
if ((argc != 4) ||
!GET_INT(env, argv[2], &len) ||
@@ -6036,11 +6228,6 @@ ERL_NIF_TERM nif_recv(ErlNifEnv* env,
* this time (resulting in an select). The read of the
* other process must be made to wait until current
* is done!
- * Basically, we need a read queue!
- *
- * A 'reading' field (boolean), which is set if we did
- * not manage to read the entire message and reset every
- * time we do.
*/
res = nrecv(env, descP, sockRef, recvRef, len, flags);
@@ -6048,23 +6235,24 @@ ERL_NIF_TERM nif_recv(ErlNifEnv* env,
MUNLOCK(descP->readMtx);
return res;
+
#endif // if defined(__WIN32__)
}
-/* The (read) buffer handling *must* be optimized!
+/* The (read) buffer handling should be optimized!
* But for now we make it easy for ourselves by
* allocating a binary (of the specified or default
* size) and then throwing it away...
*/
#if !defined(__WIN32__)
static
-ERL_NIF_TERM nrecv(ErlNifEnv* env,
- SocketDescriptor* descP,
- ERL_NIF_TERM sockRef,
- ERL_NIF_TERM recvRef,
- int len,
- int flags)
+ERL_NIF_TERM nrecv(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM sockRef,
+ ERL_NIF_TERM recvRef,
+ int len,
+ int flags)
{
ssize_t read;
ErlNifBinary buf;
@@ -6150,12 +6338,12 @@ ERL_NIF_TERM nif_recvfrom(ErlNifEnv* env,
#if defined(__WIN32__)
return enif_raise_exception(env, MKA(env, "notsup"));
#else
- SocketDescriptor* descP;
- ERL_NIF_TERM sockRef, recvRef;
- unsigned int bufSz;
- unsigned int eflags;
- int flags;
- ERL_NIF_TERM res;
+ ESockDescriptor* descP;
+ ERL_NIF_TERM sockRef, recvRef;
+ unsigned int bufSz;
+ unsigned int eflags;
+ int flags;
+ ERL_NIF_TERM res;
SGDBG( ("SOCKET", "nif_recvfrom -> entry with argc: %d\r\n", argc) );
@@ -6222,14 +6410,14 @@ ERL_NIF_TERM nif_recvfrom(ErlNifEnv* env,
*/
#if !defined(__WIN32__)
static
-ERL_NIF_TERM nrecvfrom(ErlNifEnv* env,
- SocketDescriptor* descP,
- ERL_NIF_TERM sockRef,
- ERL_NIF_TERM recvRef,
- Uint16 len,
- int flags)
+ERL_NIF_TERM nrecvfrom(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM sockRef,
+ ERL_NIF_TERM recvRef,
+ Uint16 len,
+ int flags)
{
- SocketAddress fromAddr;
+ ESockAddress fromAddr;
unsigned int addrLen;
ssize_t read;
int save_errno;
@@ -6319,13 +6507,13 @@ ERL_NIF_TERM nif_recvmsg(ErlNifEnv* env,
#if defined(__WIN32__)
return enif_raise_exception(env, MKA(env, "notsup"));
#else
- SocketDescriptor* descP;
- ERL_NIF_TERM sockRef, recvRef;
- unsigned int bufSz;
- unsigned int ctrlSz;
- unsigned int eflags;
- int flags;
- ERL_NIF_TERM res;
+ ESockDescriptor* descP;
+ ERL_NIF_TERM sockRef, recvRef;
+ unsigned int bufSz;
+ unsigned int ctrlSz;
+ unsigned int eflags;
+ int flags;
+ ERL_NIF_TERM res;
SGDBG( ("SOCKET", "nif_recvmsg -> entry with argc: %d\r\n", argc) );
@@ -6394,13 +6582,13 @@ ERL_NIF_TERM nif_recvmsg(ErlNifEnv* env,
*/
#if !defined(__WIN32__)
static
-ERL_NIF_TERM nrecvmsg(ErlNifEnv* env,
- SocketDescriptor* descP,
- ERL_NIF_TERM sockRef,
- ERL_NIF_TERM recvRef,
- Uint16 bufLen,
- Uint16 ctrlLen,
- int flags)
+ERL_NIF_TERM nrecvmsg(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM sockRef,
+ ERL_NIF_TERM recvRef,
+ Uint16 bufLen,
+ Uint16 ctrlLen,
+ int flags)
{
unsigned int addrLen;
ssize_t read;
@@ -6412,7 +6600,7 @@ ERL_NIF_TERM nrecvmsg(ErlNifEnv* env,
ErlNifBinary data[1]; // Shall we always use 1?
ErlNifBinary ctrl;
ERL_NIF_TERM readerCheck;
- SocketAddress addr;
+ ESockAddress addr;
SSDBG( descP, ("SOCKET", "nrecvmsg -> entry with"
"\r\n bufSz: %d (%d)"
@@ -6502,7 +6690,7 @@ ERL_NIF_TERM nif_close(ErlNifEnv* env,
#if defined(__WIN32__)
return enif_raise_exception(env, MKA(env, "notsup"));
#else
- SocketDescriptor* descP;
+ ESockDescriptor* descP;
if ((argc != 1) ||
!enif_get_resource(env, argv[0], sockets, (void**) &descP)) {
@@ -6519,15 +6707,11 @@ ERL_NIF_TERM nif_close(ErlNifEnv* env,
#if !defined(__WIN32__)
static
-ERL_NIF_TERM nclose(ErlNifEnv* env,
- SocketDescriptor* descP)
+ERL_NIF_TERM nclose(ErlNifEnv* env,
+ ESockDescriptor* descP)
{
ERL_NIF_TERM reply, reason;
BOOLEAN_T doClose;
- int selectRes;
- int domain = descP->domain;
- int type = descP->type;
- int protocol = descP->protocol;
SSDBG( descP, ("SOCKET",
"nclose -> [%d] entry (0x%lX, 0x%lX, 0x%lX, 0x%lX)\r\n",
@@ -6539,12 +6723,48 @@ ERL_NIF_TERM nclose(ErlNifEnv* env,
MLOCK(descP->closeMtx);
+ doClose = nclose_check(env, descP, &reason);
+
+ if (doClose) {
+ reply = nclose_do(env, descP);
+ } else {
+ reply = esock_make_error(env, reason);
+ }
+
+ MUNLOCK(descP->closeMtx);
+
+ SSDBG( descP,
+ ("SOCKET", "nclose -> [%d] done when: "
+ "\r\n state: 0x%lX"
+ "\r\n reply: %T"
+ "\r\n", descP->sock, descP->state, reply) );
+
+ return reply;
+}
+
+
+
+/* *** nclose_check ***
+ *
+ * Check if we should try to perform the first stage close.
+ */
+static
+BOOLEAN_T nclose_check(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM* reason)
+{
+ BOOLEAN_T doClose;
+
if (descP->state == SOCKET_STATE_CLOSED) {
- reason = atom_closed;
+
doClose = FALSE;
+ *reason = atom_closed;
+
} else if (descP->state == SOCKET_STATE_CLOSING) {
- reason = atom_closing;
+
doClose = FALSE;
+ *reason = atom_closing;
+
} else {
/* Store the PID of the caller,
@@ -6554,90 +6774,116 @@ ERL_NIF_TERM nclose(ErlNifEnv* env,
*/
if (enif_self(env, &descP->closerPid) == NULL) {
- MUNLOCK(descP->closeMtx);
- return esock_make_error(env, atom_exself);
- }
- /* Monitor the caller, since we should complete this operation even if
- * the caller dies (for whatever reason).
- *
- * <KOLLA>
- *
- * Can we actiually use this for anything?
- *
- * </KOLLA>
- */
-
- if (MONP("nclose -> closer",
- env, descP,
- &descP->closerPid,
- &descP->closerMon) != 0) {
- MUNLOCK(descP->closeMtx);
- return esock_make_error(env, atom_exmon);
- }
-
- descP->closeLocal = TRUE;
- descP->state = SOCKET_STATE_CLOSING;
- descP->isReadable = FALSE;
- descP->isWritable = FALSE;
- doClose = TRUE;
- }
+ doClose = FALSE;
+ *reason = atom_exself;
- if (doClose) {
- descP->closeEnv = enif_alloc_env();
- descP->closeRef = MKREF(descP->closeEnv);
- selectRes = esock_select_stop(env, descP->sock, descP);
- if (selectRes & ERL_NIF_SELECT_STOP_CALLED) {
- /* Prep done - inform the caller it can finalize (close) directly */
- SSDBG( descP,
- ("SOCKET", "nclose -> [%d] stop was called\r\n", descP->sock) );
- dec_socket(domain, type, protocol);
- reply = esock_atom_ok;
- } else if (selectRes & ERL_NIF_SELECT_STOP_SCHEDULED) {
- /* The stop callback function has been *scheduled* which means that we
- * have to wait for it to complete. */
- SSDBG( descP,
- ("SOCKET", "nclose -> [%d] stop was scheduled\r\n",
- descP->sock) );
- dec_socket(domain, type, protocol); // SHALL WE DO THIS AT finalize?
- reply = esock_make_ok2(env, descP->closeRef);
} else {
- SSDBG( descP,
- ("SOCKET", "nclose -> [%d] stop failed: %d\r\n",
- descP->sock, selectRes) );
-
- /* <KOLLA>
+ /* Monitor the caller, since we should complete this
+ * operation even if the caller dies (for whatever reason).
+ *
+ * <KOLLA>
*
- * WE SHOULD REALLY HAVE A WAY TO CLOBBER THE SOCKET,
- * SO WE DON'T LET STUFF LEAK.
- * NOW, BECAUSE WE FAILED TO SELECT, WE CANNOT FINISH
- * THE CLOSE, WHAT TO DO? ABORT?
+ * Can we actually use this for anything?
*
* </KOLLA>
*/
- // No point in having this?
- DEMONP("nclose -> closer", env, descP, &descP->closerMon);
+ if (MONP("nclose_check -> closer",
+ env, descP,
+ &descP->closerPid,
+ &descP->closerMon) != 0) {
+
+ doClose = FALSE;
+ *reason = atom_exmon;
+
+ } else {
- reason = MKT2(env, atom_select, MKI(env, selectRes));
- reply = esock_make_error(env, reason);
+ descP->closeLocal = TRUE;
+ descP->state = SOCKET_STATE_CLOSING;
+ descP->isReadable = FALSE;
+ descP->isWritable = FALSE;
+ doClose = TRUE;
+ *reason = esock_atom_undefined; // NOT used !!
+
+ }
}
+ }
+
+ return doClose;
+
+}
+
+
+
+/* *** nclose_do ***
+ *
+ * Perform (do) the first stage close.
+ */
+static
+ERL_NIF_TERM nclose_do(ErlNifEnv* env,
+ ESockDescriptor* descP)
+{
+ int domain = descP->domain;
+ int type = descP->type;
+ int protocol = descP->protocol;
+ int sres;
+ ERL_NIF_TERM reply, reason;
+
+ descP->closeEnv = esock_alloc_env("nclose-do - close-env");
+ descP->closeRef = MKREF(descP->closeEnv);
+
+ sres = esock_select_stop(env, descP->sock, descP);
+
+ if (sres & ERL_NIF_SELECT_STOP_CALLED) {
+
+ /* Prep done - inform the caller it can finalize (close) directly */
+ SSDBG( descP,
+ ("SOCKET", "nclose -> [%d] stop was called\r\n", descP->sock) );
+
+ dec_socket(domain, type, protocol);
+ reply = esock_atom_ok;
+
+ } else if (sres & ERL_NIF_SELECT_STOP_SCHEDULED) {
+
+ /* The stop callback function has been *scheduled* which means that we
+ * have to wait for it to complete. */
+ SSDBG( descP,
+ ("SOCKET", "nclose -> [%d] stop was scheduled\r\n",
+ descP->sock) );
+
+ dec_socket(domain, type, protocol); // SHALL WE DO THIS AT finalize?
+ reply = esock_make_ok2(env, enif_make_copy(env, descP->closeRef));
} else {
- reply = esock_make_error(env, reason);
- }
- MUNLOCK(descP->closeMtx);
+ SSDBG( descP,
+ ("SOCKET", "nclose -> [%d] stop failed: %d\r\n",
+ descP->sock, sres) );
- SSDBG( descP,
- ("SOCKET", "nclose -> [%d] done when: "
- "\r\n state: 0x%lX"
- "\r\n reply: %T"
- "\r\n", descP->sock, descP->state, reply) );
+ /* <KOLLA>
+ *
+ * WE SHOULD REALLY HAVE A WAY TO CLOBBER THE SOCKET,
+ * SO WE DON'T LET STUFF LEAK.
+ * NOW, BECAUSE WE FAILED TO SELECT, WE CANNOT FINISH
+ * THE CLOSE, WHAT TO DO? ABORT?
+ *
+ * </KOLLA>
+ */
+
+ // Do we need this?
+ DEMONP("nclose_do -> closer", env, descP, &descP->closerMon);
+
+ reason = MKT2(env, esock_atom_select_failed, MKI(env, sres));
+ reply = esock_make_error(env, reason);
+ }
return reply;
}
+
+
+
#endif // if !defined(__WIN32__)
@@ -6660,7 +6906,7 @@ ERL_NIF_TERM nif_finalize_close(ErlNifEnv* env,
#if defined(__WIN32__)
return enif_raise_exception(env, MKA(env, "notsup"));
#else
- SocketDescriptor* descP;
+ ESockDescriptor* descP;
/* Extract arguments and perform preliminary validation */
@@ -6679,8 +6925,8 @@ ERL_NIF_TERM nif_finalize_close(ErlNifEnv* env,
*/
#if !defined(__WIN32__)
static
-ERL_NIF_TERM nfinalize_close(ErlNifEnv* env,
- SocketDescriptor* descP)
+ERL_NIF_TERM nfinalize_close(ErlNifEnv* env,
+ ESockDescriptor* descP)
{
ERL_NIF_TERM reply;
@@ -6744,9 +6990,9 @@ ERL_NIF_TERM nif_shutdown(ErlNifEnv* env,
#if defined(__WIN32__)
return enif_raise_exception(env, MKA(env, "notsup"));
#else
- SocketDescriptor* descP;
- unsigned int ehow;
- int how;
+ ESockDescriptor* descP;
+ unsigned int ehow;
+ int how;
if ((argc != 2) ||
!enif_get_resource(env, argv[0], sockets, (void**) &descP) ||
@@ -6768,9 +7014,9 @@ ERL_NIF_TERM nif_shutdown(ErlNifEnv* env,
#if !defined(__WIN32__)
static
-ERL_NIF_TERM nshutdown(ErlNifEnv* env,
- SocketDescriptor* descP,
- int how)
+ERL_NIF_TERM nshutdown(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ int how)
{
ERL_NIF_TERM reply;
@@ -6825,13 +7071,13 @@ ERL_NIF_TERM nif_setopt(ErlNifEnv* env,
#if defined(__WIN32__)
return enif_raise_exception(env, MKA(env, "notsup"));
#else
- SocketDescriptor* descP = NULL;
- int eLevel, level = -1;
- int eOpt;
- ERL_NIF_TERM eIsEncoded;
- ERL_NIF_TERM eVal;
- BOOLEAN_T isEncoded, isOTP;
- ERL_NIF_TERM result;
+ ESockDescriptor* descP = NULL;
+ int eLevel, level = -1;
+ int eOpt;
+ ERL_NIF_TERM eIsEncoded;
+ ERL_NIF_TERM eVal;
+ BOOLEAN_T isEncoded, isOTP;
+ ERL_NIF_TERM result;
SGDBG( ("SOCKET", "nif_setopt -> entry with argc: %d\r\n", argc) );
@@ -6873,27 +7119,32 @@ ERL_NIF_TERM nif_setopt(ErlNifEnv* env,
level, eLevel,
eOpt, eVal) );
+ MLOCK(descP->cfgMtx);
+
result = nsetopt(env, descP, isEncoded, isOTP, level, eOpt, eVal);
+ MUNLOCK(descP->cfgMtx);
+
SSDBG( descP,
("SOCKET", "nif_setopt -> done when"
"\r\n result: %T"
"\r\n", result) );
return result;
+
#endif // if defined(__WIN32__)
}
#if !defined(__WIN32__)
static
-ERL_NIF_TERM nsetopt(ErlNifEnv* env,
- SocketDescriptor* descP,
- BOOLEAN_T isEncoded,
- BOOLEAN_T isOTP,
- int level,
- int eOpt,
- ERL_NIF_TERM eVal)
+ERL_NIF_TERM nsetopt(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ BOOLEAN_T isEncoded,
+ BOOLEAN_T isOTP,
+ int level,
+ int eOpt,
+ ERL_NIF_TERM eVal)
{
ERL_NIF_TERM result;
@@ -6916,10 +7167,10 @@ ERL_NIF_TERM nsetopt(ErlNifEnv* env,
/* nsetopt_otp - Handle OTP (level) options
*/
static
-ERL_NIF_TERM nsetopt_otp(ErlNifEnv* env,
- SocketDescriptor* descP,
- int eOpt,
- ERL_NIF_TERM eVal)
+ERL_NIF_TERM nsetopt_otp(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ int eOpt,
+ ERL_NIF_TERM eVal)
{
ERL_NIF_TERM result;
@@ -6966,9 +7217,9 @@ ERL_NIF_TERM nsetopt_otp(ErlNifEnv* env,
/* nsetopt_otp_debug - Handle the OTP (level) debug options
*/
static
-ERL_NIF_TERM nsetopt_otp_debug(ErlNifEnv* env,
- SocketDescriptor* descP,
- ERL_NIF_TERM eVal)
+ERL_NIF_TERM nsetopt_otp_debug(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal)
{
descP->dbg = esock_decode_bool(eVal);
@@ -6979,9 +7230,9 @@ ERL_NIF_TERM nsetopt_otp_debug(ErlNifEnv* env,
/* nsetopt_otp_iow - Handle the OTP (level) iow options
*/
static
-ERL_NIF_TERM nsetopt_otp_iow(ErlNifEnv* env,
- SocketDescriptor* descP,
- ERL_NIF_TERM eVal)
+ERL_NIF_TERM nsetopt_otp_iow(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal)
{
descP->iow = esock_decode_bool(eVal);
@@ -6993,12 +7244,11 @@ ERL_NIF_TERM nsetopt_otp_iow(ErlNifEnv* env,
/* nsetopt_otp_ctrl_proc - Handle the OTP (level) controlling_process options
*/
static
-ERL_NIF_TERM nsetopt_otp_ctrl_proc(ErlNifEnv* env,
- SocketDescriptor* descP,
- ERL_NIF_TERM eVal)
+ERL_NIF_TERM nsetopt_otp_ctrl_proc(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal)
{
ErlNifPid caller, newCtrlPid;
- // ErlNifMonitor newCtrlMon;
ESockMonitor newCtrlMon;
int xres;
@@ -7053,9 +7303,9 @@ ERL_NIF_TERM nsetopt_otp_ctrl_proc(ErlNifEnv* env,
* Where N is the max number of reads.
*/
static
-ERL_NIF_TERM nsetopt_otp_rcvbuf(ErlNifEnv* env,
- SocketDescriptor* descP,
- ERL_NIF_TERM eVal)
+ERL_NIF_TERM nsetopt_otp_rcvbuf(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal)
{
const ERL_NIF_TERM* t; // The array of the elements of the tuple
int tsz; // The size of the tuple - should be 2
@@ -7108,9 +7358,9 @@ ERL_NIF_TERM nsetopt_otp_rcvbuf(ErlNifEnv* env,
/* nsetopt_otp_rcvctrlbuf - Handle the OTP (level) rcvctrlbuf option
*/
static
-ERL_NIF_TERM nsetopt_otp_rcvctrlbuf(ErlNifEnv* env,
- SocketDescriptor* descP,
- ERL_NIF_TERM eVal)
+ERL_NIF_TERM nsetopt_otp_rcvctrlbuf(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal)
{
size_t val;
char* xres;
@@ -7131,9 +7381,9 @@ ERL_NIF_TERM nsetopt_otp_rcvctrlbuf(ErlNifEnv* env,
/* nsetopt_otp_sndctrlbuf - Handle the OTP (level) sndctrlbuf option
*/
static
-ERL_NIF_TERM nsetopt_otp_sndctrlbuf(ErlNifEnv* env,
- SocketDescriptor* descP,
- ERL_NIF_TERM eVal)
+ERL_NIF_TERM nsetopt_otp_sndctrlbuf(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal)
{
size_t val;
char* xres;
@@ -7155,11 +7405,11 @@ ERL_NIF_TERM nsetopt_otp_sndctrlbuf(ErlNifEnv* env,
* in "native mode" (option is provided as is and value as a binary).
*/
static
-ERL_NIF_TERM nsetopt_native(ErlNifEnv* env,
- SocketDescriptor* descP,
- int level,
- int opt,
- ERL_NIF_TERM eVal)
+ERL_NIF_TERM nsetopt_native(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ int level,
+ int opt,
+ ERL_NIF_TERM eVal)
{
ErlNifBinary val;
ERL_NIF_TERM result;
@@ -7195,11 +7445,11 @@ ERL_NIF_TERM nsetopt_native(ErlNifEnv* env,
/* nsetopt_level - A "proper" level (option) has been specified
*/
static
-ERL_NIF_TERM nsetopt_level(ErlNifEnv* env,
- SocketDescriptor* descP,
- int level,
- int eOpt,
- ERL_NIF_TERM eVal)
+ERL_NIF_TERM nsetopt_level(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ int level,
+ int eOpt,
+ ERL_NIF_TERM eVal)
{
ERL_NIF_TERM result;
@@ -7265,10 +7515,10 @@ ERL_NIF_TERM nsetopt_level(ErlNifEnv* env,
/* nsetopt_lvl_socket - Level *SOCKET* option
*/
static
-ERL_NIF_TERM nsetopt_lvl_socket(ErlNifEnv* env,
- SocketDescriptor* descP,
- int eOpt,
- ERL_NIF_TERM eVal)
+ERL_NIF_TERM nsetopt_lvl_socket(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ int eOpt,
+ ERL_NIF_TERM eVal)
{
ERL_NIF_TERM result;
@@ -7404,9 +7654,9 @@ ERL_NIF_TERM nsetopt_lvl_socket(ErlNifEnv* env,
#if defined(SO_BINDTODEVICE)
static
-ERL_NIF_TERM nsetopt_lvl_sock_bindtodevice(ErlNifEnv* env,
- SocketDescriptor* descP,
- ERL_NIF_TERM eVal)
+ERL_NIF_TERM nsetopt_lvl_sock_bindtodevice(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal)
{
return nsetopt_str_opt(env, descP,
SOL_SOCKET, SO_BROADCAST,
@@ -7417,9 +7667,9 @@ ERL_NIF_TERM nsetopt_lvl_sock_bindtodevice(ErlNifEnv* env,
#if defined(SO_BROADCAST)
static
-ERL_NIF_TERM nsetopt_lvl_sock_broadcast(ErlNifEnv* env,
- SocketDescriptor* descP,
- ERL_NIF_TERM eVal)
+ERL_NIF_TERM nsetopt_lvl_sock_broadcast(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal)
{
return nsetopt_bool_opt(env, descP, SOL_SOCKET, SO_BROADCAST, eVal);
}
@@ -7428,9 +7678,9 @@ ERL_NIF_TERM nsetopt_lvl_sock_broadcast(ErlNifEnv* env,
#if defined(SO_DEBUG)
static
-ERL_NIF_TERM nsetopt_lvl_sock_debug(ErlNifEnv* env,
- SocketDescriptor* descP,
- ERL_NIF_TERM eVal)
+ERL_NIF_TERM nsetopt_lvl_sock_debug(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal)
{
return nsetopt_int_opt(env, descP, SOL_SOCKET, SO_DEBUG, eVal);
}
@@ -7439,9 +7689,9 @@ ERL_NIF_TERM nsetopt_lvl_sock_debug(ErlNifEnv* env,
#if defined(SO_DONTROUTE)
static
-ERL_NIF_TERM nsetopt_lvl_sock_dontroute(ErlNifEnv* env,
- SocketDescriptor* descP,
- ERL_NIF_TERM eVal)
+ERL_NIF_TERM nsetopt_lvl_sock_dontroute(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal)
{
return nsetopt_bool_opt(env, descP, SOL_SOCKET, SO_DONTROUTE, eVal);
}
@@ -7450,9 +7700,9 @@ ERL_NIF_TERM nsetopt_lvl_sock_dontroute(ErlNifEnv* env,
#if defined(SO_KEEPALIVE)
static
-ERL_NIF_TERM nsetopt_lvl_sock_keepalive(ErlNifEnv* env,
- SocketDescriptor* descP,
- ERL_NIF_TERM eVal)
+ERL_NIF_TERM nsetopt_lvl_sock_keepalive(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal)
{
return nsetopt_bool_opt(env, descP, SOL_SOCKET, SO_KEEPALIVE, eVal);
}
@@ -7461,9 +7711,9 @@ ERL_NIF_TERM nsetopt_lvl_sock_keepalive(ErlNifEnv* env,
#if defined(SO_LINGER)
static
-ERL_NIF_TERM nsetopt_lvl_sock_linger(ErlNifEnv* env,
- SocketDescriptor* descP,
- ERL_NIF_TERM eVal)
+ERL_NIF_TERM nsetopt_lvl_sock_linger(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal)
{
ERL_NIF_TERM result;
struct linger val;
@@ -7487,9 +7737,9 @@ ERL_NIF_TERM nsetopt_lvl_sock_linger(ErlNifEnv* env,
#if defined(SO_OOBINLINE)
static
-ERL_NIF_TERM nsetopt_lvl_sock_oobinline(ErlNifEnv* env,
- SocketDescriptor* descP,
- ERL_NIF_TERM eVal)
+ERL_NIF_TERM nsetopt_lvl_sock_oobinline(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal)
{
return nsetopt_bool_opt(env, descP, SOL_SOCKET, SO_OOBINLINE, eVal);
}
@@ -7498,9 +7748,9 @@ ERL_NIF_TERM nsetopt_lvl_sock_oobinline(ErlNifEnv* env,
#if defined(SO_PEEK_OFF)
static
-ERL_NIF_TERM nsetopt_lvl_sock_peek_off(ErlNifEnv* env,
- SocketDescriptor* descP,
- ERL_NIF_TERM eVal)
+ERL_NIF_TERM nsetopt_lvl_sock_peek_off(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal)
{
return nsetopt_int_opt(env, descP, SOL_SOCKET, SO_PEEK_OFF, eVal);
}
@@ -7509,9 +7759,9 @@ ERL_NIF_TERM nsetopt_lvl_sock_peek_off(ErlNifEnv* env,
#if defined(SO_PRIORITY)
static
-ERL_NIF_TERM nsetopt_lvl_sock_priority(ErlNifEnv* env,
- SocketDescriptor* descP,
- ERL_NIF_TERM eVal)
+ERL_NIF_TERM nsetopt_lvl_sock_priority(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal)
{
return nsetopt_int_opt(env, descP, SOL_SOCKET, SO_PRIORITY, eVal);
}
@@ -7520,9 +7770,9 @@ ERL_NIF_TERM nsetopt_lvl_sock_priority(ErlNifEnv* env,
#if defined(SO_RCVBUF)
static
-ERL_NIF_TERM nsetopt_lvl_sock_rcvbuf(ErlNifEnv* env,
- SocketDescriptor* descP,
- ERL_NIF_TERM eVal)
+ERL_NIF_TERM nsetopt_lvl_sock_rcvbuf(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal)
{
return nsetopt_int_opt(env, descP, SOL_SOCKET, SO_RCVBUF, eVal);
}
@@ -7531,9 +7781,9 @@ ERL_NIF_TERM nsetopt_lvl_sock_rcvbuf(ErlNifEnv* env,
#if defined(SO_RCVLOWAT)
static
-ERL_NIF_TERM nsetopt_lvl_sock_rcvlowat(ErlNifEnv* env,
- SocketDescriptor* descP,
- ERL_NIF_TERM eVal)
+ERL_NIF_TERM nsetopt_lvl_sock_rcvlowat(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal)
{
return nsetopt_int_opt(env, descP, SOL_SOCKET, SO_RCVLOWAT, eVal);
}
@@ -7542,9 +7792,9 @@ ERL_NIF_TERM nsetopt_lvl_sock_rcvlowat(ErlNifEnv* env,
#if defined(SO_RCVTIMEO)
static
-ERL_NIF_TERM nsetopt_lvl_sock_rcvtimeo(ErlNifEnv* env,
- SocketDescriptor* descP,
- ERL_NIF_TERM eVal)
+ERL_NIF_TERM nsetopt_lvl_sock_rcvtimeo(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal)
{
return nsetopt_timeval_opt(env, descP, SOL_SOCKET, SO_RCVTIMEO, eVal);
}
@@ -7553,9 +7803,9 @@ ERL_NIF_TERM nsetopt_lvl_sock_rcvtimeo(ErlNifEnv* env,
#if defined(SO_REUSEADDR)
static
-ERL_NIF_TERM nsetopt_lvl_sock_reuseaddr(ErlNifEnv* env,
- SocketDescriptor* descP,
- ERL_NIF_TERM eVal)
+ERL_NIF_TERM nsetopt_lvl_sock_reuseaddr(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal)
{
return nsetopt_bool_opt(env, descP, SOL_SOCKET, SO_REUSEADDR, eVal);
}
@@ -7564,9 +7814,9 @@ ERL_NIF_TERM nsetopt_lvl_sock_reuseaddr(ErlNifEnv* env,
#if defined(SO_REUSEPORT)
static
-ERL_NIF_TERM nsetopt_lvl_sock_reuseport(ErlNifEnv* env,
- SocketDescriptor* descP,
- ERL_NIF_TERM eVal)
+ERL_NIF_TERM nsetopt_lvl_sock_reuseport(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal)
{
return nsetopt_bool_opt(env, descP, SOL_SOCKET, SO_REUSEPORT, eVal);
}
@@ -7575,9 +7825,9 @@ ERL_NIF_TERM nsetopt_lvl_sock_reuseport(ErlNifEnv* env,
#if defined(SO_SNDBUF)
static
-ERL_NIF_TERM nsetopt_lvl_sock_sndbuf(ErlNifEnv* env,
- SocketDescriptor* descP,
- ERL_NIF_TERM eVal)
+ERL_NIF_TERM nsetopt_lvl_sock_sndbuf(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal)
{
return nsetopt_int_opt(env, descP, SOL_SOCKET, SO_SNDBUF, eVal);
}
@@ -7586,9 +7836,9 @@ ERL_NIF_TERM nsetopt_lvl_sock_sndbuf(ErlNifEnv* env,
#if defined(SO_SNDLOWAT)
static
-ERL_NIF_TERM nsetopt_lvl_sock_sndlowat(ErlNifEnv* env,
- SocketDescriptor* descP,
- ERL_NIF_TERM eVal)
+ERL_NIF_TERM nsetopt_lvl_sock_sndlowat(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal)
{
return nsetopt_int_opt(env, descP, SOL_SOCKET, SO_SNDLOWAT, eVal);
}
@@ -7597,9 +7847,9 @@ ERL_NIF_TERM nsetopt_lvl_sock_sndlowat(ErlNifEnv* env,
#if defined(SO_SNDTIMEO)
static
-ERL_NIF_TERM nsetopt_lvl_sock_sndtimeo(ErlNifEnv* env,
- SocketDescriptor* descP,
- ERL_NIF_TERM eVal)
+ERL_NIF_TERM nsetopt_lvl_sock_sndtimeo(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal)
{
SSDBG( descP,
("SOCKET", "nsetopt_lvl_sock_sndtimeo -> entry with"
@@ -7613,9 +7863,9 @@ ERL_NIF_TERM nsetopt_lvl_sock_sndtimeo(ErlNifEnv* env,
#if defined(SO_TIMESTAMP)
static
-ERL_NIF_TERM nsetopt_lvl_sock_timestamp(ErlNifEnv* env,
- SocketDescriptor* descP,
- ERL_NIF_TERM eVal)
+ERL_NIF_TERM nsetopt_lvl_sock_timestamp(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal)
{
return nsetopt_bool_opt(env, descP, SOL_SOCKET, SO_TIMESTAMP, eVal);
}
@@ -7626,10 +7876,10 @@ ERL_NIF_TERM nsetopt_lvl_sock_timestamp(ErlNifEnv* env,
/* nsetopt_lvl_ip - Level *IP* option(s)
*/
static
-ERL_NIF_TERM nsetopt_lvl_ip(ErlNifEnv* env,
- SocketDescriptor* descP,
- int eOpt,
- ERL_NIF_TERM eVal)
+ERL_NIF_TERM nsetopt_lvl_ip(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ int eOpt,
+ ERL_NIF_TERM eVal)
{
ERL_NIF_TERM result;
@@ -7843,9 +8093,9 @@ ERL_NIF_TERM nsetopt_lvl_ip(ErlNifEnv* env,
*/
#if defined(IP_ADD_MEMBERSHIP)
static
-ERL_NIF_TERM nsetopt_lvl_ip_add_membership(ErlNifEnv* env,
- SocketDescriptor* descP,
- ERL_NIF_TERM eVal)
+ERL_NIF_TERM nsetopt_lvl_ip_add_membership(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal)
{
return nsetopt_lvl_ip_update_membership(env, descP, eVal, IP_ADD_MEMBERSHIP);
}
@@ -7863,9 +8113,9 @@ ERL_NIF_TERM nsetopt_lvl_ip_add_membership(ErlNifEnv* env,
*/
#if defined(IP_ADD_SOURCE_MEMBERSHIP)
static
-ERL_NIF_TERM nsetopt_lvl_ip_add_source_membership(ErlNifEnv* env,
- SocketDescriptor* descP,
- ERL_NIF_TERM eVal)
+ERL_NIF_TERM nsetopt_lvl_ip_add_source_membership(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal)
{
return nsetopt_lvl_ip_update_source(env, descP, eVal,
IP_ADD_SOURCE_MEMBERSHIP);
@@ -7884,9 +8134,9 @@ ERL_NIF_TERM nsetopt_lvl_ip_add_source_membership(ErlNifEnv* env,
*/
#if defined(IP_BLOCK_SOURCE)
static
-ERL_NIF_TERM nsetopt_lvl_ip_block_source(ErlNifEnv* env,
- SocketDescriptor* descP,
- ERL_NIF_TERM eVal)
+ERL_NIF_TERM nsetopt_lvl_ip_block_source(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal)
{
return nsetopt_lvl_ip_update_source(env, descP, eVal, IP_BLOCK_SOURCE);
}
@@ -7906,9 +8156,9 @@ ERL_NIF_TERM nsetopt_lvl_ip_block_source(ErlNifEnv* env,
*/
#if defined(IP_DROP_MEMBERSHIP)
static
-ERL_NIF_TERM nsetopt_lvl_ip_drop_membership(ErlNifEnv* env,
- SocketDescriptor* descP,
- ERL_NIF_TERM eVal)
+ERL_NIF_TERM nsetopt_lvl_ip_drop_membership(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal)
{
return nsetopt_lvl_ip_update_membership(env, descP, eVal,
IP_DROP_MEMBERSHIP);
@@ -7928,9 +8178,9 @@ ERL_NIF_TERM nsetopt_lvl_ip_drop_membership(ErlNifEnv* env,
*/
#if defined(IP_DROP_SOURCE_MEMBERSHIP)
static
-ERL_NIF_TERM nsetopt_lvl_ip_drop_source_membership(ErlNifEnv* env,
- SocketDescriptor* descP,
- ERL_NIF_TERM eVal)
+ERL_NIF_TERM nsetopt_lvl_ip_drop_source_membership(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal)
{
return nsetopt_lvl_ip_update_source(env, descP, eVal,
IP_DROP_SOURCE_MEMBERSHIP);
@@ -7943,9 +8193,9 @@ ERL_NIF_TERM nsetopt_lvl_ip_drop_source_membership(ErlNifEnv* env,
*/
#if defined(IP_FREEBIND)
static
-ERL_NIF_TERM nsetopt_lvl_ip_freebind(ErlNifEnv* env,
- SocketDescriptor* descP,
- ERL_NIF_TERM eVal)
+ERL_NIF_TERM nsetopt_lvl_ip_freebind(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal)
{
#if defined(SOL_IP)
int level = SOL_IP;
@@ -7963,9 +8213,9 @@ ERL_NIF_TERM nsetopt_lvl_ip_freebind(ErlNifEnv* env,
*/
#if defined(IP_HDRINCL)
static
-ERL_NIF_TERM nsetopt_lvl_ip_hdrincl(ErlNifEnv* env,
- SocketDescriptor* descP,
- ERL_NIF_TERM eVal)
+ERL_NIF_TERM nsetopt_lvl_ip_hdrincl(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal)
{
#if defined(SOL_IP)
int level = SOL_IP;
@@ -7983,9 +8233,9 @@ ERL_NIF_TERM nsetopt_lvl_ip_hdrincl(ErlNifEnv* env,
*/
#if defined(IP_MINTTL)
static
-ERL_NIF_TERM nsetopt_lvl_ip_minttl(ErlNifEnv* env,
- SocketDescriptor* descP,
- ERL_NIF_TERM eVal)
+ERL_NIF_TERM nsetopt_lvl_ip_minttl(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal)
{
#if defined(SOL_IP)
int level = SOL_IP;
@@ -8005,9 +8255,9 @@ ERL_NIF_TERM nsetopt_lvl_ip_minttl(ErlNifEnv* env,
*/
#if defined(IP_MSFILTER) && defined(IP_MSFILTER_SIZE)
static
-ERL_NIF_TERM nsetopt_lvl_ip_msfilter(ErlNifEnv* env,
- SocketDescriptor* descP,
- ERL_NIF_TERM eVal)
+ERL_NIF_TERM nsetopt_lvl_ip_msfilter(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal)
{
ERL_NIF_TERM result;
@@ -8058,7 +8308,7 @@ ERL_NIF_TERM nsetopt_lvl_ip_msfilter(ErlNifEnv* env,
return esock_make_error(env, esock_atom_einval);
}
- if (!decode_ip_msfilter_mode(env, eFMode, &msfP->imsf_fmode)) {
+ if (!decode_ip_msfilter_mode(env, eFMode, (Uint32*) &msfP->imsf_fmode)) {
FREE(msfP);
return esock_make_error(env, esock_atom_einval);
}
@@ -8138,9 +8388,9 @@ ERL_NIF_TERM nsetopt_lvl_ip_msfilter_set(ErlNifEnv* env,
*/
#if defined(IP_MTU_DISCOVER)
static
-ERL_NIF_TERM nsetopt_lvl_ip_mtu_discover(ErlNifEnv* env,
- SocketDescriptor* descP,
- ERL_NIF_TERM eVal)
+ERL_NIF_TERM nsetopt_lvl_ip_mtu_discover(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal)
{
ERL_NIF_TERM result;
int val;
@@ -8177,9 +8427,9 @@ ERL_NIF_TERM nsetopt_lvl_ip_mtu_discover(ErlNifEnv* env,
*/
#if defined(IP_MULTICAST_ALL)
static
-ERL_NIF_TERM nsetopt_lvl_ip_multicast_all(ErlNifEnv* env,
- SocketDescriptor* descP,
- ERL_NIF_TERM eVal)
+ERL_NIF_TERM nsetopt_lvl_ip_multicast_all(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal)
{
#if defined(SOL_IP)
int level = SOL_IP;
@@ -8198,9 +8448,9 @@ ERL_NIF_TERM nsetopt_lvl_ip_multicast_all(ErlNifEnv* env,
*/
#if defined(IP_MULTICAST_IF)
static
-ERL_NIF_TERM nsetopt_lvl_ip_multicast_if(ErlNifEnv* env,
- SocketDescriptor* descP,
- ERL_NIF_TERM eVal)
+ERL_NIF_TERM nsetopt_lvl_ip_multicast_if(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal)
{
ERL_NIF_TERM result;
struct in_addr ifAddr;
@@ -8235,9 +8485,9 @@ ERL_NIF_TERM nsetopt_lvl_ip_multicast_if(ErlNifEnv* env,
*/
#if defined(IP_MULTICAST_LOOP)
static
-ERL_NIF_TERM nsetopt_lvl_ip_multicast_loop(ErlNifEnv* env,
- SocketDescriptor* descP,
- ERL_NIF_TERM eVal)
+ERL_NIF_TERM nsetopt_lvl_ip_multicast_loop(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal)
{
#if defined(SOL_IP)
int level = SOL_IP;
@@ -8254,9 +8504,9 @@ ERL_NIF_TERM nsetopt_lvl_ip_multicast_loop(ErlNifEnv* env,
*/
#if defined(IP_MULTICAST_TTL)
static
-ERL_NIF_TERM nsetopt_lvl_ip_multicast_ttl(ErlNifEnv* env,
- SocketDescriptor* descP,
- ERL_NIF_TERM eVal)
+ERL_NIF_TERM nsetopt_lvl_ip_multicast_ttl(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal)
{
#if defined(SOL_IP)
int level = SOL_IP;
@@ -8273,9 +8523,9 @@ ERL_NIF_TERM nsetopt_lvl_ip_multicast_ttl(ErlNifEnv* env,
*/
#if defined(IP_NODEFRAG)
static
-ERL_NIF_TERM nsetopt_lvl_ip_nodefrag(ErlNifEnv* env,
- SocketDescriptor* descP,
- ERL_NIF_TERM eVal)
+ERL_NIF_TERM nsetopt_lvl_ip_nodefrag(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal)
{
#if defined(SOL_IP)
int level = SOL_IP;
@@ -8292,9 +8542,9 @@ ERL_NIF_TERM nsetopt_lvl_ip_nodefrag(ErlNifEnv* env,
*/
#if defined(IP_PKTINFO)
static
-ERL_NIF_TERM nsetopt_lvl_ip_pktinfo(ErlNifEnv* env,
- SocketDescriptor* descP,
- ERL_NIF_TERM eVal)
+ERL_NIF_TERM nsetopt_lvl_ip_pktinfo(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal)
{
#if defined(SOL_IP)
int level = SOL_IP;
@@ -8311,9 +8561,9 @@ ERL_NIF_TERM nsetopt_lvl_ip_pktinfo(ErlNifEnv* env,
*/
#if defined(IP_RECVDSTADDR)
static
-ERL_NIF_TERM nsetopt_lvl_ip_recvdstaddr(ErlNifEnv* env,
- SocketDescriptor* descP,
- ERL_NIF_TERM eVal)
+ERL_NIF_TERM nsetopt_lvl_ip_recvdstaddr(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal)
{
#if defined(SOL_IP)
int level = SOL_IP;
@@ -8330,9 +8580,9 @@ ERL_NIF_TERM nsetopt_lvl_ip_recvdstaddr(ErlNifEnv* env,
*/
#if defined(IP_RECVERR)
static
-ERL_NIF_TERM nsetopt_lvl_ip_recverr(ErlNifEnv* env,
- SocketDescriptor* descP,
- ERL_NIF_TERM eVal)
+ERL_NIF_TERM nsetopt_lvl_ip_recverr(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal)
{
#if defined(SOL_IP)
int level = SOL_IP;
@@ -8349,9 +8599,9 @@ ERL_NIF_TERM nsetopt_lvl_ip_recverr(ErlNifEnv* env,
*/
#if defined(IP_RECVIF)
static
-ERL_NIF_TERM nsetopt_lvl_ip_recvif(ErlNifEnv* env,
- SocketDescriptor* descP,
- ERL_NIF_TERM eVal)
+ERL_NIF_TERM nsetopt_lvl_ip_recvif(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal)
{
#if defined(SOL_IP)
int level = SOL_IP;
@@ -8368,9 +8618,9 @@ ERL_NIF_TERM nsetopt_lvl_ip_recvif(ErlNifEnv* env,
*/
#if defined(IP_RECVOPTS)
static
-ERL_NIF_TERM nsetopt_lvl_ip_recvopts(ErlNifEnv* env,
- SocketDescriptor* descP,
- ERL_NIF_TERM eVal)
+ERL_NIF_TERM nsetopt_lvl_ip_recvopts(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal)
{
#if defined(SOL_IP)
int level = SOL_IP;
@@ -8387,9 +8637,9 @@ ERL_NIF_TERM nsetopt_lvl_ip_recvopts(ErlNifEnv* env,
*/
#if defined(IP_RECVORIGDSTADDR)
static
-ERL_NIF_TERM nsetopt_lvl_ip_recvorigdstaddr(ErlNifEnv* env,
- SocketDescriptor* descP,
- ERL_NIF_TERM eVal)
+ERL_NIF_TERM nsetopt_lvl_ip_recvorigdstaddr(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal)
{
#if defined(SOL_IP)
int level = SOL_IP;
@@ -8406,9 +8656,9 @@ ERL_NIF_TERM nsetopt_lvl_ip_recvorigdstaddr(ErlNifEnv* env,
*/
#if defined(IP_RECVTOS)
static
-ERL_NIF_TERM nsetopt_lvl_ip_recvtos(ErlNifEnv* env,
- SocketDescriptor* descP,
- ERL_NIF_TERM eVal)
+ERL_NIF_TERM nsetopt_lvl_ip_recvtos(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal)
{
#if defined(SOL_IP)
int level = SOL_IP;
@@ -8425,9 +8675,9 @@ ERL_NIF_TERM nsetopt_lvl_ip_recvtos(ErlNifEnv* env,
*/
#if defined(IP_RECVTTL)
static
-ERL_NIF_TERM nsetopt_lvl_ip_recvttl(ErlNifEnv* env,
- SocketDescriptor* descP,
- ERL_NIF_TERM eVal)
+ERL_NIF_TERM nsetopt_lvl_ip_recvttl(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal)
{
#if defined(SOL_IP)
int level = SOL_IP;
@@ -8444,9 +8694,9 @@ ERL_NIF_TERM nsetopt_lvl_ip_recvttl(ErlNifEnv* env,
*/
#if defined(IP_RETOPTS)
static
-ERL_NIF_TERM nsetopt_lvl_ip_retopts(ErlNifEnv* env,
- SocketDescriptor* descP,
- ERL_NIF_TERM eVal)
+ERL_NIF_TERM nsetopt_lvl_ip_retopts(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal)
{
#if defined(SOL_IP)
int level = SOL_IP;
@@ -8463,9 +8713,9 @@ ERL_NIF_TERM nsetopt_lvl_ip_retopts(ErlNifEnv* env,
*/
#if defined(IP_ROUTER_ALERT)
static
-ERL_NIF_TERM nsetopt_lvl_ip_router_alert(ErlNifEnv* env,
- SocketDescriptor* descP,
- ERL_NIF_TERM eVal)
+ERL_NIF_TERM nsetopt_lvl_ip_router_alert(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal)
{
#if defined(SOL_IP)
int level = SOL_IP;
@@ -8482,9 +8732,9 @@ ERL_NIF_TERM nsetopt_lvl_ip_router_alert(ErlNifEnv* env,
*/
#if defined(IP_SENDSRCADDR)
static
-ERL_NIF_TERM nsetopt_lvl_ip_sendsrcaddr(ErlNifEnv* env,
- SocketDescriptor* descP,
- ERL_NIF_TERM eVal)
+ERL_NIF_TERM nsetopt_lvl_ip_sendsrcaddr(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal)
{
#if defined(SOL_IP)
int level = SOL_IP;
@@ -8501,9 +8751,9 @@ ERL_NIF_TERM nsetopt_lvl_ip_sendsrcaddr(ErlNifEnv* env,
*/
#if defined(IP_TOS)
static
-ERL_NIF_TERM nsetopt_lvl_ip_tos(ErlNifEnv* env,
- SocketDescriptor* descP,
- ERL_NIF_TERM eVal)
+ERL_NIF_TERM nsetopt_lvl_ip_tos(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal)
{
#if defined(SOL_IP)
int level = SOL_IP;
@@ -8534,9 +8784,9 @@ ERL_NIF_TERM nsetopt_lvl_ip_tos(ErlNifEnv* env,
*/
#if defined(IP_TRANSPARENT)
static
-ERL_NIF_TERM nsetopt_lvl_ip_transparent(ErlNifEnv* env,
- SocketDescriptor* descP,
- ERL_NIF_TERM eVal)
+ERL_NIF_TERM nsetopt_lvl_ip_transparent(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal)
{
#if defined(SOL_IP)
int level = SOL_IP;
@@ -8554,9 +8804,9 @@ ERL_NIF_TERM nsetopt_lvl_ip_transparent(ErlNifEnv* env,
*/
#if defined(IP_TTL)
static
-ERL_NIF_TERM nsetopt_lvl_ip_ttl(ErlNifEnv* env,
- SocketDescriptor* descP,
- ERL_NIF_TERM eVal)
+ERL_NIF_TERM nsetopt_lvl_ip_ttl(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal)
{
#if defined(SOL_IP)
int level = SOL_IP;
@@ -8581,9 +8831,9 @@ ERL_NIF_TERM nsetopt_lvl_ip_ttl(ErlNifEnv* env,
*/
#if defined(IP_UNBLOCK_SOURCE)
static
-ERL_NIF_TERM nsetopt_lvl_ip_unblock_source(ErlNifEnv* env,
- SocketDescriptor* descP,
- ERL_NIF_TERM eVal)
+ERL_NIF_TERM nsetopt_lvl_ip_unblock_source(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal)
{
return nsetopt_lvl_ip_update_source(env, descP, eVal, IP_UNBLOCK_SOURCE);
}
@@ -8593,10 +8843,10 @@ ERL_NIF_TERM nsetopt_lvl_ip_unblock_source(ErlNifEnv* env,
#if defined(IP_ADD_MEMBERSHIP) || defined(IP_DROP_MEMBERSHIP)
static
-ERL_NIF_TERM nsetopt_lvl_ip_update_membership(ErlNifEnv* env,
- SocketDescriptor* descP,
- ERL_NIF_TERM eVal,
- int opt)
+ERL_NIF_TERM nsetopt_lvl_ip_update_membership(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal,
+ int opt)
{
ERL_NIF_TERM result, eMultiAddr, eInterface;
struct ip_mreq mreq;
@@ -8647,10 +8897,10 @@ ERL_NIF_TERM nsetopt_lvl_ip_update_membership(ErlNifEnv* env,
#if defined(IP_ADD_SOURCE_MEMBERSHIP) || defined(IP_DROP_SOURCE_MEMBERSHIP) || defined(IP_BLOCK_SOURCE) || defined(IP_UNBLOCK_SOURCE)
static
-ERL_NIF_TERM nsetopt_lvl_ip_update_source(ErlNifEnv* env,
- SocketDescriptor* descP,
- ERL_NIF_TERM eVal,
- int opt)
+ERL_NIF_TERM nsetopt_lvl_ip_update_source(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal,
+ int opt)
{
ERL_NIF_TERM result, eMultiAddr, eInterface, eSourceAddr;
struct ip_mreq_source mreq;
@@ -8714,10 +8964,10 @@ ERL_NIF_TERM nsetopt_lvl_ip_update_source(ErlNifEnv* env,
*/
#if defined(HAVE_IPV6)
static
-ERL_NIF_TERM nsetopt_lvl_ipv6(ErlNifEnv* env,
- SocketDescriptor* descP,
- int eOpt,
- ERL_NIF_TERM eVal)
+ERL_NIF_TERM nsetopt_lvl_ipv6(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ int eOpt,
+ ERL_NIF_TERM eVal)
{
ERL_NIF_TERM result;
@@ -8859,9 +9109,9 @@ ERL_NIF_TERM nsetopt_lvl_ipv6(ErlNifEnv* env,
#if defined(IPV6_ADDRFORM)
static
-ERL_NIF_TERM nsetopt_lvl_ipv6_addrform(ErlNifEnv* env,
- SocketDescriptor* descP,
- ERL_NIF_TERM eVal)
+ERL_NIF_TERM nsetopt_lvl_ipv6_addrform(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal)
{
ERL_NIF_TERM result;
int res, edomain, domain;
@@ -8901,9 +9151,9 @@ ERL_NIF_TERM nsetopt_lvl_ipv6_addrform(ErlNifEnv* env,
#if defined(IPV6_ADD_MEMBERSHIP)
static
-ERL_NIF_TERM nsetopt_lvl_ipv6_add_membership(ErlNifEnv* env,
- SocketDescriptor* descP,
- ERL_NIF_TERM eVal)
+ERL_NIF_TERM nsetopt_lvl_ipv6_add_membership(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal)
{
return nsetopt_lvl_ipv6_update_membership(env, descP, eVal,
IPV6_ADD_MEMBERSHIP);
@@ -8913,9 +9163,9 @@ ERL_NIF_TERM nsetopt_lvl_ipv6_add_membership(ErlNifEnv* env,
#if defined(IPV6_AUTHHDR)
static
-ERL_NIF_TERM nsetopt_lvl_ipv6_authhdr(ErlNifEnv* env,
- SocketDescriptor* descP,
- ERL_NIF_TERM eVal)
+ERL_NIF_TERM nsetopt_lvl_ipv6_authhdr(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal)
{
return nsetopt_bool_opt(env, descP, SOL_IPV6, IPV6_AUTHHDR, eVal);
}
@@ -8924,9 +9174,9 @@ ERL_NIF_TERM nsetopt_lvl_ipv6_authhdr(ErlNifEnv* env,
#if defined(IPV6_DROP_MEMBERSHIP)
static
-ERL_NIF_TERM nsetopt_lvl_ipv6_drop_membership(ErlNifEnv* env,
- SocketDescriptor* descP,
- ERL_NIF_TERM eVal)
+ERL_NIF_TERM nsetopt_lvl_ipv6_drop_membership(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal)
{
return nsetopt_lvl_ipv6_update_membership(env, descP, eVal,
IPV6_DROP_MEMBERSHIP);
@@ -8936,9 +9186,9 @@ ERL_NIF_TERM nsetopt_lvl_ipv6_drop_membership(ErlNifEnv* env,
#if defined(IPV6_DSTOPTS)
static
-ERL_NIF_TERM nsetopt_lvl_ipv6_dstopts(ErlNifEnv* env,
- SocketDescriptor* descP,
- ERL_NIF_TERM eVal)
+ERL_NIF_TERM nsetopt_lvl_ipv6_dstopts(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal)
{
#if defined(SOL_IPV6)
int level = SOL_IPV6;
@@ -8953,9 +9203,9 @@ ERL_NIF_TERM nsetopt_lvl_ipv6_dstopts(ErlNifEnv* env,
#if defined(IPV6_FLOWINFO)
static
-ERL_NIF_TERM nsetopt_lvl_ipv6_flowinfo(ErlNifEnv* env,
- SocketDescriptor* descP,
- ERL_NIF_TERM eVal)
+ERL_NIF_TERM nsetopt_lvl_ipv6_flowinfo(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal)
{
#if defined(SOL_IPV6)
int level = SOL_IPV6;
@@ -8970,9 +9220,9 @@ ERL_NIF_TERM nsetopt_lvl_ipv6_flowinfo(ErlNifEnv* env,
#if defined(IPV6_HOPLIMIT)
static
-ERL_NIF_TERM nsetopt_lvl_ipv6_hoplimit(ErlNifEnv* env,
- SocketDescriptor* descP,
- ERL_NIF_TERM eVal)
+ERL_NIF_TERM nsetopt_lvl_ipv6_hoplimit(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal)
{
#if defined(SOL_IPV6)
int level = SOL_IPV6;
@@ -8987,9 +9237,9 @@ ERL_NIF_TERM nsetopt_lvl_ipv6_hoplimit(ErlNifEnv* env,
#if defined(IPV6_HOPOPTS)
static
-ERL_NIF_TERM nsetopt_lvl_ipv6_hopopts(ErlNifEnv* env,
- SocketDescriptor* descP,
- ERL_NIF_TERM eVal)
+ERL_NIF_TERM nsetopt_lvl_ipv6_hopopts(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal)
{
#if defined(SOL_IPV6)
int level = SOL_IPV6;
@@ -9004,9 +9254,9 @@ ERL_NIF_TERM nsetopt_lvl_ipv6_hopopts(ErlNifEnv* env,
#if defined(IPV6_MTU)
static
-ERL_NIF_TERM nsetopt_lvl_ipv6_mtu(ErlNifEnv* env,
- SocketDescriptor* descP,
- ERL_NIF_TERM eVal)
+ERL_NIF_TERM nsetopt_lvl_ipv6_mtu(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal)
{
#if defined(SOL_IPV6)
int level = SOL_IPV6;
@@ -9025,9 +9275,9 @@ ERL_NIF_TERM nsetopt_lvl_ipv6_mtu(ErlNifEnv* env,
*/
#if defined(IPV6_MTU_DISCOVER)
static
-ERL_NIF_TERM nsetopt_lvl_ipv6_mtu_discover(ErlNifEnv* env,
- SocketDescriptor* descP,
- ERL_NIF_TERM eVal)
+ERL_NIF_TERM nsetopt_lvl_ipv6_mtu_discover(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal)
{
ERL_NIF_TERM result;
int val;
@@ -9063,9 +9313,9 @@ ERL_NIF_TERM nsetopt_lvl_ipv6_mtu_discover(ErlNifEnv* env,
#if defined(IPV6_MULTICAST_HOPS)
static
-ERL_NIF_TERM nsetopt_lvl_ipv6_multicast_hops(ErlNifEnv* env,
- SocketDescriptor* descP,
- ERL_NIF_TERM eVal)
+ERL_NIF_TERM nsetopt_lvl_ipv6_multicast_hops(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal)
{
#if defined(SOL_IPV6)
int level = SOL_IPV6;
@@ -9081,9 +9331,9 @@ ERL_NIF_TERM nsetopt_lvl_ipv6_multicast_hops(ErlNifEnv* env,
#if defined(IPV6_MULTICAST_IF)
static
-ERL_NIF_TERM nsetopt_lvl_ipv6_multicast_if(ErlNifEnv* env,
- SocketDescriptor* descP,
- ERL_NIF_TERM eVal)
+ERL_NIF_TERM nsetopt_lvl_ipv6_multicast_if(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal)
{
#if defined(SOL_IPV6)
int level = SOL_IPV6;
@@ -9099,9 +9349,9 @@ ERL_NIF_TERM nsetopt_lvl_ipv6_multicast_if(ErlNifEnv* env,
#if defined(IPV6_MULTICAST_LOOP)
static
-ERL_NIF_TERM nsetopt_lvl_ipv6_multicast_loop(ErlNifEnv* env,
- SocketDescriptor* descP,
- ERL_NIF_TERM eVal)
+ERL_NIF_TERM nsetopt_lvl_ipv6_multicast_loop(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal)
{
#if defined(SOL_IPV6)
int level = SOL_IPV6;
@@ -9116,9 +9366,9 @@ ERL_NIF_TERM nsetopt_lvl_ipv6_multicast_loop(ErlNifEnv* env,
#if defined(IPV6_RECVERR)
static
-ERL_NIF_TERM nsetopt_lvl_ipv6_recverr(ErlNifEnv* env,
- SocketDescriptor* descP,
- ERL_NIF_TERM eVal)
+ERL_NIF_TERM nsetopt_lvl_ipv6_recverr(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal)
{
#if defined(SOL_IPV6)
int level = SOL_IPV6;
@@ -9133,9 +9383,9 @@ ERL_NIF_TERM nsetopt_lvl_ipv6_recverr(ErlNifEnv* env,
#if defined(IPV6_RECVPKTINFO) || defined(IPV6_PKTINFO)
static
-ERL_NIF_TERM nsetopt_lvl_ipv6_recvpktinfo(ErlNifEnv* env,
- SocketDescriptor* descP,
- ERL_NIF_TERM eVal)
+ERL_NIF_TERM nsetopt_lvl_ipv6_recvpktinfo(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal)
{
#if defined(SOL_IPV6)
int level = SOL_IPV6;
@@ -9155,9 +9405,9 @@ ERL_NIF_TERM nsetopt_lvl_ipv6_recvpktinfo(ErlNifEnv* env,
#if defined(IPV6_ROUTER_ALERT)
static
-ERL_NIF_TERM nsetopt_lvl_ipv6_router_alert(ErlNifEnv* env,
- SocketDescriptor* descP,
- ERL_NIF_TERM eVal)
+ERL_NIF_TERM nsetopt_lvl_ipv6_router_alert(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal)
{
#if defined(SOL_IPV6)
int level = SOL_IPV6;
@@ -9173,9 +9423,9 @@ ERL_NIF_TERM nsetopt_lvl_ipv6_router_alert(ErlNifEnv* env,
#if defined(IPV6_RTHDR)
static
-ERL_NIF_TERM nsetopt_lvl_ipv6_rthdr(ErlNifEnv* env,
- SocketDescriptor* descP,
- ERL_NIF_TERM eVal)
+ERL_NIF_TERM nsetopt_lvl_ipv6_rthdr(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal)
{
#if defined(SOL_IPV6)
int level = SOL_IPV6;
@@ -9190,9 +9440,9 @@ ERL_NIF_TERM nsetopt_lvl_ipv6_rthdr(ErlNifEnv* env,
#if defined(IPV6_UNICAST_HOPS)
static
-ERL_NIF_TERM nsetopt_lvl_ipv6_unicast_hops(ErlNifEnv* env,
- SocketDescriptor* descP,
- ERL_NIF_TERM eVal)
+ERL_NIF_TERM nsetopt_lvl_ipv6_unicast_hops(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal)
{
#if defined(SOL_IPV6)
int level = SOL_IPV6;
@@ -9208,9 +9458,9 @@ ERL_NIF_TERM nsetopt_lvl_ipv6_unicast_hops(ErlNifEnv* env,
#if defined(IPV6_V6ONLY)
static
-ERL_NIF_TERM nsetopt_lvl_ipv6_v6only(ErlNifEnv* env,
- SocketDescriptor* descP,
- ERL_NIF_TERM eVal)
+ERL_NIF_TERM nsetopt_lvl_ipv6_v6only(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal)
{
#if defined(SOL_IPV6)
int level = SOL_IPV6;
@@ -9225,10 +9475,10 @@ ERL_NIF_TERM nsetopt_lvl_ipv6_v6only(ErlNifEnv* env,
#if defined(IPV6_ADD_MEMBERSHIP) || defined(IPV6_DROP_MEMBERSHIP)
static
-ERL_NIF_TERM nsetopt_lvl_ipv6_update_membership(ErlNifEnv* env,
- SocketDescriptor* descP,
- ERL_NIF_TERM eVal,
- int opt)
+ERL_NIF_TERM nsetopt_lvl_ipv6_update_membership(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal,
+ int opt)
{
ERL_NIF_TERM result, eMultiAddr, eInterface;
struct ipv6_mreq mreq;
@@ -9283,10 +9533,10 @@ ERL_NIF_TERM nsetopt_lvl_ipv6_update_membership(ErlNifEnv* env,
/* nsetopt_lvl_tcp - Level *TCP* option(s)
*/
static
-ERL_NIF_TERM nsetopt_lvl_tcp(ErlNifEnv* env,
- SocketDescriptor* descP,
- int eOpt,
- ERL_NIF_TERM eVal)
+ERL_NIF_TERM nsetopt_lvl_tcp(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ int eOpt,
+ ERL_NIF_TERM eVal)
{
ERL_NIF_TERM result;
@@ -9327,9 +9577,9 @@ ERL_NIF_TERM nsetopt_lvl_tcp(ErlNifEnv* env,
*/
#if defined(TCP_CONGESTION)
static
-ERL_NIF_TERM nsetopt_lvl_tcp_congestion(ErlNifEnv* env,
- SocketDescriptor* descP,
- ERL_NIF_TERM eVal)
+ERL_NIF_TERM nsetopt_lvl_tcp_congestion(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal)
{
int max = SOCKET_OPT_TCP_CONGESTION_NAME_MAX+1;
@@ -9342,9 +9592,9 @@ ERL_NIF_TERM nsetopt_lvl_tcp_congestion(ErlNifEnv* env,
*/
#if defined(TCP_MAXSEG)
static
-ERL_NIF_TERM nsetopt_lvl_tcp_maxseg(ErlNifEnv* env,
- SocketDescriptor* descP,
- ERL_NIF_TERM eVal)
+ERL_NIF_TERM nsetopt_lvl_tcp_maxseg(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal)
{
return nsetopt_int_opt(env, descP, IPPROTO_TCP, TCP_MAXSEG, eVal);
}
@@ -9355,9 +9605,9 @@ ERL_NIF_TERM nsetopt_lvl_tcp_maxseg(ErlNifEnv* env,
*/
#if defined(TCP_NODELAY)
static
-ERL_NIF_TERM nsetopt_lvl_tcp_nodelay(ErlNifEnv* env,
- SocketDescriptor* descP,
- ERL_NIF_TERM eVal)
+ERL_NIF_TERM nsetopt_lvl_tcp_nodelay(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal)
{
return nsetopt_bool_opt(env, descP, IPPROTO_TCP, TCP_NODELAY, eVal);
}
@@ -9368,10 +9618,10 @@ ERL_NIF_TERM nsetopt_lvl_tcp_nodelay(ErlNifEnv* env,
/* nsetopt_lvl_udp - Level *UDP* option(s)
*/
static
-ERL_NIF_TERM nsetopt_lvl_udp(ErlNifEnv* env,
- SocketDescriptor* descP,
- int eOpt,
- ERL_NIF_TERM eVal)
+ERL_NIF_TERM nsetopt_lvl_udp(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ int eOpt,
+ ERL_NIF_TERM eVal)
{
ERL_NIF_TERM result;
@@ -9400,9 +9650,9 @@ ERL_NIF_TERM nsetopt_lvl_udp(ErlNifEnv* env,
*/
#if defined(UDP_CORK)
static
-ERL_NIF_TERM nsetopt_lvl_udp_cork(ErlNifEnv* env,
- SocketDescriptor* descP,
- ERL_NIF_TERM eVal)
+ERL_NIF_TERM nsetopt_lvl_udp_cork(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal)
{
return nsetopt_bool_opt(env, descP, IPPROTO_UDP, UDP_CORK, eVal);
}
@@ -9415,10 +9665,10 @@ ERL_NIF_TERM nsetopt_lvl_udp_cork(ErlNifEnv* env,
*/
#if defined(HAVE_SCTP)
static
-ERL_NIF_TERM nsetopt_lvl_sctp(ErlNifEnv* env,
- SocketDescriptor* descP,
- int eOpt,
- ERL_NIF_TERM eVal)
+ERL_NIF_TERM nsetopt_lvl_sctp(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ int eOpt,
+ ERL_NIF_TERM eVal)
{
ERL_NIF_TERM result;
@@ -9489,9 +9739,9 @@ ERL_NIF_TERM nsetopt_lvl_sctp(ErlNifEnv* env,
*/
#if defined(SCTP_ASSOCINFO)
static
-ERL_NIF_TERM nsetopt_lvl_sctp_associnfo(ErlNifEnv* env,
- SocketDescriptor* descP,
- ERL_NIF_TERM eVal)
+ERL_NIF_TERM nsetopt_lvl_sctp_associnfo(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal)
{
ERL_NIF_TERM result;
ERL_NIF_TERM eAssocId, eMaxRxt, eNumPeerDests;
@@ -9614,9 +9864,9 @@ ERL_NIF_TERM nsetopt_lvl_sctp_associnfo(ErlNifEnv* env,
*/
#if defined(SCTP_AUTOCLOSE)
static
-ERL_NIF_TERM nsetopt_lvl_sctp_autoclose(ErlNifEnv* env,
- SocketDescriptor* descP,
- ERL_NIF_TERM eVal)
+ERL_NIF_TERM nsetopt_lvl_sctp_autoclose(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal)
{
return nsetopt_int_opt(env, descP, IPPROTO_SCTP, SCTP_AUTOCLOSE, eVal);
}
@@ -9627,9 +9877,9 @@ ERL_NIF_TERM nsetopt_lvl_sctp_autoclose(ErlNifEnv* env,
*/
#if defined(SCTP_DISABLE_FRAGMENTS)
static
-ERL_NIF_TERM nsetopt_lvl_sctp_disable_fragments(ErlNifEnv* env,
- SocketDescriptor* descP,
- ERL_NIF_TERM eVal)
+ERL_NIF_TERM nsetopt_lvl_sctp_disable_fragments(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal)
{
return nsetopt_bool_opt(env, descP, IPPROTO_SCTP, SCTP_DISABLE_FRAGMENTS, eVal);
}
@@ -9640,9 +9890,9 @@ ERL_NIF_TERM nsetopt_lvl_sctp_disable_fragments(ErlNifEnv* env,
*/
#if defined(SCTP_EVENTS)
static
-ERL_NIF_TERM nsetopt_lvl_sctp_events(ErlNifEnv* env,
- SocketDescriptor* descP,
- ERL_NIF_TERM eVal)
+ERL_NIF_TERM nsetopt_lvl_sctp_events(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal)
{
ERL_NIF_TERM result;
ERL_NIF_TERM eDataIn, eAssoc, eAddr, eSndFailure;
@@ -9752,9 +10002,9 @@ ERL_NIF_TERM nsetopt_lvl_sctp_events(ErlNifEnv* env,
*/
#if defined(SCTP_INITMSG)
static
-ERL_NIF_TERM nsetopt_lvl_sctp_initmsg(ErlNifEnv* env,
- SocketDescriptor* descP,
- ERL_NIF_TERM eVal)
+ERL_NIF_TERM nsetopt_lvl_sctp_initmsg(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal)
{
ERL_NIF_TERM result;
ERL_NIF_TERM eNumOut, eMaxIn, eMaxAttempts, eMaxInitTO;
@@ -9836,9 +10086,9 @@ ERL_NIF_TERM nsetopt_lvl_sctp_initmsg(ErlNifEnv* env,
*/
#if defined(SCTP_MAXSEG)
static
-ERL_NIF_TERM nsetopt_lvl_sctp_maxseg(ErlNifEnv* env,
- SocketDescriptor* descP,
- ERL_NIF_TERM eVal)
+ERL_NIF_TERM nsetopt_lvl_sctp_maxseg(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal)
{
return nsetopt_int_opt(env, descP, IPPROTO_SCTP, SCTP_MAXSEG, eVal);
}
@@ -9849,9 +10099,9 @@ ERL_NIF_TERM nsetopt_lvl_sctp_maxseg(ErlNifEnv* env,
*/
#if defined(SCTP_NODELAY)
static
-ERL_NIF_TERM nsetopt_lvl_sctp_nodelay(ErlNifEnv* env,
- SocketDescriptor* descP,
- ERL_NIF_TERM eVal)
+ERL_NIF_TERM nsetopt_lvl_sctp_nodelay(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal)
{
return nsetopt_bool_opt(env, descP, IPPROTO_SCTP, SCTP_NODELAY, eVal);
}
@@ -9862,9 +10112,9 @@ ERL_NIF_TERM nsetopt_lvl_sctp_nodelay(ErlNifEnv* env,
*/
#if defined(SCTP_RTOINFO)
static
-ERL_NIF_TERM nsetopt_lvl_sctp_rtoinfo(ErlNifEnv* env,
- SocketDescriptor* descP,
- ERL_NIF_TERM eVal)
+ERL_NIF_TERM nsetopt_lvl_sctp_rtoinfo(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal)
{
ERL_NIF_TERM result;
ERL_NIF_TERM eAssocId, eInitial, eMax, eMin;
@@ -9925,11 +10175,6 @@ ERL_NIF_TERM nsetopt_lvl_sctp_rtoinfo(ErlNifEnv* env,
#else
SIZE CHECK FOR ASSOC ID FAILED
#endif
- /*
- if (!GET_INT(env, eAssocId, &tmpAssocId))
- return esock_make_error(env, esock_atom_einval);
- rtoInfo.srto_assoc_id = (typeof(rtoInfo.srto_assoc_id)) tmpAssocId;
- */
if (!GET_UINT(env, eInitial, &rtoInfo.srto_initial))
return esock_make_error(env, esock_atom_einval);
@@ -9971,11 +10216,11 @@ ERL_NIF_TERM nsetopt_lvl_sctp_rtoinfo(ErlNifEnv* env,
/* nsetopt_bool_opt - set an option that has an (integer) bool value
*/
static
-ERL_NIF_TERM nsetopt_bool_opt(ErlNifEnv* env,
- SocketDescriptor* descP,
- int level,
- int opt,
- ERL_NIF_TERM eVal)
+ERL_NIF_TERM nsetopt_bool_opt(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ int level,
+ int opt,
+ ERL_NIF_TERM eVal)
{
ERL_NIF_TERM result;
BOOLEAN_T val;
@@ -9998,11 +10243,11 @@ ERL_NIF_TERM nsetopt_bool_opt(ErlNifEnv* env,
/* nsetopt_int_opt - set an option that has an integer value
*/
static
-ERL_NIF_TERM nsetopt_int_opt(ErlNifEnv* env,
- SocketDescriptor* descP,
- int level,
- int opt,
- ERL_NIF_TERM eVal)
+ERL_NIF_TERM nsetopt_int_opt(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ int level,
+ int opt,
+ ERL_NIF_TERM eVal)
{
ERL_NIF_TERM result;
int val;
@@ -10037,12 +10282,12 @@ ERL_NIF_TERM nsetopt_int_opt(ErlNifEnv* env,
*/
#if defined(USE_SETOPT_STR_OPT)
static
-ERL_NIF_TERM nsetopt_str_opt(ErlNifEnv* env,
- SocketDescriptor* descP,
- int level,
- int opt,
- int max,
- ERL_NIF_TERM eVal)
+ERL_NIF_TERM nsetopt_str_opt(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ int level,
+ int opt,
+ int max,
+ ERL_NIF_TERM eVal)
{
ERL_NIF_TERM result;
char* val = MALLOC(max);
@@ -10070,11 +10315,11 @@ ERL_NIF_TERM nsetopt_str_opt(ErlNifEnv* env,
/* nsetopt_timeval_opt - set an option that has an (timeval) bool value
*/
static
-ERL_NIF_TERM nsetopt_timeval_opt(ErlNifEnv* env,
- SocketDescriptor* descP,
- int level,
- int opt,
- ERL_NIF_TERM eVal)
+ERL_NIF_TERM nsetopt_timeval_opt(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ int level,
+ int opt,
+ ERL_NIF_TERM eVal)
{
ERL_NIF_TERM result;
struct timeval timeVal;
@@ -10303,10 +10548,11 @@ ERL_NIF_TERM nif_getopt(ErlNifEnv* env,
#if defined(__WIN32__)
return enif_raise_exception(env, MKA(env, "notsup"));
#else
- SocketDescriptor* descP;
- int eLevel, level = -1;
- ERL_NIF_TERM eIsEncoded, eOpt;
- BOOLEAN_T isEncoded, isOTP;
+ ESockDescriptor* descP;
+ int eLevel, level = -1;
+ ERL_NIF_TERM eIsEncoded, eOpt;
+ BOOLEAN_T isEncoded, isOTP;
+ ERL_NIF_TERM result;
SGDBG( ("SOCKET", "nif_getopt -> entry with argc: %d\r\n", argc) );
@@ -10335,7 +10581,14 @@ ERL_NIF_TERM nif_getopt(ErlNifEnv* env,
if (!elevel2level(isEncoded, eLevel, &isOTP, &level))
return esock_make_error(env, esock_atom_einval);
- return ngetopt(env, descP, isEncoded, isOTP, level, eOpt);
+ MLOCK(descP->cfgMtx);
+
+ result = ngetopt(env, descP, isEncoded, isOTP, level, eOpt);
+
+ MUNLOCK(descP->cfgMtx);
+
+ return result;
+
#endif // if defined(__WIN32__)
}
@@ -10343,12 +10596,12 @@ ERL_NIF_TERM nif_getopt(ErlNifEnv* env,
#if !defined(__WIN32__)
static
-ERL_NIF_TERM ngetopt(ErlNifEnv* env,
- SocketDescriptor* descP,
- BOOLEAN_T isEncoded,
- BOOLEAN_T isOTP,
- int level,
- ERL_NIF_TERM eOpt)
+ERL_NIF_TERM ngetopt(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ BOOLEAN_T isEncoded,
+ BOOLEAN_T isOTP,
+ int level,
+ ERL_NIF_TERM eOpt)
{
ERL_NIF_TERM result;
int opt;
@@ -10391,9 +10644,9 @@ ERL_NIF_TERM ngetopt(ErlNifEnv* env,
/* ngetopt_otp - Handle OTP (level) options
*/
static
-ERL_NIF_TERM ngetopt_otp(ErlNifEnv* env,
- SocketDescriptor* descP,
- int eOpt)
+ERL_NIF_TERM ngetopt_otp(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ int eOpt)
{
ERL_NIF_TERM result;
@@ -10461,8 +10714,8 @@ ERL_NIF_TERM ngetopt_otp(ErlNifEnv* env,
/* ngetopt_otp_debug - Handle the OTP (level) debug option
*/
static
-ERL_NIF_TERM ngetopt_otp_debug(ErlNifEnv* env,
- SocketDescriptor* descP)
+ERL_NIF_TERM ngetopt_otp_debug(ErlNifEnv* env,
+ ESockDescriptor* descP)
{
ERL_NIF_TERM eVal = esock_encode_bool(descP->dbg);
@@ -10473,8 +10726,8 @@ ERL_NIF_TERM ngetopt_otp_debug(ErlNifEnv* env,
/* ngetopt_otp_iow - Handle the OTP (level) iow option
*/
static
-ERL_NIF_TERM ngetopt_otp_iow(ErlNifEnv* env,
- SocketDescriptor* descP)
+ERL_NIF_TERM ngetopt_otp_iow(ErlNifEnv* env,
+ ESockDescriptor* descP)
{
ERL_NIF_TERM eVal = esock_encode_bool(descP->iow);
@@ -10485,8 +10738,8 @@ ERL_NIF_TERM ngetopt_otp_iow(ErlNifEnv* env,
/* ngetopt_otp_ctrl_proc - Handle the OTP (level) controlling_process option
*/
static
-ERL_NIF_TERM ngetopt_otp_ctrl_proc(ErlNifEnv* env,
- SocketDescriptor* descP)
+ERL_NIF_TERM ngetopt_otp_ctrl_proc(ErlNifEnv* env,
+ ESockDescriptor* descP)
{
ERL_NIF_TERM eVal = MKPID(env, &descP->ctrlPid);
@@ -10498,8 +10751,8 @@ ERL_NIF_TERM ngetopt_otp_ctrl_proc(ErlNifEnv* env,
/* ngetopt_otp_rcvbuf - Handle the OTP (level) rcvbuf option
*/
static
-ERL_NIF_TERM ngetopt_otp_rcvbuf(ErlNifEnv* env,
- SocketDescriptor* descP)
+ERL_NIF_TERM ngetopt_otp_rcvbuf(ErlNifEnv* env,
+ ESockDescriptor* descP)
{
ERL_NIF_TERM eVal;
@@ -10516,8 +10769,8 @@ ERL_NIF_TERM ngetopt_otp_rcvbuf(ErlNifEnv* env,
/* ngetopt_otp_rcvctrlbuf - Handle the OTP (level) rcvctrlbuf option
*/
static
-ERL_NIF_TERM ngetopt_otp_rcvctrlbuf(ErlNifEnv* env,
- SocketDescriptor* descP)
+ERL_NIF_TERM ngetopt_otp_rcvctrlbuf(ErlNifEnv* env,
+ ESockDescriptor* descP)
{
ERL_NIF_TERM eVal = MKI(env, descP->rCtrlSz);
@@ -10528,8 +10781,8 @@ ERL_NIF_TERM ngetopt_otp_rcvctrlbuf(ErlNifEnv* env,
/* ngetopt_otp_sndctrlbuf - Handle the OTP (level) sndctrlbuf option
*/
static
-ERL_NIF_TERM ngetopt_otp_sndctrlbuf(ErlNifEnv* env,
- SocketDescriptor* descP)
+ERL_NIF_TERM ngetopt_otp_sndctrlbuf(ErlNifEnv* env,
+ ESockDescriptor* descP)
{
ERL_NIF_TERM eVal = MKI(env, descP->wCtrlSz);
@@ -10540,8 +10793,8 @@ ERL_NIF_TERM ngetopt_otp_sndctrlbuf(ErlNifEnv* env,
/* ngetopt_otp_fd - Handle the OTP (level) fd option
*/
static
-ERL_NIF_TERM ngetopt_otp_fd(ErlNifEnv* env,
- SocketDescriptor* descP)
+ERL_NIF_TERM ngetopt_otp_fd(ErlNifEnv* env,
+ ESockDescriptor* descP)
{
ERL_NIF_TERM eVal = MKI(env, descP->sock);
@@ -10552,8 +10805,8 @@ ERL_NIF_TERM ngetopt_otp_fd(ErlNifEnv* env,
/* ngetopt_otp_domain - Handle the OTP (level) domain option
*/
static
-ERL_NIF_TERM ngetopt_otp_domain(ErlNifEnv* env,
- SocketDescriptor* descP)
+ERL_NIF_TERM ngetopt_otp_domain(ErlNifEnv* env,
+ ESockDescriptor* descP)
{
ERL_NIF_TERM result, reason;
int val = descP->domain;
@@ -10588,8 +10841,8 @@ ERL_NIF_TERM ngetopt_otp_domain(ErlNifEnv* env,
/* ngetopt_otp_type - Handle the OTP (level) type options.
*/
static
-ERL_NIF_TERM ngetopt_otp_type(ErlNifEnv* env,
- SocketDescriptor* descP)
+ERL_NIF_TERM ngetopt_otp_type(ErlNifEnv* env,
+ ESockDescriptor* descP)
{
ERL_NIF_TERM result, reason;
int val = descP->type;
@@ -10629,8 +10882,8 @@ ERL_NIF_TERM ngetopt_otp_type(ErlNifEnv* env,
/* ngetopt_otp_protocol - Handle the OTP (level) protocol options.
*/
static
-ERL_NIF_TERM ngetopt_otp_protocol(ErlNifEnv* env,
- SocketDescriptor* descP)
+ERL_NIF_TERM ngetopt_otp_protocol(ErlNifEnv* env,
+ ESockDescriptor* descP)
{
ERL_NIF_TERM result, reason;
int val = descP->protocol;
@@ -10670,10 +10923,10 @@ ERL_NIF_TERM ngetopt_otp_protocol(ErlNifEnv* env,
* format: {NativeOpt :: integer(), ValueSize :: non_neg_integer()}
*/
static
-ERL_NIF_TERM ngetopt_native(ErlNifEnv* env,
- SocketDescriptor* descP,
- int level,
- ERL_NIF_TERM eOpt)
+ERL_NIF_TERM ngetopt_native(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ int level,
+ ERL_NIF_TERM eOpt)
{
ERL_NIF_TERM result = enif_make_badarg(env);
int opt;
@@ -10728,11 +10981,11 @@ ERL_NIF_TERM ngetopt_native(ErlNifEnv* env,
static
-ERL_NIF_TERM ngetopt_native_unspec(ErlNifEnv* env,
- SocketDescriptor* descP,
- int level,
- int opt,
- SOCKOPTLEN_T valueSz)
+ERL_NIF_TERM ngetopt_native_unspec(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ int level,
+ int opt,
+ SOCKOPTLEN_T valueSz)
{
ERL_NIF_TERM result = esock_make_error(env, esock_atom_einval);
int res;
@@ -10798,10 +11051,10 @@ ERL_NIF_TERM ngetopt_native_unspec(ErlNifEnv* env,
/* ngetopt_level - A "proper" level (option) has been specified
*/
static
-ERL_NIF_TERM ngetopt_level(ErlNifEnv* env,
- SocketDescriptor* descP,
- int level,
- int eOpt)
+ERL_NIF_TERM ngetopt_level(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ int level,
+ int eOpt)
{
ERL_NIF_TERM result;
@@ -10865,9 +11118,9 @@ ERL_NIF_TERM ngetopt_level(ErlNifEnv* env,
/* ngetopt_lvl_socket - Level *SOCKET* option
*/
static
-ERL_NIF_TERM ngetopt_lvl_socket(ErlNifEnv* env,
- SocketDescriptor* descP,
- int eOpt)
+ERL_NIF_TERM ngetopt_lvl_socket(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ int eOpt)
{
ERL_NIF_TERM result;
@@ -11025,8 +11278,8 @@ ERL_NIF_TERM ngetopt_lvl_socket(ErlNifEnv* env,
#if defined(SO_ACCEPTCONN)
static
-ERL_NIF_TERM ngetopt_lvl_sock_acceptconn(ErlNifEnv* env,
- SocketDescriptor* descP)
+ERL_NIF_TERM ngetopt_lvl_sock_acceptconn(ErlNifEnv* env,
+ ESockDescriptor* descP)
{
return ngetopt_bool_opt(env, descP, SOL_SOCKET, SO_ACCEPTCONN);
}
@@ -11035,8 +11288,8 @@ ERL_NIF_TERM ngetopt_lvl_sock_acceptconn(ErlNifEnv* env,
#if defined(SO_BINDTODEVICE)
static
-ERL_NIF_TERM ngetopt_lvl_sock_bindtodevice(ErlNifEnv* env,
- SocketDescriptor* descP)
+ERL_NIF_TERM ngetopt_lvl_sock_bindtodevice(ErlNifEnv* env,
+ ESockDescriptor* descP)
{
SSDBG( descP,
("SOCKET", "ngetopt_lvl_sock_bindtodevice -> entry with\r\n") );
@@ -11048,8 +11301,8 @@ ERL_NIF_TERM ngetopt_lvl_sock_bindtodevice(ErlNifEnv* env,
#if defined(SO_BROADCAST)
static
-ERL_NIF_TERM ngetopt_lvl_sock_broadcast(ErlNifEnv* env,
- SocketDescriptor* descP)
+ERL_NIF_TERM ngetopt_lvl_sock_broadcast(ErlNifEnv* env,
+ ESockDescriptor* descP)
{
return ngetopt_bool_opt(env, descP, SOL_SOCKET, SO_BROADCAST);
}
@@ -11058,8 +11311,8 @@ ERL_NIF_TERM ngetopt_lvl_sock_broadcast(ErlNifEnv* env,
#if defined(SO_DEBUG)
static
-ERL_NIF_TERM ngetopt_lvl_sock_debug(ErlNifEnv* env,
- SocketDescriptor* descP)
+ERL_NIF_TERM ngetopt_lvl_sock_debug(ErlNifEnv* env,
+ ESockDescriptor* descP)
{
return ngetopt_int_opt(env, descP, SOL_SOCKET, SO_DEBUG);
}
@@ -11068,8 +11321,8 @@ ERL_NIF_TERM ngetopt_lvl_sock_debug(ErlNifEnv* env,
#if defined(SO_DOMAIN)
static
-ERL_NIF_TERM ngetopt_lvl_sock_domain(ErlNifEnv* env,
- SocketDescriptor* descP)
+ERL_NIF_TERM ngetopt_lvl_sock_domain(ErlNifEnv* env,
+ ESockDescriptor* descP)
{
ERL_NIF_TERM result, reason;
int val;
@@ -11113,8 +11366,8 @@ ERL_NIF_TERM ngetopt_lvl_sock_domain(ErlNifEnv* env,
#if defined(SO_DONTROUTE)
static
-ERL_NIF_TERM ngetopt_lvl_sock_dontroute(ErlNifEnv* env,
- SocketDescriptor* descP)
+ERL_NIF_TERM ngetopt_lvl_sock_dontroute(ErlNifEnv* env,
+ ESockDescriptor* descP)
{
return ngetopt_bool_opt(env, descP, SOL_SOCKET, SO_DONTROUTE);
}
@@ -11123,8 +11376,8 @@ ERL_NIF_TERM ngetopt_lvl_sock_dontroute(ErlNifEnv* env,
#if defined(SO_KEEPALIVE)
static
-ERL_NIF_TERM ngetopt_lvl_sock_keepalive(ErlNifEnv* env,
- SocketDescriptor* descP)
+ERL_NIF_TERM ngetopt_lvl_sock_keepalive(ErlNifEnv* env,
+ ESockDescriptor* descP)
{
return ngetopt_bool_opt(env, descP, SOL_SOCKET, SO_KEEPALIVE);
}
@@ -11133,8 +11386,8 @@ ERL_NIF_TERM ngetopt_lvl_sock_keepalive(ErlNifEnv* env,
#if defined(SO_LINGER)
static
-ERL_NIF_TERM ngetopt_lvl_sock_linger(ErlNifEnv* env,
- SocketDescriptor* descP)
+ERL_NIF_TERM ngetopt_lvl_sock_linger(ErlNifEnv* env,
+ ESockDescriptor* descP)
{
ERL_NIF_TERM result;
struct linger val;
@@ -11163,8 +11416,8 @@ ERL_NIF_TERM ngetopt_lvl_sock_linger(ErlNifEnv* env,
#if defined(SO_OOBINLINE)
static
-ERL_NIF_TERM ngetopt_lvl_sock_oobinline(ErlNifEnv* env,
- SocketDescriptor* descP)
+ERL_NIF_TERM ngetopt_lvl_sock_oobinline(ErlNifEnv* env,
+ ESockDescriptor* descP)
{
return ngetopt_bool_opt(env, descP, SOL_SOCKET, SO_OOBINLINE);
}
@@ -11173,8 +11426,8 @@ ERL_NIF_TERM ngetopt_lvl_sock_oobinline(ErlNifEnv* env,
#if defined(SO_PEEK_OFF)
static
-ERL_NIF_TERM ngetopt_lvl_sock_peek_off(ErlNifEnv* env,
- SocketDescriptor* descP)
+ERL_NIF_TERM ngetopt_lvl_sock_peek_off(ErlNifEnv* env,
+ ESockDescriptor* descP)
{
return ngetopt_int_opt(env, descP, SOL_SOCKET, SO_PEEK_OFF);
}
@@ -11183,8 +11436,8 @@ ERL_NIF_TERM ngetopt_lvl_sock_peek_off(ErlNifEnv* env,
#if defined(SO_PRIORITY)
static
-ERL_NIF_TERM ngetopt_lvl_sock_priority(ErlNifEnv* env,
- SocketDescriptor* descP)
+ERL_NIF_TERM ngetopt_lvl_sock_priority(ErlNifEnv* env,
+ ESockDescriptor* descP)
{
return ngetopt_int_opt(env, descP, SOL_SOCKET, SO_PRIORITY);
}
@@ -11193,8 +11446,8 @@ ERL_NIF_TERM ngetopt_lvl_sock_priority(ErlNifEnv* env,
#if defined(SO_PROTOCOL)
static
-ERL_NIF_TERM ngetopt_lvl_sock_protocol(ErlNifEnv* env,
- SocketDescriptor* descP)
+ERL_NIF_TERM ngetopt_lvl_sock_protocol(ErlNifEnv* env,
+ ESockDescriptor* descP)
{
ERL_NIF_TERM result, reason;
int val;
@@ -11240,8 +11493,8 @@ ERL_NIF_TERM ngetopt_lvl_sock_protocol(ErlNifEnv* env,
#if defined(SO_RCVBUF)
static
-ERL_NIF_TERM ngetopt_lvl_sock_rcvbuf(ErlNifEnv* env,
- SocketDescriptor* descP)
+ERL_NIF_TERM ngetopt_lvl_sock_rcvbuf(ErlNifEnv* env,
+ ESockDescriptor* descP)
{
return ngetopt_int_opt(env, descP, SOL_SOCKET, SO_RCVBUF);
}
@@ -11250,8 +11503,8 @@ ERL_NIF_TERM ngetopt_lvl_sock_rcvbuf(ErlNifEnv* env,
#if defined(SO_RCVLOWAT)
static
-ERL_NIF_TERM ngetopt_lvl_sock_rcvlowat(ErlNifEnv* env,
- SocketDescriptor* descP)
+ERL_NIF_TERM ngetopt_lvl_sock_rcvlowat(ErlNifEnv* env,
+ ESockDescriptor* descP)
{
return ngetopt_int_opt(env, descP, SOL_SOCKET, SO_RCVLOWAT);
}
@@ -11260,8 +11513,8 @@ ERL_NIF_TERM ngetopt_lvl_sock_rcvlowat(ErlNifEnv* env,
#if defined(SO_RCVTIMEO)
static
-ERL_NIF_TERM ngetopt_lvl_sock_rcvtimeo(ErlNifEnv* env,
- SocketDescriptor* descP)
+ERL_NIF_TERM ngetopt_lvl_sock_rcvtimeo(ErlNifEnv* env,
+ ESockDescriptor* descP)
{
return ngetopt_timeval_opt(env, descP, SOL_SOCKET, SO_RCVTIMEO);
}
@@ -11270,8 +11523,8 @@ ERL_NIF_TERM ngetopt_lvl_sock_rcvtimeo(ErlNifEnv* env,
#if defined(SO_REUSEADDR)
static
-ERL_NIF_TERM ngetopt_lvl_sock_reuseaddr(ErlNifEnv* env,
- SocketDescriptor* descP)
+ERL_NIF_TERM ngetopt_lvl_sock_reuseaddr(ErlNifEnv* env,
+ ESockDescriptor* descP)
{
return ngetopt_bool_opt(env, descP, SOL_SOCKET, SO_REUSEADDR);
}
@@ -11280,8 +11533,8 @@ ERL_NIF_TERM ngetopt_lvl_sock_reuseaddr(ErlNifEnv* env,
#if defined(SO_REUSEPORT)
static
-ERL_NIF_TERM ngetopt_lvl_sock_reuseport(ErlNifEnv* env,
- SocketDescriptor* descP)
+ERL_NIF_TERM ngetopt_lvl_sock_reuseport(ErlNifEnv* env,
+ ESockDescriptor* descP)
{
return ngetopt_bool_opt(env, descP, SOL_SOCKET, SO_REUSEPORT);
}
@@ -11290,8 +11543,8 @@ ERL_NIF_TERM ngetopt_lvl_sock_reuseport(ErlNifEnv* env,
#if defined(SO_SNDBUF)
static
-ERL_NIF_TERM ngetopt_lvl_sock_sndbuf(ErlNifEnv* env,
- SocketDescriptor* descP)
+ERL_NIF_TERM ngetopt_lvl_sock_sndbuf(ErlNifEnv* env,
+ ESockDescriptor* descP)
{
return ngetopt_int_opt(env, descP, SOL_SOCKET, SO_SNDBUF);
}
@@ -11300,8 +11553,8 @@ ERL_NIF_TERM ngetopt_lvl_sock_sndbuf(ErlNifEnv* env,
#if defined(SO_SNDLOWAT)
static
-ERL_NIF_TERM ngetopt_lvl_sock_sndlowat(ErlNifEnv* env,
- SocketDescriptor* descP)
+ERL_NIF_TERM ngetopt_lvl_sock_sndlowat(ErlNifEnv* env,
+ ESockDescriptor* descP)
{
return ngetopt_int_opt(env, descP, SOL_SOCKET, SO_SNDLOWAT);
}
@@ -11310,8 +11563,8 @@ ERL_NIF_TERM ngetopt_lvl_sock_sndlowat(ErlNifEnv* env,
#if defined(SO_SNDTIMEO)
static
-ERL_NIF_TERM ngetopt_lvl_sock_sndtimeo(ErlNifEnv* env,
- SocketDescriptor* descP)
+ERL_NIF_TERM ngetopt_lvl_sock_sndtimeo(ErlNifEnv* env,
+ ESockDescriptor* descP)
{
return ngetopt_timeval_opt(env, descP, SOL_SOCKET, SO_SNDTIMEO);
}
@@ -11320,8 +11573,8 @@ ERL_NIF_TERM ngetopt_lvl_sock_sndtimeo(ErlNifEnv* env,
#if defined(SO_TIMESTAMP)
static
-ERL_NIF_TERM ngetopt_lvl_sock_timestamp(ErlNifEnv* env,
- SocketDescriptor* descP)
+ERL_NIF_TERM ngetopt_lvl_sock_timestamp(ErlNifEnv* env,
+ ESockDescriptor* descP)
{
return ngetopt_bool_opt(env, descP, SOL_SOCKET, SO_TIMESTAMP);
}
@@ -11330,8 +11583,8 @@ ERL_NIF_TERM ngetopt_lvl_sock_timestamp(ErlNifEnv* env,
#if defined(SO_TYPE)
static
-ERL_NIF_TERM ngetopt_lvl_sock_type(ErlNifEnv* env,
- SocketDescriptor* descP)
+ERL_NIF_TERM ngetopt_lvl_sock_type(ErlNifEnv* env,
+ ESockDescriptor* descP)
{
ERL_NIF_TERM result, reason;
int val;
@@ -11376,9 +11629,9 @@ ERL_NIF_TERM ngetopt_lvl_sock_type(ErlNifEnv* env,
/* ngetopt_lvl_ip - Level *IP* option(s)
*/
static
-ERL_NIF_TERM ngetopt_lvl_ip(ErlNifEnv* env,
- SocketDescriptor* descP,
- int eOpt)
+ERL_NIF_TERM ngetopt_lvl_ip(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ int eOpt)
{
ERL_NIF_TERM result;
@@ -11552,8 +11805,8 @@ ERL_NIF_TERM ngetopt_lvl_ip(ErlNifEnv* env,
*/
#if defined(IP_MINTTL)
static
-ERL_NIF_TERM ngetopt_lvl_ip_minttl(ErlNifEnv* env,
- SocketDescriptor* descP)
+ERL_NIF_TERM ngetopt_lvl_ip_minttl(ErlNifEnv* env,
+ ESockDescriptor* descP)
{
#if defined(SOL_IP)
int level = SOL_IP;
@@ -11570,8 +11823,8 @@ ERL_NIF_TERM ngetopt_lvl_ip_minttl(ErlNifEnv* env,
*/
#if defined(IP_FREEBIND)
static
-ERL_NIF_TERM ngetopt_lvl_ip_freebind(ErlNifEnv* env,
- SocketDescriptor* descP)
+ERL_NIF_TERM ngetopt_lvl_ip_freebind(ErlNifEnv* env,
+ ESockDescriptor* descP)
{
#if defined(SOL_IP)
int level = SOL_IP;
@@ -11588,8 +11841,8 @@ ERL_NIF_TERM ngetopt_lvl_ip_freebind(ErlNifEnv* env,
*/
#if defined(IP_HDRINCL)
static
-ERL_NIF_TERM ngetopt_lvl_ip_hdrincl(ErlNifEnv* env,
- SocketDescriptor* descP)
+ERL_NIF_TERM ngetopt_lvl_ip_hdrincl(ErlNifEnv* env,
+ ESockDescriptor* descP)
{
#if defined(SOL_IP)
int level = SOL_IP;
@@ -11606,8 +11859,8 @@ ERL_NIF_TERM ngetopt_lvl_ip_hdrincl(ErlNifEnv* env,
*/
#if defined(IP_MTU)
static
-ERL_NIF_TERM ngetopt_lvl_ip_mtu(ErlNifEnv* env,
- SocketDescriptor* descP)
+ERL_NIF_TERM ngetopt_lvl_ip_mtu(ErlNifEnv* env,
+ ESockDescriptor* descP)
{
#if defined(SOL_IP)
int level = SOL_IP;
@@ -11624,8 +11877,8 @@ ERL_NIF_TERM ngetopt_lvl_ip_mtu(ErlNifEnv* env,
*/
#if defined(IP_MTU_DISCOVER)
static
-ERL_NIF_TERM ngetopt_lvl_ip_mtu_discover(ErlNifEnv* env,
- SocketDescriptor* descP)
+ERL_NIF_TERM ngetopt_lvl_ip_mtu_discover(ErlNifEnv* env,
+ ESockDescriptor* descP)
{
ERL_NIF_TERM result;
ERL_NIF_TERM eMtuDisc;
@@ -11658,8 +11911,8 @@ ERL_NIF_TERM ngetopt_lvl_ip_mtu_discover(ErlNifEnv* env,
*/
#if defined(IP_MULTICAST_ALL)
static
-ERL_NIF_TERM ngetopt_lvl_ip_multicast_all(ErlNifEnv* env,
- SocketDescriptor* descP)
+ERL_NIF_TERM ngetopt_lvl_ip_multicast_all(ErlNifEnv* env,
+ ESockDescriptor* descP)
{
#if defined(SOL_IP)
int level = SOL_IP;
@@ -11676,8 +11929,8 @@ ERL_NIF_TERM ngetopt_lvl_ip_multicast_all(ErlNifEnv* env,
*/
#if defined(IP_MULTICAST_IF)
static
-ERL_NIF_TERM ngetopt_lvl_ip_multicast_if(ErlNifEnv* env,
- SocketDescriptor* descP)
+ERL_NIF_TERM ngetopt_lvl_ip_multicast_if(ErlNifEnv* env,
+ ESockDescriptor* descP)
{
ERL_NIF_TERM result;
ERL_NIF_TERM eAddr;
@@ -11713,8 +11966,8 @@ ERL_NIF_TERM ngetopt_lvl_ip_multicast_if(ErlNifEnv* env,
*/
#if defined(IP_MULTICAST_LOOP)
static
-ERL_NIF_TERM ngetopt_lvl_ip_multicast_loop(ErlNifEnv* env,
- SocketDescriptor* descP)
+ERL_NIF_TERM ngetopt_lvl_ip_multicast_loop(ErlNifEnv* env,
+ ESockDescriptor* descP)
{
#if defined(SOL_IP)
int level = SOL_IP;
@@ -11731,8 +11984,8 @@ ERL_NIF_TERM ngetopt_lvl_ip_multicast_loop(ErlNifEnv* env,
*/
#if defined(IP_MULTICAST_TTL)
static
-ERL_NIF_TERM ngetopt_lvl_ip_multicast_ttl(ErlNifEnv* env,
- SocketDescriptor* descP)
+ERL_NIF_TERM ngetopt_lvl_ip_multicast_ttl(ErlNifEnv* env,
+ ESockDescriptor* descP)
{
#if defined(SOL_IP)
int level = SOL_IP;
@@ -11749,8 +12002,8 @@ ERL_NIF_TERM ngetopt_lvl_ip_multicast_ttl(ErlNifEnv* env,
*/
#if defined(IP_NODEFRAG)
static
-ERL_NIF_TERM ngetopt_lvl_ip_nodefrag(ErlNifEnv* env,
- SocketDescriptor* descP)
+ERL_NIF_TERM ngetopt_lvl_ip_nodefrag(ErlNifEnv* env,
+ ESockDescriptor* descP)
{
#if defined(SOL_IP)
int level = SOL_IP;
@@ -11767,8 +12020,8 @@ ERL_NIF_TERM ngetopt_lvl_ip_nodefrag(ErlNifEnv* env,
*/
#if defined(IP_PKTINFO)
static
-ERL_NIF_TERM ngetopt_lvl_ip_pktinfo(ErlNifEnv* env,
- SocketDescriptor* descP)
+ERL_NIF_TERM ngetopt_lvl_ip_pktinfo(ErlNifEnv* env,
+ ESockDescriptor* descP)
{
#if defined(SOL_IP)
int level = SOL_IP;
@@ -11785,8 +12038,8 @@ ERL_NIF_TERM ngetopt_lvl_ip_pktinfo(ErlNifEnv* env,
*/
#if defined(IP_RECVTOS)
static
-ERL_NIF_TERM ngetopt_lvl_ip_recvtos(ErlNifEnv* env,
- SocketDescriptor* descP)
+ERL_NIF_TERM ngetopt_lvl_ip_recvtos(ErlNifEnv* env,
+ ESockDescriptor* descP)
{
#if defined(SOL_IP)
int level = SOL_IP;
@@ -11803,8 +12056,8 @@ ERL_NIF_TERM ngetopt_lvl_ip_recvtos(ErlNifEnv* env,
*/
#if defined(IP_RECVDSTADDR)
static
-ERL_NIF_TERM ngetopt_lvl_ip_recvdstaddr(ErlNifEnv* env,
- SocketDescriptor* descP)
+ERL_NIF_TERM ngetopt_lvl_ip_recvdstaddr(ErlNifEnv* env,
+ ESockDescriptor* descP)
{
#if defined(SOL_IP)
int level = SOL_IP;
@@ -11821,8 +12074,8 @@ ERL_NIF_TERM ngetopt_lvl_ip_recvdstaddr(ErlNifEnv* env,
*/
#if defined(IP_RECVERR)
static
-ERL_NIF_TERM ngetopt_lvl_ip_recverr(ErlNifEnv* env,
- SocketDescriptor* descP)
+ERL_NIF_TERM ngetopt_lvl_ip_recverr(ErlNifEnv* env,
+ ESockDescriptor* descP)
{
#if defined(SOL_IP)
int level = SOL_IP;
@@ -11839,8 +12092,8 @@ ERL_NIF_TERM ngetopt_lvl_ip_recverr(ErlNifEnv* env,
*/
#if defined(IP_RECVIF)
static
-ERL_NIF_TERM ngetopt_lvl_ip_recvif(ErlNifEnv* env,
- SocketDescriptor* descP)
+ERL_NIF_TERM ngetopt_lvl_ip_recvif(ErlNifEnv* env,
+ ESockDescriptor* descP)
{
#if defined(SOL_IP)
int level = SOL_IP;
@@ -11857,8 +12110,8 @@ ERL_NIF_TERM ngetopt_lvl_ip_recvif(ErlNifEnv* env,
*/
#if defined(IP_RECVOPTS)
static
-ERL_NIF_TERM ngetopt_lvl_ip_recvopts(ErlNifEnv* env,
- SocketDescriptor* descP)
+ERL_NIF_TERM ngetopt_lvl_ip_recvopts(ErlNifEnv* env,
+ ESockDescriptor* descP)
{
#if defined(SOL_IP)
int level = SOL_IP;
@@ -11875,8 +12128,8 @@ ERL_NIF_TERM ngetopt_lvl_ip_recvopts(ErlNifEnv* env,
*/
#if defined(IP_RECVORIGDSTADDR)
static
-ERL_NIF_TERM ngetopt_lvl_ip_recvorigdstaddr(ErlNifEnv* env,
- SocketDescriptor* descP)
+ERL_NIF_TERM ngetopt_lvl_ip_recvorigdstaddr(ErlNifEnv* env,
+ ESockDescriptor* descP)
{
#if defined(SOL_IP)
int level = SOL_IP;
@@ -11893,8 +12146,8 @@ ERL_NIF_TERM ngetopt_lvl_ip_recvorigdstaddr(ErlNifEnv* env,
*/
#if defined(IP_RECVTTL)
static
-ERL_NIF_TERM ngetopt_lvl_ip_recvttl(ErlNifEnv* env,
- SocketDescriptor* descP)
+ERL_NIF_TERM ngetopt_lvl_ip_recvttl(ErlNifEnv* env,
+ ESockDescriptor* descP)
{
#if defined(SOL_IP)
int level = SOL_IP;
@@ -11911,8 +12164,8 @@ ERL_NIF_TERM ngetopt_lvl_ip_recvttl(ErlNifEnv* env,
*/
#if defined(IP_RETOPTS)
static
-ERL_NIF_TERM ngetopt_lvl_ip_retopts(ErlNifEnv* env,
- SocketDescriptor* descP)
+ERL_NIF_TERM ngetopt_lvl_ip_retopts(ErlNifEnv* env,
+ ESockDescriptor* descP)
{
#if defined(SOL_IP)
int level = SOL_IP;
@@ -11929,8 +12182,8 @@ ERL_NIF_TERM ngetopt_lvl_ip_retopts(ErlNifEnv* env,
*/
#if defined(IP_ROUTER_ALERT)
static
-ERL_NIF_TERM ngetopt_lvl_ip_router_alert(ErlNifEnv* env,
- SocketDescriptor* descP)
+ERL_NIF_TERM ngetopt_lvl_ip_router_alert(ErlNifEnv* env,
+ ESockDescriptor* descP)
{
#if defined(SOL_IP)
int level = SOL_IP;
@@ -11947,8 +12200,8 @@ ERL_NIF_TERM ngetopt_lvl_ip_router_alert(ErlNifEnv* env,
*/
#if defined(IP_SENDSRCADDR)
static
-ERL_NIF_TERM ngetopt_lvl_ip_sendsrcaddr(ErlNifEnv* env,
- SocketDescriptor* descP)
+ERL_NIF_TERM ngetopt_lvl_ip_sendsrcaddr(ErlNifEnv* env,
+ ESockDescriptor* descP)
{
#if defined(SOL_IP)
int level = SOL_IP;
@@ -11965,8 +12218,8 @@ ERL_NIF_TERM ngetopt_lvl_ip_sendsrcaddr(ErlNifEnv* env,
*/
#if defined(IP_TOS)
static
-ERL_NIF_TERM ngetopt_lvl_ip_tos(ErlNifEnv* env,
- SocketDescriptor* descP)
+ERL_NIF_TERM ngetopt_lvl_ip_tos(ErlNifEnv* env,
+ ESockDescriptor* descP)
{
#if defined(SOL_IP)
int level = SOL_IP;
@@ -11995,8 +12248,8 @@ ERL_NIF_TERM ngetopt_lvl_ip_tos(ErlNifEnv* env,
*/
#if defined(IP_TRANSPARENT)
static
-ERL_NIF_TERM ngetopt_lvl_ip_transparent(ErlNifEnv* env,
- SocketDescriptor* descP)
+ERL_NIF_TERM ngetopt_lvl_ip_transparent(ErlNifEnv* env,
+ ESockDescriptor* descP)
{
#if defined(SOL_IP)
int level = SOL_IP;
@@ -12014,8 +12267,8 @@ ERL_NIF_TERM ngetopt_lvl_ip_transparent(ErlNifEnv* env,
*/
#if defined(IP_TTL)
static
-ERL_NIF_TERM ngetopt_lvl_ip_ttl(ErlNifEnv* env,
- SocketDescriptor* descP)
+ERL_NIF_TERM ngetopt_lvl_ip_ttl(ErlNifEnv* env,
+ ESockDescriptor* descP)
{
#if defined(SOL_IP)
int level = SOL_IP;
@@ -12033,9 +12286,9 @@ ERL_NIF_TERM ngetopt_lvl_ip_ttl(ErlNifEnv* env,
*/
#if defined(HAVE_IPV6)
static
-ERL_NIF_TERM ngetopt_lvl_ipv6(ErlNifEnv* env,
- SocketDescriptor* descP,
- int eOpt)
+ERL_NIF_TERM ngetopt_lvl_ipv6(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ int eOpt)
{
ERL_NIF_TERM result;
@@ -12157,8 +12410,8 @@ ERL_NIF_TERM ngetopt_lvl_ipv6(ErlNifEnv* env,
#if defined(IPV6_AUTHHDR)
static
-ERL_NIF_TERM ngetopt_lvl_ipv6_authhdr(ErlNifEnv* env,
- SocketDescriptor* descP)
+ERL_NIF_TERM ngetopt_lvl_ipv6_authhdr(ErlNifEnv* env,
+ ESockDescriptor* descP)
{
return ngetopt_bool_opt(env, descP, SOL_IPV6, IPV6_AUTHHDR);
}
@@ -12167,8 +12420,8 @@ ERL_NIF_TERM ngetopt_lvl_ipv6_authhdr(ErlNifEnv* env,
#if defined(IPV6_DSTOPTS)
static
-ERL_NIF_TERM ngetopt_lvl_ipv6_dstopts(ErlNifEnv* env,
- SocketDescriptor* descP)
+ERL_NIF_TERM ngetopt_lvl_ipv6_dstopts(ErlNifEnv* env,
+ ESockDescriptor* descP)
{
#if defined(SOL_IPV6)
int level = SOL_IPV6;
@@ -12182,8 +12435,8 @@ ERL_NIF_TERM ngetopt_lvl_ipv6_dstopts(ErlNifEnv* env,
#if defined(IPV6_FLOWINFO)
static
-ERL_NIF_TERM ngetopt_lvl_ipv6_flowinfo(ErlNifEnv* env,
- SocketDescriptor* descP)
+ERL_NIF_TERM ngetopt_lvl_ipv6_flowinfo(ErlNifEnv* env,
+ ESockDescriptor* descP)
{
#if defined(SOL_IPV6)
int level = SOL_IPV6;
@@ -12198,8 +12451,8 @@ ERL_NIF_TERM ngetopt_lvl_ipv6_flowinfo(ErlNifEnv* env,
#if defined(IPV6_HOPLIMIT)
static
-ERL_NIF_TERM ngetopt_lvl_ipv6_hoplimit(ErlNifEnv* env,
- SocketDescriptor* descP)
+ERL_NIF_TERM ngetopt_lvl_ipv6_hoplimit(ErlNifEnv* env,
+ ESockDescriptor* descP)
{
#if defined(SOL_IPV6)
int level = SOL_IPV6;
@@ -12214,8 +12467,8 @@ ERL_NIF_TERM ngetopt_lvl_ipv6_hoplimit(ErlNifEnv* env,
#if defined(IPV6_HOPOPTS)
static
-ERL_NIF_TERM ngetopt_lvl_ipv6_hopopts(ErlNifEnv* env,
- SocketDescriptor* descP)
+ERL_NIF_TERM ngetopt_lvl_ipv6_hopopts(ErlNifEnv* env,
+ ESockDescriptor* descP)
{
#if defined(SOL_IPV6)
int level = SOL_IPV6;
@@ -12230,8 +12483,8 @@ ERL_NIF_TERM ngetopt_lvl_ipv6_hopopts(ErlNifEnv* env,
#if defined(IPV6_MTU)
static
-ERL_NIF_TERM ngetopt_lvl_ipv6_mtu(ErlNifEnv* env,
- SocketDescriptor* descP)
+ERL_NIF_TERM ngetopt_lvl_ipv6_mtu(ErlNifEnv* env,
+ ESockDescriptor* descP)
{
#if defined(SOL_IPV6)
int level = SOL_IPV6;
@@ -12248,8 +12501,8 @@ ERL_NIF_TERM ngetopt_lvl_ipv6_mtu(ErlNifEnv* env,
*/
#if defined(IPV6_MTU_DISCOVER)
static
-ERL_NIF_TERM ngetopt_lvl_ipv6_mtu_discover(ErlNifEnv* env,
- SocketDescriptor* descP)
+ERL_NIF_TERM ngetopt_lvl_ipv6_mtu_discover(ErlNifEnv* env,
+ ESockDescriptor* descP)
{
ERL_NIF_TERM result;
ERL_NIF_TERM eMtuDisc;
@@ -12280,8 +12533,8 @@ ERL_NIF_TERM ngetopt_lvl_ipv6_mtu_discover(ErlNifEnv* env,
#if defined(IPV6_MULTICAST_HOPS)
static
-ERL_NIF_TERM ngetopt_lvl_ipv6_multicast_hops(ErlNifEnv* env,
- SocketDescriptor* descP)
+ERL_NIF_TERM ngetopt_lvl_ipv6_multicast_hops(ErlNifEnv* env,
+ ESockDescriptor* descP)
{
#if defined(SOL_IPV6)
int level = SOL_IPV6;
@@ -12296,8 +12549,8 @@ ERL_NIF_TERM ngetopt_lvl_ipv6_multicast_hops(ErlNifEnv* env,
#if defined(IPV6_MULTICAST_IF)
static
-ERL_NIF_TERM ngetopt_lvl_ipv6_multicast_if(ErlNifEnv* env,
- SocketDescriptor* descP)
+ERL_NIF_TERM ngetopt_lvl_ipv6_multicast_if(ErlNifEnv* env,
+ ESockDescriptor* descP)
{
#if defined(SOL_IPV6)
int level = SOL_IPV6;
@@ -12312,8 +12565,8 @@ ERL_NIF_TERM ngetopt_lvl_ipv6_multicast_if(ErlNifEnv* env,
#if defined(IPV6_MULTICAST_LOOP)
static
-ERL_NIF_TERM ngetopt_lvl_ipv6_multicast_loop(ErlNifEnv* env,
- SocketDescriptor* descP)
+ERL_NIF_TERM ngetopt_lvl_ipv6_multicast_loop(ErlNifEnv* env,
+ ESockDescriptor* descP)
{
#if defined(SOL_IPV6)
int level = SOL_IPV6;
@@ -12328,8 +12581,8 @@ ERL_NIF_TERM ngetopt_lvl_ipv6_multicast_loop(ErlNifEnv* env,
#if defined(IPV6_RECVERR)
static
-ERL_NIF_TERM ngetopt_lvl_ipv6_recverr(ErlNifEnv* env,
- SocketDescriptor* descP)
+ERL_NIF_TERM ngetopt_lvl_ipv6_recverr(ErlNifEnv* env,
+ ESockDescriptor* descP)
{
#if defined(SOL_IPV6)
int level = SOL_IPV6;
@@ -12344,8 +12597,8 @@ ERL_NIF_TERM ngetopt_lvl_ipv6_recverr(ErlNifEnv* env,
#if defined(IPV6_RECVPKTINFO) || defined(IPV6_PKTINFO)
static
-ERL_NIF_TERM ngetopt_lvl_ipv6_recvpktinfo(ErlNifEnv* env,
- SocketDescriptor* descP)
+ERL_NIF_TERM ngetopt_lvl_ipv6_recvpktinfo(ErlNifEnv* env,
+ ESockDescriptor* descP)
{
#if defined(SOL_IPV6)
int level = SOL_IPV6;
@@ -12365,8 +12618,8 @@ ERL_NIF_TERM ngetopt_lvl_ipv6_recvpktinfo(ErlNifEnv* env,
#if defined(IPV6_ROUTER_ALERT)
static
-ERL_NIF_TERM ngetopt_lvl_ipv6_router_alert(ErlNifEnv* env,
- SocketDescriptor* descP)
+ERL_NIF_TERM ngetopt_lvl_ipv6_router_alert(ErlNifEnv* env,
+ ESockDescriptor* descP)
{
#if defined(SOL_IPV6)
int level = SOL_IPV6;
@@ -12381,8 +12634,8 @@ ERL_NIF_TERM ngetopt_lvl_ipv6_router_alert(ErlNifEnv* env,
#if defined(IPV6_RTHDR)
static
-ERL_NIF_TERM ngetopt_lvl_ipv6_rthdr(ErlNifEnv* env,
- SocketDescriptor* descP)
+ERL_NIF_TERM ngetopt_lvl_ipv6_rthdr(ErlNifEnv* env,
+ ESockDescriptor* descP)
{
#if defined(SOL_IPV6)
int level = SOL_IPV6;
@@ -12397,8 +12650,8 @@ ERL_NIF_TERM ngetopt_lvl_ipv6_rthdr(ErlNifEnv* env,
#if defined(IPV6_UNICAST_HOPS)
static
-ERL_NIF_TERM ngetopt_lvl_ipv6_unicast_hops(ErlNifEnv* env,
- SocketDescriptor* descP)
+ERL_NIF_TERM ngetopt_lvl_ipv6_unicast_hops(ErlNifEnv* env,
+ ESockDescriptor* descP)
{
#if defined(SOL_IPV6)
int level = SOL_IPV6;
@@ -12413,8 +12666,8 @@ ERL_NIF_TERM ngetopt_lvl_ipv6_unicast_hops(ErlNifEnv* env,
#if defined(IPV6_V6ONLY)
static
-ERL_NIF_TERM ngetopt_lvl_ipv6_v6only(ErlNifEnv* env,
- SocketDescriptor* descP)
+ERL_NIF_TERM ngetopt_lvl_ipv6_v6only(ErlNifEnv* env,
+ ESockDescriptor* descP)
{
#if defined(SOL_IPV6)
int level = SOL_IPV6;
@@ -12434,9 +12687,9 @@ ERL_NIF_TERM ngetopt_lvl_ipv6_v6only(ErlNifEnv* env,
/* ngetopt_lvl_tcp - Level *TCP* option(s)
*/
static
-ERL_NIF_TERM ngetopt_lvl_tcp(ErlNifEnv* env,
- SocketDescriptor* descP,
- int eOpt)
+ERL_NIF_TERM ngetopt_lvl_tcp(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ int eOpt)
{
ERL_NIF_TERM result;
@@ -12472,8 +12725,8 @@ ERL_NIF_TERM ngetopt_lvl_tcp(ErlNifEnv* env,
*/
#if defined(TCP_CONGESTION)
static
-ERL_NIF_TERM ngetopt_lvl_tcp_congestion(ErlNifEnv* env,
- SocketDescriptor* descP)
+ERL_NIF_TERM ngetopt_lvl_tcp_congestion(ErlNifEnv* env,
+ ESockDescriptor* descP)
{
int max = SOCKET_OPT_TCP_CONGESTION_NAME_MAX+1;
@@ -12486,8 +12739,8 @@ ERL_NIF_TERM ngetopt_lvl_tcp_congestion(ErlNifEnv* env,
*/
#if defined(TCP_MAXSEG)
static
-ERL_NIF_TERM ngetopt_lvl_tcp_maxseg(ErlNifEnv* env,
- SocketDescriptor* descP)
+ERL_NIF_TERM ngetopt_lvl_tcp_maxseg(ErlNifEnv* env,
+ ESockDescriptor* descP)
{
return ngetopt_int_opt(env, descP, IPPROTO_TCP, TCP_MAXSEG);
}
@@ -12498,8 +12751,8 @@ ERL_NIF_TERM ngetopt_lvl_tcp_maxseg(ErlNifEnv* env,
*/
#if defined(TCP_NODELAY)
static
-ERL_NIF_TERM ngetopt_lvl_tcp_nodelay(ErlNifEnv* env,
- SocketDescriptor* descP)
+ERL_NIF_TERM ngetopt_lvl_tcp_nodelay(ErlNifEnv* env,
+ ESockDescriptor* descP)
{
return ngetopt_bool_opt(env, descP, IPPROTO_TCP, TCP_NODELAY);
}
@@ -12510,9 +12763,9 @@ ERL_NIF_TERM ngetopt_lvl_tcp_nodelay(ErlNifEnv* env,
/* ngetopt_lvl_udp - Level *UDP* option(s)
*/
static
-ERL_NIF_TERM ngetopt_lvl_udp(ErlNifEnv* env,
- SocketDescriptor* descP,
- int eOpt)
+ERL_NIF_TERM ngetopt_lvl_udp(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ int eOpt)
{
ERL_NIF_TERM result;
@@ -12536,8 +12789,8 @@ ERL_NIF_TERM ngetopt_lvl_udp(ErlNifEnv* env,
*/
#if defined(UDP_CORK)
static
-ERL_NIF_TERM ngetopt_lvl_udp_cork(ErlNifEnv* env,
- SocketDescriptor* descP)
+ERL_NIF_TERM ngetopt_lvl_udp_cork(ErlNifEnv* env,
+ ESockDescriptor* descP)
{
return ngetopt_bool_opt(env, descP, IPPROTO_UDP, UDP_CORK);
}
@@ -12549,9 +12802,9 @@ ERL_NIF_TERM ngetopt_lvl_udp_cork(ErlNifEnv* env,
*/
#if defined(HAVE_SCTP)
static
-ERL_NIF_TERM ngetopt_lvl_sctp(ErlNifEnv* env,
- SocketDescriptor* descP,
- int eOpt)
+ERL_NIF_TERM ngetopt_lvl_sctp(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ int eOpt)
{
ERL_NIF_TERM result;
@@ -12632,8 +12885,8 @@ ERL_NIF_TERM ngetopt_lvl_sctp(ErlNifEnv* env,
*/
#if defined(SCTP_ASSOCINFO)
static
-ERL_NIF_TERM ngetopt_lvl_sctp_associnfo(ErlNifEnv* env,
- SocketDescriptor* descP)
+ERL_NIF_TERM ngetopt_lvl_sctp_associnfo(ErlNifEnv* env,
+ ESockDescriptor* descP)
{
ERL_NIF_TERM result;
struct sctp_assocparams val;
@@ -12683,8 +12936,8 @@ ERL_NIF_TERM ngetopt_lvl_sctp_associnfo(ErlNifEnv* env,
*/
#if defined(SCTP_AUTOCLOSE)
static
-ERL_NIF_TERM ngetopt_lvl_sctp_autoclose(ErlNifEnv* env,
- SocketDescriptor* descP)
+ERL_NIF_TERM ngetopt_lvl_sctp_autoclose(ErlNifEnv* env,
+ ESockDescriptor* descP)
{
return ngetopt_int_opt(env, descP, IPPROTO_SCTP, SCTP_AUTOCLOSE);
}
@@ -12695,8 +12948,8 @@ ERL_NIF_TERM ngetopt_lvl_sctp_autoclose(ErlNifEnv* env,
*/
#if defined(SCTP_DISABLE_FRAGMENTS)
static
-ERL_NIF_TERM ngetopt_lvl_sctp_disable_fragments(ErlNifEnv* env,
- SocketDescriptor* descP)
+ERL_NIF_TERM ngetopt_lvl_sctp_disable_fragments(ErlNifEnv* env,
+ ESockDescriptor* descP)
{
return ngetopt_bool_opt(env, descP, IPPROTO_SCTP, SCTP_DISABLE_FRAGMENTS);
}
@@ -12708,8 +12961,8 @@ ERL_NIF_TERM ngetopt_lvl_sctp_disable_fragments(ErlNifEnv* env,
*/
#if defined(SCTP_INITMSG)
static
-ERL_NIF_TERM ngetopt_lvl_sctp_initmsg(ErlNifEnv* env,
- SocketDescriptor* descP)
+ERL_NIF_TERM ngetopt_lvl_sctp_initmsg(ErlNifEnv* env,
+ ESockDescriptor* descP)
{
ERL_NIF_TERM result;
struct sctp_initmsg val;
@@ -12757,8 +13010,8 @@ ERL_NIF_TERM ngetopt_lvl_sctp_initmsg(ErlNifEnv* env,
*/
#if defined(SCTP_MAXSEG)
static
-ERL_NIF_TERM ngetopt_lvl_sctp_maxseg(ErlNifEnv* env,
- SocketDescriptor* descP)
+ERL_NIF_TERM ngetopt_lvl_sctp_maxseg(ErlNifEnv* env,
+ ESockDescriptor* descP)
{
return ngetopt_int_opt(env, descP, IPPROTO_SCTP, SCTP_MAXSEG);
}
@@ -12769,8 +13022,8 @@ ERL_NIF_TERM ngetopt_lvl_sctp_maxseg(ErlNifEnv* env,
*/
#if defined(SCTP_NODELAY)
static
-ERL_NIF_TERM ngetopt_lvl_sctp_nodelay(ErlNifEnv* env,
- SocketDescriptor* descP)
+ERL_NIF_TERM ngetopt_lvl_sctp_nodelay(ErlNifEnv* env,
+ ESockDescriptor* descP)
{
return ngetopt_bool_opt(env, descP, IPPROTO_SCTP, SCTP_NODELAY);
}
@@ -12792,8 +13045,8 @@ ERL_NIF_TERM ngetopt_lvl_sctp_nodelay(ErlNifEnv* env,
*/
#if defined(SCTP_RTOINFO)
static
-ERL_NIF_TERM ngetopt_lvl_sctp_rtoinfo(ErlNifEnv* env,
- SocketDescriptor* descP)
+ERL_NIF_TERM ngetopt_lvl_sctp_rtoinfo(ErlNifEnv* env,
+ ESockDescriptor* descP)
{
ERL_NIF_TERM result;
struct sctp_rtoinfo val;
@@ -12844,10 +13097,10 @@ ERL_NIF_TERM ngetopt_lvl_sctp_rtoinfo(ErlNifEnv* env,
/* ngetopt_bool_opt - get an (integer) bool option
*/
static
-ERL_NIF_TERM ngetopt_bool_opt(ErlNifEnv* env,
- SocketDescriptor* descP,
- int level,
- int opt)
+ERL_NIF_TERM ngetopt_bool_opt(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ int level,
+ int opt)
{
ERL_NIF_TERM result;
int val;
@@ -12885,10 +13138,10 @@ ERL_NIF_TERM ngetopt_bool_opt(ErlNifEnv* env,
/* ngetopt_int_opt - get an integer option
*/
static
-ERL_NIF_TERM ngetopt_int_opt(ErlNifEnv* env,
- SocketDescriptor* descP,
- int level,
- int opt)
+ERL_NIF_TERM ngetopt_int_opt(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ int level,
+ int opt)
{
ERL_NIF_TERM result;
int val;
@@ -12911,10 +13164,10 @@ ERL_NIF_TERM ngetopt_int_opt(ErlNifEnv* env,
/* ngetopt_timeval_opt - get an timeval option
*/
static
-ERL_NIF_TERM ngetopt_timeval_opt(ErlNifEnv* env,
- SocketDescriptor* descP,
- int level,
- int opt)
+ERL_NIF_TERM ngetopt_timeval_opt(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ int level,
+ int opt)
{
ERL_NIF_TERM result;
struct timeval val;
@@ -12961,11 +13214,11 @@ ERL_NIF_TERM ngetopt_timeval_opt(ErlNifEnv* env,
*/
#if defined(USE_GETOPT_STR_OPT)
static
-ERL_NIF_TERM ngetopt_str_opt(ErlNifEnv* env,
- SocketDescriptor* descP,
- int level,
- int opt,
- int max)
+ERL_NIF_TERM ngetopt_str_opt(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ int level,
+ int opt,
+ int max)
{
ERL_NIF_TERM result;
char* val = MALLOC(max);
@@ -13021,8 +13274,8 @@ ERL_NIF_TERM nif_sockname(ErlNifEnv* env,
#if defined(__WIN32__)
return enif_raise_exception(env, MKA(env, "notsup"));
#else
- SocketDescriptor* descP;
- ERL_NIF_TERM res;
+ ESockDescriptor* descP;
+ ERL_NIF_TERM res;
SGDBG( ("SOCKET", "nif_sockname -> entry with argc: %d\r\n", argc) );
@@ -13053,12 +13306,12 @@ ERL_NIF_TERM nif_sockname(ErlNifEnv* env,
#if !defined(__WIN32__)
static
-ERL_NIF_TERM nsockname(ErlNifEnv* env,
- SocketDescriptor* descP)
+ERL_NIF_TERM nsockname(ErlNifEnv* env,
+ ESockDescriptor* descP)
{
- SocketAddress sa;
- SocketAddress* saP = &sa;
- unsigned int sz = sizeof(SocketAddress);
+ ESockAddress sa;
+ ESockAddress* saP = &sa;
+ unsigned int sz = sizeof(ESockAddress);
sys_memzero((char*) saP, sz);
if (IS_SOCKET_ERROR(sock_name(descP->sock, (struct sockaddr*) saP, &sz))) {
@@ -13095,8 +13348,8 @@ ERL_NIF_TERM nif_peername(ErlNifEnv* env,
#if defined(__WIN32__)
return enif_raise_exception(env, MKA(env, "notsup"));
#else
- SocketDescriptor* descP;
- ERL_NIF_TERM res;
+ ESockDescriptor* descP;
+ ERL_NIF_TERM res;
SGDBG( ("SOCKET", "nif_peername -> entry with argc: %d\r\n", argc) );
@@ -13127,12 +13380,12 @@ ERL_NIF_TERM nif_peername(ErlNifEnv* env,
#if !defined(__WIN32__)
static
-ERL_NIF_TERM npeername(ErlNifEnv* env,
- SocketDescriptor* descP)
+ERL_NIF_TERM npeername(ErlNifEnv* env,
+ ESockDescriptor* descP)
{
- SocketAddress sa;
- SocketAddress* saP = &sa;
- unsigned int sz = sizeof(SocketAddress);
+ ESockAddress sa;
+ ESockAddress* saP = &sa;
+ unsigned int sz = sizeof(ESockAddress);
sys_memzero((char*) saP, sz);
if (IS_SOCKET_ERROR(sock_peer(descP->sock, (struct sockaddr*) saP, &sz))) {
@@ -13170,8 +13423,8 @@ ERL_NIF_TERM nif_cancel(ErlNifEnv* env,
#if defined(__WIN32__)
return enif_raise_exception(env, MKA(env, "notsup"));
#else
- SocketDescriptor* descP;
- ERL_NIF_TERM op, sockRef, opRef, result;
+ ESockDescriptor* descP;
+ ERL_NIF_TERM op, sockRef, opRef, result;
SGDBG( ("SOCKET", "nif_cancel -> entry with argc: %d\r\n", argc) );
@@ -13208,11 +13461,11 @@ ERL_NIF_TERM nif_cancel(ErlNifEnv* env,
#if !defined(__WIN32__)
static
-ERL_NIF_TERM ncancel(ErlNifEnv* env,
- SocketDescriptor* descP,
- ERL_NIF_TERM op,
- ERL_NIF_TERM sockRef,
- ERL_NIF_TERM opRef)
+ERL_NIF_TERM ncancel(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM op,
+ ERL_NIF_TERM sockRef,
+ ERL_NIF_TERM opRef)
{
/* <KOLLA>
*
@@ -13250,9 +13503,9 @@ ERL_NIF_TERM ncancel(ErlNifEnv* env,
*
*/
static
-ERL_NIF_TERM ncancel_connect(ErlNifEnv* env,
- SocketDescriptor* descP,
- ERL_NIF_TERM opRef)
+ERL_NIF_TERM ncancel_connect(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM opRef)
{
return ncancel_write_select(env, descP, opRef);
}
@@ -13269,10 +13522,10 @@ ERL_NIF_TERM ncancel_connect(ErlNifEnv* env,
*
*/
static
-ERL_NIF_TERM ncancel_accept(ErlNifEnv* env,
- SocketDescriptor* descP,
- ERL_NIF_TERM sockRef,
- ERL_NIF_TERM opRef)
+ERL_NIF_TERM ncancel_accept(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM sockRef,
+ ERL_NIF_TERM opRef)
{
ERL_NIF_TERM res;
@@ -13312,9 +13565,9 @@ ERL_NIF_TERM ncancel_accept(ErlNifEnv* env,
* in the acceptor queue).
*/
static
-ERL_NIF_TERM ncancel_accept_current(ErlNifEnv* env,
- SocketDescriptor* descP,
- ERL_NIF_TERM sockRef)
+ERL_NIF_TERM ncancel_accept_current(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM sockRef)
{
ERL_NIF_TERM res;
@@ -13352,9 +13605,9 @@ ERL_NIF_TERM ncancel_accept_current(ErlNifEnv* env,
* remove them from the acceptor queue.
*/
static
-ERL_NIF_TERM ncancel_accept_waiting(ErlNifEnv* env,
- SocketDescriptor* descP,
- ERL_NIF_TERM opRef)
+ERL_NIF_TERM ncancel_accept_waiting(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM opRef)
{
ErlNifPid caller;
@@ -13379,10 +13632,10 @@ ERL_NIF_TERM ncancel_accept_waiting(ErlNifEnv* env,
* Its either the current writer or one of the waiting writers.
*/
static
-ERL_NIF_TERM ncancel_send(ErlNifEnv* env,
- SocketDescriptor* descP,
- ERL_NIF_TERM sockRef,
- ERL_NIF_TERM opRef)
+ERL_NIF_TERM ncancel_send(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM sockRef,
+ ERL_NIF_TERM opRef)
{
ERL_NIF_TERM res;
@@ -13423,9 +13676,9 @@ ERL_NIF_TERM ncancel_send(ErlNifEnv* env,
* in the writer queue).
*/
static
-ERL_NIF_TERM ncancel_send_current(ErlNifEnv* env,
- SocketDescriptor* descP,
- ERL_NIF_TERM sockRef)
+ERL_NIF_TERM ncancel_send_current(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM sockRef)
{
ERL_NIF_TERM res;
@@ -13459,9 +13712,9 @@ ERL_NIF_TERM ncancel_send_current(ErlNifEnv* env,
* remove them from the writer queue.
*/
static
-ERL_NIF_TERM ncancel_send_waiting(ErlNifEnv* env,
- SocketDescriptor* descP,
- ERL_NIF_TERM opRef)
+ERL_NIF_TERM ncancel_send_waiting(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM opRef)
{
ErlNifPid caller;
@@ -13486,10 +13739,10 @@ ERL_NIF_TERM ncancel_send_waiting(ErlNifEnv* env,
* Its either the current reader or one of the waiting readers.
*/
static
-ERL_NIF_TERM ncancel_recv(ErlNifEnv* env,
- SocketDescriptor* descP,
- ERL_NIF_TERM sockRef,
- ERL_NIF_TERM opRef)
+ERL_NIF_TERM ncancel_recv(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM sockRef,
+ ERL_NIF_TERM opRef)
{
ERL_NIF_TERM res;
@@ -13529,9 +13782,9 @@ ERL_NIF_TERM ncancel_recv(ErlNifEnv* env,
* in the reader queue).
*/
static
-ERL_NIF_TERM ncancel_recv_current(ErlNifEnv* env,
- SocketDescriptor* descP,
- ERL_NIF_TERM sockRef)
+ERL_NIF_TERM ncancel_recv_current(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM sockRef)
{
ERL_NIF_TERM res;
@@ -13565,9 +13818,9 @@ ERL_NIF_TERM ncancel_recv_current(ErlNifEnv* env,
* remove them from the reader queue.
*/
static
-ERL_NIF_TERM ncancel_recv_waiting(ErlNifEnv* env,
- SocketDescriptor* descP,
- ERL_NIF_TERM opRef)
+ERL_NIF_TERM ncancel_recv_waiting(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM opRef)
{
ErlNifPid caller;
@@ -13587,9 +13840,9 @@ ERL_NIF_TERM ncancel_recv_waiting(ErlNifEnv* env,
static
-ERL_NIF_TERM ncancel_read_select(ErlNifEnv* env,
- SocketDescriptor* descP,
- ERL_NIF_TERM opRef)
+ERL_NIF_TERM ncancel_read_select(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM opRef)
{
return ncancel_mode_select(env, descP, opRef,
ERL_NIF_SELECT_READ,
@@ -13598,9 +13851,9 @@ ERL_NIF_TERM ncancel_read_select(ErlNifEnv* env,
static
-ERL_NIF_TERM ncancel_write_select(ErlNifEnv* env,
- SocketDescriptor* descP,
- ERL_NIF_TERM opRef)
+ERL_NIF_TERM ncancel_write_select(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM opRef)
{
return ncancel_mode_select(env, descP, opRef,
ERL_NIF_SELECT_WRITE,
@@ -13609,11 +13862,11 @@ ERL_NIF_TERM ncancel_write_select(ErlNifEnv* env,
static
-ERL_NIF_TERM ncancel_mode_select(ErlNifEnv* env,
- SocketDescriptor* descP,
- ERL_NIF_TERM opRef,
- int smode,
- int rmode)
+ERL_NIF_TERM ncancel_mode_select(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM opRef,
+ int smode,
+ int rmode)
{
int selectRes = esock_select_cancel(env, descP->sock, smode, descP);
@@ -13643,15 +13896,16 @@ ERL_NIF_TERM ncancel_mode_select(ErlNifEnv* env,
/* *** send_check_writer ***
*
- * Checks if we have a current writer and if that is us. If not, then we must
- * be made to wait for our turn. This is done by pushing us unto the writer queue.
+ * Checks if we have a current writer and if that is us.
+ * If not (current writer), then we must be made to wait
+ * for our turn. This is done by pushing us unto the writer queue.
*/
#if !defined(__WIN32__)
static
-BOOLEAN_T send_check_writer(ErlNifEnv* env,
- SocketDescriptor* descP,
- ERL_NIF_TERM ref,
- ERL_NIF_TERM* checkResult)
+BOOLEAN_T send_check_writer(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM ref,
+ ERL_NIF_TERM* checkResult)
{
if (descP->currentWriterP != NULL) {
ErlNifPid caller;
@@ -13665,7 +13919,8 @@ BOOLEAN_T send_check_writer(ErlNifEnv* env,
/* Not the "current writer", so (maybe) push onto queue */
SSDBG( descP,
- ("SOCKET", "send_check_writer -> not (current) writer\r\n") );
+ ("SOCKET",
+ "send_check_writer -> not (current) writer\r\n") );
if (!writer_search4pid(env, descP, &caller))
*checkResult = writer_push(env, descP, caller, ref);
@@ -13683,7 +13938,8 @@ BOOLEAN_T send_check_writer(ErlNifEnv* env,
}
- *checkResult = esock_atom_ok; // Does not actually matter in this case, but ...
+ // Does not actually matter in this case, but ...
+ *checkResult = esock_atom_ok;
return TRUE;
}
@@ -13702,17 +13958,18 @@ BOOLEAN_T send_check_writer(ErlNifEnv* env,
* If the write fail, we give up and return with the appropriate error code.
*
* What about the remaining writers!!
+ *
*/
static
-ERL_NIF_TERM send_check_result(ErlNifEnv* env,
- SocketDescriptor* descP,
- ssize_t written,
- ssize_t dataSize,
- int saveErrno,
- ERL_NIF_TERM sockRef,
- ERL_NIF_TERM sendRef)
+ERL_NIF_TERM send_check_result(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ssize_t written,
+ ssize_t dataSize,
+ int saveErrno,
+ ERL_NIF_TERM sockRef,
+ ERL_NIF_TERM sendRef)
{
- int sres;
+ ERL_NIF_TERM res;
SSDBG( descP,
("SOCKET", "send_check_result -> entry with"
@@ -13723,143 +13980,219 @@ ERL_NIF_TERM send_check_result(ErlNifEnv* env,
if (written >= dataSize) {
- cnt_inc(&descP->writePkgCnt, 1);
- cnt_inc(&descP->writeByteCnt, written);
- if (descP->currentWriterP != NULL)
- DEMONP("send_check_result -> current writer",
- env, descP, &descP->currentWriter.mon);
+ res = send_check_ok(env, descP, written, dataSize, sockRef);
+
+ } else if (written < 0) {
+
+ /* Some kind of send failure - check what kind */
+
+ if ((saveErrno != EAGAIN) && (saveErrno != EINTR)) {
+
+ res = send_check_fail(env, descP, saveErrno, sockRef);
+
+ } else {
+
+ /* Ok, try again later */
+
+ SSDBG( descP, ("SOCKET", "send_check_result -> try again\r\n") );
+
+ res = send_check_retry(env, descP, written, sockRef, sendRef);
+
+ }
+
+ } else {
+
+ /* Not the entire package */
SSDBG( descP,
("SOCKET", "send_check_result -> "
- "everything written (%d,%d) - done\r\n", dataSize, written) );
+ "not entire package written (%d of %d)\r\n",
+ written, dataSize) );
- /* Ok, this write is done maybe activate the next (if any) */
+ res = send_check_retry(env, descP, written, sockRef, sendRef);
- if (!activate_next_writer(env, descP, sockRef)) {
- descP->currentWriterP = NULL;
- descP->currentWriter.ref = esock_atom_undefined;
- enif_set_pid_undefined(&descP->currentWriter.pid);
- esock_monitor_init(&descP->currentWriter.mon);
- }
+ }
- return esock_atom_ok;
+ SSDBG( descP, ("SOCKET", "send_check_result -> done: %T\r\n", res) );
- } else if (written < 0) {
+ return res;
+}
- /* Some kind of send failure - check what kind */
- if ((saveErrno != EAGAIN) && (saveErrno != EINTR)) {
- SocketRequestor req;
- ERL_NIF_TERM res, reason;
+/* *** send_check_ok ***
+ *
+ * Processing done upon successful send.
+ */
+static
+ERL_NIF_TERM send_check_ok(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ssize_t written,
+ ssize_t dataSize,
+ ERL_NIF_TERM sockRef)
+{
+ cnt_inc(&descP->writePkgCnt, 1);
+ cnt_inc(&descP->writeByteCnt, written);
- /*
- * An actual failure - we (and everyone waiting) give up
- */
+ if (descP->currentWriterP != NULL) {
+ DEMONP("send_check_ok -> current writer",
+ env, descP, &descP->currentWriter.mon);
+ esock_free_env("send_check_ok", descP->currentWriter.env);
+ }
- cnt_inc(&descP->writeFails, 1);
+ SSDBG( descP,
+ ("SOCKET", "send_check_ok -> "
+ "everything written (%d,%d) - done\r\n", dataSize, written) );
- SSDBG( descP,
- ("SOCKET",
- "send_check_result -> error: %d\r\n", saveErrno) );
+ /*
+ * Ok, this write is done maybe activate the next (if any)
+ */
- reason = MKA(env, erl_errno_id(saveErrno));
- res = esock_make_error(env, reason);
+ if (!activate_next_writer(env, descP, sockRef)) {
+ descP->currentWriterP = NULL;
+ descP->currentWriter.env = NULL;
+ descP->currentWriter.ref = esock_atom_undefined;
+ enif_set_pid_undefined(&descP->currentWriter.pid);
+ esock_monitor_init(&descP->currentWriter.mon);
+ }
- if (descP->currentWriterP != NULL) {
+ return esock_atom_ok;
+}
- DEMONP("send_check_result -> current writer",
- env, descP, &descP->currentWriter.mon);
- while (writer_pop(env, descP, &req)) {
- SSDBG( descP,
- ("SOCKET", "send_check_result -> abort %T\r\n",
- req.pid) );
- esock_send_abort_msg(env, sockRef, req.ref,
- reason, &req.pid);
- DEMONP("send_check_result -> pop'ed writer",
- env, descP, &req.mon);
- }
- }
-
- return res;
- } else {
- /* Ok, try again later */
+/* *** send_check_failure ***
+ *
+ * Processing done upon failed send.
+ * An actual failure - we (and everyone waiting) give up.
+ */
+static
+ERL_NIF_TERM send_check_fail(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ int saveErrno,
+ ERL_NIF_TERM sockRef)
+{
+ ESockRequestor req;
+ ERL_NIF_TERM reason;
- SSDBG( descP, ("SOCKET", "send_check_result -> try again\r\n") );
- }
+ cnt_inc(&descP->writeFails, 1);
- }
- else {
- SSDBG( descP,
- ("SOCKET", "send_check_result -> "
- "not entire package written (%d of %d)\r\n", written, dataSize) );
+ SSDBG( descP, ("SOCKET", "send_check_fail -> error: %d\r\n", saveErrno) );
+
+ reason = MKA(env, erl_errno_id(saveErrno));
+
+ if (descP->currentWriterP != NULL) {
+
+ DEMONP("send_check_fail -> current writer",
+ env, descP, &descP->currentWriter.mon);
+
+ while (writer_pop(env, descP, &req)) {
+ SSDBG( descP,
+ ("SOCKET", "send_check_fail -> abort %T\r\n", req.pid) );
+ esock_send_abort_msg(env, sockRef, req.ref, req.env,
+ reason, &req.pid);
+ DEMONP("send_check_fail -> pop'ed writer", env, descP, &req.mon);
+ }
}
- /* We failed to write the *entire* packet (anything less then size
- * of the packet, which is 0 <= written < sizeof packet),
- * so schedule the rest for later.
- */
+ return esock_make_error(env, reason);
+}
+
+
+
+/* *** send_check_retry ***
+ *
+ * Processing done upon uncomplete or blocked send.
+ *
+ * We failed to write the *entire* packet (anything less
+ * then size of the packet, which is 0 <= written < sizeof
+ * packet, so schedule the rest for later.
+ */
+static
+ERL_NIF_TERM send_check_retry(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ssize_t written,
+ ERL_NIF_TERM sockRef,
+ ERL_NIF_TERM sendRef)
+{
+ int sres;
+ ErlNifPid caller;
+ ERL_NIF_TERM res;
if (descP->currentWriterP == NULL) {
- ErlNifPid caller;
if (enif_self(env, &caller) == NULL)
return esock_make_error(env, atom_exself);
descP->currentWriter.pid = caller;
- if (MONP("send_check_result -> current writer",
+
+ if (MONP("send_check_retry -> current writer",
env, descP,
&descP->currentWriter.pid,
- &descP->currentWriter.mon) != 0)
+ &descP->currentWriter.mon) != 0) {
+ enif_set_pid_undefined(&descP->currentWriter.pid);
return esock_make_error(env, atom_exmon);
- descP->currentWriter.ref = enif_make_copy(descP->env, sendRef);
- descP->currentWriterP = &descP->currentWriter;
+ } else {
+ descP->currentWriter.env = esock_alloc_env("current-writer");
+ descP->currentWriter.ref = CP_TERM(descP->currentWriter.env, sendRef);
+ descP->currentWriterP = &descP->currentWriter;
+ }
}
cnt_inc(&descP->writeWaits, 1);
- sres = esock_select_write(env, descP->sock, descP, NULL, sendRef);
-
+ sres = esock_select_write(env, descP->sock, descP, NULL, sockRef, sendRef);
+
if (written >= 0) {
+
+ /* Partial *write* success */
+
if (sres < 0) {
/* Returned: {error, Reason}
* Reason: {select_failed, sres, written}
*/
- return esock_make_error(env,
- MKT3(env,
- esock_atom_select_failed,
- MKI(env, sres),
- MKI(env, written)));
+ res = esock_make_error(env,
+ MKT3(env,
+ esock_atom_select_failed,
+ MKI(env, sres),
+ MKI(env, written)));
} else {
- return esock_make_ok2(env, MKI(env, written));
+ res = esock_make_ok2(env, MKI(env, written));
}
+
} else {
+
if (sres < 0) {
/* Returned: {error, Reason}
* Reason: {select_failed, sres}
*/
- return esock_make_error(env,
- MKT2(env,
- esock_atom_select_failed,
- MKI(env, sres)));
+ res = esock_make_error(env,
+ MKT2(env,
+ esock_atom_select_failed,
+ MKI(env, sres)));
} else {
- return esock_make_error(env, esock_atom_eagain);
+ res = esock_make_error(env, esock_atom_eagain);
}
}
+
+ return res;
}
+
/* *** recv_check_reader ***
*
- * Checks if we have a current reader and if that is us. If not, then we must
- * be made to wait for our turn. This is done by pushing us unto the reader queue.
+ * Checks if we have a current reader and if that is us. If not,
+ * then we must be made to wait for our turn. This is done by pushing
+ * us unto the reader queue.
+ * Note that we do *not* actually initiate the currentReader structure
+ * here, since we do not actually know yet if we need to! We do that in
+ * the [recv|recvfrom|recvmsg]_check_result function.
*/
static
-BOOLEAN_T recv_check_reader(ErlNifEnv* env,
- SocketDescriptor* descP,
- ERL_NIF_TERM ref,
- ERL_NIF_TERM* checkResult)
+BOOLEAN_T recv_check_reader(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM ref,
+ ERL_NIF_TERM* checkResult)
{
if (descP->currentReaderP != NULL) {
ErlNifPid caller;
@@ -13875,7 +14208,8 @@ BOOLEAN_T recv_check_reader(ErlNifEnv* env,
/* Not the "current reader", so (maybe) push onto queue */
SSDBG( descP,
- ("SOCKET", "recv_check_reader -> not (current) reader\r\n") );
+ ("SOCKET",
+ "recv_check_reader -> not (current) reader\r\n") );
if (!reader_search4pid(env, descP, &caller))
tmp = reader_push(env, descP, caller, ref);
@@ -13894,7 +14228,8 @@ BOOLEAN_T recv_check_reader(ErlNifEnv* env,
}
- *checkResult = esock_atom_ok; // Does not actually matter in this case, but ...
+ // Does not actually matter in this case, but ...
+ *checkResult = esock_atom_ok;
return TRUE;
}
@@ -13907,9 +14242,9 @@ BOOLEAN_T recv_check_reader(ErlNifEnv* env,
* Including monitoring the calling process.
*/
static
-char* recv_init_current_reader(ErlNifEnv* env,
- SocketDescriptor* descP,
- ERL_NIF_TERM recvRef)
+char* recv_init_current_reader(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM recvRef)
{
if (descP->currentReaderP == NULL) {
ErlNifPid caller;
@@ -13922,10 +14257,26 @@ char* recv_init_current_reader(ErlNifEnv* env,
env, descP,
&descP->currentReader.pid,
&descP->currentReader.mon) != 0) {
+ enif_set_pid_undefined(&descP->currentReader.pid);
return str_exmon;
+ } else {
+
+ descP->currentReader.env = esock_alloc_env("current-reader");
+ descP->currentReader.ref = CP_TERM(descP->currentReader.env,
+ recvRef);
+ descP->currentReaderP = &descP->currentReader;
}
- descP->currentReader.ref = enif_make_copy(descP->env, recvRef);
- descP->currentReaderP = &descP->currentReader;
+ } else {
+
+ /*
+ * This is a retry:
+ * We have done, for instance, recv(Sock, X), but only received Y < X.
+ * We then call recv again with size = X-Y. So, we then get a new ref.
+ *
+ * Make use of the existing environment
+ */
+
+ descP->currentReader.ref = CP_TERM(descP->currentReader.env, recvRef);
}
return NULL;
@@ -13941,17 +14292,21 @@ char* recv_init_current_reader(ErlNifEnv* env,
*/
static
-ERL_NIF_TERM recv_update_current_reader(ErlNifEnv* env,
- SocketDescriptor* descP,
- ERL_NIF_TERM sockRef)
+ERL_NIF_TERM recv_update_current_reader(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM sockRef)
{
ERL_NIF_TERM res = esock_atom_ok;
if (descP->currentReaderP != NULL) {
- DEMONP("recv_update_current_reader -> current reader",
+ DEMONP("recv_update_current_reader",
env, descP, &descP->currentReader.mon);
-
+
+ esock_free_env("recv_update_current_reader - current-read-env",
+ descP->currentReader.env);
+ descP->currentReader.env = NULL;
+
if (!activate_next_reader(env, descP, sockRef)) {
SSDBG( descP,
@@ -13979,12 +14334,12 @@ ERL_NIF_TERM recv_update_current_reader(ErlNifEnv* env,
* nif_abort message will be sent (with reaf and reason).
*/
static
-void recv_error_current_reader(ErlNifEnv* env,
- SocketDescriptor* descP,
- ERL_NIF_TERM sockRef,
- ERL_NIF_TERM reason)
+void recv_error_current_reader(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM sockRef,
+ ERL_NIF_TERM reason)
{
- SocketRequestor req;
+ ESockRequestor req;
if (descP->currentReaderP != NULL) {
@@ -13995,7 +14350,8 @@ void recv_error_current_reader(ErlNifEnv* env,
SSDBG( descP,
("SOCKET", "recv_error_current_reader -> abort %T\r\n",
req.pid) );
- esock_send_abort_msg(env, sockRef, req.ref, reason, &req.pid);
+ esock_send_abort_msg(env, sockRef, req.ref, req.env,
+ reason, &req.pid);
DEMONP("recv_error_current_reader -> pop'ed reader",
env, descP, &req.mon);
}
@@ -14009,18 +14365,16 @@ void recv_error_current_reader(ErlNifEnv* env,
* Process the result of a call to recv.
*/
static
-ERL_NIF_TERM recv_check_result(ErlNifEnv* env,
- SocketDescriptor* descP,
- int read,
- int toRead,
- int saveErrno,
- ErlNifBinary* bufP,
- ERL_NIF_TERM sockRef,
- ERL_NIF_TERM recvRef)
+ERL_NIF_TERM recv_check_result(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ int read,
+ int toRead,
+ int saveErrno,
+ ErlNifBinary* bufP,
+ ERL_NIF_TERM sockRef,
+ ERL_NIF_TERM recvRef)
{
- char* xres;
- int sres;
- ERL_NIF_TERM res, data;
+ ERL_NIF_TERM res;
SSDBG( descP,
("SOCKET", "recv_check_result -> entry with"
@@ -14044,8 +14398,8 @@ ERL_NIF_TERM recv_check_result(ErlNifEnv* env,
res = esock_make_error(env, atom_closed);
/*
- * When a stream socket peer has performed an orderly shutdown, the return
- * value will be 0 (the traditional "end-of-file" return).
+ * When a stream socket peer has performed an orderly shutdown,
+ * the return value will be 0 (the traditional "end-of-file" return).
*
* *We* do never actually try to read 0 bytes from a stream socket!
*
@@ -14056,381 +14410,515 @@ ERL_NIF_TERM recv_check_result(ErlNifEnv* env,
FREE_BIN(bufP);
- return res;
+ } else {
+
+ /* There is a special case: If the provided 'to read' value is
+ * zero (0) (only for type =/= stream).
+ * That means that we reads as much as we can, using the default
+ * read buffer size.
+ */
+
+ if (bufP->size == read) {
+
+ /* +++ We filled the buffer +++ */
+
+ SSDBG( descP,
+ ("SOCKET",
+ "recv_check_result -> [%d] filled the buffer\r\n",
+ toRead) );
+
+ res = recv_check_full(env, descP, read, toRead, bufP,
+ sockRef, recvRef);
+
+ } else if (read < 0) {
+
+ /* +++ Error handling +++ */
+ res = recv_check_fail(env, descP, saveErrno, bufP, NULL,
+ sockRef, recvRef);
+
+ } else {
+
+ /* +++ We did not fill the buffer +++ */
+
+ SSDBG( descP,
+ ("SOCKET",
+ "recv_check_result -> [%d] "
+ "did not fill the buffer (%d of %d)\r\n",
+ toRead, read, bufP->size) );
+
+ res = recv_check_partial(env, descP, read, toRead, bufP,
+ sockRef, recvRef);
+
+ }
}
-
- /* There is a special case: If the provided 'to read' value is
- * zero (0) (only for type =/= stream).
- * That means that we reads as much as we can, using the default
- * read buffer size.
- */
- if (bufP->size == read) {
+ return res;
+}
+
+
+
+/* *** recv_check_full ***
+ *
+ * This function is called if we filled the allocated buffer.
+ * But are we done yet?
+ *
+ * toRead = 0 means: Give me everything you have => maybe
+ * toRead > 0 means: Yes
+ */
+static
+ERL_NIF_TERM recv_check_full(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ int read,
+ int toRead,
+ ErlNifBinary* bufP,
+ ERL_NIF_TERM sockRef,
+ ERL_NIF_TERM recvRef)
+{
+ ERL_NIF_TERM res;
- /* +++ We filled the buffer +++ */
+ if (toRead == 0) {
+
+ /* +++ Give us everything you have got => *
+ * (maybe) needs to continue +++ */
+
+ /* Send up each chunk of data for each of the read
+ * and let the erlang code assemble it: {ok, false, Bin}
+ * (when complete it should return {ok, true, Bin}).
+ * We need to read atleast one more time to be sure if its
+ * done...
+ *
+ * Also, we need to check if the rNumCnt has reached its max (rNum),
+ * in which case we will assume the read to be done!
+ */
SSDBG( descP,
- ("SOCKET",
- "recv_check_result -> [%d] filled the buffer\r\n", toRead) );
-
- if (toRead == 0) {
-
- /* +++ Give us everything you have got => *
- * (maybe) needs to continue +++ */
-
- /* How do we do this?
- * Either:
- * 1) Send up each chunk of data for each of the read
- * and let the erlang code assemble it: {ok, false, Bin}
- * (when complete it should return {ok, true, Bin}).
- * We need to read atleast one more time to be sure if its
- * done...
- * 2) Or put it in a buffer here, and then let the erlang code
- * know that it should call again (special return value)
- * (continuous binary realloc "here").
- *
- * => We choose alt 1 for now.
- *
- * Also, we need to check if the rNumCnt has reached its max (rNum),
- * in which case we will assume the read to be done!
- */
+ ("SOCKET", "recv_check_full -> shall we continue reading"
+ "\r\n read: %d"
+ "\r\n rNum: %d"
+ "\r\n rNumCnt: %d"
+ "\r\n", read, descP->rNum, descP->rNumCnt) );
- cnt_inc(&descP->readByteCnt, read);
+ res = recv_check_full_maybe_done(env, descP, read, toRead, bufP,
+ sockRef, recvRef);
- SSDBG( descP,
- ("SOCKET", "recv_check_result -> shall we continue reading"
- "\r\n read: %d"
- "\r\n rNum: %d"
- "\r\n rNumCnt: %d"
- "\r\n", read, descP->rNum, descP->rNumCnt) );
+ } else {
- if (descP->rNum > 0) {
+ /* +++ We got exactly as much as we requested => We are done +++ */
- descP->rNumCnt++;
- if (descP->rNumCnt >= descP->rNum) {
+ SSDBG( descP,
+ ("SOCKET",
+ "recv_check_full -> [%d] "
+ "we got exactly what we could fit\r\n", toRead) );
- descP->rNumCnt = 0;
+ res = recv_check_full_done(env, descP, read, bufP, sockRef);
- cnt_inc(&descP->readPkgCnt, 1);
-
- recv_update_current_reader(env, descP, sockRef);
-
- /* This transfers "ownership" of the *allocated* binary to an
- * erlang term (no need for an explicit free).
- */
- data = MKBIN(env, bufP);
-
- return esock_make_ok3(env, atom_true, data);
+ }
- }
- }
+ return res;
- /* Yes, we *do* need to continue reading */
+}
- if ((xres = recv_init_current_reader(env,
- descP, recvRef)) != NULL) {
- descP->rNumCnt = 0;
- FREE_BIN(bufP);
- return esock_make_error_str(env, xres);
- }
- /* This transfers "ownership" of the *allocated* binary to an
- * erlang term (no need for an explicit free).
- */
- data = MKBIN(env, bufP);
- SSDBG( descP,
- ("SOCKET",
- "recv_check_result -> [%d] "
- "we are done for now - read more\r\n", toRead) );
+/* *** recv_check_full_maybe_done ***
+ *
+ * Send up each chunk of data for each of the read
+ * and let the erlang code assemble it: {ok, false, Bin}
+ * (when complete it should return {ok, true, Bin}).
+ * We need to read atleast one more time to be sure if its
+ * done...
+ *
+ * Also, we need to check if the rNumCnt has reached its max (rNum),
+ * in which case we will assume the read to be done!
+ */
+static
+ERL_NIF_TERM recv_check_full_maybe_done(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ int read,
+ int toRead,
+ ErlNifBinary* bufP,
+ ERL_NIF_TERM sockRef,
+ ERL_NIF_TERM recvRef)
+{
+ char* xres;
- return esock_make_ok3(env, atom_false, data);
+ cnt_inc(&descP->readByteCnt, read);
- } else {
+ if (descP->rNum > 0) {
- /* +++ We got exactly as much as we requested => We are done +++ */
+ descP->rNumCnt++;
+ if (descP->rNumCnt >= descP->rNum) {
- cnt_inc(&descP->readPkgCnt, 1);
- cnt_inc(&descP->readByteCnt, read);
+ descP->rNumCnt = 0;
- SSDBG( descP,
- ("SOCKET",
- "recv_check_result -> [%d] "
- "we got exactly what we could fit\r\n", toRead) );
+ cnt_inc(&descP->readPkgCnt, 1);
recv_update_current_reader(env, descP, sockRef);
/* This transfers "ownership" of the *allocated* binary to an
* erlang term (no need for an explicit free).
*/
- data = MKBIN(env, bufP);
- return esock_make_ok3(env, atom_true, data);
+ return esock_make_ok3(env, atom_true, MKBIN(env, bufP));
}
+ }
- } else if (read < 0) {
-
- /* +++ Error handling +++ */
+ /* Yes, we *do* need to continue reading */
+ if ((xres = recv_init_current_reader(env, descP, recvRef)) != NULL) {
+ descP->rNumCnt = 0;
FREE_BIN(bufP);
+ return esock_make_error_str(env, xres);
+ }
- if (saveErrno == ECONNRESET) {
+ /* This transfers "ownership" of the *allocated* binary to an
+ * erlang term (no need for an explicit free).
+ */
- res = esock_make_error(env, atom_closed);
+ SSDBG( descP,
+ ("SOCKET",
+ "recv_check_full_maybe_done -> [%d] "
+ "we are done for now - read more\r\n", toRead) );
- /* +++ Oups - closed +++ */
+ return esock_make_ok3(env, atom_false, MKBIN(env, bufP));
+}
- SSDBG( descP, ("SOCKET",
- "recv_check_result -> [%d] closed\r\n", toRead) );
- /* <KOLLA>
- *
- * IF THE CURRENT PROCESS IS *NOT* THE CONTROLLING
- * PROCESS, WE NEED TO INFORM IT!!!
- *
- * ALL WAITING PROCESSES MUST ALSO GET THE ERROR!!
- * HANDLED BY THE STOP (CALLBACK) FUNCTION?
- *
- * SINCE THIS IS A REMOTE CLOSE, WE DON'T NEED TO WAIT
- * FOR OUTPUT TO BE WRITTEN (NO ONE WILL READ), JUST
- * ABORT THE SOCKET REGARDLESS OF LINGER???
- *
- * </KOLLA>
- */
- descP->closeLocal = FALSE;
- descP->state = SOCKET_STATE_CLOSING;
+/* *** recv_check_full_done ***
+ *
+ * A successful recv and we filled the buffer.
+ */
+static
+ERL_NIF_TERM recv_check_full_done(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ int read,
+ ErlNifBinary* bufP,
+ ERL_NIF_TERM sockRef)
+{
+ ERL_NIF_TERM data;
- recv_error_current_reader(env, descP, sockRef, res);
+ cnt_inc(&descP->readPkgCnt, 1);
+ cnt_inc(&descP->readByteCnt, read);
- if ((sres = esock_select_stop(env, descP->sock, descP)) < 0) {
- esock_warning_msg("Failed stop select (closed) "
- "for current reader (%T): %d\r\n",
- recvRef, sres);
- }
+ recv_update_current_reader(env, descP, sockRef);
- return res;
+ /* This transfers "ownership" of the *allocated* binary to an
+ * erlang term (no need for an explicit free).
+ */
+ data = MKBIN(env, bufP);
- } else if ((saveErrno == ERRNO_BLOCK) ||
- (saveErrno == EAGAIN)) {
+ return esock_make_ok3(env, atom_true, data);
+}
- SSDBG( descP, ("SOCKET",
- "recv_check_result -> [%d] eagain\r\n", toRead) );
- descP->rNumCnt = 0;
- if ((xres = recv_init_current_reader(env, descP, recvRef)) != NULL)
- return esock_make_error_str(env, xres);
-
- SSDBG( descP, ("SOCKET", "recv_check_result -> SELECT for more\r\n") );
-
- if ((sres = esock_select_read(env, descP->sock, descP,
- NULL, recvRef)) < 0) {
- res = esock_make_error(env,
- MKT2(env,
- esock_atom_select_failed,
- MKI(env, sres)));
- } else {
- res = esock_make_error(env, esock_atom_eagain);
- }
- return res;
- } else {
- ERL_NIF_TERM res = esock_make_error_errno(env, saveErrno);
+/* *** recv_check_fail ***
+ *
+ * Handle recv failure.
+ */
+static
+ERL_NIF_TERM recv_check_fail(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ int saveErrno,
+ ErlNifBinary* buf1P,
+ ErlNifBinary* buf2P,
+ ERL_NIF_TERM sockRef,
+ ERL_NIF_TERM recvRef)
+{
+ ERL_NIF_TERM res;
- SSDBG( descP, ("SOCKET", "recv_check_result -> [%d] errno: %d\r\n",
- toRead, saveErrno) );
+ FREE_BIN(buf1P); if (buf2P != NULL) FREE_BIN(buf2P);
- recv_error_current_reader(env, descP, sockRef, res);
+ if (saveErrno == ECONNRESET) {
- return res;
- }
+ /* +++ Oups - closed +++ */
+
+ SSDBG( descP, ("SOCKET", "recv_check_fail -> closed\r\n") );
+
+ res = recv_check_fail_closed(env, descP, sockRef, recvRef);
+
+ } else if ((saveErrno == ERRNO_BLOCK) ||
+ (saveErrno == EAGAIN)) {
+
+ SSDBG( descP, ("SOCKET", "recv_check_fail -> eagain\r\n") );
+
+ res = recv_check_retry(env, descP, sockRef, recvRef);
} else {
- /* +++ We did not fill the buffer +++ */
+ SSDBG( descP, ("SOCKET", "recv_check_fail -> errno: %d\r\n",
+ saveErrno) );
- SSDBG( descP,
- ("SOCKET",
- "recv_check_result -> [%d] "
- "did not fill the buffer (%d of %d)\r\n",
- toRead, read, bufP->size) );
+ res = recv_check_fail_gen(env, descP, saveErrno, sockRef);
+ }
- if (toRead == 0) {
+ return res;
+}
- /* +++ We got it all, but since we +++
- * +++ did not fill the buffer, we +++
- * +++ must split it into a sub-binary. +++
- */
- SSDBG( descP, ("SOCKET",
- "recv_check_result -> [%d] split buffer\r\n", toRead) );
- descP->rNumCnt = 0;
- cnt_inc(&descP->readPkgCnt, 1);
- cnt_inc(&descP->readByteCnt, read);
+/* *** recv_check_fail_closed ***
+ *
+ * We detected that the socket was closed wile reading.
+ * Inform current and waiting readers.
+ */
+static
+ERL_NIF_TERM recv_check_fail_closed(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM sockRef,
+ ERL_NIF_TERM recvRef)
+{
+ ERL_NIF_TERM res = esock_make_error(env, atom_closed);
+ int sres;
- recv_update_current_reader(env, descP, sockRef);
+ /* <KOLLA>
+ *
+ * IF THE CURRENT PROCESS IS *NOT* THE CONTROLLING
+ * PROCESS, WE NEED TO INFORM IT!!!
+ *
+ * ALL WAITING PROCESSES MUST ALSO GET THE ERROR!!
+ * HANDLED BY THE STOP (CALLBACK) FUNCTION?
+ *
+ * SINCE THIS IS A REMOTE CLOSE, WE DON'T NEED TO WAIT
+ * FOR OUTPUT TO BE WRITTEN (NO ONE WILL READ), JUST
+ * ABORT THE SOCKET REGARDLESS OF LINGER???
+ *
+ * </KOLLA>
+ */
- /* This transfers "ownership" of the *allocated* binary to an
- * erlang term (no need for an explicit free).
- */
- data = MKBIN(env, bufP);
- data = MKSBIN(env, data, 0, read);
+ descP->closeLocal = FALSE;
+ descP->state = SOCKET_STATE_CLOSING;
- SSDBG( descP,
- ("SOCKET", "recv_check_result -> [%d] done\r\n", toRead) );
+ recv_error_current_reader(env, descP, sockRef, res);
- return esock_make_ok3(env, atom_true, data);
+ if ((sres = esock_select_stop(env, descP->sock, descP)) < 0) {
+ esock_warning_msg("Failed stop select (closed) "
+ "for current reader (%T): %d\r\n",
+ recvRef, sres);
+ }
- } else {
+ return res;
+}
- /* +++ We got only a part of what was expected +++
- * +++ => select for more more later and +++
- * +++ deliver what we got. +++ */
- SSDBG( descP, ("SOCKET", "recv_check_result -> [%d] "
- "only part of message - expect more\r\n", toRead) );
- if ((xres = recv_init_current_reader(env, descP, recvRef)) != NULL) {
- FREE_BIN(bufP);
- return esock_make_error_str(env, xres);
- }
+/* *** recv_check_retry ***
+ *
+ * The recv call would have blocked, so retry.
+ */
+static
+ERL_NIF_TERM recv_check_retry(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM sockRef,
+ ERL_NIF_TERM recvRef)
+{
+ int sres;
+ char* xres;
+ ERL_NIF_TERM reason;
- data = MKBIN(env, bufP);
- data = MKSBIN(env, data, 0, read);
+ descP->rNumCnt = 0;
+ if ((xres = recv_init_current_reader(env, descP, recvRef)) != NULL)
+ return esock_make_error_str(env, xres);
+
+ SSDBG( descP, ("SOCKET", "recv_check_retry -> SELECT for more\r\n") );
+
+ if ((sres = esock_select_read(env, descP->sock, descP, NULL,
+ sockRef, recvRef)) < 0) {
+ /* Ouch
+ * Now what? We have copied ref into *its own* environment!
+ */
+ reason = MKT2(env, esock_atom_select_failed, MKI(env, sres));
+ } else {
+ reason = esock_atom_eagain;
+ }
- cnt_inc(&descP->readByteCnt, read);
+ return esock_make_error(env, reason);
- /* SELECT for more data */
+}
- if ((sres = esock_select_read(env, descP->sock, descP,
- NULL, recvRef)) < 0) {
- /* Result: {error, Reason}
- * Reason: {select_failed, sres, data}
- */
- res = esock_make_error(env,
- MKT3(env,
- esock_atom_select_failed,
- MKI(env, sres),
- data));
- } else {
- res = esock_make_ok3(env, atom_false, data);
- }
-
- /* This transfers "ownership" of the *allocated* binary to an
- * erlang term (no need for an explicit free).
- */
- return res;
- }
+
+
+/* *** recv_check_fail_gen ***
+ *
+ * The recv call had a "general" failure.
+ */
+static
+ERL_NIF_TERM recv_check_fail_gen(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ int saveErrno,
+ ERL_NIF_TERM sockRef)
+{
+ ERL_NIF_TERM res = esock_make_error_errno(env, saveErrno);
+
+ recv_error_current_reader(env, descP, sockRef, res);
+
+ return res;
+}
+
+
+
+/* *** recv_check_partial ***
+ *
+ * Handle a sucessful recv which only partly filled the specified buffer.
+ */
+static
+ERL_NIF_TERM recv_check_partial(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ int read,
+ int toRead,
+ ErlNifBinary* bufP,
+ ERL_NIF_TERM sockRef,
+ ERL_NIF_TERM recvRef)
+{
+ ERL_NIF_TERM res;
+
+ if (toRead == 0) {
+
+ /* +++ We got it all, but since we +++
+ * +++ did not fill the buffer, we +++
+ * +++ must split it into a sub-binary. +++
+ */
+
+ SSDBG( descP,
+ ("SOCKET",
+ "recv_check_partial -> [%d] split buffer\r\n", toRead) );
+
+ res = recv_check_partial_done(env, descP, read, bufP, sockRef);
+
+ } else {
+
+ SSDBG( descP, ("SOCKET", "recv_check_partial -> [%d] "
+ "only part of message - expect more\r\n", toRead) );
+
+ res = recv_check_partial_part(env, descP, read, bufP, sockRef, recvRef);
}
+
+ return res;
}
-/* The recvfrom function delivers one (1) message. If our buffer
- * is to small, the message will be truncated. So, regardless
- * if we filled the buffer or not, we have got what we are going
- * to get regarding this message.
+
+/* *** recv_check_partial_done ***
+ *
+ * A successful but only partial recv, which fulfilled the required read.
*/
static
-ERL_NIF_TERM recvfrom_check_result(ErlNifEnv* env,
- SocketDescriptor* descP,
- int read,
- int saveErrno,
- ErlNifBinary* bufP,
- SocketAddress* fromAddrP,
- unsigned int fromAddrLen,
- ERL_NIF_TERM sockRef,
- ERL_NIF_TERM recvRef)
+ERL_NIF_TERM recv_check_partial_done(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ int read,
+ ErlNifBinary* bufP,
+ ERL_NIF_TERM sockRef)
{
- char* xres;
- int sres;
- ERL_NIF_TERM data, res;
+ ERL_NIF_TERM data;
- SSDBG( descP,
- ("SOCKET", "recvfrom_check_result -> entry with"
- "\r\n read: %d"
- "\r\n saveErrno: %d"
- "\r\n recvRef: %T"
- "\r\n", read, saveErrno, recvRef) );
+ descP->rNumCnt = 0;
+ cnt_inc(&descP->readPkgCnt, 1);
+ cnt_inc(&descP->readByteCnt, read);
+ recv_update_current_reader(env, descP, sockRef);
- /* There is a special case: If the provided 'to read' value is
- * zero (0). That means that we reads as much as we can, using
- * the default read buffer size.
+ /* This transfers "ownership" of the *allocated* binary to an
+ * erlang term (no need for an explicit free).
*/
+ data = MKBIN(env, bufP);
+ data = MKSBIN(env, data, 0, read);
- if (read < 0) {
+ SSDBG( descP,
+ ("SOCKET", "recv_check_partial_done -> [%d] done\r\n", read) );
- /* +++ Error handling +++ */
+ return esock_make_ok3(env, atom_true, data);
+}
- if (saveErrno == ECONNRESET) {
- res = esock_make_error(env, atom_closed);
- /* +++ Oups - closed +++ */
- SSDBG( descP, ("SOCKET", "recvfrom_check_result -> closed\r\n") );
+/* *** recv_check_partial_part ***
+ *
+ * A successful but only partial recv, which only partly fulfilled
+ * the required read.
+ */
+static
+ERL_NIF_TERM recv_check_partial_part(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ int read,
+ ErlNifBinary* bufP,
+ ERL_NIF_TERM sockRef,
+ ERL_NIF_TERM recvRef)
+{
+ ERL_NIF_TERM res, reason, data;
+ char* xres;
+ int sres;
- /* <KOLLA>
- * IF THE CURRENT PROCESS IS *NOT* THE CONTROLLING
- * PROCESS, WE NEED TO INFORM IT!!!
- *
- * ALL WAITING PROCESSES MUST ALSO GET THE ERROR!!
- *
- * </KOLLA>
- */
+ if ((xres = recv_init_current_reader(env, descP, recvRef)) != NULL) {
+ FREE_BIN(bufP);
+ return esock_make_error_str(env, xres);
+ }
- descP->closeLocal = FALSE;
- descP->state = SOCKET_STATE_CLOSING;
+ data = MKBIN(env, bufP);
+ data = MKSBIN(env, data, 0, read);
- recv_error_current_reader(env, descP, sockRef, res);
+ cnt_inc(&descP->readByteCnt, read);
- if ((sres = esock_select_stop(env, descP->sock, descP)) < 0) {
- esock_warning_msg("Failed stop select (closed) "
- "for current reader (%T): %d\r\n",
- recvRef, sres);
- }
+ /* SELECT for more data */
- FREE_BIN(bufP);
+ sres = esock_select_read(env, descP->sock, descP, NULL,
+ sockRef, recvRef);
+ if (sres < 0) {
+ /* Result: {error, Reason}
+ * Reason: {select_failed, sres, data}
+ */
+ reason = MKT3(env, esock_atom_select_failed, MKI(env, sres), data);
+ res = esock_make_error(env, reason);
- return res;
+ } else {
- } else if ((saveErrno == ERRNO_BLOCK) ||
- (saveErrno == EAGAIN)) {
+ res = esock_make_ok3(env, atom_false, data);
- SSDBG( descP, ("SOCKET", "recvfrom_check_result -> eagain\r\n") );
+ }
- FREE_BIN(bufP);
+ /* This transfers "ownership" of the *allocated* binary to an
+ * erlang term (no need for an explicit free).
+ */
+ return res;
+}
- if ((xres = recv_init_current_reader(env, descP, recvRef)) != NULL)
- return esock_make_error_str(env, xres);
-
- if ((sres = esock_select_read(env, descP->sock, descP,
- NULL, recvRef)) < 0) {
- res = esock_make_error(env,
- MKT2(env,
- esock_atom_select_failed,
- MKI(env, sres)));
- } else {
- res = esock_make_error(env, esock_atom_eagain);
- }
- return res;
- } else {
- res = esock_make_error_errno(env, saveErrno);
- SSDBG( descP,
- ("SOCKET",
- "recvfrom_check_result -> errno: %d\r\n", saveErrno) );
-
- recv_error_current_reader(env, descP, sockRef, res);
- FREE_BIN(bufP);
+/* The recvfrom function delivers one (1) message. If our buffer
+ * is to small, the message will be truncated. So, regardless
+ * if we filled the buffer or not, we have got what we are going
+ * to get regarding this message.
+ */
+static
+ERL_NIF_TERM recvfrom_check_result(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ int read,
+ int saveErrno,
+ ErlNifBinary* bufP,
+ ESockAddress* fromAddrP,
+ unsigned int fromAddrLen,
+ ERL_NIF_TERM sockRef,
+ ERL_NIF_TERM recvRef)
+{
+ ERL_NIF_TERM data, res;
- return res;
- }
+ SSDBG( descP,
+ ("SOCKET", "recvfrom_check_result -> entry with"
+ "\r\n read: %d"
+ "\r\n saveErrno: %d"
+ "\r\n recvRef: %T"
+ "\r\n", read, saveErrno, recvRef) );
+
+ if (read < 0) {
+
+ /* +++ Error handling +++ */
+
+ res = recv_check_fail(env, descP, saveErrno, bufP, NULL,
+ sockRef, recvRef);
} else {
@@ -14443,7 +14931,9 @@ ERL_NIF_TERM recvfrom_check_result(ErlNifEnv* env,
&eSockAddr);
if (read == bufP->size) {
+
data = MKBIN(env, bufP);
+
} else {
/* +++ We got a chunk of data but +++
@@ -14458,30 +14948,34 @@ ERL_NIF_TERM recvfrom_check_result(ErlNifEnv* env,
recv_update_current_reader(env, descP, sockRef);
- return esock_make_ok2(env, MKT2(env, eSockAddr, data));
+ res = esock_make_ok2(env, MKT2(env, eSockAddr, data));
}
+
+ return res;
+
}
-/* The recvmsg function delivers one (1) message. If our buffer
+/* *** recvmsg_check_result ***
+ *
+ * The recvmsg function delivers one (1) message. If our buffer
* is to small, the message will be truncated. So, regardless
* if we filled the buffer or not, we have got what we are going
* to get regarding this message.
*/
static
-ERL_NIF_TERM recvmsg_check_result(ErlNifEnv* env,
- SocketDescriptor* descP,
- int read,
- int saveErrno,
- struct msghdr* msgHdrP,
- ErlNifBinary* dataBufP,
- ErlNifBinary* ctrlBufP,
- ERL_NIF_TERM sockRef,
- ERL_NIF_TERM recvRef)
+ERL_NIF_TERM recvmsg_check_result(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ int read,
+ int saveErrno,
+ struct msghdr* msgHdrP,
+ ErlNifBinary* dataBufP,
+ ErlNifBinary* ctrlBufP,
+ ERL_NIF_TERM sockRef,
+ ERL_NIF_TERM recvRef)
{
- int sres;
ERL_NIF_TERM res;
SSDBG( descP,
@@ -14503,8 +14997,8 @@ ERL_NIF_TERM recvmsg_check_result(ErlNifEnv* env,
if ((read == 0) && (descP->type == SOCK_STREAM)) {
/*
- * When a stream socket peer has performed an orderly shutdown, the return
- * value will be 0 (the traditional "end-of-file" return).
+ * When a stream socket peer has performed an orderly shutdown,
+ * the return value will be 0 (the traditional "end-of-file" return).
*
* *We* do never actually try to read 0 bytes from a stream socket!
*/
@@ -14526,119 +15020,76 @@ ERL_NIF_TERM recvmsg_check_result(ErlNifEnv* env,
/* +++ Error handling +++ */
- if (saveErrno == ECONNRESET) {
+ res = recv_check_fail(env, descP, saveErrno, dataBufP, ctrlBufP,
+ sockRef, recvRef);
- /* +++ Oups - closed +++ */
+ } else {
- SSDBG( descP, ("SOCKET", "recvmsg_check_result -> closed\r\n") );
+ /* +++ We sucessfully got a message - time to encode it +++ */
- /* <KOLLA>
- * IF THE CURRENT PROCESS IS *NOT* THE CONTROLLING
- * PROCESS, WE NEED TO INFORM IT!!!
- *
- * ALL WAITING PROCESSES MUST ALSO GET THE ERROR!!
- *
- * </KOLLA>
- */
+ res = recvmsg_check_msg(env, descP, read, msgHdrP,
+ dataBufP, ctrlBufP, sockRef);
- res = esock_make_error(env, atom_closed);
- descP->closeLocal = FALSE;
- descP->state = SOCKET_STATE_CLOSING;
-
- recv_error_current_reader(env, descP, sockRef, res);
+ }
- if ((sres = esock_select_stop(env, descP->sock, descP)) < 0) {
- esock_warning_msg("Failed stop select (closed) "
- "for current reader (%T): %d\r\n",
- recvRef, sres);
- }
+ return res;
- FREE_BIN(dataBufP); FREE_BIN(ctrlBufP);
+}
- return res;;
- } else if ((saveErrno == ERRNO_BLOCK) ||
- (saveErrno == EAGAIN)) {
- char* xres;
- SSDBG( descP, ("SOCKET", "recvmsg_check_result -> eagain\r\n") );
-
- FREE_BIN(dataBufP); FREE_BIN(ctrlBufP);
-
- if ((xres = recv_init_current_reader(env, descP, recvRef)) != NULL)
- return esock_make_error_str(env, xres);
-
- if ((sres = esock_select_read(env, descP->sock, descP,
- NULL, recvRef)) < 0) {
- res = esock_make_error(env,
- MKT2(env,
- esock_atom_select_failed,
- MKI(env, sres)));
- } else {
- res = esock_make_error(env, esock_atom_eagain);
- }
+/* *** recvmsg_check_msg ***
+ *
+ * We successfully read one message. Time to process.
+ */
+static
+ERL_NIF_TERM recvmsg_check_msg(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ int read,
+ struct msghdr* msgHdrP,
+ ErlNifBinary* dataBufP,
+ ErlNifBinary* ctrlBufP,
+ ERL_NIF_TERM sockRef)
+{
+ ERL_NIF_TERM res, eMsgHdr;
+ char* xres;
- return res;
+ /*
+ * <KOLLA>
+ *
+ * The return value of recvmsg is the *total* number of bytes
+ * that where successfully read. This data has been put into
+ * the *IO vector*.
+ *
+ * </KOLLA>
+ */
- } else {
+ if ((xres = encode_msghdr(env, descP,
+ read, msgHdrP, dataBufP, ctrlBufP,
+ &eMsgHdr)) != NULL) {
- res = esock_make_error_errno(env, saveErrno);
+ SSDBG( descP,
+ ("SOCKET",
+ "recvmsg_check_result -> "
+ "(msghdr) encode failed: %s\r\n", xres) );
- SSDBG( descP,
- ("SOCKET",
- "recvmsg_check_result -> errno: %d\r\n", saveErrno) );
-
- recv_error_current_reader(env, descP, sockRef, res);
+ recv_update_current_reader(env, descP, sockRef);
- FREE_BIN(dataBufP); FREE_BIN(ctrlBufP);
+ FREE_BIN(dataBufP); FREE_BIN(ctrlBufP);
- return res;
- }
+ res = esock_make_error_str(env, xres);
} else {
- /* +++ We sucessfully got a message - time to encode it +++ */
-
- ERL_NIF_TERM eMsgHdr;
- char* xres;
-
- /*
- * <KOLLA>
- *
- * The return value of recvmsg is the *total* number of bytes
- * that where successfully read. This data has been put into
- * the *IO vector*.
- *
- * </KOLLA>
- */
-
- if ((xres = encode_msghdr(env, descP,
- read, msgHdrP, dataBufP, ctrlBufP,
- &eMsgHdr)) != NULL) {
-
- SSDBG( descP,
- ("SOCKET",
- "recvmsg_check_result -> "
- "(msghdr) encode failed: %s\r\n", xres) );
-
- recv_update_current_reader(env, descP, sockRef);
-
- FREE_BIN(dataBufP); FREE_BIN(ctrlBufP);
-
- return esock_make_error_str(env, xres);
- } else {
-
- SSDBG( descP,
- ("SOCKET",
- "recvmsg_check_result -> "
- "(msghdr) encode ok: %T\r\n", eMsgHdr) );
-
- recv_update_current_reader(env, descP, sockRef);
+ SSDBG( descP,
+ ("SOCKET", "recvmsg_check_result -> (msghdr) encode ok\r\n") );
- return esock_make_ok2(env, eMsgHdr);
- }
+ recv_update_current_reader(env, descP, sockRef);
+ res = esock_make_ok2(env, eMsgHdr);
}
+
+ return res;
}
@@ -14656,13 +15107,13 @@ ERL_NIF_TERM recvmsg_check_result(ErlNifEnv* env,
*/
extern
-char* encode_msghdr(ErlNifEnv* env,
- SocketDescriptor* descP,
- int read,
- struct msghdr* msgHdrP,
- ErlNifBinary* dataBufP,
- ErlNifBinary* ctrlBufP,
- ERL_NIF_TERM* eSockAddr)
+char* encode_msghdr(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ int read,
+ struct msghdr* msgHdrP,
+ ErlNifBinary* dataBufP,
+ ErlNifBinary* ctrlBufP,
+ ERL_NIF_TERM* eSockAddr)
{
char* xres;
ERL_NIF_TERM addr, iov, ctrl, flags;
@@ -14677,7 +15128,7 @@ char* encode_msghdr(ErlNifEnv* env,
*/
if (msgHdrP->msg_namelen != 0) {
if ((xres = esock_encode_sockaddr(env,
- (SocketAddress*) msgHdrP->msg_name,
+ (ESockAddress*) msgHdrP->msg_name,
msgHdrP->msg_namelen,
&addr)) != NULL)
return xres;
@@ -14705,10 +15156,9 @@ char* encode_msghdr(ErlNifEnv* env,
SSDBG( descP,
("SOCKET", "encode_msghdr -> components encoded:"
"\r\n addr: %T"
- "\r\n iov: %T"
"\r\n ctrl: %T"
"\r\n flags: %T"
- "\r\n", addr, iov, ctrl, flags) );
+ "\r\n", addr, ctrl, flags) );
{
ERL_NIF_TERM keys[] = {esock_atom_addr,
esock_atom_iov,
@@ -14725,9 +15175,7 @@ char* encode_msghdr(ErlNifEnv* env,
if (!MKMA(env, keys, vals, numKeys, &tmp))
return ESOCK_STR_EINVAL;
- SSDBG( descP, ("SOCKET", "encode_msghdr -> msghdr: "
- "\r\n %T"
- "\r\n", tmp) );
+ SSDBG( descP, ("SOCKET", "encode_msghdr -> msghdr encoded\r\n") );
*eSockAddr = tmp;
}
@@ -14761,21 +15209,35 @@ char* encode_msghdr(ErlNifEnv* env,
*/
extern
-char* encode_cmsghdrs(ErlNifEnv* env,
- SocketDescriptor* descP,
- ErlNifBinary* cmsgBinP,
- struct msghdr* msgHdrP,
- ERL_NIF_TERM* eCMsgHdr)
+char* encode_cmsghdrs(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ErlNifBinary* cmsgBinP,
+ struct msghdr* msgHdrP,
+ ERL_NIF_TERM* eCMsgHdr)
{
ERL_NIF_TERM ctrlBuf = MKBIN(env, cmsgBinP); // The *entire* binary
SocketTArray cmsghdrs = TARRAY_CREATE(128);
struct cmsghdr* firstP = CMSG_FIRSTHDR(msgHdrP);
struct cmsghdr* currentP;
- SSDBG( descP, ("SOCKET", "encode_cmsghdrs -> entry\r\n") );
+ SSDBG( descP, ("SOCKET", "encode_cmsghdrs -> entry when"
+ "\r\n msg ctrl len: %d"
+ "\r\n (ctrl) firstP: 0x%lX"
+ "\r\n",
+ msgHdrP->msg_controllen, firstP) );
for (currentP = firstP;
- currentP != NULL;
+ /*
+ * In *old* versions of darwin, the CMSG_FIRSTHDR does not
+ * check the msg_controllen, so we do it here.
+ * We should really test this stuff during configure,
+ * but for now, this will have to do.
+ */
+#if defined(__DARWIN__)
+ (msgHdrP->msg_controllen >= sizeof(struct cmsghdr)) && (currentP != NULL);
+#else
+ (currentP != NULL);
+#endif
currentP = CMSG_NXTHDR(msgHdrP, currentP)) {
SSDBG( descP,
@@ -14788,9 +15250,23 @@ char* encode_cmsghdrs(ErlNifEnv* env,
*/
if (((CHARP(currentP) + currentP->cmsg_len) - CHARP(firstP)) >
msgHdrP->msg_controllen) {
+
/* Ouch, fatal error - give up
* We assume we cannot trust any data if this is wrong.
*/
+
+ SSDBG( descP,
+ ("SOCKET", "encode_cmsghdrs -> check failed when: "
+ "\r\n currentP: 0x%lX"
+ "\r\n (current) cmsg_len: %d"
+ "\r\n firstP: 0x%lX"
+ "\r\n => %d"
+ "\r\n msg ctrl len: %d"
+ "\r\n",
+ CHARP(currentP), currentP->cmsg_len, CHARP(firstP),
+ (CHARP(currentP) + currentP->cmsg_len) - CHARP(firstP),
+ msgHdrP->msg_controllen) );
+
TARRAY_DELETE(cmsghdrs);
return ESOCK_STR_EINVAL;
} else {
@@ -14883,12 +15359,12 @@ char* encode_cmsghdrs(ErlNifEnv* env,
*/
extern
-char* decode_cmsghdrs(ErlNifEnv* env,
- SocketDescriptor* descP,
- ERL_NIF_TERM eCMsgHdr,
- char* cmsgHdrBufP,
- size_t cmsgHdrBufLen,
- size_t* cmsgHdrBufUsed)
+char* decode_cmsghdrs(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eCMsgHdr,
+ char* cmsgHdrBufP,
+ size_t cmsgHdrBufLen,
+ size_t* cmsgHdrBufUsed)
{
ERL_NIF_TERM elem, tail, list;
char* bufP;
@@ -14966,12 +15442,12 @@ char* decode_cmsghdrs(ErlNifEnv* env,
* which means that the data is already coded.
*/
extern
-char* decode_cmsghdr(ErlNifEnv* env,
- SocketDescriptor* descP,
- ERL_NIF_TERM eCMsgHdr,
- char* bufP,
- size_t rem,
- size_t* used)
+char* decode_cmsghdr(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eCMsgHdr,
+ char* bufP,
+ size_t rem,
+ size_t* used)
{
SSDBG( descP, ("SOCKET", "decode_cmsghdr -> entry with"
"\r\n eCMsgHdr: %T"
@@ -15038,14 +15514,14 @@ char* decode_cmsghdr(ErlNifEnv* env,
* an integer and ip_tos() respectively.
*/
static
-char* decode_cmsghdr_data(ErlNifEnv* env,
- SocketDescriptor* descP,
- char* bufP,
- size_t rem,
- int level,
- int type,
- ERL_NIF_TERM eData,
- size_t* used)
+char* decode_cmsghdr_data(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ char* bufP,
+ size_t rem,
+ int level,
+ int type,
+ ERL_NIF_TERM eData,
+ size_t* used)
{
char* xres;
@@ -15137,14 +15613,14 @@ char* decode_cmsghdr_data(ErlNifEnv* env,
* This does the final create of the cmsghdr (including the data copy).
*/
static
-char* decode_cmsghdr_final(SocketDescriptor* descP,
- char* bufP,
- size_t rem,
- int level,
- int type,
- char* data,
- int sz,
- size_t* used)
+char* decode_cmsghdr_final(ESockDescriptor* descP,
+ char* bufP,
+ size_t rem,
+ int level,
+ int type,
+ char* data,
+ int sz,
+ size_t* used)
{
int len = CMSG_LEN(sz);
int space = CMSG_SPACE(sz);
@@ -15823,10 +16299,10 @@ char* encode_cmsghdr_data_ipv6(ErlNifEnv* env,
*/
extern
-char* encode_msghdr_flags(ErlNifEnv* env,
- SocketDescriptor* descP,
- int msgFlags,
- ERL_NIF_TERM* flags)
+char* encode_msghdr_flags(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ int msgFlags,
+ ERL_NIF_TERM* flags)
{
SSDBG( descP,
("SOCKET", "encode_cmsghdrs_flags -> entry with"
@@ -16281,18 +16757,22 @@ ERL_NIF_TERM encode_ip_tos(ErlNifEnv* env, int val)
*
*/
static
-SocketDescriptor* alloc_descriptor(SOCKET sock, HANDLE event)
+ESockDescriptor* alloc_descriptor(SOCKET sock, HANDLE event)
{
- SocketDescriptor* descP;
+ ESockDescriptor* descP;
- if ((descP = enif_alloc_resource(sockets, sizeof(SocketDescriptor))) != NULL) {
+ if ((descP = enif_alloc_resource(sockets, sizeof(ESockDescriptor))) != NULL) {
char buf[64]; /* Buffer used for building the mutex name */
// This needs to be released when the socket is closed!
- descP->env = enif_alloc_env();
+ // descP->env = enif_alloc_env();
- sprintf(buf, "socket[w,%d]", sock);
+ sprintf(buf, "esock[w,%d]", sock);
descP->writeMtx = MCREATE(buf);
+ enif_set_pid_undefined(&descP->currentWriter.pid);
+ MON_INIT(&descP->currentWriter.mon);
+ descP->currentWriter.env = NULL;
+ descP->currentWriter.ref = esock_atom_undefined;
descP->currentWriterP = NULL; // currentWriter not used
descP->writersQ.first = NULL;
descP->writersQ.last = NULL;
@@ -16303,8 +16783,12 @@ SocketDescriptor* alloc_descriptor(SOCKET sock, HANDLE event)
descP->writeWaits = 0;
descP->writeFails = 0;
- sprintf(buf, "socket[r,%d]", sock);
+ sprintf(buf, "esock[r,%d]", sock);
descP->readMtx = MCREATE(buf);
+ enif_set_pid_undefined(&descP->currentReader.pid);
+ MON_INIT(&descP->currentReader.mon);
+ descP->currentReader.env = NULL;
+ descP->currentReader.ref = esock_atom_undefined;
descP->currentReaderP = NULL; // currentReader not used
descP->readersQ.first = NULL;
descP->readersQ.last = NULL;
@@ -16314,17 +16798,25 @@ SocketDescriptor* alloc_descriptor(SOCKET sock, HANDLE event)
descP->readTries = 0;
descP->readWaits = 0;
- sprintf(buf, "socket[acc,%d]", sock);
+ sprintf(buf, "esock[acc,%d]", sock);
descP->accMtx = MCREATE(buf);
+ enif_set_pid_undefined(&descP->currentAcceptor.pid);
+ MON_INIT(&descP->currentAcceptor.mon);
+ descP->currentAcceptor.env = NULL;
+ descP->currentAcceptor.ref = esock_atom_undefined;
descP->currentAcceptorP = NULL; // currentAcceptor not used
descP->acceptorsQ.first = NULL;
descP->acceptorsQ.last = NULL;
- sprintf(buf, "socket[close,%d]", sock);
+ sprintf(buf, "esock[close,%d]", sock);
descP->closeMtx = MCREATE(buf);
descP->closeEnv = NULL;
descP->closeRef = esock_atom_undefined;
+ enif_set_pid_undefined(&descP->closerPid);
+ MON_INIT(&descP->closerMon);
+ sprintf(buf, "esock[cfg,%d]", sock);
+ descP->cfgMtx = MCREATE(buf);
descP->rBufSz = SOCKET_RECV_BUFFER_SIZE_DEFAULT;
descP->rNum = 0;
descP->rNumCnt = 0;
@@ -16336,11 +16828,9 @@ SocketDescriptor* alloc_descriptor(SOCKET sock, HANDLE event)
descP->sock = sock;
descP->event = event;
- MON_INIT(&descP->currentWriter.mon);
- MON_INIT(&descP->currentReader.mon);
- MON_INIT(&descP->currentAcceptor.mon);
+ enif_set_pid_undefined(&descP->ctrlPid);
MON_INIT(&descP->ctrlMon);
- MON_INIT(&descP->closerMon);
+
}
return descP;
@@ -16851,176 +17341,226 @@ size_t my_strnlen(const char *s, size_t maxlen)
#endif
-/* Send an error closed message to the specified process:
+/* Send an close message to the specified process:
+ * A message in the form:
*
- * This message is for processes that are waiting in the
- * erlang API functions for a select message.
+ * {'$socket', Socket, close, CloseRef}
+ *
+ * This message is for processes that is waiting in the
+ * erlang API (close-) function for the socket to be "closed"
+ * (actually that the 'stop' callback function has been called).
*/
-/*
static
-char* send_msg_error_closed(ErlNifEnv* env,
- ErlNifPid* pid)
+char* esock_send_close_msg(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ErlNifPid* pid)
{
- return send_msg_error(env, atom_closed, pid);
+ ERL_NIF_TERM sockRef, msg;
+ ErlNifEnv* menv;
+
+ if (descP->closeEnv != NULL) {
+ sockRef = enif_make_resource(descP->closeEnv, descP);
+ msg = mk_close_msg(descP->closeEnv, sockRef, descP->closeRef);
+ menv = descP->closeEnv;
+ } else {
+ sockRef = enif_make_resource(env, descP);
+ msg = mk_close_msg(env, sockRef, descP->closeRef);
+ menv = NULL; // This has the effect that the message will be copied
+ }
+
+ return esock_send_msg(env, pid, msg, menv);
}
-*/
-/* Send an error message to the specified process:
+
+/* Send an abort message to the specified process:
* A message in the form:
*
- * {error, Reason}
+ * {'$socket', Socket, abort, {RecvRef, Reason}}
*
- * This message is for processes that are waiting in the
+ * This message is for processes that is waiting in the
* erlang API functions for a select message.
*/
-/*
static
-char* send_msg_error(ErlNifEnv* env,
- ERL_NIF_TERM reason,
- ErlNifPid* pid)
+char* esock_send_abort_msg(ErlNifEnv* env,
+ ERL_NIF_TERM sockRef,
+ ERL_NIF_TERM opRef,
+ ErlNifEnv* msgEnv,
+ ERL_NIF_TERM reason,
+ ErlNifPid* pid)
{
- ERL_NIF_TERM msg = enif_make_tuple2(env, atom_error, reason);
+ ERL_NIF_TERM msg = mk_abort_msg(msgEnv,
+ /* sockRef not in msgEnv so copy */
+ CP_TERM(msgEnv, sockRef),
+ opRef, reason);
- return send_msg(env, msg, pid);
+ return esock_send_msg(env, pid, msg, msgEnv);
}
-*/
-/* Send an close message to the specified process:
- * A message in the form:
+/* Send a message to the specified process.
+ */
+static
+char* esock_send_msg(ErlNifEnv* env,
+ ErlNifPid* pid,
+ ERL_NIF_TERM msg,
+ ErlNifEnv* msgEnv)
+{
+ int res = enif_send(env, pid, msgEnv, msg);
+ if (msgEnv)
+ esock_free_env("esock_msg_send - msg-env", msgEnv);
+
+ if (!res)
+ return str_exsend;
+ else
+ return NULL;
+}
+
+
+
+/* *** mk_abort_msg ***
*
- * {'$socket', SockRef, close, CloseRef}
+ * Create the abort message, which has the following form:
*
- * This message is for processes that is waiting in the
- * erlang API (close-) function for the socket to be "closed"
- * (actually that the 'stop' callback function has been called).
+ * {'$socket', Socket, abort, {OpRef, Reason}}
+ *
+ * This message is for processes that are waiting in the
+ * erlang API functions for a select (or this) message.
*/
static
-char* esock_send_close_msg(ErlNifEnv* env,
- SocketDescriptor* descP,
- ERL_NIF_TERM sockRef)
+ERL_NIF_TERM mk_abort_msg(ErlNifEnv* env,
+ ERL_NIF_TERM sockRef,
+ ERL_NIF_TERM opRef,
+ ERL_NIF_TERM reason)
{
- ERL_NIF_TERM sr = ((descP->closeEnv != NULL) ?
- enif_make_copy(descP->closeEnv, sockRef) :
- sockRef);
- char* res = esock_send_socket_msg(env,
- sr,
- esock_atom_close,
- descP->closeRef,
- &descP->closerPid,
- descP->closeEnv);
+ ERL_NIF_TERM info = MKT2(env, opRef, reason);
+
+ return mk_socket_msg(env, sockRef, esock_atom_abort, info);
+}
- descP->closeEnv = NULL;
- return res;
+/* *** mk_close_msg ***
+ *
+ * Construct a close (socket) message. It has the form:
+ *
+ * {'$socket', Socket, close, closeRef}
+ *
+ */
+static
+ERL_NIF_TERM mk_close_msg(ErlNifEnv* env,
+ ERL_NIF_TERM sockRef,
+ ERL_NIF_TERM closeRef)
+{
+ return mk_socket_msg(env, sockRef, esock_atom_close, closeRef);
}
-/* Send an abort message to the specified process:
- * A message in the form:
+/* *** mk_select_msg ***
*
- * {'$socket', SockRef, abort, {RecvRef, Reason}}
+ * Construct a select (socket) message. It has the form:
+ *
+ * {'$socket', Socket, select, selectRef}
*
- * This message is for processes that is waiting in the
- * erlang API functions for a select message.
*/
static
-char* esock_send_abort_msg(ErlNifEnv* env,
+ERL_NIF_TERM mk_select_msg(ErlNifEnv* env,
ERL_NIF_TERM sockRef,
- ERL_NIF_TERM recvRef,
- ERL_NIF_TERM reason,
- ErlNifPid* pid)
+ ERL_NIF_TERM selectRef)
{
- ErlNifEnv* msg_env = enif_alloc_env();
- ERL_NIF_TERM info = MKT2(msg_env,
- enif_make_copy(msg_env, recvRef),
- enif_make_copy(msg_env, reason));
-
- return esock_send_socket_msg(env, sockRef, esock_atom_abort, info, pid,
- msg_env);
+ return mk_socket_msg(env, sockRef, atom_select, selectRef);
}
-/* *** esock_send_socket_msg ***
- *
- * This function sends a general purpose socket message to an erlang
- * process. A general 'socket' message has the ("erlang") form:
+/* *** mk_socket_msg ***
*
- * {'$socket', SockRef, Tag, Info}
+ * Construct the socket message:
*
- * Where
+ * {'$socket', Socket, Tag, Info}
*
- * SockRef: reference()
- * Tag: atom()
- * Info: term()
+ * Socket :: socket() (#socket{})
+ * Tag :: atom()
+ * Info :: term()
*
*/
-
static
-char* esock_send_socket_msg(ErlNifEnv* env,
- ERL_NIF_TERM sockRef,
- ERL_NIF_TERM tag,
- ERL_NIF_TERM info,
- ErlNifPid* pid,
- ErlNifEnv* msg_env)
-{
- ERL_NIF_TERM msg;
- if (!msg_env) {
- msg_env = enif_alloc_env();
- sockRef = enif_make_copy(msg_env, sockRef);
- tag = enif_make_copy(msg_env, tag);
- info = enif_make_copy(msg_env, info);
- }
- msg = MKT4(msg_env, esock_atom_socket_tag, sockRef, tag, info);
+ERL_NIF_TERM mk_socket_msg(ErlNifEnv* env,
+ ERL_NIF_TERM sockRef,
+ ERL_NIF_TERM tag,
+ ERL_NIF_TERM info)
+{
+ ERL_NIF_TERM socket = mk_socket(env, sockRef);
- return esock_send_msg(env, msg, pid, msg_env);
+ return MKT4(env, esock_atom_socket_tag, socket, tag, info);
}
-/* Send a message to the specified process.
+/* *** mk_socket ***
+ *
+ * Simple utility function that construct the socket resord:
+ *
+ * #socket{ref = SockRef} => {socket, SockRef :: reference()}
*/
static
-char* esock_send_msg(ErlNifEnv* env,
- ERL_NIF_TERM msg,
- ErlNifPid* pid,
- ErlNifEnv* msg_env)
+ERL_NIF_TERM mk_socket(ErlNifEnv* env,
+ ERL_NIF_TERM sockRef)
{
- int res = enif_send(env, pid, msg_env, msg);
- if (msg_env)
- enif_free_env(msg_env);
-
- if (!res)
- return str_exsend;
- else
- return NULL;
+ return MKT2(env, esock_atom_socket, sockRef);
}
-#endif // #if defined(__WIN32__)
+#endif // #if defined(__WIN32__)
+
/* ----------------------------------------------------------------------
* S e l e c t W r a p p e r F u n c t i o n s
* ----------------------------------------------------------------------
*/
+/* *** esock_select_read ***
+ *
+ * Perform a read select. When the select is triggered, a 'select'
+ * message (see mk_select_msg) will be sent.
+ *
+ * There are two ways to handle the select message:
+ * 1) Create "your own" environment and create the message using it
+ * and then pass it on to the select function.
+ * 2) Or, to create the message using any available environment,
+ * and then pass a NULL pointer to the select function.
+ * This will have the effect that the select function will
+ * create its own environment and then copy the message to it.
+ * We choose the second alternative.
+ */
static
int esock_select_read(ErlNifEnv* env,
- ErlNifEvent event,
- void* obj,
- const ErlNifPid* pid,
- ERL_NIF_TERM ref)
+ ErlNifEvent event, // The file descriptor
+ void* obj, // The socket descriptor object
+ const ErlNifPid* pid, // Destination
+ ERL_NIF_TERM sockRef, // Socket
+ ERL_NIF_TERM selectRef) // "ID" of the operation
{
- return enif_select(env, event, (ERL_NIF_SELECT_READ), obj, pid, ref);
+ ERL_NIF_TERM selectMsg = mk_select_msg(env, sockRef, selectRef);
+
+ return enif_select_read(env, event, obj, pid, selectMsg, NULL);
+
}
+/* *** esock_select_write ***
+ *
+ * Perform a write select. When the select is triggered, a 'select'
+ * message (see mk_select_msg) will be sent.
+ * The sockRef is copied to the msgEnv when the socket message is created,
+ * so no need to do that here, but the selectRef needs to be copied.
+ */
static
int esock_select_write(ErlNifEnv* env,
- ErlNifEvent event,
- void* obj,
- const ErlNifPid* pid,
- ERL_NIF_TERM ref)
+ ErlNifEvent event, // The file descriptor
+ void* obj, // The socket descriptor
+ const ErlNifPid* pid, // Destination
+ ERL_NIF_TERM sockRef, // Socket
+ ERL_NIF_TERM selectRef) // "ID" of the operation
{
- return enif_select(env, event, (ERL_NIF_SELECT_WRITE), obj, pid, ref);
+ ERL_NIF_TERM selectMsg = mk_select_msg(env, sockRef, selectRef);
+
+ return enif_select_write(env, event, obj, pid, selectMsg, NULL);
}
@@ -17058,6 +17598,8 @@ int esock_select_cancel(ErlNifEnv* env,
* Return value indicates if a new requestor was activated or not.
*/
+#if !defined(__WIN32__)
+
#define ACTIVATE_NEXT_FUNCS \
ACTIVATE_NEXT_FUNC_DECL(acceptor, read, currentAcceptor, acceptorsQ) \
ACTIVATE_NEXT_FUNC_DECL(writer, write, currentWriter, writersQ) \
@@ -17065,14 +17607,15 @@ int esock_select_cancel(ErlNifEnv* env,
#define ACTIVATE_NEXT_FUNC_DECL(F, S, R, Q) \
static \
- BOOLEAN_T activate_next_##F(ErlNifEnv* env, \
- SocketDescriptor* descP, \
- ERL_NIF_TERM sockRef) \
+ BOOLEAN_T activate_next_##F(ErlNifEnv* env, \
+ ESockDescriptor* descP, \
+ ERL_NIF_TERM sockRef) \
{ \
- BOOLEAN_T popped, activated; \
- int sres; \
- SocketRequestor* reqP = &descP->R; \
- SocketRequestQueue* q = &descP->Q; \
+ BOOLEAN_T popped, activated; \
+ int sres; \
+ ERL_NIF_TERM reason; \
+ ESockRequestor* reqP = &descP->R; \
+ ESockRequestQueue* q = &descP->Q; \
\
popped = FALSE; \
do { \
@@ -17088,15 +17631,22 @@ int esock_select_cancel(ErlNifEnv* env,
"\r\n ref: %T" \
"\r\n", reqP->pid, reqP->ref) ); \
\
+ /* We need to copy req ref to 'env' */ \
if ((sres = esock_select_##S(env, descP->sock, descP, \
- &reqP->pid, reqP->ref)) < 0) { \
+ &reqP->pid, sockRef, \
+ CP_TERM(env, reqP->ref))) < 0) { \
+ \
/* We need to inform this process, reqP->pid, */ \
/* that we failed to select, so we don't leave */ \
/* it hanging. */ \
/* => send abort */ \
\
- esock_send_abort_msg(env, sockRef, reqP->ref, \
- sres, &reqP->pid); \
+ reason = MKT2(env, \
+ esock_atom_select_failed, \
+ MKI(env, sres)); \
+ esock_send_abort_msg(env, sockRef, \
+ reqP->ref, reqP->env, \
+ reason, &reqP->pid); \
\
} else { \
\
@@ -17128,6 +17678,7 @@ ACTIVATE_NEXT_FUNCS
#undef ACTIVATE_NEXT_FUNC_DECL
+#endif // if !defined(__WIN32__)
/* ----------------------------------------------------------------------
@@ -17154,13 +17705,13 @@ ACTIVATE_NEXT_FUNCS
REQ_SEARCH4PID_FUNC_DECL(writer, writersQ) \
REQ_SEARCH4PID_FUNC_DECL(reader, readersQ)
-#define REQ_SEARCH4PID_FUNC_DECL(F, Q) \
- static \
- BOOLEAN_T F##_search4pid(ErlNifEnv* env, \
- SocketDescriptor* descP, \
- ErlNifPid* pid) \
- { \
- return qsearch4pid(env, &descP->Q, pid); \
+#define REQ_SEARCH4PID_FUNC_DECL(F, Q) \
+ static \
+ BOOLEAN_T F##_search4pid(ErlNifEnv* env, \
+ ESockDescriptor* descP, \
+ ErlNifPid* pid) \
+ { \
+ return qsearch4pid(env, &descP->Q, pid); \
}
REQ_SEARCH4PID_FUNCS
#undef REQ_SEARCH4PID_FUNC_DECL
@@ -17181,28 +17732,28 @@ REQ_SEARCH4PID_FUNCS
REQ_PUSH_FUNC_DECL(writer, writersQ) \
REQ_PUSH_FUNC_DECL(reader, readersQ)
-#define REQ_PUSH_FUNC_DECL(F, Q) \
- static \
- ERL_NIF_TERM F##_push(ErlNifEnv* env, \
- SocketDescriptor* descP, \
- ErlNifPid pid, \
- ERL_NIF_TERM ref) \
- { \
- SocketRequestQueueElement* e = MALLOC(sizeof(SocketRequestQueueElement)); \
- SocketRequestor* reqP = &e->data; \
- \
- reqP->pid = pid; \
- reqP->ref = enif_make_copy(descP->env, ref); \
- \
- if (MONP("reader_push -> " #F " request", \
- env, descP, &pid, &reqP->mon) != 0) { \
- FREE(reqP); \
- return esock_make_error(env, atom_exmon); \
- } \
- \
- qpush(&descP->Q, e); \
- \
- return esock_make_error(env, esock_atom_eagain); \
+#define REQ_PUSH_FUNC_DECL(F, Q) \
+ static \
+ ERL_NIF_TERM F##_push(ErlNifEnv* env, \
+ ESockDescriptor* descP, \
+ ErlNifPid pid, \
+ ERL_NIF_TERM ref) \
+ { \
+ ESockRequestQueueElement* e = MALLOC(sizeof(ESockRequestQueueElement)); \
+ ESockRequestor* reqP = &e->data; \
+ \
+ reqP->pid = pid; \
+ if (MONP("reader_push -> " #F " request", \
+ env, descP, &pid, &reqP->mon) != 0) { \
+ FREE(reqP); \
+ return esock_make_error(env, atom_exmon); \
+ } \
+ reqP->env = esock_alloc_env(#F "_push"); \
+ reqP->ref = enif_make_copy(reqP->env, ref); \
+ \
+ qpush(&descP->Q, e); \
+ \
+ return esock_make_error(env, esock_atom_eagain); \
}
REQ_PUSH_FUNCS
#undef REQ_PUSH_FUNC_DECL
@@ -17221,13 +17772,13 @@ REQ_PUSH_FUNCS
REQ_POP_FUNC_DECL(writer, writersQ) \
REQ_POP_FUNC_DECL(reader, readersQ)
-#define REQ_POP_FUNC_DECL(F, Q) \
- static \
- BOOLEAN_T F##_pop(ErlNifEnv* env, \
- SocketDescriptor* descP, \
- SocketRequestor* reqP) \
- { \
- return requestor_pop(&descP->Q, reqP); \
+#define REQ_POP_FUNC_DECL(F, Q) \
+ static \
+ BOOLEAN_T F##_pop(ErlNifEnv* env, \
+ ESockDescriptor* descP, \
+ ESockRequestor* reqP) \
+ { \
+ return requestor_pop(&descP->Q, reqP); \
}
REQ_POP_FUNCS
#undef REQ_POP_FUNC_DECL
@@ -17247,14 +17798,14 @@ REQ_POP_FUNCS
REQ_UNQUEUE_FUNC_DECL(writer, writersQ) \
REQ_UNQUEUE_FUNC_DECL(reader, readersQ)
-#define REQ_UNQUEUE_FUNC_DECL(F, Q) \
- static \
- BOOLEAN_T F##_unqueue(ErlNifEnv* env, \
- SocketDescriptor* descP, \
- const ErlNifPid* pid) \
- { \
- return qunqueue(env, descP, "qunqueue -> waiting " #F, \
- &descP->Q, pid); \
+#define REQ_UNQUEUE_FUNC_DECL(F, Q) \
+ static \
+ BOOLEAN_T F##_unqueue(ErlNifEnv* env, \
+ ESockDescriptor* descP, \
+ const ErlNifPid* pid) \
+ { \
+ return qunqueue(env, descP, "qunqueue -> waiting " #F, \
+ &descP->Q, pid); \
}
REQ_UNQUEUE_FUNCS
#undef REQ_UNQUEUE_FUNC_DECL
@@ -17266,21 +17817,23 @@ REQ_UNQUEUE_FUNCS
* Pop an requestor from its queue.
*/
static
-BOOLEAN_T requestor_pop(SocketRequestQueue* q,
- SocketRequestor* reqP)
+BOOLEAN_T requestor_pop(ESockRequestQueue* q,
+ ESockRequestor* reqP)
{
- SocketRequestQueueElement* e = qpop(q);
+ ESockRequestQueueElement* e = qpop(q);
if (e != NULL) {
reqP->pid = e->data.pid;
reqP->mon = e->data.mon;
+ reqP->env = e->data.env;
reqP->ref = e->data.ref;
FREE(e);
return TRUE;
} else {
- /* (writers) Queue was empty */
+ /* Queue was empty */
enif_set_pid_undefined(&reqP->pid);
- // *reqP->mon = NULL; we have no null value for monitors
+ MON_INIT(&reqP->mon);
+ reqP->env = NULL;
reqP->ref = esock_atom_undefined; // Just in case
return FALSE;
}
@@ -17289,11 +17842,11 @@ BOOLEAN_T requestor_pop(SocketRequestQueue* q,
static
-BOOLEAN_T qsearch4pid(ErlNifEnv* env,
- SocketRequestQueue* q,
- ErlNifPid* pid)
+BOOLEAN_T qsearch4pid(ErlNifEnv* env,
+ ESockRequestQueue* q,
+ ErlNifPid* pid)
{
- SocketRequestQueueElement* tmp = q->first;
+ ESockRequestQueueElement* tmp = q->first;
while (tmp != NULL) {
if (COMPARE_PIDS(&tmp->data.pid, pid) == 0)
@@ -17307,8 +17860,8 @@ BOOLEAN_T qsearch4pid(ErlNifEnv* env,
static
-void qpush(SocketRequestQueue* q,
- SocketRequestQueueElement* e)
+void qpush(ESockRequestQueue* q,
+ ESockRequestQueueElement* e)
{
if (q->first != NULL) {
q->last->nextP = e;
@@ -17323,9 +17876,9 @@ void qpush(SocketRequestQueue* q,
static
-SocketRequestQueueElement* qpop(SocketRequestQueue* q)
+ESockRequestQueueElement* qpop(ESockRequestQueue* q)
{
- SocketRequestQueueElement* e = q->first;
+ ESockRequestQueueElement* e = q->first;
if (e != NULL) {
/* Atleast one element in the queue */
@@ -17344,14 +17897,14 @@ SocketRequestQueueElement* qpop(SocketRequestQueue* q)
static
-BOOLEAN_T qunqueue(ErlNifEnv* env,
- SocketDescriptor* descP,
- const char* slogan,
- SocketRequestQueue* q,
- const ErlNifPid* pid)
+BOOLEAN_T qunqueue(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ const char* slogan,
+ ESockRequestQueue* q,
+ const ErlNifPid* pid)
{
- SocketRequestQueueElement* e = q->first;
- SocketRequestQueueElement* p = NULL;
+ ESockRequestQueueElement* e = q->first;
+ ESockRequestQueueElement* p = NULL;
/* Check if it was one of the waiting acceptor processes */
while (e != NULL) {
@@ -17446,11 +17999,11 @@ void cnt_dec(Uint32* cnt, Uint32 dec)
#if !defined(__WIN32__)
static
-int esock_monitor(const char* slogan,
- ErlNifEnv* env,
- SocketDescriptor* descP,
- const ErlNifPid* pid,
- ESockMonitor* monP)
+int esock_monitor(const char* slogan,
+ ErlNifEnv* env,
+ ESockDescriptor* descP,
+ const ErlNifPid* pid,
+ ESockMonitor* monP)
{
int res;
@@ -17458,10 +18011,10 @@ int esock_monitor(const char* slogan,
res = enif_monitor_process(env, descP, pid, &monP->mon);
if (res != 0) {
- monP->is_active = 0;
+ monP->isActive = FALSE;
SSDBG( descP, ("SOCKET", "[%d] monitor failed: %d\r\n", descP->sock, res) );
} else {
- monP->is_active = 1;
+ monP->isActive = TRUE;
}
return res;
@@ -17469,14 +18022,14 @@ int esock_monitor(const char* slogan,
static
-int esock_demonitor(const char* slogan,
- ErlNifEnv* env,
- SocketDescriptor* descP,
- ESockMonitor* monP)
+int esock_demonitor(const char* slogan,
+ ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ESockMonitor* monP)
{
int res;
- if (!monP->is_active)
+ if (!monP->isActive)
return 1;
SSDBG( descP, ("SOCKET", "[%d] %s: try demonitor\r\n", descP->sock, slogan) );
@@ -17497,20 +18050,23 @@ int esock_demonitor(const char* slogan,
static
void esock_monitor_init(ESockMonitor* monP)
{
- monP->is_active = 0;
+ monP->isActive = FALSE;
}
-#endif // if !defined(__WIN32__)
-
-/*
static
-int esock_monitor_compare(const ErlNifMonitor* mon1,
- const ESockMonitor* mon2)
+ERL_NIF_TERM esock_make_monitor_term(ErlNifEnv* env, const ESockMonitor* monP)
{
- return enif_compare_monitors(mon1, &mon2->mon);
+ if (monP->isActive)
+ return enif_make_monitor_term(env, &monP->mon);
+ else
+ return esock_atom_undefined;
}
-*/
+
+
+
+#endif // if !defined(__WIN32__)
+
/* ----------------------------------------------------------------------
@@ -17526,16 +18082,13 @@ static
void socket_dtor(ErlNifEnv* env, void* obj)
{
#if !defined(__WIN32__)
- SocketDescriptor* descP = (SocketDescriptor*) obj;
-
- enif_clear_env(descP->env);
- enif_free_env(descP->env);
- descP->env = NULL;
+ ESockDescriptor* descP = (ESockDescriptor*) obj;
MDESTROY(descP->writeMtx);
MDESTROY(descP->readMtx);
MDESTROY(descP->accMtx);
MDESTROY(descP->closeMtx);
+ MDESTROY(descP->cfgMtx);
#endif
}
@@ -17559,8 +18112,8 @@ static
void socket_stop(ErlNifEnv* env, void* obj, int fd, int is_direct_call)
{
#if !defined(__WIN32__)
- SocketDescriptor* descP = (SocketDescriptor*) obj;
- ERL_NIF_TERM sockRef;
+ ESockDescriptor* descP = (ESockDescriptor*) obj;
+ ERL_NIF_TERM sockRef;
SSDBG( descP,
("SOCKET", "socket_stop -> entry when %s"
@@ -17573,6 +18126,7 @@ void socket_stop(ErlNifEnv* env, void* obj, int fd, int is_direct_call)
MLOCK(descP->writeMtx);
MLOCK(descP->readMtx);
MLOCK(descP->accMtx);
+ MLOCK(descP->cfgMtx);
if (!is_direct_call) MLOCK(descP->closeMtx);
SSDBG( descP, ("SOCKET", "socket_stop -> "
@@ -17622,37 +18176,19 @@ void socket_stop(ErlNifEnv* env, void* obj, int fd, int is_direct_call)
*/
if (descP->currentWriterP != NULL) {
+
/* We have a (current) writer and *may* therefor also have
* writers waiting.
*/
- DEMONP("socket_stop -> current writer",
- env, descP, &descP->currentWriter.mon);
+ socket_stop_handle_current(env,
+ "writer",
+ descP, sockRef, &descP->currentWriter);
- SSDBG( descP, ("SOCKET", "socket_stop -> handle current writer\r\n") );
- if (COMPARE_PIDS(&descP->closerPid, &descP->currentWriter.pid) != 0) {
- SSDBG( descP, ("SOCKET", "socket_stop -> "
- "send abort message to current writer %T\r\n",
- descP->currentWriter.pid) );
- if (esock_send_abort_msg(env,
- sockRef,
- descP->currentWriter.ref,
- atom_closed,
- &descP->currentWriter.pid) != NULL) {
- /* Shall we really do this?
- * This happens if the controlling process has been killed!
- */
- esock_warning_msg("Failed sending abort (%T) message to "
- "current writer %T\r\n",
- descP->currentWriter.ref,
- descP->currentWriter.pid);
- }
- }
-
/* And also deal with the waiting writers (in the same way) */
SSDBG( descP, ("SOCKET", "socket_stop -> handle waiting writer(s)\r\n") );
inform_waiting_procs(env, "writer",
- descP, &descP->writersQ, TRUE, atom_closed);
+ descP, sockRef, &descP->writersQ, TRUE, atom_closed);
}
@@ -17669,38 +18205,14 @@ void socket_stop(ErlNifEnv* env, void* obj, int fd, int is_direct_call)
* readers waiting.
*/
- DEMONP("socket_stop -> current reader",
- env, descP, &descP->currentReader.mon);
+ socket_stop_handle_current(env,
+ "reader",
+ descP, sockRef, &descP->currentReader);
- SSDBG( descP, ("SOCKET", "socket_stop -> handle current reader\r\n") );
- if (COMPARE_PIDS(&descP->closerPid, &descP->currentReader.pid) != 0) {
- SSDBG( descP, ("SOCKET", "socket_stop -> "
- "send abort message to current reader %T\r\n",
- descP->currentReader.pid) );
- /*
- esock_dbg_printf("SOCKET", "socket_stop -> "
- "send abort message to current reader %T\r\n",
- descP->currentReader.pid);
- */
- if (esock_send_abort_msg(env,
- sockRef,
- descP->currentReader.ref,
- atom_closed,
- &descP->currentReader.pid) != NULL) {
- /* Shall we really do this?
- * This happens if the controlling process has been killed!
- */
- esock_warning_msg("Failed sending abort (%T) message to "
- "current reader %T\r\n",
- descP->currentReader.ref,
- descP->currentReader.pid);
- }
- }
-
/* And also deal with the waiting readers (in the same way) */
SSDBG( descP, ("SOCKET", "socket_stop -> handle waiting reader(s)\r\n") );
inform_waiting_procs(env, "reader",
- descP, &descP->readersQ, TRUE, atom_closed);
+ descP, sockRef, &descP->readersQ, TRUE, atom_closed);
}
@@ -17713,37 +18225,19 @@ void socket_stop(ErlNifEnv* env, void* obj, int fd, int is_direct_call)
*/
if (descP->currentAcceptorP != NULL) {
+
/* We have a (current) acceptor and *may* therefor also have
* acceptors waiting.
*/
-
- DEMONP("socket_stop -> current acceptor",
- env, descP, &descP->currentAcceptor.mon);
-
- SSDBG( descP, ("SOCKET", "socket_stop -> handle current acceptor\r\n") );
- if (COMPARE_PIDS(&descP->closerPid, &descP->currentAcceptor.pid) != 0) {
- SSDBG( descP, ("SOCKET", "socket_stop -> "
- "send abort message to current acceptor %T\r\n",
- descP->currentAcceptor.pid) );
- if (esock_send_abort_msg(env,
- sockRef,
- descP->currentAcceptor.ref,
- atom_closed,
- &descP->currentAcceptor.pid) != NULL) {
- /* Shall we really do this?
- * This happens if the controlling process has been killed!
- */
- esock_warning_msg("Failed sending abort (%T) message to "
- "current acceptor %T\r\n",
- descP->currentAcceptor.ref,
- descP->currentAcceptor.pid);
- }
- }
-
+
+ socket_stop_handle_current(env,
+ "acceptor",
+ descP, sockRef, &descP->currentAcceptor);
+
/* And also deal with the waiting acceptors (in the same way) */
SSDBG( descP, ("SOCKET", "socket_stop -> handle waiting acceptor(s)\r\n") );
inform_waiting_procs(env, "acceptor",
- descP, &descP->acceptorsQ, TRUE, atom_closed);
+ descP, sockRef, &descP->acceptorsQ, TRUE, atom_closed);
}
@@ -17756,15 +18250,15 @@ void socket_stop(ErlNifEnv* env, void* obj, int fd, int is_direct_call)
*/
if (descP->sock != INVALID_SOCKET) {
-
+
if (descP->closeLocal) {
if (!is_direct_call) {
/* +++ send close message to the waiting process +++ */
- esock_send_close_msg(env, descP, sockRef);
-
+ esock_send_close_msg(env, descP, &descP->closerPid);
+
DEMONP("socket_stop -> closer", env, descP, &descP->closerMon);
} else {
@@ -17773,11 +18267,8 @@ void socket_stop(ErlNifEnv* env, void* obj, int fd, int is_direct_call)
* since the message send takes care of it if scheduled.
*/
- if (descP->closeEnv != NULL) {
- enif_clear_env(descP->closeEnv);
- enif_free_env(descP->closeEnv);
- descP->closeEnv = NULL;
- }
+ if (descP->closeEnv != NULL)
+ esock_free_env("socket_stop - close-env", descP->closeEnv);
}
}
@@ -17787,6 +18278,7 @@ void socket_stop(ErlNifEnv* env, void* obj, int fd, int is_direct_call)
SSDBG( descP, ("SOCKET", "socket_stop -> unlock all mutex(s)\r\n") );
if (!is_direct_call) MUNLOCK(descP->closeMtx);
+ MUNLOCK(descP->cfgMtx);
MUNLOCK(descP->accMtx);
MUNLOCK(descP->readMtx);
MUNLOCK(descP->writeMtx);
@@ -17799,29 +18291,60 @@ void socket_stop(ErlNifEnv* env, void* obj, int fd, int is_direct_call)
+/* *** socket_stop_handle_current ***
+ *
+ * Handle current requestor (reader, writer or acceptor) during
+ * socket stop.
+ */
+#if !defined(__WIN32__)
+static
+void socket_stop_handle_current(ErlNifEnv* env,
+ const char* role,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM sockRef,
+ ESockRequestor* reqP)
+{
+ SSDBG( descP, ("SOCKET", "socket_stop -> handle current %s\r\n", role) );
+
+ DEMONP("socket_stop_handle_current", env, descP, &reqP->mon);
+
+ if (COMPARE_PIDS(&descP->closerPid, &reqP->pid) != 0) {
+
+ SSDBG( descP, ("SOCKET", "socket_stop_handle_current -> "
+ "send abort message to current %s %T\r\n",
+ role, reqP->pid) );
+
+ if (esock_send_abort_msg(env, sockRef, reqP->ref, reqP->env,
+ atom_closed, &reqP->pid) != NULL) {
+
+ esock_warning_msg("Failed sending abort (%T) message to "
+ "current %s %T\r\n",
+ reqP->ref, role, reqP->pid);
+ }
+ }
+}
+
+
+
/* This function traverse the queue and sends the specified
* nif_abort message with the specified reason to each member,
* and if the 'free' argument is TRUE, the queue will be emptied.
*/
-#if !defined(__WIN32__)
-static void inform_waiting_procs(ErlNifEnv* env,
- char* role,
- SocketDescriptor* descP,
- SocketRequestQueue* q,
- BOOLEAN_T free,
- ERL_NIF_TERM reason)
+static
+void inform_waiting_procs(ErlNifEnv* env,
+ const char* role,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM sockRef,
+ ESockRequestQueue* q,
+ BOOLEAN_T free,
+ ERL_NIF_TERM reason)
{
- SocketRequestQueueElement* currentP = q->first;
- SocketRequestQueueElement* nextP;
- ERL_NIF_TERM sockRef = enif_make_resource(env, descP);
+ ESockRequestQueueElement* currentP = q->first;
+ ESockRequestQueueElement* nextP;
- /*
- esock_dbg_printf("SOCKET", "inform_waiting_procs -> entry with: "
- "\r\n role: %s"
- "\r\n free: %s"
- "\r\n reason: %T"
- "\r\n", role, B2S(free), reason);
- */
+ SSDBG( descP,
+ ("SOCKET",
+ "inform_waiting_procs -> handle waiting %s(s)\r\n", role) );
while (currentP != NULL) {
@@ -17835,18 +18358,14 @@ static void inform_waiting_procs(ErlNifEnv* env,
*/
SSDBG( descP,
- ("SOCKET", "inform_waiting_procs -> abort request %T (from %T)\r\n",
+ ("SOCKET",
+ "inform_waiting_procs -> abort request %T (from %T)\r\n",
currentP->data.ref, currentP->data.pid) );
- /*
- esock_dbg_printf("SOCKET", "inform_waiting_procs -> "
- "try sending abort to %s %T "
- "\r\n", role, currentP->data.pid);
- */
-
if (esock_send_abort_msg(env,
sockRef,
currentP->data.ref,
+ currentP->data.env,
reason,
&currentP->data.pid) != NULL) {
@@ -17884,9 +18403,9 @@ void socket_down(ErlNifEnv* env,
const ErlNifMonitor* mon)
{
#if !defined(__WIN32__)
- SocketDescriptor* descP = (SocketDescriptor*) obj;
- int sres;
- ERL_NIF_TERM sockRef;
+ ESockDescriptor* descP = (ESockDescriptor*) obj;
+ int sres;
+ ERL_NIF_TERM sockRef;
SSDBG( descP, ("SOCKET", "socket_down -> entry with"
"\r\n sock: %d"
@@ -17912,7 +18431,7 @@ void socket_down(ErlNifEnv* env,
descP->closeLocal = TRUE;
descP->closerPid = *pid;
MON_INIT(&descP->closerMon);
-
+
sres = esock_select_stop(env, descP->sock, descP);
if (sres & ERL_NIF_SELECT_STOP_CALLED) {
@@ -18035,10 +18554,10 @@ void socket_down(ErlNifEnv* env,
*/
#if !defined(__WIN32__)
static
-void socket_down_acceptor(ErlNifEnv* env,
- SocketDescriptor* descP,
- ERL_NIF_TERM sockRef,
- const ErlNifPid* pid)
+void socket_down_acceptor(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM sockRef,
+ const ErlNifPid* pid)
{
if (COMPARE_PIDS(&descP->currentAcceptor.pid, pid) == 0) {
@@ -18080,10 +18599,10 @@ void socket_down_acceptor(ErlNifEnv* env,
*
*/
static
-void socket_down_writer(ErlNifEnv* env,
- SocketDescriptor* descP,
- ERL_NIF_TERM sockRef,
- const ErlNifPid* pid)
+void socket_down_writer(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM sockRef,
+ const ErlNifPid* pid)
{
if (COMPARE_PIDS(&descP->currentWriter.pid, pid) == 0) {
@@ -18121,10 +18640,10 @@ void socket_down_writer(ErlNifEnv* env,
*
*/
static
-void socket_down_reader(ErlNifEnv* env,
- SocketDescriptor* descP,
- ERL_NIF_TERM sockRef,
- const ErlNifPid* pid)
+void socket_down_reader(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM sockRef,
+ const ErlNifPid* pid)
{
if (COMPARE_PIDS(&descP->currentReader.pid, pid) == 0) {
diff --git a/erts/emulator/nifs/common/socket_util.c b/erts/emulator/nifs/common/socket_util.c
index 5e18355308..8ad95cb6b7 100644
--- a/erts/emulator/nifs/common/socket_util.c
+++ b/erts/emulator/nifs/common/socket_util.c
@@ -213,10 +213,10 @@ char* esock_decode_iov(ErlNifEnv* env,
*/
extern
-char* esock_decode_sockaddr(ErlNifEnv* env,
- ERL_NIF_TERM eSockAddr,
- SocketAddress* sockAddrP,
- unsigned int* addrLen)
+char* esock_decode_sockaddr(ErlNifEnv* env,
+ ERL_NIF_TERM eSockAddr,
+ ESockAddress* sockAddrP,
+ unsigned int* addrLen)
{
ERL_NIF_TERM efam;
int fam;
@@ -279,10 +279,10 @@ char* esock_decode_sockaddr(ErlNifEnv* env,
*/
extern
-char* esock_encode_sockaddr(ErlNifEnv* env,
- SocketAddress* sockAddrP,
- unsigned int addrLen,
- ERL_NIF_TERM* eSockAddr)
+char* esock_encode_sockaddr(ErlNifEnv* env,
+ ESockAddress* sockAddrP,
+ unsigned int addrLen,
+ ERL_NIF_TERM* eSockAddr)
{
char* xres;
diff --git a/erts/emulator/nifs/common/socket_util.h b/erts/emulator/nifs/common/socket_util.h
index 1b5d003155..84b1c8085f 100644
--- a/erts/emulator/nifs/common/socket_util.h
+++ b/erts/emulator/nifs/common/socket_util.h
@@ -57,15 +57,15 @@ char* esock_decode_iov(ErlNifEnv* env,
size_t len,
ssize_t* totSize);
extern
-char* esock_decode_sockaddr(ErlNifEnv* env,
- ERL_NIF_TERM eSockAddr,
- SocketAddress* sockAddrP,
- unsigned int* addrLen);
-extern
-char* esock_encode_sockaddr(ErlNifEnv* env,
- SocketAddress* sockAddrP,
- unsigned int addrLen,
- ERL_NIF_TERM* eSockAddr);
+char* esock_decode_sockaddr(ErlNifEnv* env,
+ ERL_NIF_TERM eSockAddr,
+ ESockAddress* sockAddrP,
+ unsigned int* addrLen);
+extern
+char* esock_encode_sockaddr(ErlNifEnv* env,
+ ESockAddress* sockAddrP,
+ unsigned int addrLen,
+ ERL_NIF_TERM* eSockAddr);
extern
char* esock_decode_sockaddr_in4(ErlNifEnv* env,
diff --git a/erts/emulator/sys/common/erl_check_io.c b/erts/emulator/sys/common/erl_check_io.c
index 98be50815c..fb18c837ab 100644
--- a/erts/emulator/sys/common/erl_check_io.c
+++ b/erts/emulator/sys/common/erl_check_io.c
@@ -534,6 +534,7 @@ erts_io_notify_port_task_executed(ErtsPortTaskType type,
if (state->active_events & ERTS_POLL_EV_OUT)
oready(state->driver.select->outport, state);
state->active_events = 0;
+ active_events = 0;
}
}
diff --git a/erts/emulator/sys/common/erl_poll.c b/erts/emulator/sys/common/erl_poll.c
index 9662996039..1b125056f5 100644
--- a/erts/emulator/sys/common/erl_poll.c
+++ b/erts/emulator/sys/common/erl_poll.c
@@ -924,7 +924,7 @@ update_pollset(ErtsPollSet *ps, int fd, ErtsPollOp op, ErtsPollEvents events)
ERTS_EV_SET(&evts[len++], fd, EVFILT_WRITE, flags, (void *) ERTS_POLL_EV_OUT);
}
#else
- uint32_t flags = EV_ADD;
+ uint32_t flags = EV_ADD|EV_ENABLE;
if (ps->oneshot) flags |= EV_ONESHOT;
@@ -932,9 +932,27 @@ update_pollset(ErtsPollSet *ps, int fd, ErtsPollOp op, ErtsPollEvents events)
erts_atomic_dec_nob(&ps->no_of_user_fds);
/* We don't do anything when a delete is issued. The fds will be removed
when they are triggered, or when they are closed. */
- events = 0;
+ if (ps->oneshot)
+ events = 0;
+ else {
+ flags = EV_DELETE;
+ events = ERTS_POLL_EV_IN;
+ }
} else if (op == ERTS_POLL_OP_ADD) {
erts_atomic_inc_nob(&ps->no_of_user_fds);
+ /* Only allow EV_IN in non-oneshot poll-sets */
+ ASSERT(ps->oneshot || events == ERTS_POLL_EV_IN);
+ } else if (!ps->oneshot) {
+ ASSERT(op == ERTS_POLL_OP_MOD);
+ /* If we are not oneshot and do a mod we should disable the FD.
+ We assume that it is only the read side that is active as
+ currently only read is selected upon in the non-oneshot
+ poll-sets. */
+ if (!events)
+ flags = EV_DISABLE;
+ else
+ flags = EV_ENABLE;
+ events = ERTS_POLL_EV_IN;
}
if (events & ERTS_POLL_EV_IN) {
@@ -961,16 +979,15 @@ update_pollset(ErtsPollSet *ps, int fd, ErtsPollOp op, ErtsPollEvents events)
for (i = 0; i < len; i++) {
const char *flags = "UNKNOWN";
if (evts[i].flags == (EV_DELETE)) flags = "EV_DELETE";
- if (evts[i].flags == (EV_ADD|EV_ONESHOT)) flags = "EV_ADD|EV_ONESHOT";
if (evts[i].flags == (EV_ADD)) flags = "EV_ADD";
+ if (evts[i].flags == (EV_ADD|EV_ONESHOT)) flags = "EV_ADD|EV_ONESHOT";
+ if (evts[i].flags == (EV_ENABLE)) flags = "EV_ENABLE";
+ if (evts[i].flags == (EV_DISABLE)) flags = "EV_DISABLE";
+ if (evts[i].flags == (EV_ADD|EV_DISABLE)) flags = "EV_ADD|EV_DISABLE";
#ifdef EV_DISPATCH
if (evts[i].flags == (EV_ADD|EV_DISPATCH)) flags = "EV_ADD|EV_DISPATCH";
- if (evts[i].flags == (EV_ADD|EV_DISABLE)) flags = "EV_ADD|EV_DISABLE";
if (evts[i].flags == (EV_ENABLE|EV_DISPATCH)) flags = "EV_ENABLE|EV_DISPATCH";
- if (evts[i].flags == (EV_ENABLE)) flags = "EV_ENABLE";
- if (evts[i].flags == (EV_DISABLE)) flags = "EV_DISABLE";
if (evts[i].flags == (EV_DISABLE|EV_DISPATCH)) flags = "EV_DISABLE|EV_DISABLE";
- if (evts[i].flags == (EV_DISABLE)) flags = "EV_DISABLE";
#endif
keventbp += sprintf(keventbp, "%s{%lu, %s, %s}",i > 0 ? ", " : "",
diff --git a/erts/emulator/test/driver_SUITE.erl b/erts/emulator/test/driver_SUITE.erl
index cbed71cedd..f6d7c55017 100644
--- a/erts/emulator/test/driver_SUITE.erl
+++ b/erts/emulator/test/driver_SUITE.erl
@@ -120,29 +120,6 @@
-define(heap_binary_size, 64).
-init_per_testcase(Case, Config) when is_atom(Case), is_list(Config) ->
- CIOD = rpc(Config,
- fun() ->
- case catch erts_debug:get_internal_state(available_internal_state) of
- true -> ok;
- _ -> erts_debug:set_internal_state(available_internal_state, true)
- end,
- erts_debug:get_internal_state(check_io_debug)
- end),
- erlang:display({init_per_testcase, Case}),
- 0 = element(1, CIOD),
- [{testcase, Case}|Config].
-
-end_per_testcase(Case, Config) ->
- erlang:display({end_per_testcase, Case}),
- CIOD = rpc(Config,
- fun() ->
- get_stable_check_io_info(),
- erts_debug:get_internal_state(check_io_debug)
- end),
- 0 = element(1, CIOD),
- ok.
-
suite() ->
[{ct_hooks,[ts_install_cth]},
{timetrap, {minutes, 1}}].
@@ -219,6 +196,48 @@ end_per_group(_GroupName, Config) ->
end,
Config.
+init_per_testcase(Case, Config) when is_atom(Case), is_list(Config) ->
+ CIOD = rpc(Config,
+ fun() ->
+ case catch erts_debug:get_internal_state(available_internal_state) of
+ true -> ok;
+ _ -> erts_debug:set_internal_state(available_internal_state, true)
+ end,
+ erts_debug:get_internal_state(check_io_debug)
+ end),
+ erlang:display({init_per_testcase, Case}),
+ 0 = element(1, CIOD),
+ [{testcase, Case}|Config].
+
+end_per_testcase(Case, Config) ->
+ erlang:display({end_per_testcase, Case}),
+ try rpc(Config, fun() ->
+ get_stable_check_io_info(),
+ erts_debug:get_internal_state(check_io_debug)
+ end) of
+ CIOD ->
+ 0 = element(1, CIOD)
+ catch _E:_R:_ST ->
+ %% Logs some info about the system
+ ct_os_cmd("epmd -names"),
+ ct_os_cmd("ps aux"),
+ %% Restart the node
+ case proplists:get_value(node, Config) of
+ undefined ->
+ ok;
+ Node ->
+ timer:sleep(1000), %% Give the node time to die
+ [NodeName, _] = string:lexemes(atom_to_list(Node),"@"),
+ {ok, Node} = start_node_final(
+ list_to_atom(NodeName),
+ proplists:get_value(node_args, Config))
+ end
+ end,
+ ok.
+
+ct_os_cmd(Cmd) ->
+ ct:log("~s: ~s",[Cmd,os:cmd(Cmd)]).
+
%% Test sending bad types to port with an outputv-capable driver.
outputv_errors(Config) when is_list(Config) ->
Path = proplists:get_value(data_dir, Config),
@@ -2644,7 +2663,6 @@ start_node(Config) when is_list(Config) ->
start_node(Name) ->
start_node(Name, "").
start_node(NodeName, Args) ->
- Pa = filename:dirname(code:which(?MODULE)),
Name = list_to_atom(atom_to_list(?MODULE)
++ "-"
++ atom_to_list(NodeName)
@@ -2652,7 +2670,17 @@ start_node(NodeName, Args) ->
++ integer_to_list(erlang:system_time(second))
++ "-"
++ integer_to_list(erlang:unique_integer([positive]))),
- test_server:start_node(Name, slave, [{args, Args ++ " -pa "++Pa}]).
+ start_node_final(Name, Args).
+start_node_final(Name, Args) ->
+ {ok, Pwd} = file:get_cwd(),
+ FinalArgs = [Args, " -pa ", filename:dirname(code:which(?MODULE))],
+ {ok, Node} = test_server:start_node(Name, slave, [{args, FinalArgs}]),
+ LogPath = Pwd ++ "/error_log." ++ atom_to_list(Name),
+ ct:pal("Logging to: ~s", [LogPath]),
+ rpc:call(Node, logger, add_handler, [file_handler, logger_std_h,
+ #{formatter => {logger_formatter,#{ single_line => false }},
+ config => #{file => LogPath }}]),
+ {ok, Node}.
stop_node(Node) ->
test_server:stop_node(Node).
diff --git a/erts/emulator/test/net_SUITE.erl b/erts/emulator/test/net_SUITE.erl
index 1a973cacb2..6111fc76a5 100644
--- a/erts/emulator/test/net_SUITE.erl
+++ b/erts/emulator/test/net_SUITE.erl
@@ -127,12 +127,17 @@ api_basic_cases() ->
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
init_per_suite(Config) ->
- case os:type() of
- {win32, _} ->
- not_yet_implemented();
- _ ->
- %% ?LOGGER:start(),
- Config
+ case lists:member(socket, erlang:loaded()) of
+ true ->
+ case os:type() of
+ {win32, _} ->
+ not_yet_implemented();
+ _ ->
+ %% ?LOGGER:start(),
+ Config
+ end;
+ false ->
+ {skip, "esock disabled"}
end.
end_per_suite(_) ->
diff --git a/erts/emulator/test/socket_SUITE.erl b/erts/emulator/test/socket_SUITE.erl
index 2e3f40a350..e3545ccbf9 100644
--- a/erts/emulator/test/socket_SUITE.erl
+++ b/erts/emulator/test/socket_SUITE.erl
@@ -28,10 +28,14 @@
%% ESOCK_TEST_TRAFFIC: include
%% ESOCK_TEST_TTEST: exclude
%%
+%% Variable that controls "verbosity" of the test case(s):
+%%
+%% ESOCK_TEST_QUIET: true (default) | false
+%%
%% Defines the runtime of the ttest cases
%% (This is the time during which "measurement" is performed.
%% the actual time it takes for the test case to complete
-%% will be longer)
+%% will be longer; setup, completion, ...)
%%
%% ESOCK_TEST_TTEST_RUNTIME: 10 seconds
%% Format of values: <integer>[<unit>]
@@ -1381,22 +1385,27 @@ ttest_ssockt_csockt_cases() ->
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
init_per_suite(Config) ->
- case os:type() of
- {win32, _} ->
- not_yet_implemented();
- _ ->
- case quiet_mode(Config) of
- default ->
- ?LOGGER:start(),
- Config;
- Quiet ->
- ?LOGGER:start(Quiet),
- [{esock_test_quiet, Quiet}|Config]
- end
+ case lists:member(socket, erlang:loaded()) of
+ true ->
+ case os:type() of
+ {win32, _} ->
+ (catch not_yet_implemented());
+ _ ->
+ case quiet_mode(Config) of
+ default ->
+ ?LOGGER:start(),
+ Config;
+ Quiet ->
+ ?LOGGER:start(Quiet),
+ [{esock_test_quiet, Quiet}|Config]
+ end
+ end;
+ false ->
+ {skip, "esock disabled"}
end.
end_per_suite(_) ->
- ?LOGGER:stop(),
+ (catch ?LOGGER:stop()),
ok.
@@ -1643,6 +1652,8 @@ api_b_sendmsg_and_recvmsg_udp4(_Config) when is_list(_Config) ->
tc_try(api_b_sendmsg_and_recvmsg_udp4,
fun() ->
Send = fun(Sock, Data, Dest) ->
+ %% We need tests for this,
+ %% but this is not the place it.
%% CMsgHdr = #{level => ip,
%% type => tos,
%% data => reliability},
@@ -1653,9 +1664,12 @@ api_b_sendmsg_and_recvmsg_udp4(_Config) when is_list(_Config) ->
socket:sendmsg(Sock, MsgHdr)
end,
Recv = fun(Sock) ->
+ %% We have some issues on old darwing...
+ socket:setopt(Sock, otp, debug, true),
case socket:recvmsg(Sock) of
{ok, #{addr := Source,
iov := [Data]}} ->
+ socket:setopt(Sock, otp, debug, false),
{ok, {Source, Data}};
{error, _} = ERROR ->
ERROR
@@ -1714,21 +1728,37 @@ api_b_send_and_recv_udp(InitState) ->
end},
#{desc => "send req (to dst)",
cmd => fun(#{sock_src := Sock, sa_dst := Dst, send := Send}) ->
- ok = Send(Sock, ?BASIC_REQ, Dst)
+ Send(Sock, ?BASIC_REQ, Dst)
end},
#{desc => "recv req (from src)",
cmd => fun(#{sock_dst := Sock, sa_src := Src, recv := Recv}) ->
- {ok, {Src, ?BASIC_REQ}} = Recv(Sock),
- ok
+ case Recv(Sock) of
+ {ok, {Src, ?BASIC_REQ}} ->
+ ok;
+ {ok, UnexpData} ->
+ {error, {unexpected_data, UnexpData}};
+ {error, _} = ERROR ->
+ %% At the moment there is no way to get
+ %% status or state for the socket...
+ ERROR
+ end
end},
#{desc => "send rep (to src)",
cmd => fun(#{sock_dst := Sock, sa_src := Src, send := Send}) ->
- ok = Send(Sock, ?BASIC_REP, Src)
+ Send(Sock, ?BASIC_REP, Src)
end},
#{desc => "recv rep (from dst)",
cmd => fun(#{sock_src := Sock, sa_dst := Dst, recv := Recv}) ->
- {ok, {Dst, ?BASIC_REP}} = Recv(Sock),
- ok
+ case Recv(Sock) of
+ {ok, {Dst, ?BASIC_REP}} ->
+ ok;
+ {ok, UnexpData} ->
+ {error, {unexpected_data, UnexpData}};
+ {error, _} = ERROR ->
+ %% At the moment there is no way to get
+ %% status or state for the socket...
+ ERROR
+ end
end},
#{desc => "close src socket",
cmd => fun(#{sock_src := Sock}) ->
@@ -3585,8 +3615,8 @@ api_to_connect_tcp(InitState) ->
?SEV_IPRINT("client node ~p started",
[Node]),
{ok, State#{node => Node}};
- {error, Reason, _} ->
- {error, Reason}
+ {error, Reason} ->
+ {skip, Reason}
end
end},
#{desc => "monitor client node",
@@ -3921,7 +3951,7 @@ api_to_connect_tcp_await_timeout2(_ID, To, ServerSA, NewSock) ->
case socket:connect(Sock, ServerSA, To) of
{error, timeout} ->
Stop = t(),
- TDiff = tdiff(Start, Stop),
+ TDiff = Stop - Start,
if
(TDiff >= To) ->
(catch socket:close(Sock)),
@@ -4033,7 +4063,7 @@ api_to_accept_tcp(InitState) ->
end},
#{desc => "validate timeout time",
cmd => fun(#{start := Start, stop := Stop, timeout := To} = _State) ->
- TDiff = tdiff(Start, Stop),
+ TDiff = Stop - Start,
if
(TDiff >= To) ->
ok;
@@ -4169,7 +4199,7 @@ api_to_maccept_tcp(InitState) ->
end},
#{desc => "validate timeout time",
cmd => fun(#{start := Start, stop := Stop, timeout := To} = _State) ->
- TDiff = tdiff(Start, Stop),
+ TDiff = Stop - Start,
if
(TDiff >= To) ->
ok;
@@ -4242,7 +4272,7 @@ api_to_maccept_tcp(InitState) ->
end},
#{desc => "validate timeout time",
cmd => fun(#{start := Start, stop := Stop, timeout := To} = State) ->
- TDiff = tdiff(Start, Stop),
+ TDiff = Stop - Start,
if
(TDiff >= To) ->
State1 = maps:remove(start, State),
@@ -4693,7 +4723,7 @@ api_to_receive_tcp(InitState) ->
end},
#{desc => "validate timeout time",
cmd => fun(#{start := Start, stop := Stop, timeout := To} = State) ->
- TDiff = tdiff(Start, Stop),
+ TDiff = Stop - Start,
if
(TDiff >= To) ->
State1 = maps:remove(start, State),
@@ -5000,7 +5030,8 @@ api_to_receive_udp(InitState) ->
Start = t(),
case Recv(Sock, To) of
{error, timeout} ->
- {ok, State#{start => Start, stop => t()}};
+ {ok, State#{start => Start,
+ stop => t()}};
{ok, _} ->
{error, unexpected_sucsess};
{error, _} = ERROR ->
@@ -5009,7 +5040,7 @@ api_to_receive_udp(InitState) ->
end},
#{desc => "validate timeout time",
cmd => fun(#{start := Start, stop := Stop, timeout := To} = _State) ->
- TDiff = tdiff(Start, Stop),
+ TDiff = Stop - Start,
if
(TDiff >= To) ->
ok;
@@ -5021,7 +5052,7 @@ api_to_receive_udp(InitState) ->
%% *** Termination ***
#{desc => "close socket",
cmd => fun(#{sock := Sock} = _State) ->
- socket:setopt(Sock, otp, debug, true),
+ %% socket:setopt(Sock, otp, debug, true),
sock_close(Sock),
ok
end},
@@ -5591,7 +5622,7 @@ sc_lc_receive_response_tcp(InitState) ->
State1 = maps:remove(sock, State),
{ok, State1};
{error, Reason} = ERROR ->
- ?SEV_EPRINT("Unexpected read faulure: "
+ ?SEV_EPRINT("Unexpected read failure: "
"~n ~p", [Reason]),
ERROR
end
@@ -7218,8 +7249,8 @@ sc_rc_receive_response_tcp(InitState) ->
{ok, Node} ->
?SEV_IPRINT("client node ~p started", [Node]),
{ok, State#{node => Node}};
- {error, Reason, _} ->
- {error, Reason}
+ {error, Reason} ->
+ {skip, Reason}
end
end},
#{desc => "monitor client node 1",
@@ -8095,8 +8126,8 @@ sc_rs_send_shutdown_receive_tcp(InitState) ->
?SEV_IPRINT("client node ~p started",
[Node]),
{ok, State#{node => Node}};
- {error, Reason, _} ->
- {error, Reason}
+ {error, Reason} ->
+ {skip, Reason}
end
end},
#{desc => "monitor client node",
@@ -8987,6 +9018,7 @@ traffic_send_and_recv_chunks_tcp(InitState) ->
end},
#{desc => "recv (one big)",
cmd => fun(#{tester := Tester, csock := Sock, size := Size} = _State) ->
+ %% socket:setopt(Sock, otp, debug, true),
case socket:recv(Sock, Size) of
{ok, Data} ->
?SEV_ANNOUNCE_READY(Tester,
@@ -9045,8 +9077,8 @@ traffic_send_and_recv_chunks_tcp(InitState) ->
?SEV_IPRINT("(remote) client node ~p started",
[Node]),
{ok, State#{node => Node}};
- {error, Reason, _} ->
- {error, Reason}
+ {error, Reason} ->
+ {skip, Reason}
end
end},
#{desc => "monitor client node",
@@ -10169,7 +10201,7 @@ traffic_ping_pong_small_sendmsg_and_recvmsg_udp4(_Config) when is_list(_Config)
Num = ?TPP_SMALL_NUM,
tc_try(traffic_ping_pong_small_sendmsg_and_recvmsg_udp4,
fun() ->
- ?TT(?SECS(20)),
+ ?TT(?SECS(60)),
InitState = #{domain => inet,
msg => Msg,
num => Num},
@@ -10196,7 +10228,7 @@ traffic_ping_pong_small_sendmsg_and_recvmsg_udp6(_Config) when is_list(_Config)
tc_try(traffic_ping_pong_small_sendmsg_and_recvmsg_udp6,
fun() -> has_support_ipv6() end,
fun() ->
- ?TT(?SECS(20)),
+ ?TT(?SECS(30)),
InitState = #{domain => inet,
msg => Msg,
num => Num},
@@ -10523,8 +10555,8 @@ traffic_ping_pong_send_and_receive_tcp2(InitState) ->
?SEV_IPRINT("(remote) client node ~p started",
[Node]),
{ok, State#{node => Node}};
- {error, Reason, _} ->
- {error, Reason}
+ {error, Reason} ->
+ {skip, Reason}
end
end},
#{desc => "monitor client node",
@@ -11044,7 +11076,7 @@ tpp_tcp_client_msg_exchange_loop(Sock, _Send, _Recv, _Msg,
end;
tpp_tcp_client_msg_exchange_loop(Sock, Send, Recv, Data,
Num, N, Sent, Received, Start) ->
- %% d("tpp_tcp_client_msg_exchange_loop(~w,~w) try send", [Num,N]),
+ %% d("tpp_tcp_client_msg_exchange_loop(~w,~w) try send ~w", [Num,N,size(Data)]),
case tpp_tcp_send_req(Sock, Send, Data) of
{ok, SendSz} ->
%% d("tpp_tcp_client_msg_exchange_loop(~w,~w) sent - "
@@ -11057,11 +11089,13 @@ tpp_tcp_client_msg_exchange_loop(Sock, Send, Recv, Data,
Received+RecvSz,
Start);
{error, RReason} ->
- ?SEV_EPRINT("recv (~w of ~w): ~p", [N, Num, RReason]),
+ ?SEV_EPRINT("recv (~w of ~w): ~p: "
+ "~n ~p", [N, Num, RReason, mq()]),
exit({recv, RReason, N})
end;
{error, SReason} ->
- ?SEV_EPRINT("send (~w of ~w): ~p", [N, Num, SReason]),
+ ?SEV_EPRINT("send (~w of ~w): ~p"
+ "~n ~p", [N, Num, SReason, mq()]),
exit({send, SReason, N})
end.
@@ -11121,7 +11155,7 @@ tpp_tcp_recv(Sock, Recv, Tag) ->
tpp_tcp_recv(Sock, Recv, Tag, Remains, size(Msg), [Data]);
{ok, <<Tag:32/integer, _/binary>>} ->
{error, {invalid_msg_tag, Tag}};
- {error, _} = ERROR ->
+ {error, _R} = ERROR ->
ERROR
end.
@@ -11135,7 +11169,7 @@ tpp_tcp_recv(Sock, Recv, Tag, Remaining, AccSz, Acc) ->
tpp_tcp_recv(Sock, Recv, Tag,
Remaining - size(Data), AccSz + size(Data),
[Data | Acc]);
- {error, _} = ERROR ->
+ {error, _R} = ERROR ->
ERROR
end.
@@ -11173,6 +11207,14 @@ tpp_tcp_send_msg(Sock, Send, Msg, AccSz) when is_binary(Msg) ->
%% size_of_iovec([B|IOVec], Sz) ->
%% size_of_iovec(IOVec, Sz+size(B)).
+mq() ->
+ mq(self()).
+
+mq(Pid) when is_pid(Pid) ->
+ Tag = messages,
+ {Tag, Msgs} = process_info(Pid, Tag),
+ Msgs.
+
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -11198,7 +11240,7 @@ traffic_ping_pong_sendmsg_and_recvmsg_udp(InitState) ->
MsgHdr = #{addr => Dest, iov => Data},
socket:sendmsg(Sock, MsgHdr)
end,
- Recv = fun(Sock, Sz) ->
+ Recv = fun(Sock, Sz) ->
case socket:recvmsg(Sock, Sz, 0) of
{ok, #{addr := Source,
iov := [Data]}} ->
@@ -11329,7 +11371,9 @@ traffic_ping_pong_send_and_receive_udp2(InitState) ->
[{handler, Handler}])
end},
#{desc => "order handler to recv",
- cmd => fun(#{handler := Handler} = _State) ->
+ cmd => fun(#{handler := Handler,
+ sock := _Sock} = _State) ->
+ %% socket:setopt(Sock, otp, debug, true),
?SEV_ANNOUNCE_CONTINUE(Handler, recv),
ok
end},
@@ -11425,8 +11469,8 @@ traffic_ping_pong_send_and_receive_udp2(InitState) ->
?SEV_IPRINT("(remote) client node ~p started",
[Node]),
{ok, State#{node => Node}};
- {error, Reason, _} ->
- {error, Reason}
+ {error, Reason} ->
+ {skip, Reason}
end
end},
#{desc => "monitor client node",
@@ -17272,8 +17316,8 @@ ttest_tcp(InitState) ->
case start_node(Host, server) of
{ok, Node} ->
{ok, State#{node => Node}};
- {error, Reason, _} ->
- {error, Reason}
+ {error, Reason} ->
+ {skip, Reason}
end
end},
#{desc => "monitor server node",
@@ -17369,8 +17413,8 @@ ttest_tcp(InitState) ->
case start_node(Host, client) of
{ok, Node} ->
{ok, State#{node => Node}};
- {error, Reason, _} ->
- {error, Reason}
+ {error, Reason} ->
+ {skip, Reason}
end
end},
#{desc => "monitor client node",
@@ -17686,7 +17730,28 @@ ttest_tcp_client_start(Node,
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% This mechanism has only one purpose: So that we are able to kill
+%% the node-starter process if it takes to long. The node-starter
+%% runs on the local node.
+%% This crapola is hopefully temporary, but we have seen that on
+%% some platforms the ct_slave:start simply hangs.
+-define(NODE_START_TIMEOUT, 10000).
start_node(Host, NodeName) ->
+ start_node(Host, NodeName, ?NODE_START_TIMEOUT).
+
+start_node(Host, NodeName, Timeout) ->
+ {NodeStarter, _} =
+ spawn_monitor(fun() -> exit(start_unique_node(Host, NodeName)) end),
+ receive
+ {'DOWN', _, process, NodeStarter, Result} ->
+ %% i("Node Starter (~p) reported: ~p", [NodeStarter, Result]),
+ Result
+ after Timeout ->
+ exit(NodeStarter, kill),
+ {error, {failed_starting_node, NodeName, timeout}}
+ end.
+
+start_unique_node(Host, NodeName) ->
UniqueNodeName = f("~w_~w", [NodeName, erlang:system_time(millisecond)]),
case do_start_node(Host, UniqueNodeName) of
{ok, _} = OK ->
@@ -17720,7 +17785,7 @@ stop_node(Node) ->
ERROR
end.
-
+
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -17877,9 +17942,15 @@ which_addr2(Domain, [_|IFO]) ->
%% Here are all the *general* test vase condition functions.
%% The idea is that this function shall test if the test host has
-%% support for IPv6. If not there is no point in running IPv6 tests.
+%% support for IPv6. If not, there is no point in running IPv6 tests.
%% Currently we just skip.
has_support_ipv6() ->
+ %% case socket:supports(ipv6) of
+ %% true ->
+ %% ok;
+ %% false ->
+ %% {error, not_supported}
+ %% end.
not_yet_implemented().
@@ -17896,8 +17967,10 @@ skip(Reason) ->
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
t() ->
- os:timestamp().
+ ts(ms).
+ts(ms) ->
+ erlang:monotonic_time(milli_seconds).
tdiff({A1, B1, C1} = _T1x, {A2, B2, C2} = _T2x) ->
T1 = A1*1000000000+B1*1000+(C1 div 1000),
@@ -17930,11 +18003,15 @@ set_tc_name(N) when is_list(N) ->
%% get(tc_name).
tc_begin(TC) ->
+ OldVal = process_flag(trap_exit, true),
+ put(old_trap_exit, OldVal),
set_tc_name(TC),
tc_print("begin ***",
"~n----------------------------------------------------~n", "").
tc_end(Result) when is_list(Result) ->
+ OldVal = erase(old_trap_exit),
+ process_flag(trap_exit, OldVal),
tc_print("done: ~s", [Result],
"", "----------------------------------------------------~n~n"),
ok.
@@ -17965,26 +18042,44 @@ tc_try(Case, TCCondFun, TCFun)
tc_end("ok")
end
catch
- throw:{skip, _} = SKIP ->
- tc_end("skipping"),
+ C:{skip, _} = SKIP when ((C =:= throw) orelse (C =:= exit)) ->
+ %% i("catched[tc] (skip): "
+ %% "~n C: ~p"
+ %% "~n SKIP: ~p"
+ %% "~n", [C, SKIP]),
+ tc_end( f("skipping(catched,~w,tc)", [C]) ),
SKIP;
- Class:Error:Stack ->
- tc_end("failed"),
- erlang:raise(Class, Error, Stack)
+ C:E:S ->
+ %% i("catched[tc]: "
+ %% "~n C: ~p"
+ %% "~n E: ~p"
+ %% "~n S: ~p"
+ %% "~n", [C, E, S]),
+ tc_end( f("failed(catched,~w,tc)", [C]) ),
+ erlang:raise(C, E, S)
end;
{skip, _} = SKIP ->
- tc_end("skipping"),
+ tc_end("skipping(tc)"),
SKIP;
{error, Reason} ->
- tc_end("failed"),
+ tc_end("failed(tc)"),
exit({tc_cond_failed, Reason})
catch
- throw:{skip, _} = SKIP ->
- tc_end("skipping"),
+ C:{skip, _} = SKIP when ((C =:= throw) orelse (C =:= exit)) ->
+ %% i("catched[cond] (skip): "
+ %% "~n C: ~p"
+ %% "~n SKIP: ~p"
+ %% "~n", [C, SKIP]),
+ tc_end( f("skipping(catched,~w,cond)", [C]) ),
SKIP;
- Class:Error:Stack ->
- tc_end("failed"),
- erlang:raise(Class, Error, Stack)
+ C:E:S ->
+ %% i("catched[cond]: "
+ %% "~n C: ~p"
+ %% "~n E: ~p"
+ %% "~n S: ~p"
+ %% "~n", [C, E, S]),
+ tc_end( f("failed(catched,~w,cond)", [C]) ),
+ erlang:raise(C, E, S)
end.
diff --git a/erts/emulator/test/socket_test_evaluator.erl b/erts/emulator/test/socket_test_evaluator.erl
index c5748ac21b..694f0d5f1e 100644
--- a/erts/emulator/test/socket_test_evaluator.erl
+++ b/erts/emulator/test/socket_test_evaluator.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2018-2018. All Rights Reserved.
+%% Copyright Ericsson AB 2018-2019. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -106,12 +106,13 @@ start(Name, Seq, InitState)
InitState2 = InitState#{parent => self()},
Pid = erlang:spawn_link(
fun() -> init(Name, Seq, InitState2) end),
- MRef = erlang:monitor(process, Pid),
- #ev{name = Name, pid = Pid, mref = MRef}
+ %% MRef = erlang:monitor(process, Pid),
+ #ev{name = Name, pid = Pid}%, mref = MRef}
end.
init(Name, Seq, Init) ->
put(sname, Name),
+ process_flag(trap_exit, true),
loop(1, Seq, Init).
loop(_ID, [], FinalState) ->
@@ -125,21 +126,26 @@ loop(ID, [#{desc := Desc,
{ok, NewState} ->
loop(ID + 1, Cmds, NewState);
{skip, Reason} ->
+ ?SEV_IPRINT("command ~w skip: "
+ "~n ~p", [ID, Reason]),
exit({skip, Reason});
{error, Reason} ->
- eprint("command ~w failed: "
- "~n Reason: ~p", [ID, Reason]),
+ ?SEV_EPRINT("command ~w failed: "
+ "~n ~p", [ID, Reason]),
exit({command_failed, ID, Reason, State})
catch
- throw:{skip, R} = E:_ ->
- eprint("command ~w skip: "
- "~n Skip Reason: ~p", [ID, R]),
+ C:{skip, command} = E:_ when ((C =:= throw) orelse (C =:= exit)) ->
+ %% Secondary skip
+ exit(E);
+ C:{skip, R} = E:_ when ((C =:= throw) orelse (C =:= exit)) ->
+ ?SEV_IPRINT("command ~w skip catched(~w): "
+ "~n Reason: ~p", [ID, C, R]),
exit(E);
C:E:S ->
- eprint("command ~w crashed: "
- "~n Class: ~p"
- "~n Error: ~p"
- "~n Call Stack: ~p", [ID, C, E, S]),
+ ?SEV_EPRINT("command ~w crashed: "
+ "~n Class: ~p"
+ "~n Error: ~p"
+ "~n Call Stack: ~p", [ID, C, E, S]),
exit({command_crashed, ID, {C,E,S}, State})
end.
@@ -168,18 +174,32 @@ await_finish(Evs, OK, Fails) ->
{Evs2, OK2, Fails2} = await_finish_normal(Pid, Evs, OK, Fails),
await_finish(Evs2, OK2, Fails2);
- %% The evaluator can skip the teat case:
+ %% The evaluator can skip the test case:
{'DOWN', _MRef, process, Pid, {skip, Reason}} ->
+ %% ?SEV_IPRINT("await_finish -> skip (down) received: "
+ %% "~n Pid: ~p"
+ %% "~n Reason: ~p", [Pid, Reason]),
await_finish_skip(Pid, Reason, Evs, OK);
{'EXIT', Pid, {skip, Reason}} ->
+ %% ?SEV_IPRINT("await_finish -> skip (exit) received: "
+ %% "~n Pid: ~p"
+ %% "~n Reason: ~p", [Pid, Reason]),
await_finish_skip(Pid, Reason, Evs, OK);
%% Evaluator failed
{'DOWN', _MRef, process, Pid, Reason} ->
- {Evs2, OK2, Fails2} = await_finish_fail(Pid, Reason, Evs, OK, Fails),
+ %% ?SEV_IPRINT("await_finish -> fail (down) received: "
+ %% "~n Pid: ~p"
+ %% "~n Reason: ~p", [Pid, Reason]),
+ {Evs2, OK2, Fails2} =
+ await_finish_fail(Pid, Reason, Evs, OK, Fails),
await_finish(Evs2, OK2, Fails2);
{'EXIT', Pid, Reason} ->
- {Evs2, OK2, Fails2} = await_finish_fail(Pid, Reason, Evs, OK, Fails),
+ %% ?SEV_IPRINT("await_finish -> fail (exit) received: "
+ %% "~n Pid: ~p"
+ %% "~n Reason: ~p", [Pid, Reason]),
+ {Evs2, OK2, Fails2} =
+ await_finish_fail(Pid, Reason, Evs, OK, Fails),
await_finish(Evs2, OK2, Fails2)
end.
@@ -202,22 +222,83 @@ await_finish_normal(Pid, Evs, OK, Fails) ->
end.
await_finish_skip(Pid, Reason, Evs, OK) ->
- case lists:keysearch(Pid, #ev.pid, Evs) of
- {value, #ev{name = Name}} ->
- iprint("evaluator '~s' (~p) issued SKIP: "
- "~n ~p", [Name, Pid, Reason]);
- false ->
- case lists:member(Pid, OK) of
- true ->
- ok;
- false ->
- iprint("unknown process ~p issued SKIP: "
- "~n ~p", [Pid, Reason])
- end
- end,
+ Evs2 =
+ case lists:keysearch(Pid, #ev.pid, Evs) of
+ {value, #ev{name = Name}} ->
+ ?SEV_IPRINT("evaluator '~s' (~p) issued SKIP: "
+ "~n ~p", [Name, Pid, Reason]),
+ lists:keydelete(Pid, #ev.pid, Evs);
+ false ->
+ case lists:member(Pid, OK) of
+ true ->
+ ?SEV_IPRINT("already terminated (ok) process ~p skip"
+ "~n ~p", [Pid]),
+ ok;
+ false ->
+ ?SEV_IPRINT("unknown process ~p issued SKIP: "
+ "~n ~p", [Pid, Reason]),
+ iprint("unknown process ~p issued SKIP: "
+ "~n ~p", [Pid, Reason])
+ end,
+ Evs
+ end,
+ await_evs_terminated(Evs2),
?LIB:skip(Reason).
+await_evs_terminated(Evs) ->
+ Instructions =
+ [
+ %% Just wait for the evaluators to die on their own
+ {fun() -> ?SEV_IPRINT("await (no action) evs termination") end,
+ fun(_) -> ok end},
+
+ %% Send them a skip message, causing the evaluators to
+ %% die with a skip reason.
+ {fun() -> ?SEV_IPRINT("await (send skip message) evs termination") end,
+ fun(#ev{pid = Pid}) -> Pid ! skip end},
+ %% And if nothing else works, try to kill the remaining evaluators
+ {fun() -> ?SEV_IPRINT("await (issue exit kill) evs termination") end,
+ fun(#ev{pid = Pid}) -> exit(Pid, kill) end}],
+
+ await_evs_terminated(Evs, Instructions).
+
+await_evs_terminated([], _) ->
+ ok;
+await_evs_terminated(Evs, []) ->
+ {error, {failed_terminated, [P||#ev{pid=P} <- Evs]}};
+await_evs_terminated(Evs, [{Inform, Command}|Instructions]) ->
+ Inform(),
+ lists:foreach(Command, Evs),
+ RemEvs = await_evs_termination(Evs),
+ await_evs_terminated(RemEvs, Instructions).
+
+await_evs_termination(Evs) ->
+ await_evs_termination(Evs, 2000).
+
+await_evs_termination([], _Timeout) ->
+ [];
+await_evs_termination(Evs, Timeout) ->
+ T = t(),
+ receive
+ {'DOWN', _MRef, process, Pid, _Reason} ->
+ %% ?SEV_IPRINT("await_evs_termination -> DOWN: "
+ %% "~n Pid: ~p"
+ %% "~n Reason: ~p", [Pid, Reason]),
+ Evs2 = lists:keydelete(Pid, #ev.pid, Evs),
+ await_evs_termination(Evs2, tdiff(T, t()));
+ {'EXIT', Pid, _Reason} ->
+ %% ?SEV_IPRINT("await_evs_termination -> EXIT: "
+ %% "~n Pid: ~p"
+ %% "~n Reason: ~p", [Pid, Reason]),
+ Evs2 = lists:keydelete(Pid, #ev.pid, Evs),
+ await_evs_termination(Evs2, tdiff(T, t()))
+
+ after Timeout ->
+ Evs
+ end.
+
+
await_finish_fail(Pid, Reason, Evs, OK, Fails) ->
case lists:keysearch(Pid, #ev.pid, Evs) of
{value, #ev{name = Name}} ->
@@ -454,7 +535,7 @@ await_termination(Pid, ExpReason) ->
{'DOWN', _, process, Pid, Reason} when (ExpReason =:= Reason) ->
ok;
{'DOWN', _, process, Pid, Reason} ->
- {error, {unexpected_exit, ExpReason, Reason}}
+ {error, {unexpected_reason, ExpReason, Reason}}
end.
@@ -480,6 +561,10 @@ await(ExpPid, Name, Announcement, Slogan, OtherPids)
is_atom(Slogan) andalso
is_list(OtherPids) ->
receive
+ skip ->
+ %% This means that another evaluator has issued a skip,
+ %% and we have been instructed to terminate as a result.
+ ?LIB:skip(command);
{Announcement, Pid, Slogan, ?EXTRA_NOTHING} when (ExpPid =:= any) ->
{ok, Pid};
{Announcement, Pid, Slogan, Extra} when (ExpPid =:= any) ->
@@ -495,12 +580,15 @@ await(ExpPid, Name, Announcement, Slogan, OtherPids)
{'DOWN', _, process, Pid, Reason} when (Pid =:= ExpPid) ->
eprint("Unexpected DOWN from ~w (~p): "
"~n ~p", [Name, Pid, Reason]),
- {error, {unexpected_exit, Name}};
+ {error, {unexpected_exit, Name, Reason}};
{'DOWN', _, process, OtherPid, Reason} ->
case check_down(OtherPid, Reason, OtherPids) of
ok ->
iprint("DOWN from unknown process ~p: "
- "~n ~p", [OtherPid, Reason]),
+ "~n ~p"
+ "~n when"
+ "~n OtherPids: "
+ "~n ~p", [OtherPid, Reason, OtherPids]),
await(ExpPid, Name, Announcement, Slogan, OtherPids);
{error, _} = ERROR ->
ERROR
@@ -527,7 +615,7 @@ check_down(Pid, DownReason, Pids) ->
{value, {_, Name}} ->
eprint("Unexpected DOWN from ~w (~p): "
"~n ~p", [Name, Pid, DownReason]),
- {error, {unexpected_exit, Name}};
+ {error, {unexpected_exit, Name, DownReason}};
false ->
ok
end.
@@ -561,3 +649,16 @@ print(Prefix, F, A) ->
end,
?LOGGER:format("[~s]~s ~s" ++ F,
[?LIB:formated_timestamp(), IDStr, Prefix | A]).
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+t() ->
+ os:timestamp().
+
+
+tdiff({A1, B1, C1} = _T1x, {A2, B2, C2} = _T2x) ->
+ T1 = A1*1000000000+B1*1000+(C1 div 1000),
+ T2 = A2*1000000000+B2*1000+(C2 div 1000),
+ T2 - T1.
+
diff --git a/erts/etc/common/erlexec.c b/erts/etc/common/erlexec.c
index ec4a4ead23..8203c46a39 100644
--- a/erts/etc/common/erlexec.c
+++ b/erts/etc/common/erlexec.c
@@ -408,7 +408,6 @@ int main(int argc, char **argv)
int process_args = 1;
int print_args_exit = 0;
int print_qouted_cmd_exit = 0;
- erts_cpu_info_t *cpuinfo = NULL;
char* emu_name;
#ifdef __WIN32__
@@ -467,8 +466,6 @@ int main(int argc, char **argv)
/*
* Construct the path of the executable.
*/
- cpuinfo = erts_cpu_info_create();
-
#if defined(__WIN32__) && defined(WIN32_ALWAYS_DEBUG)
emu_type = "debug";
#endif
@@ -526,9 +523,6 @@ int main(int argc, char **argv)
i++;
}
- erts_cpu_info_destroy(cpuinfo);
- cpuinfo = NULL;
-
if (malloc_lib) {
if (strcmp(malloc_lib, "libc") != 0)
usage("+MYm");
@@ -662,15 +656,6 @@ int main(int argc, char **argv)
}
break;
- case 'i':
- if (strcmp(argv[i], "-instr") == 0) {
- add_Eargs("-Mim");
- add_Eargs("true");
- }
- else
- add_arg(argv[i]);
- break;
-
case 'e':
if (strcmp(argv[i], "-extra") == 0) {
process_args = 0;
diff --git a/erts/etc/unix/etp-commands.in b/erts/etc/unix/etp-commands.in
index f2b2ab1d9a..66d6d20c4e 100644
--- a/erts/etc/unix/etp-commands.in
+++ b/erts/etc/unix/etp-commands.in
@@ -4124,14 +4124,6 @@ define etp-block-size-1
set $etp_blk_sz = ($arg0)->bhdr & ~7
else
# Allocated block
- if !$etp_MBC_ABLK_SZ_MASK
- if etp_arch_bits == 64
- set $etp_MBC_ABLK_OFFSET_SHIFT = (64 - 24)
- else
- set $etp_MBC_ABLK_OFFSET_SHIFT = (32 - 9)
- end
- set $etp_MBC_ABLK_SZ_MASK = ((UWord)1 << $etp_MBC_ABLK_OFFSET_SHIFT) - 1 - 7
- end
set $etp_blk_sz = ($arg0)->bhdr & $etp_MBC_ABLK_SZ_MASK
end
end
@@ -4146,14 +4138,7 @@ define etp-block2mbc-1
set $etp_mbc = ($arg0)->u.carrier
else
# Allocated block
- if !$etp_MBC_ABLK_OFFSET_SHIFT
- if etp_arch_bits == 64
- set $etp_MBC_ABLK_OFFSET_SHIFT = (64 - 24)
- else
- set $etp_MBC_ABLK_OFFSET_SHIFT = (32 - 9)
- end
- end
- set $etp_mbc = (Carrier_t*) ((((UWord)($arg0) >> 18) - (($arg0)->bhdr >> $etp_MBC_ABLK_OFFSET_SHIFT)) << 18)
+ set $etp_mbc = (Carrier_t*) ((((UWord)($arg0) >> 18) - ((($arg0)->bhdr & $etp_MBC_ABLK_OFFSET_MASK) >> $etp_MBC_ABLK_OFFSET_SHIFT)) << 18)
end
end
@@ -4197,7 +4182,7 @@ document etp-smp-atomic
%---------------------------------------------------------------------------
end
-define etp-carrier-blocks
+define etp-carrier-blocks-1
set $etp_crr = (Carrier_t*) $arg0
etp-smp-atomic $etp_crr->allctr $etp_alc
set $etp_alc = (Allctr_t*)($etp_alc & ~7)
@@ -4209,12 +4194,6 @@ define etp-carrier-blocks
set $etp_fblk_cnt = 0
set $etp_aborted = 0
- if $argc == 2
- set $etp_be_silent = $arg1
- else
- set $etp_be_silent = 0
- end
-
while 1
if !$etp_be_silent
etp-block $etp_blk
@@ -4237,6 +4216,12 @@ define etp-carrier-blocks
printf "ERROR: Missing PREV_FREE_BLK_HDR_FLG (2) in block at %#lx\n", $etp_blk
set $etp_error_cnt = $etp_error_cnt + 1
end
+ else
+ # Prev is ALLOCATED
+ if ($etp_blk->bhdr & 2)
+ printf "ERROR: Invalid PREV_FREE_BLK_HDR_FLG (2) set in block at %#lx\n", $etp_blk
+ set $etp_error_cnt = $etp_error_cnt + 1
+ end
end
end
if $etp_blk->bhdr & 1
@@ -4274,13 +4259,31 @@ define etp-carrier-blocks
end
end
-document etp-carrier-blocks
+define etp-carrier-print
+ set $etp_be_silent = 0
+ etp-carrier-blocks-1 $arg0
+end
+
+document etp-carrier-print
+%---------------------------------------------------------------------------
+% Print all memory blocks in carrier
+% Args: (Carrier_t*)
+%---------------------------------------------------------------------------
+end
+
+define etp-carrier-check
+ set $etp_be_silent = 1
+ etp-carrier-blocks-1 $arg0
+end
+
+document etp-carrier-check
%---------------------------------------------------------------------------
-% Check and (maybe) print all memory blocks in carrier
-% Args: (Carrier_t*) [1=be_silent]
+% Check all memory blocks in carrier
+% Args: (Carrier_t*)
%---------------------------------------------------------------------------
end
+
define etp-address-to-beam-opcode
set $etp_i = 0
set $etp_min_diff = ((UWord)1 << (sizeof(UWord)*8 - 1))
@@ -4412,9 +4415,14 @@ define etp-init
set $etp_arch64 = (sizeof(void *) == 8)
if $etp_arch64
set $etp_nil = 0xfffffffffffffffb
+ set $etp_MBC_ABLK_OFFSET_BITS = 23
else
set $etp_nil = 0xfffffffb
+ set $etp_MBC_ABLK_OFFSET_BITS = 8
end
+ set $etp_MBC_ABLK_OFFSET_SHIFT = (sizeof(UWord)*8 - 1 - $etp_MBC_ABLK_OFFSET_BITS)
+ set $etp_MBC_ABLK_OFFSET_MASK = ((((UWord)1 << $etp_MBC_ABLK_OFFSET_BITS) - 1) << $etp_MBC_ABLK_OFFSET_SHIFT)
+ set $etp_MBC_ABLK_SZ_MASK = ((UWord)1 << $etp_MBC_ABLK_OFFSET_SHIFT) - 1 - 7
set $etp_flat = 0
set $etp_chart_id = 0
set $etp_chart = 0
diff --git a/erts/preloaded/ebin/erl_init.beam b/erts/preloaded/ebin/erl_init.beam
index 81be5b021a..0313988e3e 100644
--- a/erts/preloaded/ebin/erl_init.beam
+++ b/erts/preloaded/ebin/erl_init.beam
Binary files differ
diff --git a/erts/preloaded/ebin/net.beam b/erts/preloaded/ebin/net.beam
index ebb1296b95..f61b2b4a69 100644
--- a/erts/preloaded/ebin/net.beam
+++ b/erts/preloaded/ebin/net.beam
Binary files differ
diff --git a/erts/preloaded/ebin/socket.beam b/erts/preloaded/ebin/socket.beam
index e44dff8475..558a886565 100644
--- a/erts/preloaded/ebin/socket.beam
+++ b/erts/preloaded/ebin/socket.beam
Binary files differ
diff --git a/erts/preloaded/src/Makefile b/erts/preloaded/src/Makefile
index efeb92dce9..27d450c873 100644
--- a/erts/preloaded/src/Makefile
+++ b/erts/preloaded/src/Makefile
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 2008-2018. All Rights Reserved.
+# Copyright Ericsson AB 2008-2019. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -33,14 +33,22 @@ STATIC_EBIN=../ebin
include $(ERL_TOP)/erts/vsn.mk
include $(ERL_TOP)/lib/kernel/vsn.mk
+ifeq ($(USE_ESOCK), yes)
+PRE_LOADED_ERL_ESOCK_MODULES = \
+ socket \
+ net
+else
+PRE_LOADED_ERL_ESOCK_MODULES = \
+ net
+endif
+
PRE_LOADED_ERL_MODULES = \
erl_prim_loader \
init \
prim_buffer \
prim_file \
prim_inet \
- socket \
- net \
+ $(PRE_LOADED_ERL_ESOCK_MODULES) \
zlib \
prim_zip \
erl_init \
@@ -73,6 +81,11 @@ STATIC_TARGET_FILES = $(PRE_LOADED_MODULES:%=$(STATIC_EBIN)/%.$(EMULATOR))
APP_FILE= erts.app
APP_SRC= $(APP_FILE).src
APP_TARGET= $(STATIC_EBIN)/$(APP_FILE)
+ifeq ($(USE_ESOCK), yes)
+APP_ESOCK_MODS= net, socket
+else
+APP_ESOCK_MODS= net
+endif
KERNEL_SRC=$(ERL_TOP)/lib/kernel/src
@@ -94,7 +107,7 @@ copy:
cp *.beam $(STATIC_EBIN)
$(APP_TARGET): $(APP_SRC) $(ERL_TOP)/erts/vsn.mk
- $(vsn_verbose)sed -e 's;%VSN%;$(VSN);' $< > $@
+ $(vsn_verbose)sed -e 's;%VSN%;$(VSN);' -e 's;%ESOCK_MODS%;$(APP_ESOCK_MODS);' $< > $@
include $(ERL_TOP)/make/otp_release_targets.mk
diff --git a/erts/preloaded/src/erl_init.erl b/erts/preloaded/src/erl_init.erl
index 6edead362c..d209c4033b 100644
--- a/erts/preloaded/src/erl_init.erl
+++ b/erts/preloaded/src/erl_init.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2000-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2000-2019. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -35,8 +35,7 @@ start(Mod, BootArgs) ->
erl_tracer:on_load(),
prim_buffer:on_load(),
prim_file:on_load(),
- socket:on_load(),
- net:on_load(),
+ conditional_load(socket, [socket, net]), % socket:on_load(), net:on_load(),
%% Proceed to the specified boot module
run(Mod, boot, BootArgs).
@@ -48,3 +47,24 @@ run(M, F, A) ->
true ->
M:F(A)
end.
+
+conditional_load(CondMod, Mods2Load) ->
+ conditional_load(CondMod, erlang:loaded(), Mods2Load).
+
+conditional_load(_CondMod, [], _Mods2LOad) ->
+ ok;
+conditional_load(CondMod, [CondMod|_], Mods2Load) ->
+ on_load(Mods2Load);
+conditional_load(CondMod, [_|T], Mods2Load) ->
+ conditional_load(CondMod, T, Mods2Load).
+
+on_load([]) ->
+ ok;
+on_load([Mod|Mods]) ->
+ Mod:on_load(),
+ on_load(Mods).
+
+
+
+
+
diff --git a/erts/preloaded/src/erts.app.src b/erts/preloaded/src/erts.app.src
index c2a8511b6d..132397b478 100644
--- a/erts/preloaded/src/erts.app.src
+++ b/erts/preloaded/src/erts.app.src
@@ -36,8 +36,7 @@
atomics,
counters,
zlib,
- net,
- socket
+ %ESOCK_MODS%
]},
{registered, []},
{applications, []},
diff --git a/erts/preloaded/src/net.erl b/erts/preloaded/src/net.erl
index a24b5c8ce3..13d2e3a117 100644
--- a/erts/preloaded/src/net.erl
+++ b/erts/preloaded/src/net.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2018-2018. All Rights Reserved.
+%% Copyright Ericsson AB 2018-2019. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -178,12 +178,28 @@ getnameinfo(SockAddr, [] = _Flags) ->
getnameinfo(#{family := Fam, addr := _Addr} = SockAddr, Flags)
when ((Fam =:= inet) orelse (Fam =:= inet6)) andalso
(is_list(Flags) orelse (Flags =:= undefined)) ->
- nif_getnameinfo(socket:ensure_sockaddr(SockAddr), Flags);
+ nif_getnameinfo((catch ensure_sockaddr(SockAddr)), Flags);
getnameinfo(#{family := Fam, path := _Path} = SockAddr, Flags)
when (Fam =:= local) andalso (is_list(Flags) orelse (Flags =:= undefined)) ->
nif_getnameinfo(SockAddr, Flags).
+%% This function is intended to "handle" the case when the user
+%% has built their (OTP) system with "--disable-esock".
+%% That means the socket module does not exist. This is not really
+%% a problem since the nif_getnameinfo won't work either (since
+%% the nif file is not part of the system). The result of calling
+%% getnameinfo will be a undef exception (erlang:nif_error(undef)).
+%%
+%% The only functions in this module that actually work in this case
+%% (--disable-esock) is the depricated stuff (call, cast, ...).
+%%
+ensure_sockaddr(SockAddr) ->
+ try socket:ensure_sockaddr(SockAddr)
+ catch
+ error:undef:_ ->
+ undefined
+ end.
%% ===========================================================================
%%
@@ -334,3 +350,4 @@ nif_if_index2name(_Id) ->
nif_if_names() ->
erlang:nif_error(undef).
+
diff --git a/erts/preloaded/src/socket.erl b/erts/preloaded/src/socket.erl
index 5c1647290d..126db66cdd 100644
--- a/erts/preloaded/src/socket.erl
+++ b/erts/preloaded/src/socket.erl
@@ -520,7 +520,7 @@
%% necessary adapt (increase) the buffer size until all of
%% it fits.
%%
-%% Note that not all of these flags is useful for every recv function!
+%% Note that not all of these flags are useful for every recv function!
%%
-type recv_flags() :: [recv_flag()].
-type recv_flag() :: cmsg_cloexec |
@@ -531,7 +531,6 @@
-type shutdown_how() :: read | write | read_write.
-%% These are just place-holder(s) - used by the sendmsg/recvmsg functions...
-type msghdr_flag() :: ctrunc | eor | errqueue | oob | trunc.
-type msghdr_flags() :: [msghdr_flag()].
-type msghdr() :: #{
@@ -586,6 +585,12 @@
#{level := integer(), type := integer(), data := binary()}.
+%% This is used in messages sent from the nif-code to erlang processes:
+%%
+%% {?SOCKET_TAG, Socket :: socket(), Tag :: atom(), Info :: term()}
+%%
+-define(SOCKET_TAG, '$socket').
+
-define(SOCKET_DOMAIN_LOCAL, 1).
-define(SOCKET_DOMAIN_UNIX, ?SOCKET_DOMAIN_LOCAL).
-define(SOCKET_DOMAIN_INET, 2).
@@ -949,77 +954,50 @@ supports(_Key1, _Key2, _Key3) ->
%% ===========================================================================
%%
-%% open - create an endpoint for communication
-%%
-%% Extra: netns
-%%
%% <KOLLA>
%%
%% How do we handle the case when an fd has been created (somehow)
%% and we shall create a socket "from it".
%% Can we figure out Domain, Type and Protocol from fd?
-%% Yes we can: SO_DOMAIN, SO_PROTOCOL, SO_TYPE
-%% But does that work on all platforms? Or shall we require that the
-%% caller provide this explicitly?
-%%
+%% No we can't: For instance, its not possible to 'get' domain on FreeBSD.
+%%
+%% Instead, require: open(Domain, Stream, Proto, #{fd => FD}).
+%% The last argument, Extra, is used to provide the fd.
+%%
%% </KOLLA>
%%
%%
%% <KOLLA>
%%
-%% Start a controller process here, *before* the nif_open call.
-%% If that call is successful, update with owner process (controlling
-%% process) and SockRef. If the open fails, kill the process.
-%% "Register" the process on success:
-%%
-%% nif_register(SockRef, self()).
-%%
-%% <ALSO>
-%%
-%% Maybe register the process under a name?
-%% Something like:
-%%
-%% list_to_atom(lists:flatten(io_lib:format("socket-~p", [SockRef]))).
-%%
-%% </ALSO>
+%% Possibly add a "registry" in the nif, allowing the user processes to
+%% "register" themselves.
+%% The point of this would be to ensure that these processes are
+%% informed if the socket "terminates". Could possibly be used for
+%% other things? If gen_tcp implements the active feature using
+%% a reader process, the nif may need to know about this process,
+%% since its probably "hidden" from the socket "owner" (someone
+%% needs to handle it if it dies).
+%% Register under a name?
%%
%% The nif sets up a monitor to this process, and if it dies the socket
%% is closed. It is also used if someone wants to monitor the socket.
%%
-%% We therefor need monitor function(s):
+%% We may therefor need monitor function(s):
%%
%% socket:monitor(Socket)
%% socket:demonitor(Socket)
%%
-%% These are basically used to monitor the controller process.
-%% Should the socket record therefor contain the pid of the controller process?
-%%
%% </KOLLA>
%%
-%% -spec open(FD) -> {ok, Socket} | {error, Reason} when
-%% Socket :: socket(),
-%% Reason :: term().
-
-%% open(FD) ->
-%% try
-%% begin
-%% case nif_open(FD) of
-%% {ok, {SockRef, Domain, Type, Protocol}} ->
-%% SocketInfo = #{domain => Domain,
-%% type => Type,
-%% protocol => Protocol},
-%% Socket = #socket{info = SocketInfo,
-%% ref = SockRef},
-%% {ok, Socket};
-%% {error, _} = ERROR ->
-%% ERROR
-%% end
-%% end
-%% catch
-%% _:_ -> % This must be improved!!
-%% {error, einval}
-%% end.
+
+
+%% ===========================================================================
+%%
+%% open - create an endpoint for communication
+%%
+%% Extra: Currently only used for netns
+%%
-spec open(Domain, Type) -> {ok, Socket} | {error, Reason} when
Domain :: domain(),
@@ -1245,21 +1223,7 @@ connect(#socket{ref = SockRef}, #{family := Fam} = SockAddr, Timeout)
%% Connecting...
NewTimeout = next_timeout(TS, Timeout),
receive
- {select, SockRef, Ref, ready_output} ->
- %% <KOLLA>
- %%
- %% See open above!!
- %%
- %% * Here we should start and *register* the reader process
- %% (This will cause the nif code to create a monitor to
- %% the process)
- %% * The reader is basically used to implement the active-X
- %% feature!
- %% * If the reader dies for whatever reason, then the socket
- %% (resource) closes and the owner (controlling) process
- %% is informed (closed message).
- %%
- %% </KOLLA>
+ {?SOCKET_TAG, #socket{ref = SockRef}, select, Ref} ->
nif_finalize_connection(SockRef)
after NewTimeout ->
cancel(SockRef, connect, Ref),
@@ -1325,16 +1289,6 @@ do_accept(LSockRef, Timeout) ->
AccRef = make_ref(),
case nif_accept(LSockRef, AccRef) of
{ok, SockRef} ->
- %% <KOLLA>
- %%
- %% * Here we should start and *register* the reader process
- %% (This will cause the nif code to create a monitor to the process)
- %% * The reader is basically used to implement the active-X feature!
- %% * If the reader dies for whatever reason, then the socket (resource)
- %% closes and the owner (controlling) process is informed (closed
- %% message).
- %%
- %% </KOLLA>
Socket = #socket{ref = SockRef},
{ok, Socket};
@@ -1344,10 +1298,10 @@ do_accept(LSockRef, Timeout) ->
%% the receive.
NewTimeout = next_timeout(TS, Timeout),
receive
- {select, LSockRef, AccRef, ready_input} ->
+ {?SOCKET_TAG, #socket{ref = LSockRef}, select, AccRef} ->
do_accept(LSockRef, next_timeout(TS, Timeout));
- {'$socket', _, abort, {AccRef, Reason}} ->
+ {?SOCKET_TAG, _Socket, abort, {AccRef, Reason}} ->
{error, Reason}
after NewTimeout ->
@@ -1416,15 +1370,17 @@ do_send(SockRef, Data, EFlags, Timeout) ->
NewTimeout = next_timeout(TS, Timeout),
%% We are partially done, wait for continuation
receive
- {select, SockRef, SendRef, ready_output} when (Written > 0) ->
+ {?SOCKET_TAG, #socket{ref = SockRef}, select, SendRef}
+ when (Written > 0) ->
<<_:Written/binary, Rest/binary>> = Data,
do_send(SockRef, Rest, EFlags,
next_timeout(TS, Timeout));
- {select, SockRef, SendRef, ready_output} ->
+
+ {?SOCKET_TAG, #socket{ref = SockRef}, select, SendRef} ->
do_send(SockRef, Data, EFlags,
next_timeout(TS, Timeout));
- {'$socket', _, abort, {SendRef, Reason}} ->
+ {?SOCKET_TAG, _Socket, abort, {SendRef, Reason}} ->
{error, Reason}
after NewTimeout ->
@@ -1433,11 +1389,11 @@ do_send(SockRef, Data, EFlags, Timeout) ->
end;
{error, eagain} ->
receive
- {select, SockRef, SendRef, ready_output} ->
+ {?SOCKET_TAG, #socket{ref = SockRef}, select, SendRef} ->
do_send(SockRef, Data, EFlags,
next_timeout(TS, Timeout));
- {'$socket', _, abort, {SendRef, Reason}} ->
+ {?SOCKET_TAG, _Socket, abort, {SendRef, Reason}} ->
{error, Reason}
after Timeout ->
@@ -1521,15 +1477,17 @@ do_sendto(SockRef, Data, Dest, EFlags, Timeout) ->
{ok, Written} ->
%% We are partially done, wait for continuation
receive
- {select, SockRef, SendRef, ready_output} when (Written > 0) ->
+ {?SOCKET_TAG, #socket{ref = SockRef}, select, SendRef}
+ when (Written > 0) ->
<<_:Written/binary, Rest/binary>> = Data,
do_sendto(SockRef, Rest, Dest, EFlags,
next_timeout(TS, Timeout));
- {select, SockRef, SendRef, ready_output} ->
+
+ {?SOCKET_TAG, #socket{ref = SockRef}, select, SendRef} ->
do_sendto(SockRef, Data, Dest, EFlags,
next_timeout(TS, Timeout));
- {'$socket', _, abort, {SendRef, Reason}} ->
+ {?SOCKET_TAG, _Socket, abort, {SendRef, Reason}} ->
{error, Reason}
after Timeout ->
@@ -1539,11 +1497,11 @@ do_sendto(SockRef, Data, Dest, EFlags, Timeout) ->
{error, eagain} ->
receive
- {select, SockRef, SendRef, ready_output} ->
+ {?SOCKET_TAG, #socket{ref = SockRef}, select, SendRef} ->
do_sendto(SockRef, Data, Dest, EFlags,
next_timeout(TS, Timeout));
- {'$socket', _, abort, {SendRef, Reason}} ->
+ {?SOCKET_TAG, _Socket, abort, {SendRef, Reason}} ->
{error, Reason}
after Timeout ->
@@ -1593,7 +1551,8 @@ sendmsg(Socket, MsgHdr, Timeout)
sendmsg(Socket, MsgHdr, ?SOCKET_SENDMSG_FLAGS_DEFAULT, Timeout).
--spec sendmsg(Socket, MsgHdr, Flags, Timeout) -> ok | {ok, Remaining} | {error, Reason} when
+-spec sendmsg(Socket, MsgHdr, Flags, Timeout) ->
+ ok | {ok, Remaining} | {error, Reason} when
Socket :: socket(),
MsgHdr :: msghdr(),
Flags :: send_flags(),
@@ -1625,7 +1584,6 @@ do_sendmsg(SockRef, MsgHdr, EFlags, Timeout) ->
ok;
{ok, Written} when is_integer(Written) andalso (Written > 0) ->
-
%% We should not retry here since the protocol may not
%% be able to handle a message being split. Leave it to
%% the caller to figure out (call again with the rest).
@@ -1638,9 +1596,10 @@ do_sendmsg(SockRef, MsgHdr, EFlags, Timeout) ->
{error, eagain} ->
receive
- {select, SockRef, SendRef, ready_output} ->
+ {?SOCKET_TAG, #socket{ref = SockRef}, select, SendRef} ->
do_sendmsg(SockRef, MsgHdr, EFlags,
next_timeout(TS, Timeout))
+
after Timeout ->
cancel(SockRef, sendmsg, SendRef),
{error, timeout}
@@ -1668,13 +1627,6 @@ ensure_msghdr(_) ->
%% ===========================================================================
%%
-%% writev - write data into multiple buffers
-%%
-
-
-
-%% ===========================================================================
-%%
%% recv, recvfrom, recvmsg - receive a message from a socket
%%
%% Description:
@@ -1757,14 +1709,10 @@ do_recv(SockRef, _OldRef, Length, EFlags, Acc, Timeout)
(is_integer(Timeout) andalso (Timeout > 0)) ->
TS = timestamp(Timeout),
RecvRef = make_ref(),
- %% p("do_recv -> try read with"
- %% "~n Length: ~p", [Length]),
case nif_recv(SockRef, RecvRef, Length, EFlags) of
{ok, true = _Complete, Bin} when (size(Acc) =:= 0) ->
- %% p("do_recv -> complete success: ~w", [size(Bin)]),
{ok, Bin};
{ok, true = _Complete, Bin} ->
- %% p("do_recv -> completed success: ~w (~w)", [size(Bin), size(Acc)]),
{ok, <<Acc/binary, Bin/binary>>};
%% It depends on the amount of bytes we tried to read:
@@ -1773,7 +1721,6 @@ do_recv(SockRef, _OldRef, Length, EFlags, Acc, Timeout)
%% > 0 - We got a part of the message and we will be notified
%% when there is more to read (a select message)
{ok, false = _Complete, Bin} when (Length =:= 0) ->
- %% p("do_recv -> partial success: ~w", [size(Bin)]),
do_recv(SockRef, RecvRef,
Length, EFlags,
<<Acc/binary, Bin/binary>>,
@@ -1783,17 +1730,15 @@ do_recv(SockRef, _OldRef, Length, EFlags, Acc, Timeout)
%% We got the first chunk of it.
%% We will be notified (select message) when there
%% is more to read.
- %% p("do_recv -> partial success(~w): ~w"
- %% "~n ~p", [Length, size(Bin), Bin]),
NewTimeout = next_timeout(TS, Timeout),
receive
- {select, SockRef, RecvRef, ready_input} ->
+ {?SOCKET_TAG, #socket{ref = SockRef}, select, RecvRef} ->
do_recv(SockRef, RecvRef,
Length-size(Bin), EFlags,
Bin,
next_timeout(TS, Timeout));
- {'$socket', _, abort, {RecvRef, Reason}} ->
+ {?SOCKET_TAG, _Socket, abort, {RecvRef, Reason}} ->
{error, Reason}
after NewTimeout ->
@@ -1803,17 +1748,15 @@ do_recv(SockRef, _OldRef, Length, EFlags, Acc, Timeout)
{ok, false = _Completed, Bin} ->
%% We got a chunk of it!
- %% p("do_recv -> partial success(~w): ~w (~w)",
- %% [Length, size(Bin), size(Acc)]),
NewTimeout = next_timeout(TS, Timeout),
receive
- {select, SockRef, RecvRef, ready_input} ->
+ {?SOCKET_TAG, #socket{ref = SockRef}, select, RecvRef} ->
do_recv(SockRef, RecvRef,
Length-size(Bin), EFlags,
<<Acc/binary, Bin/binary>>,
next_timeout(TS, Timeout));
- {'$socket', _, abort, {RecvRef, Reason}} ->
+ {?SOCKET_TAG, _Socket, abort, {RecvRef, Reason}} ->
{error, Reason}
after NewTimeout ->
@@ -1829,16 +1772,15 @@ do_recv(SockRef, _OldRef, Length, EFlags, Acc, Timeout)
{error, eagain} ->
%% There is nothing just now, but we will be notified when there
%% is something to read (a select message).
- %% p("do_recv -> eagain(~w): ~w", [Length, size(Acc)]),
NewTimeout = next_timeout(TS, Timeout),
receive
- {select, SockRef, RecvRef, ready_input} ->
+ {?SOCKET_TAG, #socket{ref = SockRef}, select, RecvRef} ->
do_recv(SockRef, RecvRef,
Length, EFlags,
Acc,
next_timeout(TS, Timeout));
- {'$socket', _, abort, {RecvRef, Reason}} ->
+ {?SOCKET_TAG, _Socket, abort, {RecvRef, Reason}} ->
{error, Reason}
after NewTimeout ->
@@ -1887,7 +1829,7 @@ do_recv(_SockRef, _RecvRef, _Length, _EFlags, _Acc, _Timeout) ->
%% It may be impossible to know what (buffer) size is appropriate
%% "in advance", and in those cases it may be convenient to use the
%% (recv) 'peek' flag. When this flag is provided the message is *not*
-%% "consumed" from the underlying buffers, so another recvfrom call
+%% "consumed" from the underlying (OS) buffers, so another recvfrom call
%% is needed, possibly with a then adjusted buffer size.
%%
@@ -1973,11 +1915,11 @@ do_recvfrom(SockRef, BufSz, EFlags, Timeout) ->
%% is something to read (a select message).
NewTimeout = next_timeout(TS, Timeout),
receive
- {select, SockRef, RecvRef, ready_input} ->
+ {?SOCKET_TAG, #socket{ref = SockRef}, select, RecvRef} ->
do_recvfrom(SockRef, BufSz, EFlags,
next_timeout(TS, Timeout));
- {'$socket', _, abort, {RecvRef, Reason}} ->
+ {?SOCKET_TAG, _Socket, abort, {RecvRef, Reason}} ->
{error, Reason}
after NewTimeout ->
@@ -1990,13 +1932,6 @@ do_recvfrom(SockRef, BufSz, EFlags, Timeout) ->
end.
-%% pi(Item) ->
-%% pi(self(), Item).
-
-%% pi(Pid, Item) ->
-%% {Item, Info} = process_info(Pid, Item),
-%% Info.
-
%% ---------------------------------------------------------------------------
%%
@@ -2077,11 +2012,11 @@ do_recvmsg(SockRef, BufSz, CtrlSz, EFlags, Timeout) ->
%% is something to read (a select message).
NewTimeout = next_timeout(TS, Timeout),
receive
- {select, SockRef, RecvRef, ready_input} ->
+ {?SOCKET_TAG, #socket{ref = SockRef}, select, RecvRef} ->
do_recvmsg(SockRef, BufSz, CtrlSz, EFlags,
next_timeout(TS, Timeout));
- {'$socket', _, abort, {RecvRef, Reason}} ->
+ {?SOCKET_TAG, _Socket, abort, {RecvRef, Reason}} ->
{error, Reason}
after NewTimeout ->
@@ -2100,12 +2035,6 @@ do_recvmsg(SockRef, BufSz, CtrlSz, EFlags, Timeout) ->
-%% ===========================================================================
-%%
-%% readv - read data into multiple buffers
-%%
-
-
%% ===========================================================================
%%
@@ -2118,10 +2047,9 @@ do_recvmsg(SockRef, BufSz, CtrlSz, EFlags, Timeout) ->
%% 1) nif_close + the socket_stop (nif) callback function
%% This is for everything that can be done safely NON-BLOCKING.
%% 2) nif_finalize_close which is executed by a *dirty* scheduler
-%% Before we call the socket close function, we se the socket
+%% Before we call the socket close function, we set the socket
%% BLOCKING. Thereby linger is handled properly.
-
-spec close(Socket) -> ok | {error, Reason} when
Socket :: socket(),
Reason :: term().
@@ -2137,7 +2065,7 @@ do_close(SockRef) ->
%% We must wait for the socket_stop callback function to
%% complete its work
receive
- {'$socket', SockRef, close, CloseRef} ->
+ {?SOCKET_TAG, #socket{ref = SockRef}, close, CloseRef} ->
nif_finalize_close(SockRef)
end;
{error, _} = ERROR ->
@@ -2381,6 +2309,8 @@ which_protocol(SockRef) ->
end.
+
+
%% ===========================================================================
%%
%% sockname - return the current address of the socket.
@@ -3499,7 +3429,7 @@ cancel(SockRef, Op, OpRef) ->
flush_select_msgs(SockRef, Ref) ->
receive
- {select, SockRef, Ref, _} ->
+ {?SOCKET_TAG, #socket{ref = SockRef}, select, Ref} ->
flush_select_msgs(SockRef, Ref)
after 0 ->
ok
@@ -3568,8 +3498,9 @@ tdiff(T1, T2) ->
%% p(undefined, F, A) ->
%% p("***", F, A);
%% p(SName, F, A) ->
-%% io:format(user,"[~s,~p] " ++ F ++ "~n", [SName, self()|A]),
-%% io:format("[~s,~p] " ++ F ++ "~n", [SName, self()|A]).
+%% TS = formated_timestamp(),
+%% io:format(user,"[~s][~s,~p] " ++ F ++ "~n", [TS, SName, self()|A]),
+%% io:format("[~s][~s,~p] " ++ F ++ "~n", [TS, SName, self()|A]).
diff --git a/lib/compiler/src/beam_ssa_pre_codegen.erl b/lib/compiler/src/beam_ssa_pre_codegen.erl
index bad43a9c4e..bf99e8fc26 100644
--- a/lib/compiler/src/beam_ssa_pre_codegen.erl
+++ b/lib/compiler/src/beam_ssa_pre_codegen.erl
@@ -342,21 +342,22 @@ make_save_point_dict_1([], Ctx, I, Acc) ->
[{Ctx,I}|Acc].
bs_restores([{L,#b_blk{is=Is,last=Last}}|Bs], CtxChain, D0, Rs0) ->
- FPos = case D0 of
- #{L:=Pos0} -> Pos0;
- #{} -> #{}
- end,
- {SPos,Rs} = bs_restores_is(Is, CtxChain, FPos, Rs0),
- D = bs_update_successors(Last, SPos, FPos, D0),
+ InPos = maps:get(L, D0, #{}),
+ {SuccPos, FailPos, Rs} = bs_restores_is(Is, CtxChain, InPos, InPos, Rs0),
+
+ D = bs_update_successors(Last, SuccPos, FailPos, D0),
bs_restores(Bs, CtxChain, D, Rs);
bs_restores([], _, _, Rs) -> Rs.
bs_update_successors(#b_br{succ=Succ,fail=Fail}, SPos, FPos, D) ->
join_positions([{Succ,SPos},{Fail,FPos}], D);
-bs_update_successors(#b_switch{fail=Fail,list=List}, SPos, _FPos, D) ->
+bs_update_successors(#b_switch{fail=Fail,list=List}, SPos, FPos, D) ->
+ SPos = FPos, %Assertion.
Update = [{L,SPos} || {_,L} <- List] ++ [{Fail,SPos}],
join_positions(Update, D);
-bs_update_successors(#b_ret{}, _, _, D) -> D.
+bs_update_successors(#b_ret{}, SPos, FPos, D) ->
+ SPos = FPos, %Assertion.
+ D.
join_positions([{L,MapPos0}|T], D) ->
case D of
@@ -382,75 +383,91 @@ join_positions_1(MapPos0, MapPos1) ->
end, MapPos1),
maps:merge(MapPos0, MapPos2).
+%%
+%% Updates the restore and position maps according to the given instructions.
+%%
+%% Note that positions may be updated even when a match fails; if a match
+%% requires a restore, the position at the fail block will be the position
+%% we've *restored to* and not the one we entered the current block with.
+%%
+
bs_restores_is([#b_set{op=bs_start_match,dst=Start}|Is],
- CtxChain, PosMap0, Rs) ->
- PosMap = PosMap0#{Start=>Start},
- bs_restores_is(Is, CtxChain, PosMap, Rs);
+ CtxChain, SPos0, FPos, Rs) ->
+ %% We only allow one match per block.
+ SPos0 = FPos, %Assertion.
+ SPos = SPos0#{Start=>Start},
+ bs_restores_is(Is, CtxChain, SPos, FPos, Rs);
bs_restores_is([#b_set{op=bs_match,dst=NewPos,args=Args}=I|Is],
- CtxChain, PosMap0, Rs0) ->
+ CtxChain, SPos0, FPos0, Rs0) ->
+ SPos0 = FPos0, %Assertion.
Start = bs_subst_ctx(NewPos, CtxChain),
[_,FromPos|_] = Args,
- case PosMap0 of
+ case SPos0 of
#{Start:=FromPos} ->
%% Same position, no restore needed.
- PosMap = case bs_match_type(I) of
+ SPos = case bs_match_type(I) of
plain ->
%% Update position to new position.
- PosMap0#{Start:=NewPos};
+ SPos0#{Start:=NewPos};
_ ->
%% Position will not change (test_unit
%% instruction or no instruction at
%% all).
- PosMap0#{Start:=FromPos}
+ SPos0#{Start:=FromPos}
end,
- bs_restores_is(Is, CtxChain, PosMap, Rs0);
+ bs_restores_is(Is, CtxChain, SPos, FPos0, Rs0);
#{Start:=_} ->
%% Different positions, might need a restore instruction.
case bs_match_type(I) of
none ->
- %% The tail test will be optimized away.
- %% No need to do a restore.
- PosMap = PosMap0#{Start:=FromPos},
- bs_restores_is(Is, CtxChain, PosMap, Rs0);
+ %% This is a tail test that will be optimized away.
+ %% There's no need to do a restore, and all
+ %% positions are unchanged.
+ bs_restores_is(Is, CtxChain, SPos0, FPos0, Rs0);
test_unit ->
%% This match instruction will be replaced by
%% a test_unit instruction. We will need a
%% restore. The new position will be the position
%% restored to (NOT NewPos).
- PosMap = PosMap0#{Start:=FromPos},
+ SPos = SPos0#{Start:=FromPos},
+ FPos = FPos0#{Start:=FromPos},
Rs = Rs0#{NewPos=>{Start,FromPos}},
- bs_restores_is(Is, CtxChain, PosMap, Rs);
+ bs_restores_is(Is, CtxChain, SPos, FPos, Rs);
plain ->
%% Match or skip. Position will be changed.
- PosMap = PosMap0#{Start:=NewPos},
+ SPos = SPos0#{Start:=NewPos},
+ FPos = FPos0#{Start:=FromPos},
Rs = Rs0#{NewPos=>{Start,FromPos}},
- bs_restores_is(Is, CtxChain, PosMap, Rs)
+ bs_restores_is(Is, CtxChain, SPos, FPos, Rs)
end
end;
bs_restores_is([#b_set{op=bs_extract,args=[FromPos|_]}|Is],
- CtxChain, PosMap, Rs) ->
+ CtxChain, SPos, FPos, Rs) ->
Start = bs_subst_ctx(FromPos, CtxChain),
- #{Start:=FromPos} = PosMap, %Assertion.
- bs_restores_is(Is, CtxChain, PosMap, Rs);
+ #{Start:=FromPos} = SPos, %Assertion.
+ #{Start:=FromPos} = FPos, %Assertion.
+ bs_restores_is(Is, CtxChain, SPos, FPos, Rs);
bs_restores_is([#b_set{op=call,dst=Dst,args=Args}|Is],
- CtxChain, PosMap0, Rs0) ->
- {Rs,PosMap1} = bs_restore_args(Args, PosMap0, CtxChain, Dst, Rs0),
- PosMap = bs_invalidate_pos(Args, PosMap1, CtxChain),
- bs_restores_is(Is, CtxChain, PosMap, Rs);
-bs_restores_is([#b_set{op=landingpad}|Is], CtxChain, PosMap0, Rs) ->
+ CtxChain, SPos0, FPos0, Rs0) ->
+ {Rs, SPos1, FPos1} = bs_restore_args(Args, SPos0, FPos0, CtxChain, Dst, Rs0),
+ {SPos, FPos} = bs_invalidate_pos(Args, SPos1, FPos1, CtxChain),
+ bs_restores_is(Is, CtxChain, SPos, FPos, Rs);
+bs_restores_is([#b_set{op=landingpad}|Is], CtxChain, SPos0, FPos0, Rs) ->
%% We can land here from any point, so all positions are invalid.
- PosMap = maps:map(fun(_Start,_Pos) -> unknown end, PosMap0),
- bs_restores_is(Is, CtxChain, PosMap, Rs);
+ Invalidate = fun(_Start,_Pos) -> unknown end,
+ SPos = maps:map(Invalidate, SPos0),
+ FPos = maps:map(Invalidate, FPos0),
+ bs_restores_is(Is, CtxChain, SPos, FPos, Rs);
bs_restores_is([#b_set{op=Op,dst=Dst,args=Args}|Is],
- CtxChain, PosMap0, Rs0)
+ CtxChain, SPos0, FPos0, Rs0)
when Op =:= bs_test_tail;
Op =:= bs_get_tail ->
- {Rs,PosMap} = bs_restore_args(Args, PosMap0, CtxChain, Dst, Rs0),
- bs_restores_is(Is, CtxChain, PosMap, Rs);
-bs_restores_is([_|Is], CtxChain, PosMap, Rs) ->
- bs_restores_is(Is, CtxChain, PosMap, Rs);
-bs_restores_is([], _CtxChain, PosMap, Rs) ->
- {PosMap,Rs}.
+ {Rs, SPos, FPos} = bs_restore_args(Args, SPos0, FPos0, CtxChain, Dst, Rs0),
+ bs_restores_is(Is, CtxChain, SPos, FPos, Rs);
+bs_restores_is([_|Is], CtxChain, SPos, FPos, Rs) ->
+ bs_restores_is(Is, CtxChain, SPos, FPos, Rs);
+bs_restores_is([], _CtxChain, SPos, FPos, Rs) ->
+ {SPos, FPos, Rs}.
bs_match_type(#b_set{args=[#b_literal{val=skip},_Ctx,
#b_literal{val=binary},_Flags,
@@ -464,40 +481,42 @@ bs_match_type(_) ->
%% Call instructions leave the match position in an undefined state,
%% requiring us to invalidate each affected argument.
-bs_invalidate_pos([#b_var{}=Arg|Args], PosMap0, CtxChain) ->
+bs_invalidate_pos([#b_var{}=Arg|Args], SPos0, FPos0, CtxChain) ->
Start = bs_subst_ctx(Arg, CtxChain),
- case PosMap0 of
+ case SPos0 of
#{Start:=_} ->
- PosMap = PosMap0#{Start:=unknown},
- bs_invalidate_pos(Args, PosMap, CtxChain);
+ SPos = SPos0#{Start:=unknown},
+ FPos = FPos0#{Start:=unknown},
+ bs_invalidate_pos(Args, SPos, FPos, CtxChain);
#{} ->
%% Not a match context.
- bs_invalidate_pos(Args, PosMap0, CtxChain)
+ bs_invalidate_pos(Args, SPos0, FPos0, CtxChain)
end;
-bs_invalidate_pos([_|Args], PosMap, CtxChain) ->
- bs_invalidate_pos(Args, PosMap, CtxChain);
-bs_invalidate_pos([], PosMap, _CtxChain) ->
- PosMap.
+bs_invalidate_pos([_|Args], SPos, FPos, CtxChain) ->
+ bs_invalidate_pos(Args, SPos, FPos, CtxChain);
+bs_invalidate_pos([], SPos, FPos, _CtxChain) ->
+ {SPos, FPos}.
-bs_restore_args([#b_var{}=Arg|Args], PosMap0, CtxChain, Dst, Rs0) ->
+bs_restore_args([#b_var{}=Arg|Args], SPos0, FPos0, CtxChain, Dst, Rs0) ->
Start = bs_subst_ctx(Arg, CtxChain),
- case PosMap0 of
+ case SPos0 of
#{Start:=Arg} ->
%% Same position, no restore needed.
- bs_restore_args(Args, PosMap0, CtxChain, Dst, Rs0);
+ bs_restore_args(Args, SPos0, FPos0, CtxChain, Dst, Rs0);
#{Start:=_} ->
%% Different positions, need a restore instruction.
- PosMap = PosMap0#{Start:=Arg},
+ SPos = SPos0#{Start:=Arg},
+ FPos = FPos0#{Start:=Arg},
Rs = Rs0#{Dst=>{Start,Arg}},
- bs_restore_args(Args, PosMap, CtxChain, Dst, Rs);
+ bs_restore_args(Args, SPos, FPos, CtxChain, Dst, Rs);
#{} ->
%% Not a match context.
- bs_restore_args(Args, PosMap0, CtxChain, Dst, Rs0)
+ bs_restore_args(Args, SPos0, FPos0, CtxChain, Dst, Rs0)
end;
-bs_restore_args([_|Args], PosMap, CtxChain, Dst, Rs) ->
- bs_restore_args(Args, PosMap, CtxChain, Dst, Rs);
-bs_restore_args([], PosMap, _CtxChain, _Dst, Rs) ->
- {Rs,PosMap}.
+bs_restore_args([_|Args], SPos, FPos, CtxChain, Dst, Rs) ->
+ bs_restore_args(Args, SPos, FPos, CtxChain, Dst, Rs);
+bs_restore_args([], SPos, FPos, _CtxChain, _Dst, Rs) ->
+ {Rs,SPos,FPos}.
%% Insert all bs_save and bs_restore instructions.
diff --git a/lib/compiler/test/bs_match_SUITE.erl b/lib/compiler/test/bs_match_SUITE.erl
index 41e4918b1e..d97f49c56e 100644
--- a/lib/compiler/test/bs_match_SUITE.erl
+++ b/lib/compiler/test/bs_match_SUITE.erl
@@ -1891,15 +1891,37 @@ expression_before_match_1(R) ->
%% Make sure that context positions are updated on calls.
restore_on_call(Config) when is_list(Config) ->
- ok = restore_on_call_1(<<0, 1, 2>>).
+ ok = restore_on_call_plain(<<0, 1, 2>>),
+ <<"x">> = restore_on_call_match(<<0, "x">>),
+ ok.
-restore_on_call_1(<<0, Rest/binary>>) ->
- <<2>> = restore_on_call_2(Rest),
- <<2>> = restore_on_call_2(Rest), %% {badmatch, <<>>} on missing restore.
+restore_on_call_plain(<<0, Rest/binary>>) ->
+ <<2>> = restore_on_call_plain_1(Rest),
+ %% {badmatch, <<>>} on missing restore.
+ <<2>> = restore_on_call_plain_1(Rest),
ok.
-restore_on_call_2(<<1, Rest/binary>>) -> Rest;
-restore_on_call_2(Other) -> Other.
+restore_on_call_plain_1(<<1, Rest/binary>>) -> Rest;
+restore_on_call_plain_1(Other) -> Other.
+
+%% Calls a function that moves the match context passed to it, and then matches
+%% on its result to confuse the reposition algorithm's success/fail logic.
+restore_on_call_match(<<0, Bin/binary>>) ->
+ case skip_until_zero(Bin) of
+ {skipped, Rest} ->
+ Rest;
+ not_found ->
+ %% The match context did not get repositioned before the
+ %% bs_get_tail instruction here.
+ Bin
+ end.
+
+skip_until_zero(<<0,Rest/binary>>) ->
+ {skipped, Rest};
+skip_until_zero(<<_C,Rest/binary>>) ->
+ skip_until_zero(Rest);
+skip_until_zero(_) ->
+ not_found.
%% 'catch' must invalidate positions.
restore_after_catch(Config) when is_list(Config) ->
@@ -1983,5 +2005,4 @@ do_matching_meets_apply(_Bin, {Handler, State}) ->
%% Another case of the above.
Handler:abs(State).
-
id(I) -> I.
diff --git a/lib/crypto/doc/src/crypto.xml b/lib/crypto/doc/src/crypto.xml
index 641738247e..d1d1252f29 100644
--- a/lib/crypto/doc/src/crypto.xml
+++ b/lib/crypto/doc/src/crypto.xml
@@ -678,7 +678,8 @@
</p>
<p>For encryption, set the <c>EncryptFlag</c> to <c>true</c>. For decryption, set it to <c>false</c>.
</p>
- <p>See <seealso marker="crypto:new_api#the-new-api">examples in the User's Guide.</seealso>
+ <p>See <seealso marker="crypto:new_api#examples-of-crypto_init-4-and-crypto_update-2">
+ examples in the User's Guide.</seealso>
</p>
</desc>
</func>
@@ -696,7 +697,8 @@
or
<seealso marker="crypto#crypto_init/4">crypto_init/4</seealso>.
</p>
- <p>See <seealso marker="crypto:new_api#the-new-api">examples in the User's Guide.</seealso>
+ <p>See <seealso marker="crypto:new_api#examples-of-crypto_init-4-and-crypto_update-2">
+ examples in the User's Guide.</seealso>
</p>
</desc>
</func>
@@ -712,8 +714,6 @@
</p>
<p>For encryption, set the <c>EncryptFlag</c> to <c>true</c>. For decryption, set it to <c>false</c>.
</p>
- <p>See <seealso marker="crypto:new_api#the-new-api">examples in the User's Guide.</seealso>
- </p>
</desc>
</func>
@@ -726,8 +726,6 @@
The <c>State</c> should be created with
<seealso marker="crypto#crypto_dyn_iv_init/3">crypto_dyn_iv_init/3</seealso>.
</p>
- <p>See <seealso marker="crypto:new_api#the-new-api">examples in the User's Guide.</seealso>
- </p>
</desc>
</func>
@@ -744,11 +742,11 @@
<fsummary>Do a complete encrypt or decrypt of the full text</fsummary>
<desc>
<p>Part of the <seealso marker="crypto:new_api#the-new-api">new API</seealso>.
- Do a complete encrypt or decrypt of the full text.
+ Do a complete encrypt or decrypt of the full text in the argument <c>Data</c>.
</p>
<p>For encryption, set the <c>EncryptFlag</c> to <c>true</c>. For decryption, set it to <c>false</c>.
</p>
- <p>See <seealso marker="crypto:new_api#the-new-api">examples in the User's Guide.</seealso>
+ <p>See <seealso marker="crypto:new_api#example-of-crypto_one_time-5">examples in the User's Guide.</seealso>
</p>
</desc>
</func>
@@ -768,10 +766,23 @@
<p>For decryption, set the <c>EncryptFlag</c> to <c>false</c> and put the tag to be checked
in the argument <c>TagOrTagLength</c>.
</p>
- <p>See <seealso marker="crypto:new_api#the-new-api">examples in the User's Guide.</seealso>
+ <p>See <seealso marker="crypto:new_api#example-of-crypto_one_time_aead-6">examples in the User's Guide.</seealso>
</p>
</desc>
</func>
+
+ <func>
+ <name name="supports" arity="1" since="OTP 22.0"/>
+ <fsummary>Provide a list of available crypto algorithms.</fsummary>
+ <desc>
+ <p> Can be used to determine which crypto algorithms that are supported
+ by the underlying libcrypto library</p>
+ <p>See <seealso marker="#hash_info-1">hash_info/1</seealso> and <seealso marker="#cipher_info-1">cipher_info/1</seealso>
+ for information about the hash and cipher algorithms.
+ </p>
+ </desc>
+ </func>
+
</funcs>
<section>
@@ -1425,18 +1436,6 @@ FloatValue = rand:uniform(). % again
</desc>
</func>
- <func>
- <name name="supports" arity="0" since="OTP R16B01"/>
- <fsummary>Provide a list of available crypto algorithms.</fsummary>
- <desc>
- <p> Can be used to determine which crypto algorithms that are supported
- by the underlying libcrypto library</p>
- <p>See <seealso marker="#hash_info-1">hash_info/1</seealso> and <seealso marker="#cipher_info-1">cipher_info/1</seealso>
- for information about the hash and cipher algorithms.
- </p>
- </desc>
- </func>
-
<func>
<name name="ec_curves" arity="0" since="OTP 17.0"/>
<fsummary>Provide a list of available named elliptic curves.</fsummary>
@@ -1947,6 +1946,21 @@ FloatValue = rand:uniform(). % again
</desc>
</func>
+ <func>
+ <name name="supports" arity="0" since="OTP R16B01"/>
+ <fsummary>Provide a list of available crypto algorithms.</fsummary>
+ <desc>
+ <dont><p>Don't use this function for new programs! Use
+ <seealso marker="crypto#supports-1">supports/1</seealso> in
+ <seealso marker="crypto:new_api">the new api</seealso>.</p></dont>
+ <p> Can be used to determine which crypto algorithms that are supported
+ by the underlying libcrypto library</p>
+ <p>See <seealso marker="#hash_info-1">hash_info/1</seealso> and <seealso marker="#cipher_info-1">cipher_info/1</seealso>
+ for information about the hash and cipher algorithms.
+ </p>
+ </desc>
+ </func>
+
</funcs>
diff --git a/lib/crypto/doc/src/new_api.xml b/lib/crypto/doc/src/new_api.xml
index 79096b55e8..bd2334ac9f 100644
--- a/lib/crypto/doc/src/new_api.xml
+++ b/lib/crypto/doc/src/new_api.xml
@@ -59,8 +59,9 @@
<item><seealso marker="crypto#stream_init-2">stream_init/3</seealso></item>
<item><seealso marker="crypto#stream_encrypt-2">stream_encrypt/2</seealso></item>
<item><seealso marker="crypto#stream_decrypt-2">stream_decrypt/2</seealso></item>
+ <item><seealso marker="crypto#supports-0">supports/0</seealso></item>
</list>
- <p>They are not deprecated for now, but may be in a future.
+ <p>They are not deprecated for now, but may be in a future release.
</p>
</section>
@@ -75,7 +76,8 @@
<item><seealso marker="crypto#crypto_one_time_aead/7">crypto_one_time_aead/7</seealso></item>
</list>
<p>In those functions the internal crypto state is first created and initialized
- with the cipher type, the key and possibly other data. Then the data is encrypted or decrypted,
+ with the cipher type, the key and possibly other data. Then the single binary is encrypted
+ or decrypted,
the crypto state is de-allocated and the result of the crypto operation is returned.
</p>
<p>The <c>crypto_one_time_aead</c> functions are for the ciphers of mode <c>ccm</c> or
@@ -94,7 +96,7 @@
<c>crypto_update</c> does the acual encryption or decryption. Note that AEAD ciphers
can't be handled this way due to their nature.
</p>
- <p>Finally, for repeated encryption or decryption of a text divided in parts where the
+ <p>For repeated encryption or decryption of a text divided in parts where the
same cipher and same key is used, but a new initialization vector (nounce) should be applied
for each part, the functions are:
</p>
@@ -103,32 +105,49 @@
<item><seealso marker="crypto#crypto_dyn_iv_update/3">crypto_dyn_iv_update/3</seealso></item>
</list>
<p>An example of where those functions are needed, is when handling the TLS protocol.</p>
+ <p>For information about available algorithms, use:
+ </p>
+ <list>
+ <item><seealso marker="crypto#supports-1">supports/1</seealso></item>
+ <item><seealso marker="crypto#hash_info-1">hash_info/1</seealso></item>
+ <item><seealso marker="crypto#cipher_info-1">cipher_info/1</seealso></item>
+ </list>
<section>
<title>Examples of crypto_init/4 and crypto_update/2</title>
- <p>Encrypting two blocks:</p>
+ <p>The functions <seealso marker="crypto#crypto_init/4">crypto_init/4</seealso>
+ and <seealso marker="crypto#crypto_update/2">crypto_update/2</seealso> are intended
+ to be used for encrypting or decrypting a sequence of blocks. First one call of
+ <c>crypto_init/4</c> initialises the crypto context. One or more calls <c>crypto_update/2</c>
+ does the actual encryption or decryption for each block.
+ </p>
+ <p>This example shows first the encryption of two blocks and then decryptions of the cipher
+ text, but divided into three blocks just to show that it is possible to divide the plain text and
+ cipher text differently for some ciphers:</p>
<code type="erl">
1> crypto:start().
ok
2> Key = &lt;&lt;1:128>>.
- 2> IV = &lt;&lt;0:128>>.
- 2> StateEnc = crypto:crypto_init(aes_128_ctr, Key, IV, true). % encrypt -> true
+ &lt;&lt;0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1>>
+ 3> IV = &lt;&lt;0:128>>.
+ &lt;&lt;0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0>>
+ 4> StateEnc = crypto:crypto_init(aes_128_ctr, Key, IV, true). % encrypt -> true
#Ref&lt;0.3768901617.1128660993.124047>
- 3> crypto:crypto_update(StateEnc, &lt;&lt;"First bytes">>).
+ 5> crypto:crypto_update(StateEnc, &lt;&lt;"First bytes">>).
&lt;&lt;67,44,216,166,25,130,203,5,66,6,162>>
- 4> crypto:crypto_update(StateEnc, &lt;&lt;"Second bytes">>).
+ 6> crypto:crypto_update(StateEnc, &lt;&lt;"Second bytes">>).
&lt;&lt;16,79,94,115,234,197,94,253,16,144,151,41>>
- 5>
- 5> StateDec = crypto:crypto_init(aes_128_ctr, Key, IV, false). % decrypt -> false
+ 7>
+ 7> StateDec = crypto:crypto_init(aes_128_ctr, Key, IV, false). % decrypt -> false
#Ref&lt;0.3768901617.1128660994.124255>
- 6> crypto:crypto_update(StateDec, &lt;&lt;67,44,216,166,25,130,203>>).
+ 8> crypto:crypto_update(StateDec, &lt;&lt;67,44,216,166,25,130,203>>).
&lt;&lt;"First b">>
- 7> crypto:crypto_update(StateDec, &lt;&lt;5,66,6,162,16,79,94,115,234,197,
- 94,253,16,144,151>>).
+ 9> crypto:crypto_update(StateDec, &lt;&lt;5,66,6,162,16,79,94,115,234,197,
+ 94,253,16,144,151>>).
&lt;&lt;"ytesSecond byte">>
- 8> crypto:crypto_update(StateDec, &lt;&lt;41>>).
+ 10> crypto:crypto_update(StateDec, &lt;&lt;41>>).
&lt;&lt;"s">>
- 9>
+ 11>
</code>
<p>Note that the internal data that the <c>StateEnc</c> and <c>StateDec</c> references are
destructivly updated by the calls to <seealso marker="crypto#crypto_update/2">crypto_update/2</seealso>.
@@ -155,21 +174,51 @@
<title>Example of crypto_one_time/5</title>
<p>The same example as in the
<seealso marker="#examples-of-crypto_init-4-and-crypto_update-2">previous section</seealso>,
- but now with one call to <c>crypto_one_time/5</c>:
+ but now with one call to <seealso marker="crypto#crypto_one_time/5">crypto_one_time/5</seealso>:
</p>
<code>
- 2> Key = &lt;&lt;1:128>>.
+ 1> Key = &lt;&lt;1:128>>.
+ &lt;&lt;0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1>>
2> IV = &lt;&lt;0:128>>.
- 2> Txt = [&lt;&lt;"First bytes">>,&lt;&lt;"Second bytes">>],
- 2> crypto:crypto_one_time(aes_128_ctr, Key, IV, Txt, true).
+ &lt;&lt;0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0>>
+ 3> Txt = [&lt;&lt;"First bytes">>,&lt;&lt;"Second bytes">>].
+ [&lt;&lt;"First bytes">>,&lt;&lt;"Second bytes">>]
+ 4> crypto:crypto_one_time(aes_128_ctr, Key, IV, Txt, true).
&lt;&lt;67,44,216,166,25,130,203,5,66,6,162,16,79,94,115,234,
197,94,253,16,144,151,41>>
- 3>
+ 5>
+ </code>
+ <p>The <c>[&lt;&lt;"First bytes">>,&lt;&lt;"Second bytes">>]</c> could of course have been one
+ single binary: <c>&lt;&lt;"First bytesSecond bytes">></c>.
+ </p>
+ </section>
+
+ <section>
+ <title>Example of crypto_one_time_aead/6</title>
+ <p>The same example as in the
+ <seealso marker="#example-of-crypto_one_time-5">previous section</seealso>,
+ but now with one call to <seealso marker="crypto#crypto_one_time_aead/6">crypto_one_time_aead/6</seealso>:
+ </p>
+ <code>
+ 1> Key = &lt;&lt;1:128>>.
+ &lt;&lt;0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1>>
+ 2> IV = &lt;&lt;0:128>>.
+ &lt;&lt;0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0>>
+ 3> Txt = [&lt;&lt;"First bytes">>,&lt;&lt;"Second bytes">>].
+ [&lt;&lt;"First bytes">>,&lt;&lt;"Second bytes">>]
+ 4> AAD = &lt;&lt;"Some bytes">>.
+ &lt;&lt;"Some bytes">>
+ 5> crypto:crypto_one_time_aead(aes_128_gcm, Key, IV, Txt, AAD, true).
+ {&lt;&lt;240,130,38,96,130,241,189,52,3,190,179,213,132,1,72,
+ 192,103,176,90,104,15,71,158>>,
+ &lt;&lt;131,47,45,91,142,85,9,244,21,141,214,71,31,135,2,155>>}
+ 9>
</code>
<p>The <c>[&lt;&lt;"First bytes">>,&lt;&lt;"Second bytes">>]</c> could of course have been one
single binary: <c>&lt;&lt;"First bytesSecond bytes">></c>.
</p>
</section>
+
</section>
<section>
diff --git a/lib/crypto/src/crypto.erl b/lib/crypto/src/crypto.erl
index 98378412d4..8ffdde2b90 100644
--- a/lib/crypto/src/crypto.erl
+++ b/lib/crypto/src/crypto.erl
@@ -509,6 +509,27 @@ supports() ->
{rsa_opts, rsa_opts_algorithms()}
].
+
+-spec supports(Type) -> Support
+ when Type :: hashs
+ | ciphers
+ | public_keys
+ | macs
+ | curves
+ | rsa_opts,
+ Support :: Hashs
+ | Ciphers
+ | PKs
+ | Macs
+ | Curves
+ | RSAopts,
+ Hashs :: [sha1() | sha2() | sha3() | blake2() | ripemd160 | compatibility_only_hash()],
+ Ciphers :: [cipher()],
+ PKs :: [rsa | dss | ecdsa | dh | ecdh | ec_gf2m],
+ Macs :: [hmac | cmac | poly1305],
+ Curves :: [ec_named_curve() | edwards_curve_dh() | edwards_curve_ed()],
+ RSAopts :: [rsa_sign_verify_opt() | rsa_opt()] .
+
supports(hashs) -> hash_algorithms();
supports(public_keys) -> pubkey_algorithms();
supports(ciphers) -> cipher_algorithms();
diff --git a/lib/erl_interface/doc/src/ei.xml b/lib/erl_interface/doc/src/ei.xml
index 254ae27cc8..7808bfd94f 100644
--- a/lib/erl_interface/doc/src/ei.xml
+++ b/lib/erl_interface/doc/src/ei.xml
@@ -183,28 +183,36 @@ typedef enum {
</func>
<func>
- <name since="OTP @OTP-15712@"><ret>int</ret><nametext>ei_decode_bitstring(const char *buf, int *index, void *p, size_t plen, size_t *bitsp)</nametext></name>
+ <name since="OTP @OTP-15712@"><ret>int</ret><nametext>ei_decode_bitstring(const char *buf, int *index, const char **pp, unsigned int *bitoffsp, size_t *nbitsp)</nametext></name>
<fsummary>Decode a bitstring.</fsummary>
<desc>
- <p>Decodes a bitstring from the binary format.</p>
+ <p>Decodes a bit string from the binary format.</p>
<taglist>
- <tag><c>p</c></tag>
- <item><p>Either <c>NULL</c> or points to a buffer where the bytes of the
- bitstring will be written.</p>
+ <tag><c>pp</c></tag>
+ <item><p>Either <c>NULL</c> or <c>*pp</c> returns a pointer to
+ the first byte of the bit string. The returned bit string is
+ readable as long as the buffer pointed to by <c>buf</c> is
+ readable and not written to.</p>
</item>
- <tag><c>plen</c></tag>
- <item><p>The max size of the bitstring in <em>bytes</em>, that is the
- size of the buffer if <c>p != NULL</c>.</p>
+ <tag><c>bitoffsp</c></tag>
+ <item><p>Either <c>NULL</c> or <c>*bitoffsp</c> returns the
+ number of unused bits in the first byte pointed to by
+ <c>*pp</c>. The value of <c>*bitoffsp</c> is between 0 and 7.
+ Unused bits in the first byte are the most significant bits.</p>
</item>
- <tag><c>*bitsp</c></tag>
- <item><p>If <c>bitsp</c> is not <c>NULL</c>, set to the actual
- number of <em>bits</em> of the bitstring.</p>
+ <tag><c>nbitsp</c></tag>
+ <item><p>Either <c>NULL</c> or <c>*nbitsp</c> returns the length
+ of the bit string in <em>bits</em>.</p>
</item>
</taglist>
- <p>Returns <c>0</c> if it was a bitstring no longer than <c>plen</c>
- bytes. The actual length of the bitstring will be
- <c>(*bitsp+7)/8</c> bytes. If <c>(*bitsp % 8) > 0</c> only the high
- <c>(*bitsp % 8)</c> bits of the last byte are significant.</p>
+ <p>Returns <c>0</c> if it was a bit string term.</p>
+ <p>The number of <em>bytes</em> pointed to by <c>*pp</c>, which are
+ part of the bit string, is <c>(*bitoffsp + *nbitsp + 7)/8</c>. If
+ <c>(*bitoffsp + *bitsp)%8 > 0</c> then only <c>(*bitoffsp +
+ *bitsp)%8</c> bits of the last byte are used. Unused bits in
+ the last byte are the least significant bits.</p>
+ <p>The values of unused bits in the first and last byte are undefined
+ and cannot be relied on.</p>
<p>Number of bits may be divisible by 8, which means a binary
decodable by <c>ei_decode_binary</c> is also decodable by
<c>ei_decode_bitstring</c>.</p>
@@ -490,14 +498,24 @@ typedef enum {
</func>
<func>
- <name since="OTP @OTP-15712@"><ret>int</ret><nametext>ei_encode_bitstring(char *buf, int *index, const void *p, size_t bits)</nametext></name>
- <name since="OTP @OTP-15712@"><ret>int</ret><nametext>ei_x_encode_bitstring(ei_x_buff* x, const void *p, size_t bits)</nametext></name>
+ <name since="OTP @OTP-15712@"><ret>int</ret>
+ <nametext>ei_encode_bitstring(char *buf, int *index, const char *p, size_t bitoffs, size_t nbits)</nametext></name>
+ <name since="OTP @OTP-15712@"><ret>int</ret>
+ <nametext>ei_x_encode_bitstring(ei_x_buff* x, const char *p, size_t bitoffs, size_t nbits)</nametext></name>
<fsummary>Encode a bitstring.</fsummary>
<desc>
- <p>Encodes a bitstring in the binary format. The data is at
- <c>p</c>. The size of the data is <c>bits</c> bits or
- <c>(bits+7)/8</c> bytes. If <c>(bits%8) > 0</c> only the high
- <c>(bits%8)</c> bits of the last byte are significant.</p>
+ <p>Encodes a bit string in the binary format.</p>
+ <p>The data is at <c>p</c>. The length of the bit string is <c>nbits</c>
+ bits. The first <c>bitoffs</c> bits of the data at <c>p</c> are unused.
+ The first byte which is part of the bit string is
+ <c>p[bitoffs/8]</c>. The <c>bitoffs%8</c> most significant bits of
+ the first byte <c>p[bitoffs/8]</c> are unused.</p>
+ <p>The number of bytes which is part of the bit string is <c>(bitoffs +
+ nbits + 7)/8</c>. If <c>(bitoffs + nbits)%8 > 0</c> then only <c>(bitoffs +
+ nbits)%8</c> bits of the last byte are used. Unused bits in
+ the last byte are the least significant bits.</p>
+ <p>The values of unused bits are disregarded and does not need to be
+ cleared.</p>
</desc>
</func>
diff --git a/lib/erl_interface/include/ei.h b/lib/erl_interface/include/ei.h
index a860df3f77..ed0420300d 100644
--- a/lib/erl_interface/include/ei.h
+++ b/lib/erl_interface/include/ei.h
@@ -526,9 +526,9 @@ int ei_x_encode_atom_len(ei_x_buff* x, const char* s, int len);
int ei_x_encode_atom_len_as(ei_x_buff* x, const char* s, int len,
erlang_char_encoding from, erlang_char_encoding to);
int ei_encode_binary(char *buf, int *index, const void *p, long len);
-int ei_encode_bitstring(char *buf, int *index, const void *p, size_t bits);
+int ei_encode_bitstring(char *buf, int *index, const char *p, size_t bitoffs, size_t bits);
int ei_x_encode_binary(ei_x_buff* x, const void* s, int len);
-int ei_x_encode_bitstring(ei_x_buff* x, const void* p, size_t bits);
+int ei_x_encode_bitstring(ei_x_buff* x, const char* p, size_t bitoffs, size_t bits);
int ei_encode_pid(char *buf, int *index, const erlang_pid *p);
int ei_x_encode_pid(ei_x_buff* x, const erlang_pid* pid);
int ei_encode_fun(char* buf, int* index, const erlang_fun* p);
@@ -578,7 +578,9 @@ int ei_decode_string(const char *buf, int *index, char *p);
int ei_decode_atom(const char *buf, int *index, char *p);
int ei_decode_atom_as(const char *buf, int *index, char *p, int destlen, erlang_char_encoding want, erlang_char_encoding* was, erlang_char_encoding* result);
int ei_decode_binary(const char *buf, int *index, void *p, long *len);
-int ei_decode_bitstring(const char *buf, int *index, void *p, size_t plen, size_t *bitsp);
+int ei_decode_bitstring(const char *buf, int *index, const char** pp,
+ unsigned int* bitoffsp, size_t *nbitsp);
+
int ei_decode_fun(const char* buf, int* index, erlang_fun* p);
void free_fun(erlang_fun* f);
int ei_decode_pid(const char *buf, int *index, erlang_pid *p);
diff --git a/lib/erl_interface/src/decode/decode_binary.c b/lib/erl_interface/src/decode/decode_binary.c
index 2799438bef..0d28c67230 100644
--- a/lib/erl_interface/src/decode/decode_binary.c
+++ b/lib/erl_interface/src/decode/decode_binary.c
@@ -40,40 +40,41 @@ int ei_decode_binary(const char *buf, int *index, void *p, long *lenp)
return 0;
}
-int ei_decode_bitstring(const char *buf, int *index, void *p, size_t plen,
- size_t *bitsp)
+int ei_decode_bitstring(const char *buf, int *index,
+ const char** pp,
+ unsigned int* bitoffsp,
+ size_t *nbitsp)
{
- const char *s = buf + *index;
- const char *s0 = s;
- unsigned long len;
- unsigned char last_bits;
- const unsigned char tag = get8(s);
+ const char *s = buf + *index;
+ const char *s0 = s;
+ unsigned char last_bits;
+ const unsigned char tag = get8(s);
+ size_t len = get32be(s);
- if (tag == ERL_BINARY_EXT) {
- long bytes;
- int ret = ei_decode_binary(buf, index, p, &bytes);
- if (bitsp)
- *bitsp = (size_t)bytes * 8;
- return ret;
- }
+ switch(tag) {
+ case ERL_BINARY_EXT:
+ if (nbitsp)
+ *nbitsp = len * 8;
+ break;
+ case ERL_BIT_BINARY_EXT:
+ last_bits = get8(s);
+ if (((last_bits==0) != (len==0)) || last_bits > 8)
+ return -1;
- if (tag != ERL_BIT_BINARY_EXT)
- return -1;
-
- len = get32be(s);
- last_bits = get8(s);
-
- if (len > plen || ((last_bits==0) != (len==0)) || last_bits > 8)
- return -1;
-
- if (p)
- memcpy(p, s, len);
- s += len;
+ if (nbitsp)
+ *nbitsp = (len == 0) ? 0 : ((len-1) * 8) + last_bits;
+ break;
+ default:
+ return -1;
+ }
- if (bitsp)
- *bitsp = (len == 0) ? 0 : ((len-1) * 8) + last_bits;
+ if (pp)
+ *pp = s;
+ if (bitoffsp)
+ *bitoffsp = 0;
- *index += s-s0;
- return 0;
+ s += len;
+ *index += s-s0;
+ return 0;
}
diff --git a/lib/erl_interface/src/decode/decode_skip.c b/lib/erl_interface/src/decode/decode_skip.c
index 11d3bc1786..736c00e074 100644
--- a/lib/erl_interface/src/decode/decode_skip.c
+++ b/lib/erl_interface/src/decode/decode_skip.c
@@ -21,14 +21,6 @@
#include "eiext.h"
#include "decode_skip.h"
-#ifdef HAVE_STDINT_H
-# include <stdint.h>
-#endif
-
-#ifndef SIZE_MAX
-# define SIZE_MAX (~((size_t)0))
-#endif
-
int ei_skip_term(const char* buf, int* index)
{
int i, n, ty;
@@ -88,7 +80,7 @@ int ei_skip_term(const char* buf, int* index)
return -1;
break;
case ERL_BIT_BINARY_EXT:
- if (ei_decode_bitstring(buf, index, NULL, SIZE_MAX, NULL) < 0)
+ if (ei_decode_bitstring(buf, index, NULL, NULL, NULL) < 0)
return -1;
break;
case ERL_SMALL_INTEGER_EXT:
diff --git a/lib/erl_interface/src/encode/encode_binary.c b/lib/erl_interface/src/encode/encode_binary.c
index 4aa9f6bc16..0562979417 100644
--- a/lib/erl_interface/src/encode/encode_binary.c
+++ b/lib/erl_interface/src/encode/encode_binary.c
@@ -22,6 +22,10 @@
#include "eiext.h"
#include "putget.h"
+static void copy_bits(const unsigned char* src, size_t soffs,
+ unsigned char* dst, size_t n);
+
+
int ei_encode_binary(char *buf, int *index, const void *p, long len)
{
char *s = buf + *index;
@@ -40,23 +44,28 @@ int ei_encode_binary(char *buf, int *index, const void *p, long len)
return 0;
}
-int ei_encode_bitstring(char *buf, int *index, const void *p, size_t bits)
+int ei_encode_bitstring(char *buf, int *index,
+ const char *p,
+ size_t bitoffs,
+ size_t bits)
{
char *s = buf + *index;
char *s0 = s;
size_t bytes = (bits + 7) / 8;
char last_bits = bits % 8;
- if (bytes == 0 || last_bits == 0)
- return ei_encode_binary(buf, index, p, bytes);
-
- if (!buf) s += 6;
+ if (!buf) s += last_bits ? 6 : 5;
else {
- put8(s, ERL_BIT_BINARY_EXT);
+ char* tagp = s++;
put32be(s, bytes);
- put8(s, last_bits);
- memcpy(s, p, bytes);
- s[bytes-1] &= (0xff << (8-last_bits));
+ if (last_bits) {
+ *tagp = ERL_BIT_BINARY_EXT;
+ put8(s, last_bits);
+ }
+ else
+ *tagp = ERL_BINARY_EXT;
+
+ copy_bits((const unsigned char*)p, bitoffs, (unsigned char*)s, bits);
}
s += bytes;
@@ -64,3 +73,77 @@ int ei_encode_bitstring(char *buf, int *index, const void *p, size_t bits)
return 0;
}
+
+
+/*
+ * MAKE_MASK(n) constructs a mask with n bits.
+ * Example: MAKE_MASK(3) returns the binary number 00000111.
+ */
+#define MAKE_MASK(n) ((((unsigned) 1) << (n))-1)
+
+
+static
+void copy_bits(const unsigned char* src, /* Base pointer to source. */
+ size_t soffs, /* Bit offset for source relative to src. */
+ unsigned char* dst, /* Destination. */
+ size_t n) /* Number of bits to copy. */
+{
+ unsigned rmask;
+ unsigned count;
+ unsigned deoffs;
+ unsigned bits;
+ unsigned bits1;
+ unsigned rshift;
+
+ if (n == 0)
+ return;
+
+ deoffs = n & 7;
+ rmask = deoffs ? (MAKE_MASK(deoffs) << (8-deoffs)) : 0;
+
+ if (soffs == 0) {
+ unsigned nbytes = (n + 7) / 8;
+ memcpy(dst, src, nbytes);
+ if (rmask)
+ dst[nbytes-1] &= rmask;
+ return;
+ }
+
+ src += soffs / 8;
+ soffs &= 7;
+
+ if (n < 8) { /* Less than one byte */
+ bits = (*src << soffs);
+ if (soffs+n > 8) {
+ src++;
+ bits |= (*src >> (8 - soffs));
+ }
+ *dst = bits & rmask;
+ return;
+ }
+
+ count = n >> 3;
+
+ rshift = 8 - soffs;
+ bits = *src;
+ if (soffs + n > 8) {
+ src++;
+ }
+
+ while (count--) {
+ bits1 = bits << soffs;
+ bits = *src;
+ src++;
+ *dst = bits1 | (bits >> rshift);
+ dst++;
+ }
+
+ if (rmask) {
+ bits1 = bits << soffs;
+ if ((rmask << rshift) & 0xff) {
+ bits = *src;
+ bits1 |= (bits >> rshift);
+ }
+ *dst = bits1 & rmask;
+ }
+}
diff --git a/lib/erl_interface/src/misc/ei_printterm.c b/lib/erl_interface/src/misc/ei_printterm.c
index a89b990ac1..5c40fb7747 100644
--- a/lib/erl_interface/src/misc/ei_printterm.c
+++ b/lib/erl_interface/src/misc/ei_printterm.c
@@ -250,12 +250,13 @@ static int print_term(FILE* fp, ei_x_buff* x,
ei_free(p);
break;
case ERL_BIT_BINARY_EXT: {
+ const char* cp;
size_t bits;
+ unsigned int bitoffs;
int trunc = 0;
- p = ei_malloc(n);
- if (p == NULL) goto err;
- if (ei_decode_bitstring(buf, index, p, n, &bits) < 0) {
- ei_free(p);
+
+ if (ei_decode_bitstring(buf, index, &cp, &bitoffs, &bits) < 0
+ || bitoffs != 0) {
goto err;
}
ch_written += xprintf(fp, x, "#Bits<");
@@ -266,15 +267,14 @@ static int print_term(FILE* fp, ei_x_buff* x,
}
--m;
for (i = 0; i < m; ++i) {
- ch_written += xprintf(fp, x, "%d,", p[i]);
+ ch_written += xprintf(fp, x, "%d,", cp[i]);
}
- ch_written += xprintf(fp, x, "%d", p[i]);
+ ch_written += xprintf(fp, x, "%d", cp[i]);
if (trunc)
ch_written += xprintf(fp, x, ",...");
else if (bits % 8 != 0)
ch_written += xprintf(fp, x, ":%u", (unsigned)(bits % 8));
xputc('>', fp, x); ++ch_written;
- ei_free(p);
break;
}
case ERL_SMALL_INTEGER_EXT:
diff --git a/lib/erl_interface/src/misc/ei_x_encode.c b/lib/erl_interface/src/misc/ei_x_encode.c
index 2da271795f..8e77679d2a 100644
--- a/lib/erl_interface/src/misc/ei_x_encode.c
+++ b/lib/erl_interface/src/misc/ei_x_encode.c
@@ -117,14 +117,14 @@ int ei_x_encode_binary(ei_x_buff* x, const void* p, int len)
return ei_encode_binary(x->buff, &x->index, p, len);
}
-int ei_x_encode_bitstring(ei_x_buff* x, const void* p, size_t bits)
+int ei_x_encode_bitstring(ei_x_buff* x, const char* p, size_t bitoffs, size_t bits)
{
int i = x->index;
- if (ei_encode_bitstring(NULL, &i, p, bits) == -1)
+ if (ei_encode_bitstring(NULL, &i, p, bitoffs, bits) == -1)
return -1;
if (!x_fix_buff(x, i))
return -1;
- return ei_encode_bitstring(x->buff, &x->index, p, bits);
+ return ei_encode_bitstring(x->buff, &x->index, p, bitoffs, bits);
}
int ei_x_encode_long(ei_x_buff* x, long n)
diff --git a/lib/erl_interface/src/misc/show_msg.c b/lib/erl_interface/src/misc/show_msg.c
index 2d49eb6449..805d69e9b3 100644
--- a/lib/erl_interface/src/misc/show_msg.c
+++ b/lib/erl_interface/src/misc/show_msg.c
@@ -24,13 +24,6 @@
#include <stdlib.h>
#include <stdarg.h>
#include <string.h>
-#ifdef HAVE_STDINT_H
-# include <stdint.h>
-#endif
-
-#ifndef SIZE_MAX
-# define SIZE_MAX (~((size_t)0))
-#endif
#include <sys/types.h>
@@ -464,7 +457,7 @@ static void show_term(const char *termbuf, int *index, FILE *stream)
case ERL_BIT_BINARY_EXT: {
size_t bits;
- ei_decode_bitstring(termbuf, index, NULL, SIZE_MAX, &bits);
+ ei_decode_bitstring(termbuf, index, NULL, NULL, &bits);
fprintf(stream, "#Bits<%lu>", (unsigned long)bits);
break;
}
diff --git a/lib/erl_interface/test/ei_connect_SUITE_data/ei_connect_test.c b/lib/erl_interface/test/ei_connect_SUITE_data/ei_connect_test.c
index 7c9e79f837..385bcdd422 100644
--- a/lib/erl_interface/test/ei_connect_SUITE_data/ei_connect_test.c
+++ b/lib/erl_interface/test/ei_connect_SUITE_data/ei_connect_test.c
@@ -209,8 +209,9 @@ static void cmd_ei_send_funs(char* buf, int len)
erlang_pid pid;
ei_x_buff x;
erlang_fun fun1, fun2;
- unsigned char bitstring[10];
+ char* bitstring;
size_t bits;
+ int bitoffs;
if (ei_decode_long(buf, &index, &fd) < 0)
fail("expected long");
@@ -224,7 +225,7 @@ static void cmd_ei_send_funs(char* buf, int len)
fail("expected Fun1");
if (ei_decode_fun(buf, &index, &fun2) < 0)
fail("expected Fun2");
- if (ei_decode_bitstring(buf, &index, bitstring, sizeof(bitstring), &bits) < 0)
+ if (ei_decode_bitstring(buf, &index, &bitstring, &bitoffs, &bits) < 0)
fail("expected bitstring");
if (ei_x_new_with_version(&x) < 0)
fail("ei_x_new_with_version");
@@ -234,7 +235,7 @@ static void cmd_ei_send_funs(char* buf, int len)
fail("encode fun1");
if (ei_x_encode_fun(&x, &fun2) < 0)
fail("encode fun2");
- if (ei_x_encode_bitstring(&x, bitstring, bits) < 0)
+ if (ei_x_encode_bitstring(&x, bitstring, bitoffs, bits) < 0)
fail("encode bitstring");
free_fun(&fun1);
free_fun(&fun2);
diff --git a/lib/erl_interface/test/ei_decode_SUITE_data/ei_decode_test.c b/lib/erl_interface/test/ei_decode_SUITE_data/ei_decode_test.c
index d39970a857..46d6b8f2af 100644
--- a/lib/erl_interface/test/ei_decode_SUITE_data/ei_decode_test.c
+++ b/lib/erl_interface/test/ei_decode_SUITE_data/ei_decode_test.c
@@ -319,17 +319,18 @@ static void decode_bin(int exp_size, const char* val, int exp_len)
static void decode_bits(int exp_size, const char* val, size_t exp_bits)
{
- char p[1024];
+ const char* p;
char *buf;
size_t bits;
+ int bitoffs;
int size1 = 0;
int size2 = 0;
int err;
message("ei_decode_bitstring should be %d bits", (int)exp_bits);
buf = read_packet(NULL);
- err = ei_decode_bitstring(buf+1, &size1, NULL, sizeof(p), &bits);
- message("err = %d, size = %d, len = %d, expected size = %d, expected bits = %d\n",\
- err,size1, (int)bits, exp_size, (int)exp_bits);
+ err = ei_decode_bitstring(buf+1, &size1, NULL, &bitoffs, &bits);
+ message("err = %d, size = %d, bitoffs = %d, bits = %d, expected size = %d, expected bits = %d\n",\
+ err,size1, bitoffs, (int)bits, exp_size, (int)exp_bits);
if (err != 0) {
if (err != -1) {
@@ -344,8 +345,12 @@ static void decode_bits(int exp_size, const char* val, size_t exp_bits)
fail("number of bits is not correct");
return;
}
+ if (bitoffs != 0) {
+ fail("non zero bit offset");
+ return;
+ }
- err = ei_decode_bitstring(buf+1, &size2, p, sizeof(p), &bits);
+ err = ei_decode_bitstring(buf+1, &size2, &p, NULL, &bits);
message("err = %d, size = %d, len = %d, expected size = %d, expected len = %d\n",\
err,size2, (int)bits, exp_size, (int)exp_bits);
if (err != 0) {
diff --git a/lib/erl_interface/test/ei_decode_encode_SUITE.erl b/lib/erl_interface/test/ei_decode_encode_SUITE.erl
index d8b0bce3ae..3451d9f503 100644
--- a/lib/erl_interface/test/ei_decode_encode_SUITE.erl
+++ b/lib/erl_interface/test/ei_decode_encode_SUITE.erl
@@ -122,9 +122,29 @@ test_ei_decode_encode(Config) when is_list(Config) ->
[send_rec(P, <<16#dec0deb175:B/little>>) || B <- lists:seq(0,48)],
+ % And last an ugly duckling to test ei_encode_bitstring with bitoffs != 0
+ encode_bitstring(P),
+
runner:recv_eot(P),
ok.
+encode_bitstring(P) ->
+ %% Send one bitstring to c-node
+ Bits = <<16#18f6d4b2907e5c3a1:66>>,
+ P ! {self(), {command, term_to_binary(Bits, [{minor_version, 2}])}},
+
+ %% and then receive and verify a number of different sub-bitstrings
+ receive_sub_bitstring(P, Bits, 0, bit_size(Bits)).
+
+receive_sub_bitstring(_, _, _, NBits) when NBits < 0 ->
+ ok;
+receive_sub_bitstring(P, Bits, BitOffs, NBits) ->
+ <<_:BitOffs, Sub:NBits/bits, _/bits>> = Bits,
+ %%io:format("expecting term_to_binary(~p) = ~p\n", [Sub, term_to_binary(Sub)]),
+ {_B,Sub} = get_buf_and_term(P),
+ receive_sub_bitstring(P, Bits, BitOffs+1, NBits - ((NBits div 20)+1)).
+
+
%% ######################################################################## %%
diff --git a/lib/erl_interface/test/ei_decode_encode_SUITE_data/ei_decode_encode_test.c b/lib/erl_interface/test/ei_decode_encode_SUITE_data/ei_decode_encode_test.c
index f9c05b2739..85ca6c56e9 100644
--- a/lib/erl_interface/test/ei_decode_encode_SUITE_data/ei_decode_encode_test.c
+++ b/lib/erl_interface/test/ei_decode_encode_SUITE_data/ei_decode_encode_test.c
@@ -42,7 +42,8 @@ typedef struct
typedef struct
{
- char bytes[MAXATOMLEN_UTF8];
+ const char* bytes;
+ unsigned int bitoffs;
size_t nbits;
}my_bitstring;
@@ -128,17 +129,17 @@ struct Type my_atom_type = {
int ei_decode_my_bits(const char *buf, int *index, my_bitstring* a)
{
- return ei_decode_bitstring(buf, index, (a ? a->bytes : NULL),
- sizeof(a->bytes),
+ return ei_decode_bitstring(buf, index, (a ? &a->bytes : NULL),
+ (a ? &a->bitoffs : NULL),
(a ? &a->nbits : NULL));
}
int ei_encode_my_bits(char *buf, int *index, my_bitstring* a)
{
- return ei_encode_bitstring(buf, index, a->bytes, a->nbits);
+ return ei_encode_bitstring(buf, index, a->bytes, a->bitoffs, a->nbits);
}
int ei_x_encode_my_bits(ei_x_buff* x, my_bitstring* a)
{
- return ei_x_encode_bitstring(x, a->bytes, a->nbits);
+ return ei_x_encode_bitstring(x, a->bytes, a->bitoffs, a->nbits);
}
struct Type my_bitstring_type = {
@@ -264,11 +265,7 @@ void decode_encode(struct Type** tv, int nobj)
size1 = 0;
err = t->ei_decode_fp(inp, &size1, NULL);
if (err != 0) {
- if (err != -1) {
- fail("decode returned non zero but not -1");
- } else {
- fail1("decode '%s' returned non zero", t->name);
- }
+ fail2("decode '%s' returned non zero %d", t->name, err);
return;
}
if (size1 < 1) {
@@ -497,6 +494,66 @@ void decode_encode_big(struct Type* t)
}
+void encode_bitstring(void)
+{
+ char* packet;
+ char* inp;
+ char out_buf[BUFSZ];
+ int size;
+ int err, i;
+ ei_x_buff arg;
+ const char* p;
+ unsigned int bitoffs;
+ size_t nbits, org_nbits;
+
+ packet = read_packet(NULL);
+ inp = packet+1;
+
+ size = 0;
+ err = ei_decode_bitstring(inp, &size, &p, &bitoffs, &nbits);
+ if (err != 0) {
+ fail1("ei_decode_bitstring returned non zero %d", err);
+ return;
+ }
+
+ /*
+ * Now send a bunch of different sub-bitstrings back
+ * encoded both with ei_encode_ and ei_x_encode_.
+ */
+ org_nbits = nbits;
+ do {
+ size = 0;
+ err = ei_encode_bitstring(out_buf, &size, p, bitoffs, nbits);
+ if (err != 0) {
+ fail1("ei_encode_bitstring returned non zero %d", err);
+ return;
+ }
+
+ ei_x_new(&arg);
+ err = ei_x_encode_bitstring(&arg, p, bitoffs, nbits);
+ if (err != 0) {
+ fail1("ei_x_encode_bitstring returned non zero %d", err);
+ ei_x_free(&arg);
+ return;
+ }
+
+ if (arg.index < 1) {
+ fail("size is < 1");
+ ei_x_free(&arg);
+ return;
+ }
+
+ send_buffer(out_buf, size);
+ send_buffer(arg.buff, arg.index);
+ ei_x_free(&arg);
+
+ bitoffs++;
+ nbits -= (nbits / 20) + 1;
+ } while (nbits < org_nbits);
+
+ free_packet(packet);
+}
+
/* ******************************************************************** */
@@ -568,6 +625,8 @@ TESTCASE(test_ei_decode_encode)
decode_encode_one(&my_bitstring_type);
}
+ encode_bitstring();
+
report(1);
}
diff --git a/lib/kernel/src/erl_distribution.erl b/lib/kernel/src/erl_distribution.erl
index 0bec78e938..cdb2d2f1f6 100644
--- a/lib/kernel/src/erl_distribution.erl
+++ b/lib/kernel/src/erl_distribution.erl
@@ -21,6 +21,8 @@
-behaviour(supervisor).
+-include_lib("kernel/include/logger.hrl").
+
-export([start_link/0,start_link/2,init/1,start/1,stop/0]).
-define(DBG,erlang:display([?MODULE,?LINE])).
@@ -83,6 +85,10 @@ do_start_link([{Arg,Flag}|T]) ->
case init:get_argument(Arg) of
{ok,[[Name]]} ->
start_link([list_to_atom(Name),Flag|ticktime()], true);
+ {ok,[[Name]|_Rest]} ->
+ ?LOG_WARNING("Multiple -~p given to erl, using the first, ~p",
+ [Arg, Name]),
+ start_link([list_to_atom(Name),Flag|ticktime()], true);
_ ->
do_start_link(T)
end;
diff --git a/lib/kernel/src/user_drv.erl b/lib/kernel/src/user_drv.erl
index 08286dd476..69ff8e7971 100644
--- a/lib/kernel/src/user_drv.erl
+++ b/lib/kernel/src/user_drv.erl
@@ -120,7 +120,7 @@ server1(Iport, Oport, Shell) ->
{Curr,Shell1} =
case init:get_argument(remsh) of
{ok,[[Node]]} ->
- ANode = list_to_atom(Node),
+ ANode = list_to_atom(append_hostname(Node)),
RShell = {ANode,shell,start,[]},
RGr = group:start(self(), RShell, rem_sh_opts(ANode)),
{RGr,RShell};
@@ -139,6 +139,12 @@ server1(Iport, Oport, Shell) ->
%% Enter the server loop.
server_loop(Iport, Oport, Curr, User, Gr, {false, queue:new()}).
+append_hostname(Node) ->
+ case string:find(Node, "@") of
+ nomatch -> Node ++ string:find(atom_to_list(node()), "@");
+ _ -> Node
+ end.
+
rem_sh_opts(Node) ->
[{expand_fun,fun(B)-> rpc:call(Node,edlin_expand,expand,[B]) end}].
diff --git a/lib/kernel/test/erl_distribution_SUITE.erl b/lib/kernel/test/erl_distribution_SUITE.erl
index 8dd4ef1987..c3a022df0a 100644
--- a/lib/kernel/test/erl_distribution_SUITE.erl
+++ b/lib/kernel/test/erl_distribution_SUITE.erl
@@ -205,6 +205,9 @@ nodenames(Config) when is_list(Config) ->
legal("a-1@b"),
legal("a_1@b"),
+ %% Test that giving two -sname works as it should
+ test_node("a_1@b", false, long_or_short() ++ "a_0@b"),
+
illegal("cdé@a"),
illegal("te欢st@a").
@@ -258,8 +261,11 @@ illegal(Name) ->
test_node(Name) ->
test_node(Name, false).
test_node(Name, Illigal) ->
+ test_node(Name, Illigal, "").
+test_node(Name, Illigal, ExtraArgs) ->
ProgName = ct:get_progname(),
- Command = ProgName ++ " -noinput " ++ long_or_short() ++ Name ++
+ Command = ProgName ++ " -noinput " ++ ExtraArgs ++
+ long_or_short() ++ Name ++
" -eval \"net_adm:ping('" ++ atom_to_list(node()) ++ "')\"" ++
case Illigal of
true ->
diff --git a/lib/sasl/src/Makefile b/lib/sasl/src/Makefile
index 7338bdf016..fd62588f5c 100644
--- a/lib/sasl/src/Makefile
+++ b/lib/sasl/src/Makefile
@@ -61,7 +61,11 @@ TARGET_FILES= $(MODULES:%=$(EBIN)/%.$(EMULATOR)) $(APP_TARGET) $(APPUP_TARGET)
# ----------------------------------------------------
# FLAGS
# ----------------------------------------------------
+
ERL_COMPILE_FLAGS += -I../../stdlib/include -Werror
+ifeq ($(USE_ESOCK), yes)
+ERL_COMPILE_FLAGS += -DUSE_ESOCK=true
+endif
# ----------------------------------------------------
diff --git a/lib/sasl/src/systools_make.erl b/lib/sasl/src/systools_make.erl
index c2c91fd667..b5a6b44f93 100644
--- a/lib/sasl/src/systools_make.erl
+++ b/lib/sasl/src/systools_make.erl
@@ -33,6 +33,7 @@
-export([read_application/4]).
-export([make_hybrid_boot/4]).
+-export([preloaded/0]). % Exported just for testing
-import(lists, [filter/2, keysort/2, keysearch/3, map/2, reverse/1,
append/1, foldl/3, member/2, foreach/2]).
@@ -45,6 +46,13 @@
-compile({inline,[{badarg,2}]}).
+-ifdef(USE_ESOCK).
+-define(ESOCK_MODS, [socket]).
+-else.
+-define(ESOCK_MODS, []).
+-endif.
+
+
%%-----------------------------------------------------------------
%% Create a boot script from a release file.
%% Options is a list of {path, Path} | silent | local
@@ -1566,7 +1574,7 @@ preloaded() ->
erts_code_purger,erts_dirty_process_signal_handler,
erts_internal,erts_literal_area_collector,
init,net,persistent_term,prim_buffer,prim_eval,prim_file,
- prim_inet,prim_zip,socket,zlib].
+ prim_inet,prim_zip] ++ ?ESOCK_MODS ++ [zlib].
%%______________________________________________________________________
%% Kernel processes; processes that are specially treated by the init
diff --git a/lib/ssh/doc/src/notes.xml b/lib/ssh/doc/src/notes.xml
index bad5815f40..78990c48f2 100644
--- a/lib/ssh/doc/src/notes.xml
+++ b/lib/ssh/doc/src/notes.xml
@@ -30,6 +30,28 @@
<file>notes.xml</file>
</header>
+<section><title>Ssh 4.7.6</title>
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ When an SSH server receives the very first message on a
+ new TCP connection, and that message is not the expected
+ one, the 64 first bytes of the received message are now
+ dumped in the INFO REPORT that reports the Protocol
+ Error.</p>
+ <p>
+ This facilitates the debugging of who sends the bad
+ message or of detecting a possible port scanning.</p>
+ <p>
+ Own Id: OTP-15772</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>Ssh 4.7.5</title>
<section><title>Fixed Bugs and Malfunctions</title>
diff --git a/lib/ssh/src/ssh.app.src b/lib/ssh/src/ssh.app.src
index 410061cded..7449405d20 100644
--- a/lib/ssh/src/ssh.app.src
+++ b/lib/ssh/src/ssh.app.src
@@ -44,10 +44,10 @@
{env, []},
{mod, {ssh_app, []}},
{runtime_dependencies, [
- "crypto-4.2",
- "erts-6.0",
- "kernel-3.0",
- "public_key-1.5.2",
- "stdlib-3.3"
+ "crypto-@OTP-15644@",
+ "erts-9.0",
+ "kernel-5.3",
+ "public_key-1.6.1",
+ "stdlib-3.4.1"
]}]}.
diff --git a/lib/ssh/vsn.mk b/lib/ssh/vsn.mk
index 2947f82556..837da27ab0 100644
--- a/lib/ssh/vsn.mk
+++ b/lib/ssh/vsn.mk
@@ -1,4 +1,4 @@
#-*-makefile-*- ; force emacs to enter makefile-mode
-SSH_VSN = 4.7.5
+SSH_VSN = 4.7.6
APP_VSN = "ssh-$(SSH_VSN)"
diff --git a/lib/ssl/doc/src/standards_compliance.xml b/lib/ssl/doc/src/standards_compliance.xml
index 25840d0fc6..ca98385f85 100644
--- a/lib/ssl/doc/src/standards_compliance.xml
+++ b/lib/ssl/doc/src/standards_compliance.xml
@@ -133,7 +133,8 @@
<list type="bulleted">
<item>Key Exchange: ECDHE</item>
<item>Groups: all standard groups supported for the Diffie-Hellman key exchange</item>
- <item>Ciphers: TLS_AES_128_GCM_SHA256 and TLS_AES_256_GCM_SHA384</item>
+ <item>Ciphers: TLS_AES_128_GCM_SHA256, TLS_AES_256_GCM_SHA384,
+ TLS_CHACHA20_POLY1305_SHA256 and TLS_AES_128_CCM_SHA256</item>
<item>Signature Algorithms: RSA and RSA PSS</item>
<item>Certificates: currently only certificates with RSA keys are supported</item>
</list>
@@ -1967,8 +1968,8 @@
<row>
<cell align="left" valign="middle"></cell>
<cell align="left" valign="middle">SHOULD implement the TLS_CHACHA20_POLY1305_SHA256</cell>
- <cell align="left" valign="middle"><em>NC</em></cell>
- <cell align="left" valign="middle"></cell>
+ <cell align="left" valign="middle"><em>C</em></cell>
+ <cell align="left" valign="middle">22</cell>
</row>
<row>
@@ -2203,14 +2204,14 @@
<row>
<cell align="left" valign="middle"></cell>
<cell align="left" valign="middle">TLS_CHACHA20_POLY1305_SHA256</cell>
- <cell align="left" valign="middle"><em>NC</em></cell>
- <cell align="left" valign="middle"></cell>
+ <cell align="left" valign="middle"><em>C</em></cell>
+ <cell align="left" valign="middle">22</cell>
</row>
<row>
<cell align="left" valign="middle"></cell>
<cell align="left" valign="middle">TLS_AES_128_CCM_SHA256</cell>
- <cell align="left" valign="middle"><em>NC</em></cell>
- <cell align="left" valign="middle"></cell>
+ <cell align="left" valign="middle"><em>C</em></cell>
+ <cell align="left" valign="middle">22</cell>
</row>
<row>
<cell align="left" valign="middle"></cell>
diff --git a/lib/ssl/src/ssl_cipher.hrl b/lib/ssl/src/ssl_cipher.hrl
index 9c5e2f80a9..0fa5f66c49 100644
--- a/lib/ssl/src/ssl_cipher.hrl
+++ b/lib/ssl/src/ssl_cipher.hrl
@@ -690,9 +690,9 @@
-define(TLS_CHACHA20_POLY1305_SHA256, <<?BYTE(16#13),?BYTE(16#03)>>).
%% %% TLS_AES_128_CCM_SHA256 = {0x13,0x04}
-%% -define(TLS_AES_128_CCM_SHA256, <<?BYTE(16#13), ?BYTE(16#04)>>).
+-define(TLS_AES_128_CCM_SHA256, <<?BYTE(16#13), ?BYTE(16#04)>>).
%% %% TLS_AES_128_CCM_8_SHA256 = {0x13,0x05}
-%% -define(TLS_AES_128_CCM_8_SHA256, <<?BYTE(16#13),?BYTE(16#05)>>).
+-define(TLS_AES_128_CCM_8_SHA256, <<?BYTE(16#13),?BYTE(16#05)>>).
-endif. % -ifdef(ssl_cipher).
diff --git a/lib/ssl/src/ssl_cipher_format.erl b/lib/ssl/src/ssl_cipher_format.erl
index 887eb6c653..577156a4b5 100644
--- a/lib/ssl/src/ssl_cipher_format.erl
+++ b/lib/ssl/src/ssl_cipher_format.erl
@@ -955,12 +955,12 @@ suite_bin_to_map(?TLS_CHACHA20_POLY1305_SHA256) ->
#{key_exchange => any,
cipher => chacha20_poly1305,
mac => aead,
- prf => sha256}.
-%% suite_bin_to_map(?TLS_AES_128_CCM_SHA256) ->
-%% #{key_exchange => any,
-%% cipher => aes_128_ccm,
-%% mac => aead
-%% prf => sha256};
+ prf => sha256};
+suite_bin_to_map(?TLS_AES_128_CCM_SHA256) ->
+ #{key_exchange => any,
+ cipher => aes_128_ccm,
+ mac => aead,
+ prf => sha256}.
%% suite_bin_to_map(?TLS_AES_128_CCM_8_SHA256) ->
%% #{key_exchange => any,
%% cipher => aes_128_ccm_8,
@@ -1690,12 +1690,12 @@ suite_map_to_bin(#{key_exchange := any,
cipher := chacha20_poly1305,
mac := aead,
prf := sha256}) ->
- ?TLS_CHACHA20_POLY1305_SHA256.
-%% suite_map_to_bin(#{key_exchange := any,
-%% cipher := aes_128_ccm,
-%% mac := aead,
-%% prf := sha256}) ->
-%% ?TLS_AES_128_CCM_SHA256;
+ ?TLS_CHACHA20_POLY1305_SHA256;
+suite_map_to_bin(#{key_exchange := any,
+ cipher := aes_128_ccm,
+ mac := aead,
+ prf := sha256}) ->
+ ?TLS_AES_128_CCM_SHA256.
%% suite_map_to_bin(#{key_exchange := any,
%% cipher := aes_128_ccm_8,
%% mac := aead,
diff --git a/lib/ssl/src/tls_v1.erl b/lib/ssl/src/tls_v1.erl
index f103f3218b..27cd5765e5 100644
--- a/lib/ssl/src/tls_v1.erl
+++ b/lib/ssl/src/tls_v1.erl
@@ -501,18 +501,18 @@ suites(3) ->
suites(4) ->
[?TLS_AES_256_GCM_SHA384,
?TLS_AES_128_GCM_SHA256,
- ?TLS_CHACHA20_POLY1305_SHA256
+ ?TLS_CHACHA20_POLY1305_SHA256,
+ ?TLS_AES_128_CCM_SHA256
%% Not supported
- %% ?TLS_AES_128_CCM_SHA256,
%% ?TLS_AES_128_CCM_8_SHA256
] ++ suites(3);
suites('TLS_v1.3') ->
[?TLS_AES_256_GCM_SHA384,
?TLS_AES_128_GCM_SHA256,
- ?TLS_CHACHA20_POLY1305_SHA256
+ ?TLS_CHACHA20_POLY1305_SHA256,
+ ?TLS_AES_128_CCM_SHA256
%% Not supported
- %% ?TLS_AES_128_CCM_SHA256,
%% ?TLS_AES_128_CCM_8_SHA256
].
diff --git a/lib/ssl/test/Makefile b/lib/ssl/test/Makefile
index f7fae16088..dba90aaff0 100644
--- a/lib/ssl/test/Makefile
+++ b/lib/ssl/test/Makefile
@@ -44,6 +44,7 @@ MODULES = \
ssl_bench_SUITE \
ssl_cipher_SUITE \
ssl_cipher_suite_SUITE \
+ openssl_server_cipher_suite_SUITE\
ssl_certificate_verify_SUITE\
ssl_crl_SUITE\
ssl_dist_SUITE \
diff --git a/lib/ssl/test/openssl_server_cipher_suite_SUITE.erl b/lib/ssl/test/openssl_server_cipher_suite_SUITE.erl
new file mode 100644
index 0000000000..907de1abe2
--- /dev/null
+++ b/lib/ssl/test/openssl_server_cipher_suite_SUITE.erl
@@ -0,0 +1,768 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2019-2019. All Rights Reserved.
+%%
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+%%
+
+-module(openssl_server_cipher_suite_SUITE).
+
+%% Note: This directive should only be used in test suites.
+-compile(export_all).
+
+-include_lib("common_test/include/ct.hrl").
+
+%%--------------------------------------------------------------------
+%% Common Test interface functions -----------------------------------
+%%--------------------------------------------------------------------
+all() ->
+ [
+ {group, 'tlsv1.2'},
+ {group, 'tlsv1.1'},
+ {group, 'tlsv1'},
+ {group, 'sslv3'},
+ {group, 'dtlsv1.2'},
+ {group, 'dtlsv1'}
+ ].
+
+groups() ->
+ %% TODO: Enable SRP, PSK suites (needs OpenSSL s_server conf)
+ %% TODO: Enable all "kex" on DTLS
+ [
+ {'tlsv1.2', [], kex()},
+ {'tlsv1.1', [], kex()},
+ {'tlsv1', [], kex()},
+ {'sslv3', [], kex()},
+ {'dtlsv1.2', [], dtls_kex()},
+ {'dtlsv1', [], dtls_kex()},
+ {dhe_rsa, [],[dhe_rsa_3des_ede_cbc,
+ dhe_rsa_aes_128_cbc,
+ dhe_rsa_aes_256_cbc,
+ dhe_rsa_chacha20_poly1305
+ ]},
+ {ecdhe_rsa, [], [ecdhe_rsa_3des_ede_cbc,
+ ecdhe_rsa_aes_128_cbc,
+ ecdhe_rsa_aes_128_gcm,
+ ecdhe_rsa_aes_256_cbc,
+ ecdhe_rsa_aes_256_gcm,
+ ecdhe_rsa_chacha20_poly1305
+ ]},
+ {ecdhe_ecdsa, [],[ecdhe_ecdsa_rc4_128,
+ ecdhe_ecdsa_3des_ede_cbc,
+ ecdhe_ecdsa_aes_128_cbc,
+ ecdhe_ecdsa_aes_128_gcm,
+ ecdhe_ecdsa_aes_256_cbc,
+ ecdhe_ecdsa_aes_256_gcm,
+ ecdhe_ecdsa_chacha20_poly1305
+ ]},
+ {rsa, [], [rsa_3des_ede_cbc,
+ rsa_aes_128_cbc,
+ rsa_aes_256_cbc,
+ rsa_rc4_128
+ ]},
+ {dhe_dss, [], [dhe_dss_3des_ede_cbc,
+ dhe_dss_aes_128_cbc,
+ dhe_dss_aes_256_cbc]},
+ %% {srp_rsa, [], [srp_rsa_3des_ede_cbc,
+ %% srp_rsa_aes_128_cbc,
+ %% srp_rsa_aes_256_cbc]},
+ %% {srp_dss, [], [srp_dss_3des_ede_cbc,
+ %% srp_dss_aes_128_cbc,
+ %% srp_dss_aes_256_cbc]},
+ %% {rsa_psk, [], [rsa_psk_3des_ede_cbc,
+ %% rsa_psk_rc4_128,
+ %% rsa_psk_aes_128_cbc,
+ %% rsa_psk_aes_256_cbc
+ %% ]},
+ {dh_anon, [], [dh_anon_rc4_128,
+ dh_anon_3des_ede_cbc,
+ dh_anon_aes_128_cbc,
+ dh_anon_aes_128_gcm,
+ dh_anon_aes_256_cbc,
+ dh_anon_aes_256_gcm]},
+ {ecdh_anon, [], [ecdh_anon_3des_ede_cbc,
+ ecdh_anon_aes_128_cbc,
+ ecdh_anon_aes_256_cbc
+ ]}
+ %% {srp_anon, [], [srp_anon_3des_ede_cbc,
+ %% srp_anon_aes_128_cbc,
+ %% srp_anon_aes_256_cbc]},
+ %% {psk, [], [psk_3des_ede_cbc,
+ %% psk_rc4_128,
+ %% psk_aes_128_cbc,
+ %% psk_aes_128_ccm,
+ %% psk_aes_128_ccm_8,
+ %% psk_aes_256_cbc,
+ %% psk_aes_256_ccm,
+ %% psk_aes_256_ccm_8
+ %% ]},
+ %% {dhe_psk, [], [dhe_psk_3des_ede_cbc,
+ %% dhe_psk_rc4_128,
+ %% dhe_psk_aes_128_cbc,
+ %% dhe_psk_aes_128_ccm,
+ %% dhe_psk_aes_128_ccm_8,
+ %% dhe_psk_aes_256_cbc,
+ %% dhe_psk_aes_256_ccm,
+ %% dhe_psk_aes_256_ccm_8
+ %% ]},
+ %% {ecdhe_psk, [], [ecdhe_psk_3des_ede_cbc,
+ %% ecdhe_psk_rc4_128,
+ %% ecdhe_psk_aes_128_cbc,
+ %% ecdhe_psk_aes_128_ccm,
+ %% ecdhe_psk_aes_128_ccm_8,
+ %% ecdhe_psk_aes_256_cbc
+ %% ]}
+ ].
+
+kex() ->
+ rsa() ++ ecdsa() ++ dss() ++ anonymous().
+
+dtls_kex() -> %% Should be all kex in the future
+ dtls_rsa() ++ dss() ++ anonymous().
+
+rsa() ->
+ [{group, dhe_rsa},
+ {group, ecdhe_rsa},
+ {group, rsa} %%, {group, srp_rsa},
+ %%{group, rsa_psk}
+ ].
+
+dtls_rsa() ->
+ [
+ {group, rsa}
+ %%,{group, rsa_psk}
+ ].
+
+ecdsa() ->
+ [{group, ecdhe_ecdsa}].
+
+dss() ->
+ [{group, dhe_dss}
+ %%{group, srp_dss}
+ ].
+
+anonymous() ->
+ [{group, dh_anon},
+ {group, ecdh_anon}
+ %% {group, psk},
+ %%{group, dhe_psk},
+ %%{group, ecdhe_psk}
+ %%{group, srp_anon}
+ ].
+
+init_per_suite(Config) ->
+ catch crypto:stop(),
+ try crypto:start() of
+ ok ->
+ ssl_test_lib:clean_start(),
+ Config
+ catch _:_ ->
+ {skip, "Crypto did not start"}
+ end.
+
+end_per_suite(_Config) ->
+ ssl:stop(),
+ application:stop(crypto).
+
+%%--------------------------------------------------------------------
+init_per_group(GroupName, Config) ->
+ case ssl_test_lib:is_tls_version(GroupName) of
+ true ->
+ case ssl_test_lib:supports_ssl_tls_version(GroupName) of
+ true ->
+ do_init_per_group(GroupName, Config);
+ false ->
+ {skip, {openssl_does_not_support, GroupName}}
+ end;
+ false ->
+ do_init_per_group(GroupName, Config)
+ end.
+
+do_init_per_group(GroupName, Config) when GroupName == ecdh_anon;
+ GroupName == ecdhe_rsa;
+ GroupName == ecdhe_psk ->
+ case proplists:get_bool(ecdh, proplists:get_value(public_keys, crypto:supports())) of
+ true ->
+ init_certs(GroupName, Config);
+ false ->
+ {skip, "Missing EC crypto support"}
+ end;
+do_init_per_group(ecdhe_ecdsa = GroupName, Config) ->
+ PKAlg = proplists:get_value(public_keys, crypto:supports()),
+ case lists:member(ecdh, PKAlg) andalso lists:member(ecdsa, PKAlg) of
+ true ->
+ init_certs(GroupName, Config);
+ false ->
+ {skip, "Missing EC crypto support"}
+ end;
+do_init_per_group(dhe_dss = GroupName, Config) ->
+ PKAlg = proplists:get_value(public_keys, crypto:supports()),
+ case lists:member(dss, PKAlg) andalso lists:member(dh, PKAlg) of
+ true ->
+ init_certs(GroupName, Config);
+ false ->
+ {skip, "Missing DSS crypto support"}
+ end;
+do_init_per_group(srp_dss = GroupName, Config) ->
+ PKAlg = proplists:get_value(public_keys, crypto:supports()),
+ case lists:member(dss, PKAlg) andalso lists:member(srp, PKAlg) of
+ true ->
+ init_certs(GroupName, Config);
+ false ->
+ {skip, "Missing DSS_SRP crypto support"}
+ end;
+do_init_per_group(GroupName, Config) when GroupName == srp_anon;
+ GroupName == srp_rsa ->
+ PKAlg = proplists:get_value(public_keys, crypto:supports()),
+ case lists:member(srp, PKAlg) of
+ true ->
+ init_certs(GroupName, Config);
+ false ->
+ {skip, "Missing SRP crypto support"}
+ end;
+do_init_per_group(dhe_psk = GroupName, Config) ->
+ PKAlg = proplists:get_value(public_keys, crypto:supports()),
+ case lists:member(dh, PKAlg) of
+ true ->
+ init_certs(GroupName, Config);
+ false ->
+ {skip, "Missing SRP crypto support"}
+ end;
+do_init_per_group(GroupName, Config0) ->
+ case ssl_test_lib:is_tls_version(GroupName) of
+ true ->
+ ssl_test_lib:init_tls_version(GroupName, end_per_group(GroupName, Config0));
+ false ->
+ init_certs(GroupName, Config0)
+ end.
+
+end_per_group(GroupName, Config) ->
+ case ssl_test_lib:is_tls_version(GroupName) of
+ true ->
+ ssl_test_lib:clean_tls_version(Config);
+ false ->
+ Config
+ end.
+
+init_per_testcase(TestCase, Config) when TestCase == psk_3des_ede_cbc;
+ TestCase == srp_anon_3des_ede_cbc;
+ TestCase == dhe_psk_3des_ede_cbc;
+ TestCase == ecdhe_psk_3des_ede_cbc;
+ TestCase == srp_rsa_3des_ede_cbc;
+ TestCase == srp_dss_3des_ede_cbc;
+ TestCase == rsa_psk_3des_ede_cbc;
+ TestCase == rsa_3des_ede_cbc;
+ TestCase == dhe_rsa_3des_ede_cbc;
+ TestCase == dhe_dss_3des_ede_cbc;
+ TestCase == ecdhe_rsa_3des_ede_cbc;
+ TestCase == srp_anon_dss_3des_ede_cbc;
+ TestCase == dh_anon_3des_ede_cbc;
+ TestCase == ecdh_anon_3des_ede_cbc;
+ TestCase == ecdhe_ecdsa_3des_ede_cbc ->
+ SupCiphers = proplists:get_value(ciphers, crypto:supports()),
+ case lists:member(des_ede3, SupCiphers) of
+ true ->
+ ct:timetrap({seconds, 5}),
+ Config;
+ _ ->
+ {skip, "Missing 3DES crypto support"}
+ end;
+init_per_testcase(TestCase, Config) when TestCase == psk_rc4_128;
+ TestCase == ecdhe_psk_rc4_128;
+ TestCase == dhe_psk_rc4_128;
+ TestCase == rsa_psk_rc4_128;
+ TestCase == rsa_rc4_128;
+ TestCase == ecdhe_rsa_rc4_128;
+ TestCase == ecdhe_ecdsa_rc4_128;
+ TestCase == dh_anon_rc4_128 ->
+ SupCiphers = proplists:get_value(ciphers, crypto:supports()),
+ case lists:member(rc4, SupCiphers) of
+ true ->
+ ct:timetrap({seconds, 5}),
+ Config;
+ _ ->
+ {skip, "Missing RC4 crypto support"}
+ end;
+init_per_testcase(TestCase, Config) when TestCase == psk_aes_128_ccm_8;
+ TestCase == rsa_psk_aes_128_ccm_8;
+ TestCase == psk_aes_128_ccm_8;
+ TestCase == dhe_psk_aes_128_ccm_8;
+ TestCase == ecdhe_psk_aes_128_ccm_8 ->
+ SupCiphers = proplists:get_value(ciphers, crypto:supports()),
+ case lists:member(aes_128_ccm, SupCiphers) of
+ true ->
+ ct:timetrap({seconds, 5}),
+ Config;
+ _ ->
+ {skip, "Missing AES_128_CCM crypto support"}
+ end;
+init_per_testcase(TestCase, Config) when TestCase == psk_aes_256_ccm_8;
+ TestCase == rsa_psk_aes_256_ccm_8;
+ TestCase == psk_aes_256_ccm_8;
+ TestCase == dhe_psk_aes_256_ccm_8;
+ TestCase == ecdhe_psk_aes_256_ccm_8 ->
+ SupCiphers = proplists:get_value(ciphers, crypto:supports()),
+ case lists:member(aes_256_ccm, SupCiphers) of
+ true ->
+ ct:timetrap({seconds, 5}),
+ Config;
+ _ ->
+ {skip, "Missing AES_256_CCM crypto support"}
+ end;
+init_per_testcase(TestCase, Config) ->
+ Cipher = ssl_test_lib:test_cipher(TestCase, Config),
+ SupCiphers = proplists:get_value(ciphers, crypto:supports()),
+ case lists:member(Cipher, SupCiphers) of
+ true ->
+ ct:timetrap({seconds, 5}),
+ Config;
+ _ ->
+ {skip, {Cipher, SupCiphers}}
+ end.
+
+end_per_testcase(_TestCase, Config) ->
+ Config.
+
+%%--------------------------------------------------------------------
+%% Initializtion ------------------------------------------
+%%--------------------------------------------------------------------
+init_certs(srp_rsa, Config) ->
+ {ClientOpts, ServerOpts} = ssl_test_lib:make_rsa_cert_chains([{server_chain, ssl_test_lib:default_cert_chain_conf()},
+ {client_chain, ssl_test_lib:default_cert_chain_conf()}],
+ Config, ""),
+ [{tls_config, #{server_config => [{user_lookup_fun, {fun ssl_test_lib:user_lookup/3, undefined}} | ServerOpts],
+ client_config => [{srp_identity, {"Test-User", "secret"}} | ClientOpts]}} |
+ proplists:delete(tls_config, Config)];
+init_certs(srp_anon, Config) ->
+ [{tls_config, #{server_config => [{user_lookup_fun, {fun ssl_test_lib:user_lookup/3, undefined}}],
+ client_config => [{srp_identity, {"Test-User", "secret"}}]}} |
+ proplists:delete(tls_config, Config)];
+init_certs(rsa_psk, Config) ->
+ Ext = x509_test:extensions([{key_usage, [digitalSignature, keyEncipherment]}]),
+ {ClientOpts, ServerOpts} = ssl_test_lib:make_rsa_cert_chains([{server_chain,
+ [[ssl_test_lib:digest()],[ssl_test_lib:digest()],
+ [ssl_test_lib:digest(), {extensions, Ext}]]},
+ {client_chain, ssl_test_lib:default_cert_chain_conf()}],
+ Config, "_peer_keyEncipherment"),
+ PskSharedSecret = <<1,2,3,4,5,6,7,8,9,10,11,12,13,14,15>>,
+ [{tls_config, #{server_config => [{user_lookup_fun, {fun ssl_test_lib:user_lookup/3, PskSharedSecret}} | ServerOpts],
+ client_config => [{psk_identity, "Test-User"},
+ {user_lookup_fun, {fun ssl_test_lib:user_lookup/3, PskSharedSecret}} | ClientOpts]}} |
+ proplists:delete(tls_config, Config)];
+init_certs(rsa, Config) ->
+ Ext = x509_test:extensions([{key_usage, [digitalSignature, keyEncipherment]}]),
+ {ClientOpts, ServerOpts} = ssl_test_lib:make_rsa_cert_chains([{server_chain,
+ [[ssl_test_lib:digest()],[ssl_test_lib:digest()],
+ [ssl_test_lib:digest(), {extensions, Ext}]]}
+ ],
+ Config, "_peer_keyEncipherment"),
+ [{tls_config, #{server_config => ServerOpts,
+ client_config => ClientOpts}} |
+ proplists:delete(tls_config, Config)];
+init_certs(dhe_dss, Config) ->
+ {ClientOpts, ServerOpts} = ssl_test_lib:make_dsa_cert_chains([{server_chain, ssl_test_lib:default_cert_chain_conf()},
+ {client_chain, ssl_test_lib:default_cert_chain_conf()}],
+ Config, ""),
+ [{tls_config, #{server_config => ServerOpts,
+ client_config => ClientOpts}} |
+ proplists:delete(tls_config, Config)];
+init_certs(srp_dss, Config) ->
+ {ClientOpts, ServerOpts} = ssl_test_lib:make_dsa_cert_chains([{server_chain, ssl_test_lib:default_cert_chain_conf()},
+ {client_chain, ssl_test_lib:default_cert_chain_conf()}],
+ Config, ""),
+ [{tls_config, #{server_config => [{user_lookup_fun, {fun ssl_test_lib:user_lookup/3, undefined}} | ServerOpts],
+ client_config => [{srp_identity, {"Test-User", "secret"}} | ClientOpts]}} |
+ proplists:delete(tls_config, Config)];
+init_certs(GroupName, Config) when GroupName == dhe_rsa;
+ GroupName == ecdhe_rsa ->
+ {ClientOpts, ServerOpts} = ssl_test_lib:make_rsa_cert_chains([{server_chain, ssl_test_lib:default_cert_chain_conf()},
+ {client_chain, ssl_test_lib:default_cert_chain_conf()}],
+ Config, ""),
+ [{tls_config, #{server_config => ServerOpts,
+ client_config => ClientOpts}} |
+ proplists:delete(tls_config, Config)];
+init_certs(GroupName, Config) when GroupName == dhe_ecdsa;
+ GroupName == ecdhe_ecdsa ->
+ {ClientOpts, ServerOpts} = ssl_test_lib:make_ecc_cert_chains([{server_chain, ssl_test_lib:default_cert_chain_conf()},
+ {client_chain, ssl_test_lib:default_cert_chain_conf()}],
+ Config, ""),
+ [{tls_config, #{server_config => ServerOpts,
+ client_config => ClientOpts}} |
+ proplists:delete(tls_config, Config)];
+init_certs(GroupName, Config) when GroupName == psk;
+ GroupName == dhe_psk;
+ GroupName == ecdhe_psk ->
+ PskSharedSecret = <<1,2,3,4,5,6,7,8,9,10,11,12,13,14,15>>,
+ [{tls_config, #{server_config => [{user_lookup_fun, {fun ssl_test_lib:user_lookup/3, PskSharedSecret}}],
+ client_config => [{psk_identity, "Test-User"},
+ {user_lookup_fun, {fun ssl_test_lib:user_lookup/3, PskSharedSecret}}]}} |
+ proplists:delete(tls_config, Config)];
+init_certs(srp, Config) ->
+ [{tls_config, #{server_config => [{user_lookup_fun, {fun ssl_test_lib:user_lookup/3, undefined}}],
+ client_config => [{srp_identity, {"Test-User", "secret"}}]}} |
+ proplists:delete(tls_config, Config)];
+init_certs(_GroupName, Config) ->
+ %% Anonymous does not need certs
+ [{tls_config, #{server_config => [],
+ client_config => []}} |
+ proplists:delete(tls_config, Config)].
+%%--------------------------------------------------------------------
+%% Test Cases --------------------------------------------------------
+%%--------------------------------------------------------------------
+
+%%--------------------------------------------------------------------
+%% SRP --------------------------------------------------------
+%%--------------------------------------------------------------------
+srp_rsa_3des_ede_cbc(Config) when is_list(Config) ->
+ run_ciphers_test(srp_rsa, '3des_ede_cbc', Config).
+
+srp_rsa_aes_128_cbc(Config) when is_list(Config) ->
+ run_ciphers_test(srp_rsa, 'aes_128_cbc', Config).
+
+srp_rsa_aes_256_cbc(Config) when is_list(Config) ->
+ run_ciphers_test(srp_rsa, 'aes_256_cbc', Config).
+
+srp_dss_3des_ede_cbc(Config) when is_list(Config) ->
+ run_ciphers_test(srp_dss, '3des_ede_cbc', Config).
+
+srp_dss_aes_128_cbc(Config) when is_list(Config) ->
+ run_ciphers_test(srp_dss, 'aes_128_cbc', Config).
+
+srp_dss_aes_256_cbc(Config) when is_list(Config) ->
+ run_ciphers_test(srp_dss, 'aes_256_cbc', Config).
+
+%%--------------------------------------------------------------------
+%% PSK --------------------------------------------------------
+%%--------------------------------------------------------------------
+rsa_psk_3des_ede_cbc(Config) when is_list(Config) ->
+ run_ciphers_test(rsa_psk, '3des_ede_cbc', Config).
+
+rsa_psk_aes_128_cbc(Config) when is_list(Config) ->
+ run_ciphers_test(rsa_psk, 'aes_128_cbc', Config).
+
+rsa_psk_aes_128_ccm(Config) when is_list(Config) ->
+ run_ciphers_test(rsa_psk, 'aes_128_ccm', Config).
+
+rsa_psk_aes_128_ccm_8(Config) when is_list(Config) ->
+ run_ciphers_test(rsa_psk, 'aes_128_ccm_8', Config).
+
+rsa_psk_aes_256_cbc(Config) when is_list(Config) ->
+ run_ciphers_test(rsa_psk, 'aes_256_cbc', Config).
+
+rsa_psk_aes_256_ccm(Config) when is_list(Config) ->
+ run_ciphers_test(rsa_psk, 'aes_256_ccm', Config).
+
+rsa_psk_aes_256_ccm_8(Config) when is_list(Config) ->
+ run_ciphers_test(rsa_psk, 'aes_256_ccm_8', Config).
+
+rsa_psk_rc4_128(Config) when is_list(Config) ->
+ run_ciphers_test(rsa_psk, 'rc4_128', Config).
+
+%%--------------------------------------------------------------------
+%% RSA --------------------------------------------------------
+%%--------------------------------------------------------------------
+rsa_des_cbc(Config) when is_list(Config) ->
+ run_ciphers_test(rsa, 'des_cbc', Config).
+
+rsa_3des_ede_cbc(Config) when is_list(Config) ->
+ run_ciphers_test(rsa, '3des_ede_cbc', Config).
+
+rsa_aes_128_cbc(Config) when is_list(Config) ->
+ run_ciphers_test(rsa, 'aes_128_cbc', Config).
+
+rsa_aes_256_cbc(Config) when is_list(Config) ->
+ run_ciphers_test(rsa, 'aes_256_cbc', Config).
+
+rsa_aes_128_gcm(Config) when is_list(Config) ->
+ run_ciphers_test(rsa, 'aes_128_gcm', Config).
+
+rsa_aes_256_gcm(Config) when is_list(Config) ->
+ run_ciphers_test(rsa, 'aes_256_gcm', Config).
+
+rsa_rc4_128(Config) when is_list(Config) ->
+ run_ciphers_test(rsa, 'rc4_128', Config).
+%%--------------------------------------------------------------------
+%% DHE_RSA --------------------------------------------------------
+%%--------------------------------------------------------------------
+dhe_rsa_3des_ede_cbc(Config) when is_list(Config) ->
+ run_ciphers_test(dhe_rsa, '3des_ede_cbc', Config).
+
+dhe_rsa_aes_128_cbc(Config) when is_list(Config) ->
+ run_ciphers_test(dhe_rsa, 'aes_128_cbc', Config).
+
+dhe_rsa_aes_128_gcm(Config) when is_list(Config) ->
+ run_ciphers_test(dhe_rsa, 'aes_128_gcm', Config).
+
+dhe_rsa_aes_256_cbc(Config) when is_list(Config) ->
+ run_ciphers_test(dhe_rsa, 'aes_256_cbc', Config).
+
+dhe_rsa_aes_256_gcm(Config) when is_list(Config) ->
+ run_ciphers_test(dhe_rsa, 'aes_256_gcm', Config).
+
+dhe_rsa_chacha20_poly1305(Config) when is_list(Config) ->
+ run_ciphers_test(dhe_rsa, 'chacha20_poly1305', Config).
+%%--------------------------------------------------------------------
+%% ECDHE_RSA --------------------------------------------------------
+%%--------------------------------------------------------------------
+ecdhe_rsa_3des_ede_cbc(Config) when is_list(Config) ->
+ run_ciphers_test(ecdhe_rsa, '3des_ede_cbc', Config).
+
+ecdhe_rsa_aes_128_cbc(Config) when is_list(Config) ->
+ run_ciphers_test(ecdhe_rsa, 'aes_128_cbc', Config).
+
+ecdhe_rsa_aes_128_gcm(Config) when is_list(Config) ->
+ run_ciphers_test(ecdhe_rsa, 'aes_128_gcm', Config).
+
+ecdhe_rsa_aes_256_cbc(Config) when is_list(Config) ->
+ run_ciphers_test(ecdhe_rsa, 'aes_256_cbc', Config).
+
+ecdhe_rsa_aes_256_gcm(Config) when is_list(Config) ->
+ run_ciphers_test(ecdhe_rsa, 'aes_256_gcm', Config).
+
+ecdhe_rsa_rc4_128(Config) when is_list(Config) ->
+ run_ciphers_test(ecdhe_rsa, 'rc4_128', Config).
+
+ecdhe_rsa_chacha20_poly1305(Config) when is_list(Config) ->
+ run_ciphers_test(ecdhe_rsa, 'chacha20_poly1305', Config).
+
+%%--------------------------------------------------------------------
+%% ECDHE_ECDSA --------------------------------------------------------
+%%--------------------------------------------------------------------
+ecdhe_ecdsa_rc4_128(Config) when is_list(Config) ->
+ run_ciphers_test(ecdhe_ecdsa, 'rc4_128', Config).
+
+ecdhe_ecdsa_3des_ede_cbc(Config) when is_list(Config) ->
+ run_ciphers_test(ecdhe_ecdsa, '3des_ede_cbc', Config).
+
+ecdhe_ecdsa_aes_128_cbc(Config) when is_list(Config) ->
+ run_ciphers_test(ecdhe_ecdsa, 'aes_128_cbc', Config).
+
+ecdhe_ecdsa_aes_128_gcm(Config) when is_list(Config) ->
+ run_ciphers_test(ecdhe_ecdsa, 'aes_128_gcm', Config).
+
+ecdhe_ecdsa_aes_256_cbc(Config) when is_list(Config) ->
+ run_ciphers_test(ecdhe_ecdsa, 'aes_256_cbc', Config).
+
+ecdhe_ecdsa_aes_256_gcm(Config) when is_list(Config) ->
+ run_ciphers_test(ecdhe_ecdsa, 'aes_256_gcm', Config).
+
+ecdhe_ecdsa_chacha20_poly1305(Config) when is_list(Config) ->
+ run_ciphers_test(ecdhe_ecdsa, 'chacha20_poly1305', Config).
+%%--------------------------------------------------------------------
+%% DHE_DSS --------------------------------------------------------
+%%--------------------------------------------------------------------
+dhe_dss_des_cbc(Config) when is_list(Config) ->
+ run_ciphers_test(dhe_dss, 'des_cbc', Config).
+
+dhe_dss_3des_ede_cbc(Config) when is_list(Config) ->
+ run_ciphers_test(dhe_dss, '3des_ede_cbc', Config).
+
+dhe_dss_aes_128_cbc(Config) when is_list(Config) ->
+ run_ciphers_test(dhe_dss, 'aes_128_cbc', Config).
+
+dhe_dss_aes_256_cbc(Config) when is_list(Config) ->
+ run_ciphers_test(dhe_dss, 'aes_256_cbc', Config).
+
+dhe_dss_aes_128_gcm(Config) when is_list(Config) ->
+ run_ciphers_test(dhe_dss, 'aes_128_gcm', Config).
+
+dhe_dss_aes_256_gcm(Config) when is_list(Config) ->
+ run_ciphers_test(dhe_dss, 'aes_256_gcm', Config).
+
+%%--------------------------------------------------------------------
+%% Anonymous --------------------------------------------------------
+%%--------------------------------------------------------------------
+dh_anon_3des_ede_cbc(Config) when is_list(Config) ->
+ run_ciphers_test(dh_anon, '3des_ede_cbc', Config).
+
+dh_anon_aes_128_cbc(Config) when is_list(Config) ->
+ run_ciphers_test(dh_anon, 'aes_128_cbc', Config).
+
+dh_anon_aes_128_gcm(Config) when is_list(Config) ->
+ run_ciphers_test(dh_anon, 'aes_128_gcm', Config).
+
+dh_anon_aes_256_cbc(Config) when is_list(Config) ->
+ run_ciphers_test(dh_anon, 'aes_256_cbc', Config).
+
+dh_anon_aes_256_gcm(Config) when is_list(Config) ->
+ run_ciphers_test(dh_anon, 'aes_256_gcm', Config).
+
+dh_anon_rc4_128(Config) when is_list(Config) ->
+ run_ciphers_test(dh_anon, 'rc4_128', Config).
+
+ecdh_anon_3des_ede_cbc(Config) when is_list(Config) ->
+ run_ciphers_test(ecdh_anon, '3des_ede_cbc', Config).
+
+ecdh_anon_aes_128_cbc(Config) when is_list(Config) ->
+ run_ciphers_test(ecdh_anon, 'aes_128_cbc', Config).
+
+ecdh_anon_aes_256_cbc(Config) when is_list(Config) ->
+ run_ciphers_test(ecdh_anon, 'aes_256_cbc', Config).
+
+srp_anon_3des_ede_cbc(Config) when is_list(Config) ->
+ run_ciphers_test(srp_anon, '3des_ede_cbc', Config).
+
+srp_anon_aes_128_cbc(Config) when is_list(Config) ->
+ run_ciphers_test(srp_anon, 'aes_128_cbc', Config).
+
+srp_anon_aes_256_cbc(Config) when is_list(Config) ->
+ run_ciphers_test(srp_anon, 'aes_256_cbc', Config).
+
+dhe_psk_des_cbc(Config) when is_list(Config) ->
+ run_ciphers_test(dhe_psk, 'des_cbc', Config).
+
+dhe_psk_rc4_128(Config) when is_list(Config) ->
+ run_ciphers_test(dhe_psk, 'rc4_128', Config).
+
+dhe_psk_3des_ede_cbc(Config) when is_list(Config) ->
+ run_ciphers_test(dhe_psk, '3des_ede_cbc', Config).
+
+dhe_psk_aes_128_cbc(Config) when is_list(Config) ->
+ run_ciphers_test(dhe_psk, 'aes_128_cbc', Config).
+
+dhe_psk_aes_256_cbc(Config) when is_list(Config) ->
+ run_ciphers_test(dhe_psk, 'aes_256_cbc', Config).
+
+dhe_psk_aes_128_gcm(Config) when is_list(Config) ->
+ run_ciphers_test(dhe_psk, 'aes_128_gcm', Config).
+
+dhe_psk_aes_256_gcm(Config) when is_list(Config) ->
+ run_ciphers_test(dhe_psk, 'aes_256_gcm', Config).
+
+dhe_psk_aes_128_ccm(Config) when is_list(Config) ->
+ run_ciphers_test(dhe_psk, 'aes_128_ccm', Config).
+
+dhe_psk_aes_256_ccm(Config) when is_list(Config) ->
+ run_ciphers_test(dhe_psk, 'aes_256_ccm', Config).
+
+dhe_psk_aes_128_ccm_8(Config) when is_list(Config) ->
+ run_ciphers_test(dhe_psk, 'aes_128_ccm_8', Config).
+
+dhe_psk_aes_256_ccm_8(Config) when is_list(Config) ->
+ run_ciphers_test(dhe_psk, 'aes_256_ccm_8', Config).
+
+ecdhe_psk_des_cbc(Config) when is_list(Config) ->
+ run_ciphers_test(ecdhe_psk, 'des_cbc', Config).
+
+ecdhe_psk_rc4_128(Config) when is_list(Config) ->
+ run_ciphers_test(ecdhe_psk, 'rc4_128', Config).
+
+ecdhe_psk_3des_ede_cbc(Config) when is_list(Config) ->
+ run_ciphers_test(ecdhe_psk, '3des_ede_cbc', Config).
+
+ecdhe_psk_aes_128_cbc(Config) when is_list(Config) ->
+ run_ciphers_test(ecdhe_psk, 'aes_128_cbc', Config).
+
+ecdhe_psk_aes_256_cbc(Config) when is_list(Config) ->
+ run_ciphers_test(ecdhe_psk, 'aes_256_cbc', Config).
+
+ecdhe_psk_aes_128_gcm(Config) when is_list(Config) ->
+ run_ciphers_test(ecdhe_psk, 'aes_128_gcm', Config).
+
+ecdhe_psk_aes_256_gcm(Config) when is_list(Config) ->
+ run_ciphers_test(ecdhe_psk, 'aes_256_gcm', Config).
+
+ecdhe_psk_aes_128_ccm(Config) when is_list(Config) ->
+ run_ciphers_test(ecdhe_psk, 'aes_128_ccm', Config).
+
+ecdhe_psk_aes_128_ccm_8(Config) when is_list(Config) ->
+ run_ciphers_test(ecdhe_psk, 'aes_128_ccm_8', Config).
+
+psk_des_cbc(Config) when is_list(Config) ->
+ run_ciphers_test(psk, 'des_cbc', Config).
+
+psk_rc4_128(Config) when is_list(Config) ->
+ run_ciphers_test(psk, 'rc4_128', Config).
+
+psk_3des_ede_cbc(Config) when is_list(Config) ->
+ run_ciphers_test(psk, '3des_ede_cbc', Config).
+
+psk_aes_128_cbc(Config) when is_list(Config) ->
+ run_ciphers_test(psk, 'aes_128_cbc', Config).
+
+psk_aes_256_cbc(Config) when is_list(Config) ->
+ run_ciphers_test(psk, 'aes_256_cbc', Config).
+
+psk_aes_128_gcm(Config) when is_list(Config) ->
+ run_ciphers_test(psk, 'aes_128_gcm', Config).
+
+psk_aes_256_gcm(Config) when is_list(Config) ->
+ run_ciphers_test(psk, 'aes_256_gcm', Config).
+
+psk_aes_128_ccm(Config) when is_list(Config) ->
+ run_ciphers_test(psk, 'aes_128_ccm', Config).
+
+psk_aes_256_ccm(Config) when is_list(Config) ->
+ run_ciphers_test(psk, 'aes_256_ccm', Config).
+
+psk_aes_128_ccm_8(Config) when is_list(Config) ->
+ run_ciphers_test(psk, 'aes_128_ccm_8', Config).
+
+psk_aes_256_ccm_8(Config) when is_list(Config) ->
+ run_ciphers_test(psk, 'aes_256_ccm_8', Config).
+
+%%--------------------------------------------------------------------
+%% Internal functions ----------------------------------------------
+%%--------------------------------------------------------------------
+run_ciphers_test(Kex, Cipher, Config) ->
+ Version = ssl_test_lib:protocol_version(Config),
+ TestCiphers = test_ciphers(Kex, Cipher, Version),
+
+ case TestCiphers of
+ [_|_] ->
+ lists:foreach(fun(TestCipher) ->
+ cipher_suite_test(TestCipher, Version, Config)
+ end, TestCiphers);
+ [] ->
+ {skip, {not_sup, Kex, Cipher, Version}}
+ end.
+
+cipher_suite_test(CipherSuite, _Version, Config) ->
+ #{server_config := SOpts,
+ client_config := COpts} = proplists:get_value(tls_config, Config),
+ ServerOpts = ssl_test_lib:ssl_options(SOpts, Config),
+ ClientOpts = ssl_test_lib:ssl_options(COpts, Config),
+ ct:log("Testing CipherSuite ~p~n", [CipherSuite]),
+ ct:log("Server Opts ~p~n", [ServerOpts]),
+ ct:log("Client Opts ~p~n", [ClientOpts]),
+ ssl_test_lib:basic_test([{ciphers, [CipherSuite]} | COpts], SOpts, [{client_type, erlang},
+ {server_type, openssl} | Config]).
+
+
+test_ciphers(Kex, Cipher, Version) ->
+ Ciphers = ssl:filter_cipher_suites(ssl:cipher_suites(default, Version) ++ ssl:cipher_suites(anonymous, Version),
+ [{key_exchange,
+ fun(Kex0) when Kex0 == Kex -> true;
+ (_) -> false
+ end},
+ {cipher,
+ fun(Cipher0) when Cipher0 == Cipher -> true;
+ (_) -> false
+ end}]),
+ ct:log("Version ~p Testing ~p~n", [Version, Ciphers]),
+ OpenSSLCiphers = openssl_ciphers(),
+ ct:log("OpenSSLCiphers ~p~n", [OpenSSLCiphers]),
+ lists:filter(fun(C) ->
+ ct:log("Cipher ~p~n", [C]),
+ lists:member(ssl_cipher_format:suite_map_to_openssl_str(C), OpenSSLCiphers)
+ end, Ciphers).
+
+
+openssl_ciphers() ->
+ Str = os:cmd("openssl ciphers"),
+ string:split(string:strip(Str, right, $\n), ":", all).
diff --git a/lib/ssl/test/ssl_ECC_SUITE.erl b/lib/ssl/test/ssl_ECC_SUITE.erl
index c64358960c..d02888793c 100644
--- a/lib/ssl/test/ssl_ECC_SUITE.erl
+++ b/lib/ssl/test/ssl_ECC_SUITE.erl
@@ -51,35 +51,7 @@ groups() ->
].
test_cases()->
- key_cert_combinations()
- ++ misc()
- ++ ecc_negotiation().
-
-key_cert_combinations() ->
- server_ecdh_rsa() ++
- server_ecdhe_rsa() ++
- server_ecdh_ecdsa() ++
- server_ecdhe_ecdsa().
-
-server_ecdh_rsa() ->
- [client_ecdh_rsa_server_ecdh_rsa,
- client_ecdhe_rsa_server_ecdh_rsa,
- client_ecdhe_ecdsa_server_ecdh_rsa].
-
-server_ecdhe_rsa() ->
- [client_ecdh_rsa_server_ecdhe_rsa,
- client_ecdhe_rsa_server_ecdhe_rsa,
- client_ecdhe_ecdsa_server_ecdhe_rsa].
-
-server_ecdh_ecdsa() ->
- [client_ecdh_ecdsa_server_ecdh_ecdsa,
- client_ecdhe_rsa_server_ecdh_ecdsa,
- client_ecdhe_ecdsa_server_ecdh_ecdsa].
-
-server_ecdhe_ecdsa() ->
- [client_ecdh_rsa_server_ecdhe_ecdsa,
- client_ecdh_ecdsa_server_ecdhe_ecdsa,
- client_ecdhe_ecdsa_server_ecdhe_ecdsa].
+ misc() ++ ecc_negotiation().
misc()->
[client_ecdsa_server_ecdsa_with_raw_key].
@@ -160,35 +132,6 @@ end_per_testcase(_TestCase, Config) ->
%% Test diffrent certificate chain types, note that it is the servers
%% chain that affect what cipher suit that will be choosen
-%% ECDH_RSA
-client_ecdh_rsa_server_ecdh_rsa(Config) when is_list(Config) ->
- ssl_ECC:client_ecdh_rsa_server_ecdh_rsa(Config).
-client_ecdhe_rsa_server_ecdh_rsa(Config) when is_list(Config) ->
- ssl_ECC:client_ecdhe_rsa_server_ecdh_rsa(Config).
-client_ecdhe_ecdsa_server_ecdh_rsa(Config) when is_list(Config) ->
- ssl_ECC:client_ecdhe_ecdsa_server_ecdh_rsa(Config).
-%% ECDHE_RSA
-client_ecdh_rsa_server_ecdhe_rsa(Config) when is_list(Config) ->
- ssl_ECC:client_ecdh_rsa_server_ecdhe_rsa(Config).
-client_ecdhe_rsa_server_ecdhe_rsa(Config) when is_list(Config) ->
- ssl_ECC:client_ecdhe_rsa_server_ecdhe_rsa(Config).
-client_ecdhe_ecdsa_server_ecdhe_rsa(Config) when is_list(Config) ->
- ssl_ECC:client_ecdhe_ecdsa_server_ecdhe_rsa(Config).
-%% ECDH_ECDSA
-client_ecdh_ecdsa_server_ecdh_ecdsa(Config) when is_list(Config) ->
- ssl_ECC:client_ecdh_ecdsa_server_ecdh_ecdsa(Config).
-client_ecdhe_rsa_server_ecdh_ecdsa(Config) when is_list(Config) ->
- ssl_ECC:client_ecdhe_rsa_server_ecdh_ecdsa(Config).
-client_ecdhe_ecdsa_server_ecdh_ecdsa(Config) when is_list(Config) ->
- ssl_ECC:client_ecdhe_ecdsa_server_ecdh_ecdsa(Config).
-%% ECDHE_ECDSA
-client_ecdh_rsa_server_ecdhe_ecdsa(Config) when is_list(Config) ->
- ssl_ECC:client_ecdh_rsa_server_ecdhe_ecdsa(Config).
-client_ecdh_ecdsa_server_ecdhe_ecdsa(Config) when is_list(Config) ->
- ssl_ECC:client_ecdh_ecdsa_server_ecdhe_ecdsa(Config).
-client_ecdhe_ecdsa_server_ecdhe_ecdsa(Config) when is_list(Config) ->
- ssl_ECC:client_ecdhe_ecdsa_server_ecdhe_ecdsa(Config).
-
client_ecdsa_server_ecdsa_with_raw_key(Config) when is_list(Config) ->
Default = ssl_test_lib:default_cert_chain_conf(),
{COpts0, SOpts0} = ssl_test_lib:make_ec_cert_chains([{server_chain, Default},
diff --git a/lib/ssl/test/ssl_ECC_openssl_SUITE.erl b/lib/ssl/test/ssl_ECC_openssl_SUITE.erl
index 81a7dfd2da..68d4e910fd 100644
--- a/lib/ssl/test/ssl_ECC_openssl_SUITE.erl
+++ b/lib/ssl/test/ssl_ECC_openssl_SUITE.erl
@@ -33,77 +33,23 @@
%%--------------------------------------------------------------------
all() ->
- case test_cases() of
- [_|_] ->
- all_groups();
- [] ->
- [skip]
- end.
-
-all_groups() ->
case ssl_test_lib:openssl_sane_dtls() of
true ->
[{group, 'tlsv1.2'},
- {group, 'tlsv1.1'},
- {group, 'tlsv1'},
- {group, 'dtlsv1.2'},
- {group, 'dtlsv1'}];
+ {group, 'dtlsv1.2'}];
false ->
- [{group, 'tlsv1.2'},
- {group, 'tlsv1.1'},
- {group, 'tlsv1'}]
+ [{group, 'tlsv1.2'}]
end.
groups() ->
case ssl_test_lib:openssl_sane_dtls() of
true ->
- [{'tlsv1.2', [], [mix_sign | test_cases()]},
- {'tlsv1.1', [], test_cases()},
- {'tlsv1', [], test_cases()},
- {'dtlsv1.2', [], [mix_sign | test_cases()]},
- {'dtlsv1', [], test_cases()}];
+ [{'tlsv1.2', [], [mix_sign]},
+ {'dtlsv1.2', [], [mix_sign]}];
false ->
- [{'tlsv1.2', [], [mix_sign | test_cases()]},
- {'tlsv1.1', [], test_cases()},
- {'tlsv1', [], test_cases()}]
+ [{'tlsv1.2', [], [mix_sign]}]
end.
-
-test_cases()->
- cert_combinations().
-cert_combinations() ->
- lists:append(lists:map(fun({Name, Suites}) ->
- case ssl_test_lib:openssl_filter(Name) of
- [] ->
- [];
- [_|_] ->
- Suites
- end
- end, [{"ECDH-ECDSA", server_ecdh_ecdsa()},
- {"ECDH-RSA", server_ecdh_rsa()},
- {"ECDHE-RSA", server_ecdhe_rsa()},
- {"ECDHE-ECDSA", server_ecdhe_ecdsa()}
- ])).
-server_ecdh_rsa() ->
- [client_ecdh_rsa_server_ecdh_rsa,
- client_ecdhe_rsa_server_ecdh_rsa,
- client_ecdhe_ecdsa_server_ecdh_rsa].
-
-server_ecdhe_rsa() ->
- [client_ecdh_rsa_server_ecdhe_rsa,
- client_ecdhe_rsa_server_ecdhe_rsa,
- client_ecdhe_ecdsa_server_ecdhe_rsa].
-
-server_ecdh_ecdsa() ->
- [client_ecdh_ecdsa_server_ecdh_ecdsa,
- client_ecdhe_rsa_server_ecdh_ecdsa,
- client_ecdhe_ecdsa_server_ecdh_ecdsa].
-
-server_ecdhe_ecdsa() ->
- [client_ecdh_rsa_server_ecdhe_ecdsa,
- client_ecdh_ecdsa_server_ecdhe_ecdsa,
- client_ecdhe_ecdsa_server_ecdhe_ecdsa].
-
%%--------------------------------------------------------------------
init_per_suite(Config0) ->
end_per_suite(Config0),
@@ -171,38 +117,6 @@ end_per_testcase(_TestCase, Config) ->
skip(Config) when is_list(Config) ->
{skip, openssl_does_not_support_ECC}.
-%% Test diffrent certificate chain types, note that it is the servers
-%% chain that affect what cipher suit that will be choosen
-
-%% ECDH_RSA
-client_ecdh_rsa_server_ecdh_rsa(Config) when is_list(Config) ->
- ssl_ECC:client_ecdh_rsa_server_ecdh_rsa(Config).
-client_ecdhe_rsa_server_ecdh_rsa(Config) when is_list(Config) ->
- ssl_ECC:client_ecdhe_rsa_server_ecdh_rsa(Config).
-client_ecdhe_ecdsa_server_ecdh_rsa(Config) when is_list(Config) ->
- ssl_ECC:client_ecdhe_ecdsa_server_ecdh_rsa(Config).
-%% ECDHE_RSA
-client_ecdh_rsa_server_ecdhe_rsa(Config) when is_list(Config) ->
- ssl_ECC:client_ecdh_rsa_server_ecdhe_rsa(Config).
-client_ecdhe_rsa_server_ecdhe_rsa(Config) when is_list(Config) ->
- ssl_ECC:client_ecdhe_rsa_server_ecdhe_rsa(Config).
-client_ecdhe_ecdsa_server_ecdhe_rsa(Config) when is_list(Config) ->
- ssl_ECC:client_ecdhe_ecdsa_server_ecdhe_rsa(Config).
-%% ECDH_ECDSA
-client_ecdh_ecdsa_server_ecdh_ecdsa(Config) when is_list(Config) ->
- ssl_ECC:client_ecdh_ecdsa_server_ecdh_ecdsa(Config).
-client_ecdhe_rsa_server_ecdh_ecdsa(Config) when is_list(Config) ->
- ssl_ECC:client_ecdhe_rsa_server_ecdh_ecdsa(Config).
-client_ecdhe_ecdsa_server_ecdh_ecdsa(Config) when is_list(Config) ->
- ssl_ECC:client_ecdhe_ecdsa_server_ecdh_ecdsa(Config).
-%% ECDHE_ECDSA
-client_ecdh_rsa_server_ecdhe_ecdsa(Config) when is_list(Config) ->
- ssl_ECC:client_ecdh_rsa_server_ecdhe_ecdsa(Config).
-client_ecdh_ecdsa_server_ecdhe_ecdsa(Config) when is_list(Config) ->
- ssl_ECC:client_ecdh_ecdsa_server_ecdhe_ecdsa(Config).
-client_ecdhe_ecdsa_server_ecdhe_ecdsa(Config) when is_list(Config) ->
- ssl_ECC:client_ecdhe_ecdsa_server_ecdhe_ecdsa(Config).
-
mix_sign(Config) ->
{COpts0, SOpts0} = ssl_test_lib:make_mix_cert(Config),
COpts = ssl_test_lib:ssl_options(COpts0, Config),
diff --git a/lib/ssl/test/ssl_cipher_suite_SUITE.erl b/lib/ssl/test/ssl_cipher_suite_SUITE.erl
index 8805df7b52..51788c29e7 100644
--- a/lib/ssl/test/ssl_cipher_suite_SUITE.erl
+++ b/lib/ssl/test/ssl_cipher_suite_SUITE.erl
@@ -127,7 +127,6 @@ groups() ->
]}
].
-
kex() ->
rsa() ++ ecdsa() ++ dss() ++ anonymous().
@@ -154,7 +153,6 @@ anonymous() ->
{group, ecdhe_psk},
{group, srp_anon}
].
-
init_per_suite(Config) ->
catch crypto:stop(),
@@ -170,7 +168,7 @@ end_per_suite(_Config) ->
ssl:stop(),
application:stop(crypto).
-%%--------------------------------------------------------------------
+
init_per_group(GroupName, Config) when GroupName == ecdh_anon;
GroupName == ecdhe_rsa;
GroupName == ecdhe_psk ->
@@ -236,6 +234,7 @@ end_per_group(GroupName, Config) ->
false ->
Config
end.
+
init_per_testcase(TestCase, Config) when TestCase == psk_3des_ede_cbc;
TestCase == srp_anon_3des_ede_cbc;
TestCase == dhe_psk_3des_ede_cbc;
@@ -302,8 +301,7 @@ init_per_testcase(TestCase, Config) when TestCase == psk_aes_256_ccm_8;
{skip, "Missing AES_256_CCM crypto support"}
end;
init_per_testcase(TestCase, Config) ->
- Cipher = test_cipher(TestCase, Config),
- %%Reason = io_lib:format("Missing ~p crypto support", [Cipher]),
+ Cipher = ssl_test_lib:test_cipher(TestCase, Config),
SupCiphers = proplists:get_value(ciphers, crypto:supports()),
case lists:member(Cipher, SupCiphers) of
true ->
@@ -316,17 +314,21 @@ init_per_testcase(TestCase, Config) ->
end_per_testcase(_TestCase, Config) ->
Config.
+%%--------------------------------------------------------------------
+%% Initializtion ------------------------------------------
+%%--------------------------------------------------------------------
+
init_certs(srp_rsa, Config) ->
DefConf = ssl_test_lib:default_cert_chain_conf(),
CertChainConf = ssl_test_lib:gen_conf(rsa, rsa, DefConf, DefConf),
#{server_config := ServerOpts,
client_config := ClientOpts}
= public_key:pkix_test_data(CertChainConf),
- [{tls_config, #{server_config => [{user_lookup_fun, {fun user_lookup/3, undefined}} | ServerOpts],
+ [{tls_config, #{server_config => [{user_lookup_fun, {fun ssl_test_lib:user_lookup/3, undefined}} | ServerOpts],
client_config => [{srp_identity, {"Test-User", "secret"}} | ClientOpts]}} |
proplists:delete(tls_config, Config)];
init_certs(srp_anon, Config) ->
- [{tls_config, #{server_config => [{user_lookup_fun, {fun user_lookup/3, undefined}}],
+ [{tls_config, #{server_config => [{user_lookup_fun, {fun ssl_test_lib:user_lookup/3, undefined}}],
client_config => [{srp_identity, {"Test-User", "secret"}}]}} |
proplists:delete(tls_config, Config)];
init_certs(rsa_psk, Config) ->
@@ -335,9 +337,9 @@ init_certs(rsa_psk, Config) ->
[[],[],[{extensions, ClientExt}]]}],
Config, "_peer_keyEncipherment"),
PskSharedSecret = <<1,2,3,4,5,6,7,8,9,10,11,12,13,14,15>>,
- [{tls_config, #{server_config => [{user_lookup_fun, {fun user_lookup/3, PskSharedSecret}} | ServerOpts],
+ [{tls_config, #{server_config => [{user_lookup_fun, {fun ssl_test_lib:user_lookup/3, PskSharedSecret}} | ServerOpts],
client_config => [{psk_identity, "Test-User"},
- {user_lookup_fun, {fun user_lookup/3, PskSharedSecret}} | ClientOpts]}} |
+ {user_lookup_fun, {fun ssl_test_lib:user_lookup/3, PskSharedSecret}} | ClientOpts]}} |
proplists:delete(tls_config, Config)];
init_certs(rsa, Config) ->
ClientExt = x509_test:extensions([{key_usage, [digitalSignature, keyEncipherment]}]),
@@ -362,7 +364,7 @@ init_certs(srp_dss, Config) ->
#{server_config := ServerOpts,
client_config := ClientOpts}
= public_key:pkix_test_data(CertChainConf),
- [{tls_config, #{server_config => [{user_lookup_fun, {fun user_lookup/3, undefined}} | ServerOpts],
+ [{tls_config, #{server_config => [{user_lookup_fun, {fun ssl_test_lib:user_lookup/3, undefined}} | ServerOpts],
client_config => [{srp_identity, {"Test-User", "secret"}} | ClientOpts]}} |
proplists:delete(tls_config, Config)];
init_certs(GroupName, Config) when GroupName == dhe_rsa;
@@ -389,12 +391,12 @@ init_certs(GroupName, Config) when GroupName == psk;
GroupName == dhe_psk;
GroupName == ecdhe_psk ->
PskSharedSecret = <<1,2,3,4,5,6,7,8,9,10,11,12,13,14,15>>,
- [{tls_config, #{server_config => [{user_lookup_fun, {fun user_lookup/3, PskSharedSecret}}],
+ [{tls_config, #{server_config => [{user_lookup_fun, {fun ssl_test_lib:user_lookup/3, PskSharedSecret}}],
client_config => [{psk_identity, "Test-User"},
- {user_lookup_fun, {fun user_lookup/3, PskSharedSecret}}]}} |
+ {user_lookup_fun, {fun ssl_test_lib:user_lookup/3, PskSharedSecret}}]}} |
proplists:delete(tls_config, Config)];
init_certs(srp, Config) ->
- [{tls_config, #{server_config => [{user_lookup_fun, {fun user_lookup/3, undefined}}],
+ [{tls_config, #{server_config => [{user_lookup_fun, {fun ssl_test_lib:user_lookup/3, undefined}}],
client_config => [{srp_identity, {"Test-User", "secret"}}]}} |
proplists:delete(tls_config, Config)];
init_certs(_GroupName, Config) ->
@@ -402,6 +404,7 @@ init_certs(_GroupName, Config) ->
[{tls_config, #{server_config => [],
client_config => []}} |
proplists:delete(tls_config, Config)].
+
%%--------------------------------------------------------------------
%% Test Cases --------------------------------------------------------
%%--------------------------------------------------------------------
@@ -700,10 +703,6 @@ psk_aes_256_ccm_8(Config) when is_list(Config) ->
%%--------------------------------------------------------------------
%% Internal functions ----------------------------------------------
%%--------------------------------------------------------------------
-test_cipher(TestCase, Config) ->
- [{name, Group} |_] = proplists:get_value(tc_group_properties, Config),
- list_to_atom(re:replace(atom_to_list(TestCase), atom_to_list(Group) ++ "_", "", [{return, list}])).
-
run_ciphers_test(Kex, Cipher, Config) ->
Version = ssl_test_lib:protocol_version(Config),
TestCiphers = test_ciphers(Kex, Cipher, Version),
@@ -717,30 +716,28 @@ run_ciphers_test(Kex, Cipher, Config) ->
{skip, {not_sup, Kex, Cipher, Version}}
end.
-cipher_suite_test(CipherSuite, Version, Config) ->
+cipher_suite_test(ErlangCipherSuite, Version, Config) ->
#{server_config := SOpts,
client_config := COpts} = proplists:get_value(tls_config, Config),
ServerOpts = ssl_test_lib:ssl_options(SOpts, Config),
ClientOpts = ssl_test_lib:ssl_options(COpts, Config),
- ct:log("Testing CipherSuite ~p~n", [CipherSuite]),
+ ct:log("Testing CipherSuite ~p~n", [ErlangCipherSuite]),
ct:log("Server Opts ~p~n", [ServerOpts]),
ct:log("Client Opts ~p~n", [ClientOpts]),
{ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
- ErlangCipherSuite = erlang_cipher_suite(CipherSuite),
-
ConnectionInfo = {ok, {Version, ErlangCipherSuite}},
Server = ssl_test_lib:start_server([{node, ServerNode}, {port, 0},
{from, self()},
{mfa, {ssl_test_lib, cipher_result, [ConnectionInfo]}},
- {options, [{versions, [Version]}, {ciphers, [CipherSuite]} | ServerOpts]}]),
+ {options, [{versions, [Version]}, {ciphers, [ErlangCipherSuite]} | ServerOpts]}]),
Port = ssl_test_lib:inet_port(Server),
Client = ssl_test_lib:start_client([{node, ClientNode}, {port, Port},
{host, Hostname},
{from, self()},
{mfa, {ssl_test_lib, cipher_result, [ConnectionInfo]}},
- {options, [{versions, [Version]}, {ciphers, [CipherSuite]} |
+ {options, [{versions, [Version]}, {ciphers, [ErlangCipherSuite]} |
ClientOpts]}]),
ssl_test_lib:check_result(Server, ok, Client, ok),
@@ -748,17 +745,6 @@ cipher_suite_test(CipherSuite, Version, Config) ->
ssl_test_lib:close(Server),
ssl_test_lib:close(Client).
-erlang_cipher_suite(Suite) when is_list(Suite)->
- ssl_cipher_format:suite_definition(ssl_cipher_format:suite_openssl_str_to_map(Suite));
-erlang_cipher_suite(Suite) ->
- Suite.
-
-user_lookup(psk, _Identity, UserState) ->
- {ok, UserState};
-user_lookup(srp, Username, _UserState) ->
- Salt = ssl_cipher:random_bytes(16),
- UserPassHash = crypto:hash(sha, [Salt, crypto:hash(sha, [Username, <<$:>>, <<"secret">>])]),
- {ok, {srp_1024, Salt, UserPassHash}}.
test_ciphers(Kex, Cipher, Version) ->
ssl:filter_cipher_suites(ssl:cipher_suites(all, Version) ++ ssl:cipher_suites(anonymous, Version),
@@ -770,3 +756,4 @@ test_ciphers(Kex, Cipher, Version) ->
fun(Cipher0) when Cipher0 == Cipher -> true;
(_) -> false
end}]).
+
diff --git a/lib/ssl/test/ssl_test_lib.erl b/lib/ssl/test/ssl_test_lib.erl
index 65b8998cc3..3b161a0c8a 100644
--- a/lib/ssl/test/ssl_test_lib.erl
+++ b/lib/ssl/test/ssl_test_lib.erl
@@ -631,6 +631,40 @@ make_rsa_cert_chains(UserConf, Config, Suffix) ->
[{reuseaddr, true}, {verify, verify_peer} | ServerConf]
}.
+make_ecc_cert_chains(UserConf, Config, Suffix) ->
+ ClientChain = proplists:get_value(client_chain, UserConf, default_cert_chain_conf()),
+ ServerChain = proplists:get_value(server_chain, UserConf, default_cert_chain_conf()),
+ CertChainConf = gen_conf(ecdsa, ecdsa, ClientChain, ServerChain),
+ ClientFileBase = filename:join([proplists:get_value(priv_dir, Config), "ecdsa" ++ Suffix]),
+ ServerFileBase = filename:join([proplists:get_value(priv_dir, Config), "ecdsa" ++ Suffix]),
+ GenCertData = public_key:pkix_test_data(CertChainConf),
+ [{server_config, ServerConf},
+ {client_config, ClientConf}] =
+ x509_test:gen_pem_config_files(GenCertData, ClientFileBase, ServerFileBase),
+ {[{verify, verify_peer} | ClientConf],
+ [{reuseaddr, true}, {verify, verify_peer} | ServerConf]
+ }.
+
+
+make_dsa_cert_chains(UserConf, Config, Suffix) ->
+ CryptoSupport = crypto:supports(),
+ case proplists:get_bool(dss, proplists:get_value(public_keys, CryptoSupport)) of
+ true ->
+ ClientChain = proplists:get_value(client_chain, UserConf, default_cert_chain_conf()),
+ ServerChain = proplists:get_value(server_chain, UserConf, default_cert_chain_conf()),
+ CertChainConf = gen_conf(dsa, dsa, ClientChain, ServerChain),
+ ClientFileBase = filename:join([proplists:get_value(priv_dir, Config), "dsa" ++ Suffix]),
+ ServerFileBase = filename:join([proplists:get_value(priv_dir, Config), "dsa" ++ Suffix]),
+ GenCertData = public_key:pkix_test_data(CertChainConf),
+ [{server_config, ServerConf},
+ {client_config, ClientConf}] =
+ x509_test:gen_pem_config_files(GenCertData, ClientFileBase, ServerFileBase),
+ {[{verify, verify_peer} | ClientConf],
+ [{reuseaddr, true}, {verify, verify_peer} | ServerConf]};
+ false ->
+ Config
+ end.
+
make_ec_cert_chains(UserConf, ClientChainType, ServerChainType, Config) ->
make_ec_cert_chains(UserConf, ClientChainType, ServerChainType, Config, ?DEFAULT_CURVE).
%%
@@ -1067,7 +1101,7 @@ accepters(Acc, N) ->
basic_test(COpts, SOpts, Config) ->
SType = proplists:get_value(server_type, Config),
CType = proplists:get_value(client_type, Config),
- {Server, Port} = start_server(SType, SOpts, Config),
+ {Server, Port} = start_server(SType, COpts, SOpts, Config),
Client = start_client(CType, Port, COpts, Config),
gen_check_result(Server, SType, Client, CType),
stop(Server, Client).
@@ -1134,7 +1168,7 @@ start_client(erlang, Port, ClientOpts, Config) ->
{host, Hostname},
{from, self()},
{mfa, {ssl_test_lib, check_key_exchange_send_active, [KeyEx]}},
- {options, [{verify, verify_peer} | ClientOpts]}]).
+ {options, ClientOpts}]).
%% Workaround for running tests on machines where openssl
%% s_client would use an IPv6 address with localhost. As
@@ -1169,20 +1203,19 @@ start_client_ecc_error(erlang, Port, ClientOpts, ECCOpts, Config) ->
[{verify, verify_peer} | ClientOpts]}]).
-start_server(openssl, ServerOpts, Config) ->
- Cert = proplists:get_value(certfile, ServerOpts),
- Key = proplists:get_value(keyfile, ServerOpts),
- CA = proplists:get_value(cacertfile, ServerOpts),
+start_server(openssl, ClientOpts, ServerOpts, Config) ->
Port = inet_port(node()),
Version = protocol_version(Config),
Exe = "openssl",
- Args = ["s_server", "-accept", integer_to_list(Port), ssl_test_lib:version_flag(Version),
- "-verify", "2", "-cert", Cert, "-CAfile", CA,
- "-key", Key, "-msg", "-debug"],
+ CertArgs = openssl_cert_options(ServerOpts),
+ [Cipher|_] = proplists:get_value(ciphers, ClientOpts, ssl:cipher_suites(default,Version)),
+ Args = ["s_server", "-accept", integer_to_list(Port), "-cipher",
+ ssl_cipher_format:suite_map_to_openssl_str(Cipher),
+ ssl_test_lib:version_flag(Version)] ++ CertArgs ++ ["-msg", "-debug"],
OpenSslPort = portable_open_port(Exe, Args),
true = port_command(OpenSslPort, "Hello world"),
{OpenSslPort, Port};
-start_server(erlang, ServerOpts, Config) ->
+start_server(erlang, _, ServerOpts, Config) ->
{_, ServerNode, _} = ssl_test_lib:run_where(Config),
KeyEx = proplists:get_value(check_keyex, Config, false),
Server = start_server([{node, ServerNode}, {port, 0},
@@ -1245,6 +1278,29 @@ stop(Client, Server) ->
close(Server),
close(Client).
+
+openssl_cert_options(ServerOpts) ->
+ Cert = proplists:get_value(certfile, ServerOpts, undefined),
+ Key = proplists:get_value(keyfile, ServerOpts, undefined),
+ CA = proplists:get_value(cacertfile, ServerOpts, undefined),
+ case CA of
+ undefined ->
+ case cert_option("-cert", Cert) ++ cert_option("-key", Key) of
+ [] ->
+ ["-nocert"];
+ Other ->
+ Other
+ end;
+ _ ->
+ cert_option("-cert", Cert) ++ cert_option("-CAfile", CA) ++
+ cert_option("-key", Key) ++ ["-verify", "2"]
+ end.
+
+cert_option(_, undefined) ->
+ [];
+cert_option(Opt, Value) ->
+ [Opt, Value].
+
supported_eccs(Opts) ->
ToCheck = proplists:get_value(eccs, Opts, []),
Supported = ssl:eccs(),
@@ -2374,3 +2430,16 @@ user_lookup(srp, Username, _UserState) ->
Salt = ssl_cipher:random_bytes(16),
UserPassHash = crypto:hash(sha, [Salt, crypto:hash(sha, [Username, <<$:>>, <<"secret">>])]),
{ok, {srp_1024, Salt, UserPassHash}}.
+
+test_cipher(TestCase, Config) ->
+ [{name, Group} |_] = proplists:get_value(tc_group_properties, Config),
+ list_to_atom(re:replace(atom_to_list(TestCase), atom_to_list(Group) ++ "_", "", [{return, list}])).
+
+digest() ->
+ case application:get_env(ssl, protocol_version, application:get_env(ssl, dtls_protocol_version)) of
+ Ver when Ver == 'tlsv1.2';
+ Ver == 'dtlsv1.2' ->
+ {digest, sha256};
+ _ ->
+ {digest, sha1}
+ end.
diff --git a/lib/stdlib/doc/src/gb_trees.xml b/lib/stdlib/doc/src/gb_trees.xml
index 570c9c7cb6..08aa1865e8 100644
--- a/lib/stdlib/doc/src/gb_trees.xml
+++ b/lib/stdlib/doc/src/gb_trees.xml
@@ -42,11 +42,8 @@
<section>
<title>Data Structure</title>
- <code type="none">
-{Size, Tree}</code>
-
- <p><c>Tree</c> is composed of nodes of the form <c>{Key, Value, Smaller,
- Bigger}</c> and the "empty tree" node <c>nil</c>.</p>
+ <p>Trees and iterators are built using opaque data structures that should
+ not be pattern-matched from outside this module.</p>
<p>There is no attempt to balance trees after deletions. As
deletions do not increase the height of a tree, this should be OK.</p>
diff --git a/lib/stdlib/doc/src/queue.xml b/lib/stdlib/doc/src/queue.xml
index 83a8afea81..89cce6d85b 100644
--- a/lib/stdlib/doc/src/queue.xml
+++ b/lib/stdlib/doc/src/queue.xml
@@ -168,7 +168,7 @@
<fsummary>Test if a queue is empty.</fsummary>
<desc>
<p>Tests if <c><anno>Q</anno></c> is empty and returns <c>true</c> if
- so, otherwise otherwise.</p>
+ so, otherwise <c>false</c>.</p>
</desc>
</func>
diff --git a/lib/tools/doc/src/make.xml b/lib/tools/doc/src/make.xml
index af2404707f..322d77323f 100644
--- a/lib/tools/doc/src/make.xml
+++ b/lib/tools/doc/src/make.xml
@@ -145,5 +145,10 @@ Modules.
{'*',[debug_info]}. </code>
<p></p>
</section>
+
+ <section>
+ <title>See Also</title>
+ <p><seealso marker="compiler:compile"><c>compile(3)</c></seealso></p>
+ </section>
</erlref>
diff --git a/make/configure.in b/make/configure.in
index bf3fd0751f..c4b89c4f45 100644
--- a/make/configure.in
+++ b/make/configure.in
@@ -2,7 +2,7 @@ dnl Process this file with autoconf to produce a configure script.
dnl %CopyrightBegin%
dnl
-dnl Copyright Ericsson AB 1998-2016. All Rights Reserved.
+dnl Copyright Ericsson AB 1998-2019. All Rights Reserved.
dnl
dnl Licensed under the Apache License, Version 2.0 (the "License");
dnl you may not use this file except in compliance with the License.
@@ -298,6 +298,10 @@ AC_ARG_ENABLE(builtin-zlib,
AS_HELP_STRING([--enable-builtin-zlib],
[force use of our own built-in zlib]))
+AC_ARG_ENABLE(esock,
+AS_HELP_STRING([--enable-esock], [enable builtin experimental socket (as a nif) support (default)])
+AS_HELP_STRING([--disable-esock], [disable builtin experimental socket (as a nif) support]))
+
AC_ARG_ENABLE(sharing-preserving,
AS_HELP_STRING([--enable-sharing-preserving],
[enable copying of terms without destroying sharing]))
diff --git a/make/otp.mk.in b/make/otp.mk.in
index ceff8f7c31..cdddb90734 100644
--- a/make/otp.mk.in
+++ b/make/otp.mk.in
@@ -4,7 +4,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 1997-2016. All Rights Reserved.
+# Copyright Ericsson AB 1997-2019. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -51,6 +51,8 @@ TYPES = @TYPES@
USE_PGO = @USE_PGO@
+USE_ESOCK = @USE_ESOCK@
+
# Slash separated list of return values from $(origin VAR)
# that are untrusted - set default in this file instead.
# The list is not space separated since some return values
diff --git a/otp_versions.table b/otp_versions.table
index 62c09ba410..566aa3cb4c 100644
--- a/otp_versions.table
+++ b/otp_versions.table
@@ -1,3 +1,4 @@
+OTP-21.3.7 : ssh-4.7.6 # asn1-5.0.8 common_test-1.17.1 compiler-7.3.2 crypto-4.4.2 debugger-4.2.6 dialyzer-3.3.2 diameter-2.2.1 edoc-0.10 eldap-1.2.6 erl_docgen-0.9 erl_interface-3.11.2 erts-10.3.4 et-1.6.4 eunit-2.3.7 ftp-1.0.2 hipe-3.18.3 inets-7.0.7 jinterface-1.9.1 kernel-6.3.1 megaco-3.18.4 mnesia-4.15.6 observer-2.9 odbc-2.12.3 os_mon-2.4.7 otp_mibs-1.2.1 parsetools-2.1.8 public_key-1.6.5 reltool-0.7.8 runtime_tools-1.13.2 sasl-3.3 snmp-5.2.12 ssl-9.2.2 stdlib-3.8.1 syntax_tools-2.1.7 tftp-1.0.1 tools-3.1 wx-1.8.7 xmerl-1.3.20 :
OTP-21.3.6 : ssl-9.2.2 # asn1-5.0.8 common_test-1.17.1 compiler-7.3.2 crypto-4.4.2 debugger-4.2.6 dialyzer-3.3.2 diameter-2.2.1 edoc-0.10 eldap-1.2.6 erl_docgen-0.9 erl_interface-3.11.2 erts-10.3.4 et-1.6.4 eunit-2.3.7 ftp-1.0.2 hipe-3.18.3 inets-7.0.7 jinterface-1.9.1 kernel-6.3.1 megaco-3.18.4 mnesia-4.15.6 observer-2.9 odbc-2.12.3 os_mon-2.4.7 otp_mibs-1.2.1 parsetools-2.1.8 public_key-1.6.5 reltool-0.7.8 runtime_tools-1.13.2 sasl-3.3 snmp-5.2.12 ssh-4.7.5 stdlib-3.8.1 syntax_tools-2.1.7 tftp-1.0.1 tools-3.1 wx-1.8.7 xmerl-1.3.20 :
OTP-21.3.5 : diameter-2.2.1 erts-10.3.4 inets-7.0.7 # asn1-5.0.8 common_test-1.17.1 compiler-7.3.2 crypto-4.4.2 debugger-4.2.6 dialyzer-3.3.2 edoc-0.10 eldap-1.2.6 erl_docgen-0.9 erl_interface-3.11.2 et-1.6.4 eunit-2.3.7 ftp-1.0.2 hipe-3.18.3 jinterface-1.9.1 kernel-6.3.1 megaco-3.18.4 mnesia-4.15.6 observer-2.9 odbc-2.12.3 os_mon-2.4.7 otp_mibs-1.2.1 parsetools-2.1.8 public_key-1.6.5 reltool-0.7.8 runtime_tools-1.13.2 sasl-3.3 snmp-5.2.12 ssh-4.7.5 ssl-9.2.1 stdlib-3.8.1 syntax_tools-2.1.7 tftp-1.0.1 tools-3.1 wx-1.8.7 xmerl-1.3.20 :
OTP-21.3.4 : common_test-1.17.1 crypto-4.4.2 erl_interface-3.11.2 erts-10.3.3 ssh-4.7.5 # asn1-5.0.8 compiler-7.3.2 debugger-4.2.6 dialyzer-3.3.2 diameter-2.2 edoc-0.10 eldap-1.2.6 erl_docgen-0.9 et-1.6.4 eunit-2.3.7 ftp-1.0.2 hipe-3.18.3 inets-7.0.6 jinterface-1.9.1 kernel-6.3.1 megaco-3.18.4 mnesia-4.15.6 observer-2.9 odbc-2.12.3 os_mon-2.4.7 otp_mibs-1.2.1 parsetools-2.1.8 public_key-1.6.5 reltool-0.7.8 runtime_tools-1.13.2 sasl-3.3 snmp-5.2.12 ssl-9.2.1 stdlib-3.8.1 syntax_tools-2.1.7 tftp-1.0.1 tools-3.1 wx-1.8.7 xmerl-1.3.20 :
diff --git a/scripts/run-dialyzer b/scripts/run-dialyzer
index 621de3fa65..44436594d3 100755
--- a/scripts/run-dialyzer
+++ b/scripts/run-dialyzer
@@ -1,17 +1,47 @@
#!/bin/bash
set -e
-set -x
-$ERL_TOP/bin/dialyzer --build_plt --apps asn1 compiler crypto dialyzer edoc erts et ftp hipe inets kernel mnesia observer public_key runtime_tools snmp ssh ssl stdlib syntax_tools tftp wx xmerl --statistics
-$ERL_TOP/bin/dialyzer -n -Wunknown -Wunmatched_returns --apps compiler erts ftp tftp kernel stdlib asn1 crypto dialyzer hipe parsetools public_key runtime_tools sasl tools --statistics
-$ERL_TOP/bin/dialyzer -n --apps common_test debugger edoc ftp inets mnesia observer ssh ssl syntax_tools tftp wx xmerl --statistics
+filter () {
+ FILTER_RESULT=""
+ for app in $1; do
+ if echo " $2 " | grep -v " $app " > /dev/null; then
+ FILTER_RESULT="$FILTER_RESULT $app"
+ fi
+ done
+}
+
+ALL_APPLICATIONS=$(ls -d -1 lib/*/ | sed 's:^lib\|/::g')
+echo "All applications: $ALL_APPLICATIONS" |tr '\n' ' ' && echo ""
+
+BASE_PLT="compiler crypto erts hipe kernel stdlib syntax_tools"
+APP_PLT="asn1 edoc et ftp inets mnesia observer public_key sasl runtime_tools snmp ssl tftp wx xmerl tools"
+NO_UNMATCHED="common_test debugger edoc eunit ftp inets mnesia observer reltool ssh ssl syntax_tools tftp wx xmerl"
+WARNINGS="diameter megaco snmp"
+
+TRAVIS_SKIP=""
+if [ "X$TRAVIS" = "Xtrue" ]; then
+ TRAVIS_SKIP="common_test eldap erl_docgen odbc eunit reltool os_mon diameter megaco snmp"
+fi
+
+filter "$ALL_APPLICATIONS" "$NO_UNMATCHED $WARNINGS $TRAVIS_SKIP"
+UNMATCHED=$FILTER_RESULT
+filter "$APP_PLT" "$TRAVIS_SKIP"
+APP_PLT=$FILTER_RESULT
+filter "$NO_UNMATCHED" "$TRAVIS_SKIP"
+NO_UNMATCHED=$FILTER_RESULT
+filter "$WARNINGS" "$TRAVIS_SKIP"
+WARNINGS=$FILTER_RESULT
-# In travis we don't dialyze everything as it takes too much time
-if [ "X$TRAVIS" != "Xtrue" ]; then
- $ERL_TOP/bin/dialyzer -n -Wunknown -Wunmatched_returns --apps eldap erl_docgen et odbc --statistics
- $ERL_TOP/bin/dialyzer -n --apps eunit reltool os_mon --statistics
+echo "UNMATCHED = $UNMATCHED"
+echo "NO_UNMATCHED = $NO_UNMATCHED"
+echo "WARNINGS = $WARNINGS"
+
+set -x
- # These application are not run always as the currently have dialyzer warnings
- # $ERL_TOP/bin/dialyzer -n --apps diameter megaco snmp --statistics
+$ERL_TOP/bin/dialyzer --build_plt -Wunknown --apps $BASE_PLT $APP_PLT --statistics
+$ERL_TOP/bin/dialyzer -n -Wunknown -Wunmatched_returns --apps $UNMATCHED --statistics
+$ERL_TOP/bin/dialyzer -n -Wunknown --apps $NO_UNMATCHED --statistics
+if [ "X$WARNINGS" != "X" ]; then
+ $ERL_TOP/bin/dialyzer -n --apps $WARNINGS --statistics
fi