aboutsummaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/asn1/doc/src/asn1_getting_started.xml2
-rw-r--r--lib/asn1/doc/src/asn1_introduction.xml2
-rw-r--r--lib/asn1/doc/src/notes.xml4
-rw-r--r--lib/common_test/doc/src/common_test_app.xml2
-rw-r--r--lib/common_test/doc/src/ct.xml6
-rw-r--r--lib/common_test/doc/src/ct_hooks.xml2
-rw-r--r--lib/common_test/doc/src/ct_hooks_chapter.xml8
-rw-r--r--lib/common_test/doc/src/ct_ssh.xml106
-rw-r--r--lib/common_test/doc/src/ct_telnet.xml2
-rw-r--r--lib/common_test/doc/src/event_handler_chapter.xml6
-rw-r--r--lib/common_test/doc/src/introduction.xml2
-rw-r--r--lib/common_test/doc/src/run_test_chapter.xml6
-rw-r--r--lib/common_test/doc/src/write_test_chapter.xml10
-rw-r--r--lib/common_test/test_server/ts_run.erl2
-rw-r--r--lib/compiler/doc/src/compile.xml6
-rw-r--r--lib/compiler/doc/src/notes.xml4
-rw-r--r--lib/compiler/doc/src/ref_man.xml2
-rw-r--r--lib/crypto/doc/src/notes.xml2
-rw-r--r--lib/debugger/doc/src/i.xml4
-rw-r--r--lib/hipe/sparc/hipe_rtl_to_sparc.erl40
-rw-r--r--lib/hipe/test/hipe_testsuite_driver.erl2
-rw-r--r--lib/inets/doc/src/http_server.xml36
-rw-r--r--lib/inets/doc/src/httpc.xml4
-rw-r--r--lib/inets/doc/src/httpd.xml16
-rw-r--r--lib/inets/doc/src/mod_auth.xml2
-rw-r--r--lib/inets/src/inets_app/inets.appup.src6
-rw-r--r--lib/inets/vsn.mk2
-rw-r--r--lib/kernel/doc/src/app.xml6
-rw-r--r--lib/kernel/doc/src/application.xml6
-rw-r--r--lib/kernel/doc/src/auth.xml4
-rw-r--r--lib/kernel/doc/src/code.xml12
-rw-r--r--lib/kernel/doc/src/erl_boot_server.xml4
-rw-r--r--lib/kernel/doc/src/erl_ddll.xml6
-rw-r--r--lib/kernel/doc/src/error_logger.xml30
-rw-r--r--lib/kernel/doc/src/file.xml28
-rw-r--r--lib/kernel/doc/src/gen_tcp.xml6
-rw-r--r--lib/kernel/doc/src/inet.xml22
-rw-r--r--lib/kernel/doc/src/init_stub.xml2
-rw-r--r--lib/kernel/doc/src/kernel_app.xml20
-rw-r--r--lib/kernel/doc/src/net_kernel.xml12
-rw-r--r--lib/kernel/doc/src/notes.xml2
-rw-r--r--lib/kernel/doc/src/rpc.xml4
-rw-r--r--lib/kernel/doc/src/zlib_stub.xml2
-rw-r--r--lib/kernel/src/os.erl14
-rw-r--r--lib/kernel/test/os_SUITE.erl19
-rw-r--r--lib/kernel/test/os_SUITE_data/Makefile.src8
-rw-r--r--lib/kernel/test/os_SUITE_data/my_fds.c9
-rw-r--r--lib/mnesia/doc/src/Mnesia_chap1.xml28
-rw-r--r--lib/mnesia/doc/src/Mnesia_chap8.xml8
-rw-r--r--lib/mnesia/doc/src/Mnesia_overview.xml42
-rw-r--r--lib/mnesia/doc/src/mnesia.xml336
-rw-r--r--lib/mnesia/doc/src/mnesia_frag_hash.xml12
-rw-r--r--lib/mnesia/doc/src/mnesia_registry.xml12
-rw-r--r--lib/mnesia/doc/src/part.xml2
-rw-r--r--lib/mnesia/doc/src/ref_man.xml2
-rw-r--r--lib/observer/doc/src/ttb.xml2
-rw-r--r--lib/observer/src/observer_tv_wx.erl22
-rw-r--r--lib/observer/src/observer_wx.erl8
-rw-r--r--lib/odbc/doc/src/notes.xml2
-rw-r--r--lib/parsetools/doc/src/yecc.xml2
-rw-r--r--lib/reltool/doc/src/notes.xml4
-rw-r--r--lib/reltool/doc/src/part.xml2
-rw-r--r--lib/reltool/doc/src/ref_man.xml2
-rw-r--r--lib/reltool/doc/src/reltool.xml8
-rw-r--r--lib/reltool/doc/src/reltool_intro.xml4
-rw-r--r--lib/runtime_tools/doc/src/dbg.xml2
-rw-r--r--lib/runtime_tools/doc/src/notes.xml2
-rw-r--r--lib/sasl/doc/src/alarm_handler.xml4
-rw-r--r--lib/sasl/doc/src/appup.xml10
-rw-r--r--lib/sasl/doc/src/error_logging.xml18
-rw-r--r--lib/sasl/doc/src/notes.xml2
-rw-r--r--lib/sasl/doc/src/part.xml2
-rw-r--r--lib/sasl/doc/src/rb.xml6
-rw-r--r--lib/sasl/doc/src/ref_man.xml2
-rw-r--r--lib/sasl/doc/src/rel.xml6
-rw-r--r--lib/sasl/doc/src/release_handler.xml20
-rw-r--r--lib/sasl/doc/src/sasl_app.xml24
-rw-r--r--lib/sasl/doc/src/sasl_intro.xml2
-rw-r--r--lib/sasl/doc/src/systools.xml6
-rw-r--r--lib/ssh/doc/src/ssh.xml6
-rw-r--r--lib/ssh/doc/src/ssh_app.xml4
-rw-r--r--lib/ssh/doc/src/ssh_channel.xml2
-rw-r--r--lib/ssh/src/ssh_auth.erl131
-rw-r--r--lib/ssh/src/ssh_connection_handler.erl23
-rw-r--r--lib/ssh/src/ssh_transport.erl7
-rw-r--r--lib/ssl/doc/src/ssl_distribution.xml4
-rw-r--r--lib/ssl/src/dtls_connection.erl173
-rw-r--r--lib/ssl/src/dtls_handshake.erl20
-rw-r--r--lib/ssl/src/dtls_record.erl209
-rw-r--r--lib/ssl/src/ssl.appup.src2
-rw-r--r--lib/ssl/src/ssl.erl7
-rw-r--r--lib/ssl/src/ssl_alert.erl4
-rw-r--r--lib/ssl/src/ssl_connection.erl624
-rw-r--r--lib/ssl/src/ssl_connection.hrl2
-rw-r--r--lib/ssl/src/ssl_handshake.erl81
-rw-r--r--lib/ssl/src/ssl_record.erl438
-rw-r--r--lib/ssl/src/ssl_record.hrl42
-rw-r--r--lib/ssl/src/ssl_sup.erl11
-rw-r--r--lib/ssl/src/tls_connection.erl447
-rw-r--r--lib/ssl/src/tls_handshake.erl13
-rw-r--r--lib/ssl/src/tls_record.erl131
-rw-r--r--lib/ssl/test/ssl_basic_SUITE.erl9
-rw-r--r--lib/ssl/test/ssl_npn_hello_SUITE.erl13
-rw-r--r--lib/ssl/test/ssl_test_lib.erl26
-rw-r--r--lib/ssl/test/ssl_to_openssl_SUITE.erl60
-rw-r--r--lib/stdlib/doc/src/dets.xml2
-rw-r--r--lib/stdlib/doc/src/ets.xml6
-rw-r--r--lib/stdlib/doc/src/notes.xml4
-rw-r--r--lib/stdlib/doc/src/proc_lib.xml4
-rw-r--r--lib/stdlib/doc/src/stdlib_app.xml8
-rw-r--r--lib/stdlib/doc/src/timer.xml2
-rw-r--r--lib/stdlib/doc/src/unicode_usage.xml8
-rw-r--r--lib/stdlib/doc/src/zip.xml6
-rw-r--r--lib/stdlib/src/beam_lib.erl2
-rw-r--r--lib/syntax_tools/src/erl_tidy.erl4
-rw-r--r--lib/tools/doc/src/xref_chapter.xml6
116 files changed, 1978 insertions, 1669 deletions
diff --git a/lib/asn1/doc/src/asn1_getting_started.xml b/lib/asn1/doc/src/asn1_getting_started.xml
index 3c8ec24723..d40b294c39 100644
--- a/lib/asn1/doc/src/asn1_getting_started.xml
+++ b/lib/asn1/doc/src/asn1_getting_started.xml
@@ -678,7 +678,7 @@ ok
1081,32,1043,1085,1086,1084]</pre>
<p>For details, see the <seealso marker="stdlib:unicode">unicode</seealso>
- module in <c>stdlib</c>.</p>
+ module in STDLIB.</p>
<p>In the following example, this ASN.1 specification is used:</p>
<pre>
diff --git a/lib/asn1/doc/src/asn1_introduction.xml b/lib/asn1/doc/src/asn1_introduction.xml
index d8b81aa467..e4f406364d 100644
--- a/lib/asn1/doc/src/asn1_introduction.xml
+++ b/lib/asn1/doc/src/asn1_introduction.xml
@@ -30,7 +30,7 @@
<file>asn1_introduction.xml</file>
</header>
- <p>The <c>ASN.1</c> application provides the following:</p>
+ <p>The ASN.1 application provides the following:</p>
<list type="bulleted">
<item>An ASN.1 compiler for Erlang, which generates encode and
diff --git a/lib/asn1/doc/src/notes.xml b/lib/asn1/doc/src/notes.xml
index 68d335f451..ac3d9c828e 100644
--- a/lib/asn1/doc/src/notes.xml
+++ b/lib/asn1/doc/src/notes.xml
@@ -329,7 +329,7 @@
</item>
<item>
<p>
- The <c>asn1</c> application would fail to build if the
+ The ASN.1 application would fail to build if the
<c>.erlang</c> file printed something to standard output.</p>
<p>
Own Id: OTP-11360</p>
@@ -997,7 +997,7 @@
also been extended. </item><item> The <c>configure</c>
scripts of <c>erl_interface</c> and <c>odbc</c> now
search for thread libraries and thread library quirks the
- same way as <c>erts</c> do. </item><item> The
+ same way as ERTS do. </item><item> The
<c>configure</c> script of the <c>odbc</c> application
now also looks for odbc libraries in <c>lib64</c> and
<c>lib/64</c> directories when building on a 64-bit
diff --git a/lib/common_test/doc/src/common_test_app.xml b/lib/common_test/doc/src/common_test_app.xml
index 3f83747485..48ffe653e4 100644
--- a/lib/common_test/doc/src/common_test_app.xml
+++ b/lib/common_test/doc/src/common_test_app.xml
@@ -566,7 +566,7 @@
(which also causes the test case process to terminate).</p>
<p>Elements from the <c>Config</c> list can, for example, be read
- with <c>proplists:get_value/2</c> in <c>STDLIB</c>
+ with <c>proplists:get_value/2</c> in STDLIB
(or the macro <c>?config</c> defined in <c>ct.hrl</c>).</p>
<p>If you decide not to run the test case after all, return
diff --git a/lib/common_test/doc/src/ct.xml b/lib/common_test/doc/src/ct.xml
index 264bcff251..ffc64cba67 100644
--- a/lib/common_test/doc/src/ct.xml
+++ b/lib/common_test/doc/src/ct.xml
@@ -777,7 +777,7 @@
caught by any installed event manager.</p>
<p>See also
- <seealso marker="stdlib:gen_event"><c>stdlib:gen_event(3)</c></seealso>.</p>
+ <seealso marker="stdlib:gen_event"><c>gen_event(3)</c></seealso>.</p>
</desc>
</func>
@@ -1236,7 +1236,7 @@
<v>Millisecs = integer() | float()</v>
</type>
<desc><marker id="sleep-1"/>
- <p>This function, similar to <c>timer:sleep/1</c> in <c>STDLIB</c>,
+ <p>This function, similar to <c>timer:sleep/1</c> in STDLIB,
suspends the test case for a specified time.
However, this function also multiplies <c>Time</c> with the
<c>multiply_timetraps</c> value (if set) and under certain
@@ -1330,7 +1330,7 @@
caught by any installed event manager.</p>
<p>See also
- <seealso marker="stdlib:gen_event"><c>stdlib:gen_event(3)</c></seealso>.
+ <seealso marker="stdlib:gen_event"><c>gen_event(3)</c></seealso>.
</p>
</desc>
</func>
diff --git a/lib/common_test/doc/src/ct_hooks.xml b/lib/common_test/doc/src/ct_hooks.xml
index 3b1e564b66..c2cf29c530 100644
--- a/lib/common_test/doc/src/ct_hooks.xml
+++ b/lib/common_test/doc/src/ct_hooks.xml
@@ -94,7 +94,7 @@
<seealso marker="#Module:id-1"><c>ct_hooks:id/1</c></seealso>,
or a <c>reference</c> (created using
<seealso marker="erts:erlang#make_ref-0">erlang:make_ref/0</seealso>
- in <c>ERTS</c>) if
+ in ERTS) if
<seealso marker="#Module:id-1"><c>ct_hooks:id/1</c></seealso>
is not implemented.</p>
diff --git a/lib/common_test/doc/src/ct_hooks_chapter.xml b/lib/common_test/doc/src/ct_hooks_chapter.xml
index 1998f15697..0e4c35e11f 100644
--- a/lib/common_test/doc/src/ct_hooks_chapter.xml
+++ b/lib/common_test/doc/src/ct_hooks_chapter.xml
@@ -374,7 +374,7 @@
<title>Example CTH</title>
<p>The following CTH logs information about a test run into a format
parseable by <seealso marker="kernel:file#consult-1">file:consult/1</seealso>
- (in <c>Kernel</c>):
+ (in Kernel):
</p>
<code>
%%% @doc Common Test Example Common Test Hook module.
@@ -499,13 +499,13 @@
<tag><c>cth_log_redirect</c></tag>
<item>
<p>Built-in</p>
- <p>Captures all <c>error_logger</c> and <c>SASL</c> logging
+ <p>Captures all <c>error_logger</c> and SASL logging
events and prints them to the current test case log. If an event cannot be
associated with a test case, it is printed in the <c>Common Test</c> framework log.
This happens for test cases running in parallel and events occuring
in-between test cases. You can configure the level of
- <seealso marker="sasl:sasl_app"><c>SASL</c></seealso> events report
- using the normal <c>SASL</c> mechanisms.</p>
+ <seealso marker="sasl:sasl_app">SASL</seealso> events report
+ using the normal SASL mechanisms.</p>
</item>
<tag><c>cth_surefire</c></tag>
<item>
diff --git a/lib/common_test/doc/src/ct_ssh.xml b/lib/common_test/doc/src/ct_ssh.xml
index d00737aa5a..137e4c3f1d 100644
--- a/lib/common_test/doc/src/ct_ssh.xml
+++ b/lib/common_test/doc/src/ct_ssh.xml
@@ -64,7 +64,7 @@
<p><c>ConnType = ssh | sftp</c>.</p>
<p>For other types, see
- <seealso marker="ssh:ssh"><c>ssh:ssh(3)</c></seealso>.</p>
+ <seealso marker="ssh:ssh"><c>ssh(3)</c></seealso>.</p>
<p>All time-out parameters in <c>ct_ssh</c> functions are values in
milliseconds.</p>
@@ -88,7 +88,7 @@
<tag><c>ssh_sftp_return() = term()</c></tag>
<item><marker id="type-ssh_sftp_return"/>
<p>Return value from an
- <seealso marker="ssh:ssh_sftp"><c>ssh:ssh_sftp</c></seealso>
+ <seealso marker="ssh:ssh_sftp"><c>ssh_sftp</c></seealso>
function.</p></item>
</taglist>
</section>
@@ -104,7 +104,7 @@
</type>
<desc><marker id="apread-4"/>
<p>For information and other types, see
- <seealso marker="ssh:ssh_sftp"><c>ssh:ssh_sftp(3)</c></seealso>.</p>
+ <seealso marker="ssh:ssh_sftp"><c>ssh_sftp(3)</c></seealso>.</p>
</desc>
</func>
@@ -118,7 +118,7 @@
</type>
<desc><marker id="apread-5"/>
<p>For information and other types, see
- <seealso marker="ssh:ssh_sftp"><c>ssh:ssh_sftp(3)</c></seealso>.</p>
+ <seealso marker="ssh:ssh_sftp"><c>ssh_sftp(3)</c></seealso>.</p>
</desc>
</func>
@@ -132,7 +132,7 @@
</type>
<desc><marker id="apwrite-4"/>
<p>For information and other types, see
- <seealso marker="ssh:ssh_sftp"><c>ssh:ssh_sftp(3)</c></seealso>.</p>
+ <seealso marker="ssh:ssh_sftp"><c>ssh_sftp(3)</c></seealso>.</p>
</desc>
</func>
@@ -146,7 +146,7 @@
</type>
<desc><marker id="apwrite-5"/>
<p>For information and other types, see
- <seealso marker="ssh:ssh_sftp"><c>ssh:ssh_sftp(3)</c></seealso>.</p>
+ <seealso marker="ssh:ssh_sftp"><c>ssh_sftp(3)</c></seealso>.</p>
</desc>
</func>
@@ -160,7 +160,7 @@
</type>
<desc><marker id="aread-3"/>
<p>For information and other types, see
- <seealso marker="ssh:ssh_sftp"><c>ssh:ssh_sftp(3)</c></seealso>.</p>
+ <seealso marker="ssh:ssh_sftp"><c>ssh_sftp(3)</c></seealso>.</p>
</desc>
</func>
@@ -174,7 +174,7 @@
</type>
<desc><marker id="aread-4"/>
<p>For information and other types, see
- <seealso marker="ssh:ssh_sftp"><c>ssh:ssh_sftp(3)</c></seealso>.</p>
+ <seealso marker="ssh:ssh_sftp"><c>ssh_sftp(3)</c></seealso>.</p>
</desc>
</func>
@@ -188,7 +188,7 @@
</type>
<desc><marker id="awrite-3"/>
<p>For information and other types, see
- <seealso marker="ssh:ssh_sftp"><c>ssh:ssh_sftp(3)</c></seealso>.</p>
+ <seealso marker="ssh:ssh_sftp"><c>ssh_sftp(3)</c></seealso>.</p>
</desc>
</func>
@@ -202,7 +202,7 @@
</type>
<desc><marker id="awrite-4"/>
<p>For information and other types, see
- <seealso marker="ssh:ssh_sftp"><c>ssh:ssh_sftp(3)</c></seealso>.</p>
+ <seealso marker="ssh:ssh_sftp"><c>ssh_sftp(3)</c></seealso>.</p>
</desc>
</func>
@@ -216,7 +216,7 @@
</type>
<desc><marker id="close-2"/>
<p>For information and other types, see
- <seealso marker="ssh:ssh_sftp"><c>ssh:ssh_sftp(3)</c></seealso>.</p>
+ <seealso marker="ssh:ssh_sftp"><c>ssh_sftp(3)</c></seealso>.</p>
</desc>
</func>
@@ -230,7 +230,7 @@
</type>
<desc><marker id="close-3"/>
<p>For information and other types, see
- <seealso marker="ssh:ssh_sftp"><c>ssh:ssh_sftp(3)</c></seealso>.</p>
+ <seealso marker="ssh:ssh_sftp"><c>ssh_sftp(3)</c></seealso>.</p>
</desc>
</func>
@@ -310,7 +310,7 @@
</type>
<desc><marker id="del_dir-2"/>
<p>For information and other types, see
- <seealso marker="ssh:ssh_sftp"><c>ssh:ssh_sftp(3)</c></seealso>.</p>
+ <seealso marker="ssh:ssh_sftp"><c>ssh_sftp(3)</c></seealso>.</p>
</desc>
</func>
@@ -324,7 +324,7 @@
</type>
<desc><marker id="del_dir-3"/>
<p>For information and other types, see
- <seealso marker="ssh:ssh_sftp"><c>ssh:ssh_sftp(3)</c></seealso>.</p>
+ <seealso marker="ssh:ssh_sftp"><c>ssh_sftp(3)</c></seealso>.</p>
</desc>
</func>
@@ -338,7 +338,7 @@
</type>
<desc><marker id="delete-2"/>
<p>For information and other types, see
- <seealso marker="ssh:ssh_sftp"><c>ssh:ssh_sftp(3)</c></seealso>.</p>
+ <seealso marker="ssh:ssh_sftp"><c>ssh_sftp(3)</c></seealso>.</p>
</desc>
</func>
@@ -352,7 +352,7 @@
</type>
<desc><marker id="delete-3"/>
<p>For information and other types, see
- <seealso marker="ssh:ssh_sftp"><c>ssh:ssh_sftp(3)</c></seealso>.</p>
+ <seealso marker="ssh:ssh_sftp"><c>ssh_sftp(3)</c></seealso>.</p>
</desc>
</func>
@@ -423,7 +423,7 @@
</type>
<desc><marker id="get_file_info-2"/>
<p>For information and other types, see
- <seealso marker="ssh:ssh_sftp"><c>ssh:ssh_sftp(3)</c></seealso>.</p>
+ <seealso marker="ssh:ssh_sftp"><c>ssh_sftp(3)</c></seealso>.</p>
</desc>
</func>
@@ -437,7 +437,7 @@
</type>
<desc><marker id="get_file_info-3"/>
<p>For information and other types, see
- <seealso marker="ssh:ssh_sftp"><c>ssh:ssh_sftp(3)</c></seealso>.</p>
+ <seealso marker="ssh:ssh_sftp"><c>ssh_sftp(3)</c></seealso>.</p>
</desc>
</func>
@@ -451,7 +451,7 @@
</type>
<desc><marker id="list_dir-2"/>
<p>For information and other types, see
- <seealso marker="ssh:ssh_sftp"><c>ssh:ssh_sftp(3)</c></seealso>.</p>
+ <seealso marker="ssh:ssh_sftp"><c>ssh_sftp(3)</c></seealso>.</p>
</desc>
</func>
@@ -465,7 +465,7 @@
</type>
<desc><marker id="list_dir-3"/>
<p>For information and other types, see
- <seealso marker="ssh:ssh_sftp"><c>ssh:ssh_sftp(3)</c></seealso>.</p>
+ <seealso marker="ssh:ssh_sftp"><c>ssh_sftp(3)</c></seealso>.</p>
</desc>
</func>
@@ -479,7 +479,7 @@
</type>
<desc><marker id="make_dir-2"/>
<p>For information and other types, see
- <seealso marker="ssh:ssh_sftp"><c>ssh:ssh_sftp(3)</c></seealso>.</p>
+ <seealso marker="ssh:ssh_sftp"><c>ssh_sftp(3)</c></seealso>.</p>
</desc>
</func>
@@ -493,7 +493,7 @@
</type>
<desc><marker id="make_dir-3"/>
<p>For information and other types, see
- <seealso marker="ssh:ssh_sftp"><c>ssh:ssh_sftp(3)</c></seealso>.</p>
+ <seealso marker="ssh:ssh_sftp"><c>ssh_sftp(3)</c></seealso>.</p>
</desc>
</func>
@@ -507,7 +507,7 @@
</type>
<desc><marker id="make_symlink-3"/>
<p>For information and other types, see
- <seealso marker="ssh:ssh_sftp"><c>ssh:ssh_sftp(3)</c></seealso>.</p>
+ <seealso marker="ssh:ssh_sftp"><c>ssh_sftp(3)</c></seealso>.</p>
</desc>
</func>
@@ -521,7 +521,7 @@
</type>
<desc><marker id="make_symlink-4"/>
<p>For information and other types, see
- <seealso marker="ssh:ssh_sftp"><c>ssh:ssh_sftp(3)</c></seealso>.</p>
+ <seealso marker="ssh:ssh_sftp"><c>ssh_sftp(3)</c></seealso>.</p>
</desc>
</func>
@@ -535,7 +535,7 @@
</type>
<desc><marker id="open-3"/>
<p>For information and other types, see
- <seealso marker="ssh:ssh_sftp"><c>ssh:ssh_sftp(3)</c></seealso>.</p>
+ <seealso marker="ssh:ssh_sftp"><c>ssh_sftp(3)</c></seealso>.</p>
</desc>
</func>
@@ -549,7 +549,7 @@
</type>
<desc><marker id="open-4"/>
<p>For information and other types, see
- <seealso marker="ssh:ssh_sftp"><c>ssh:ssh_sftp(3)</c></seealso>.</p>
+ <seealso marker="ssh:ssh_sftp"><c>ssh_sftp(3)</c></seealso>.</p>
</desc>
</func>
@@ -563,7 +563,7 @@
</type>
<desc><marker id="opendir-2"/>
<p>For information and other types, see
- <seealso marker="ssh:ssh_sftp"><c>ssh:ssh_sftp(3)</c></seealso>.</p>
+ <seealso marker="ssh:ssh_sftp"><c>ssh_sftp(3)</c></seealso>.</p>
</desc>
</func>
@@ -577,7 +577,7 @@
</type>
<desc><marker id="opendir-3"/>
<p>For information and other types, see
- <seealso marker="ssh:ssh_sftp"><c>ssh:ssh_sftp(3)</c></seealso>.</p>
+ <seealso marker="ssh:ssh_sftp"><c>ssh_sftp(3)</c></seealso>.</p>
</desc>
</func>
@@ -591,7 +591,7 @@
</type>
<desc><marker id="position-3"/>
<p>For information and other types, see
- <seealso marker="ssh:ssh_sftp"><c>ssh:ssh_sftp(3)</c></seealso>.</p>
+ <seealso marker="ssh:ssh_sftp"><c>ssh_sftp(3)</c></seealso>.</p>
</desc>
</func>
@@ -605,7 +605,7 @@
</type>
<desc><marker id="position-4"/>
<p>For information and other types, see
- <seealso marker="ssh:ssh_sftp"><c>ssh:ssh_sftp(3)</c></seealso>.</p>
+ <seealso marker="ssh:ssh_sftp"><c>ssh_sftp(3)</c></seealso>.</p>
</desc>
</func>
@@ -619,7 +619,7 @@
</type>
<desc><marker id="pread-4"/>
<p>For information and other types, see
- <seealso marker="ssh:ssh_sftp"><c>ssh:ssh_sftp(3)</c></seealso>.</p>
+ <seealso marker="ssh:ssh_sftp"><c>ssh_sftp(3)</c></seealso>.</p>
</desc>
</func>
@@ -633,7 +633,7 @@
</type>
<desc><marker id="pread-5"/>
<p>For information and other types, see
- <seealso marker="ssh:ssh_sftp"><c>ssh:ssh_sftp(3)</c></seealso>.</p>
+ <seealso marker="ssh:ssh_sftp"><c>ssh_sftp(3)</c></seealso>.</p>
</desc>
</func>
@@ -647,7 +647,7 @@
</type>
<desc><marker id="pwrite-4"/>
<p>For information and other types, see
- <seealso marker="ssh:ssh_sftp"><c>ssh:ssh_sftp(3)</c></seealso>.</p>
+ <seealso marker="ssh:ssh_sftp"><c>ssh_sftp(3)</c></seealso>.</p>
</desc>
</func>
@@ -661,7 +661,7 @@
</type>
<desc><marker id="pwrite-5"/>
<p>For information and other types, see
- <seealso marker="ssh:ssh_sftp"><c>ssh:ssh_sftp(3)</c></seealso>.</p>
+ <seealso marker="ssh:ssh_sftp"><c>ssh_sftp(3)</c></seealso>.</p>
</desc>
</func>
@@ -675,7 +675,7 @@
</type>
<desc><marker id="read-3"/>
<p>For information and other types, see
- <seealso marker="ssh:ssh_sftp"><c>ssh:ssh_sftp(3)</c></seealso>.</p>
+ <seealso marker="ssh:ssh_sftp"><c>ssh_sftp(3)</c></seealso>.</p>
</desc>
</func>
@@ -689,7 +689,7 @@
</type>
<desc><marker id="read-4"/>
<p>For information and other types, see
- <seealso marker="ssh:ssh_sftp"><c>ssh:ssh_sftp(3)</c></seealso>.</p>
+ <seealso marker="ssh:ssh_sftp"><c>ssh_sftp(3)</c></seealso>.</p>
</desc>
</func>
@@ -703,7 +703,7 @@
</type>
<desc><marker id="read_file-2"/>
<p>For information and other types, see
- <seealso marker="ssh:ssh_sftp"><c>ssh:ssh_sftp(3)</c></seealso>.</p>
+ <seealso marker="ssh:ssh_sftp"><c>ssh_sftp(3)</c></seealso>.</p>
</desc>
</func>
@@ -717,7 +717,7 @@
</type>
<desc><marker id="read_file-3"/>
<p>For information and other types, see
- <seealso marker="ssh:ssh_sftp"><c>ssh:ssh_sftp(3)</c></seealso>.</p>
+ <seealso marker="ssh:ssh_sftp"><c>ssh_sftp(3)</c></seealso>.</p>
</desc>
</func>
@@ -731,7 +731,7 @@
</type>
<desc><marker id="read_file_info-2"/>
<p>For information and other types, see
- <seealso marker="ssh:ssh_sftp"><c>ssh:ssh_sftp(3)</c></seealso>.</p>
+ <seealso marker="ssh:ssh_sftp"><c>ssh_sftp(3)</c></seealso>.</p>
</desc>
</func>
@@ -745,7 +745,7 @@
</type>
<desc><marker id="read_file_info-3"/>
<p>For information and other types, see
- <seealso marker="ssh:ssh_sftp"><c>ssh:ssh_sftp(3)</c></seealso>.</p>
+ <seealso marker="ssh:ssh_sftp"><c>ssh_sftp(3)</c></seealso>.</p>
</desc>
</func>
@@ -759,7 +759,7 @@
</type>
<desc><marker id="read_link-2"/>
<p>For information and other types, see
- <seealso marker="ssh:ssh_sftp"><c>ssh:ssh_sftp(3)</c></seealso>.</p>
+ <seealso marker="ssh:ssh_sftp"><c>ssh_sftp(3)</c></seealso>.</p>
</desc>
</func>
@@ -773,7 +773,7 @@
</type>
<desc><marker id="read_link-3"/>
<p>For information and other types, see
- <seealso marker="ssh:ssh_sftp"><c>ssh:ssh_sftp(3)</c></seealso>.</p>
+ <seealso marker="ssh:ssh_sftp"><c>ssh_sftp(3)</c></seealso>.</p>
</desc>
</func>
@@ -787,7 +787,7 @@
</type>
<desc><marker id="read_link_info-2"/>
<p>For information and other types, see
- <seealso marker="ssh:ssh_sftp"><c>ssh:ssh_sftp(3)</c></seealso>.</p>
+ <seealso marker="ssh:ssh_sftp"><c>ssh_sftp(3)</c></seealso>.</p>
</desc>
</func>
@@ -801,7 +801,7 @@
</type>
<desc><marker id="read_link_info-3"/>
<p>For information and other types, see
- <seealso marker="ssh:ssh_sftp"><c>ssh:ssh_sftp(3)</c></seealso>.</p>
+ <seealso marker="ssh:ssh_sftp"><c>ssh_sftp(3)</c></seealso>.</p>
</desc>
</func>
@@ -853,7 +853,7 @@ ChannelId, End, DefaultTimeout)</c></seealso>.</p>
<p>If <c>End</c> is a fun, this fun is called with one argument, the
data value in a received <c>ssh_cm</c> message (see
- <seealso marker="ssh:ssh_connection"><c>ssh:ssh_connection(3)</c></seealso>.
+ <seealso marker="ssh:ssh_connection"><c>ssh_connection(3)</c></seealso>.
The fun is to return either <c>true</c> to end the receiving
operation (and have the so far collected data returned) or
<c>false</c> to wait for more data from the server. Even if a fun
@@ -872,7 +872,7 @@ ChannelId, End, DefaultTimeout)</c></seealso>.</p>
</type>
<desc><marker id="rename-3"/>
<p>For information and other types, see
- <seealso marker="ssh:ssh_sftp"><c>ssh:ssh_sftp(3)</c></seealso>.</p>
+ <seealso marker="ssh:ssh_sftp"><c>ssh_sftp(3)</c></seealso>.</p>
</desc>
</func>
@@ -886,7 +886,7 @@ ChannelId, End, DefaultTimeout)</c></seealso>.</p>
</type>
<desc><marker id="rename-4"/>
<p>For information and other types, see
- <seealso marker="ssh:ssh_sftp"><c>ssh:ssh_sftp(3)</c></seealso>.</p>
+ <seealso marker="ssh:ssh_sftp"><c>ssh_sftp(3)</c></seealso>.</p>
</desc>
</func>
@@ -1070,7 +1070,7 @@ ChannelId, 0, Data, End, Timeout)</c></seealso>.</p>
</type>
<desc><marker id="write-3"/>
<p>For information and other types, see
- <seealso marker="ssh:ssh_sftp"><c>ssh:ssh_sftp(3)</c></seealso>.</p>
+ <seealso marker="ssh:ssh_sftp"><c>ssh_sftp(3)</c></seealso>.</p>
</desc>
</func>
@@ -1084,7 +1084,7 @@ ChannelId, 0, Data, End, Timeout)</c></seealso>.</p>
</type>
<desc><marker id="write-4"/>
<p>For information and other types, see
- <seealso marker="ssh:ssh_sftp"><c>ssh:ssh_sftp(3)</c></seealso>.</p>
+ <seealso marker="ssh:ssh_sftp"><c>ssh_sftp(3)</c></seealso>.</p>
</desc>
</func>
@@ -1098,7 +1098,7 @@ ChannelId, 0, Data, End, Timeout)</c></seealso>.</p>
</type>
<desc><marker id="write_file-3"/>
<p>For information and other types, see
- <seealso marker="ssh:ssh_sftp"><c>ssh:ssh_sftp(3)</c></seealso>.</p>
+ <seealso marker="ssh:ssh_sftp"><c>ssh_sftp(3)</c></seealso>.</p>
</desc>
</func>
@@ -1112,7 +1112,7 @@ ChannelId, 0, Data, End, Timeout)</c></seealso>.</p>
</type>
<desc><marker id="write_file-4"/>
<p>For information and other types, see
- <seealso marker="ssh:ssh_sftp"><c>ssh:ssh_sftp(3)</c></seealso>.</p>
+ <seealso marker="ssh:ssh_sftp"><c>ssh_sftp(3)</c></seealso>.</p>
</desc>
</func>
@@ -1126,7 +1126,7 @@ ChannelId, 0, Data, End, Timeout)</c></seealso>.</p>
</type>
<desc><marker id="write_file_info-3"/>
<p>For information and other types, see
- <seealso marker="ssh:ssh_sftp"><c>ssh:ssh_sftp(3)</c></seealso>.</p>
+ <seealso marker="ssh:ssh_sftp"><c>ssh_sftp(3)</c></seealso>.</p>
</desc>
</func>
@@ -1140,7 +1140,7 @@ ChannelId, 0, Data, End, Timeout)</c></seealso>.</p>
</type>
<desc><marker id="write_file_info-4"/>
<p>For information and other types, see
- <seealso marker="ssh:ssh_sftp"><c>ssh:ssh_sftp(3)</c></seealso>.</p>
+ <seealso marker="ssh:ssh_sftp"><c>ssh_sftp(3)</c></seealso>.</p>
</desc>
</func>
</funcs>
diff --git a/lib/common_test/doc/src/ct_telnet.xml b/lib/common_test/doc/src/ct_telnet.xml
index e2a45e894b..eba3c3030d 100644
--- a/lib/common_test/doc/src/ct_telnet.xml
+++ b/lib/common_test/doc/src/ct_telnet.xml
@@ -198,7 +198,7 @@
<item><marker id="type-prompt_regexp"/>
<p>Regular expression matching all possible prompts for a specific
target type. <c>regexp</c> must not have any groups, that is, when
- matching, <c>re:run/3</c> (in <c>STDLIB</c>) must return a list with
+ matching, <c>re:run/3</c> (in STDLIB) must return a list with
one single element.</p></item>
</taglist>
</section>
diff --git a/lib/common_test/doc/src/event_handler_chapter.xml b/lib/common_test/doc/src/event_handler_chapter.xml
index 2978226a19..bd9ed21cb4 100644
--- a/lib/common_test/doc/src/event_handler_chapter.xml
+++ b/lib/common_test/doc/src/event_handler_chapter.xml
@@ -50,7 +50,7 @@
pass the information on. The event handlers are Erlang modules
implemented by the <c>Common Test</c> user according to the <c>gen_event</c>
behavior (for details, see module
- <seealso marker="stdlib:gen_event"><c>stdlib:gen_event</c></seealso> and
+ <seealso marker="stdlib:gen_event"><c>gen_event</c></seealso> and
section
<seealso marker="doc/design_principles:events"><c>gen_event Behaviour</c></seealso>
in OTP Design Principles in the System Documentation).
@@ -69,8 +69,8 @@
manager, either by telling <c>Common Test</c> to install them before the test
run (described later), or by adding the handlers dynamically during the test
run using
- <seealso marker="stdlib:gen_event#add_handler-3"><c>stdlib:gen_event:add_handler/3</c></seealso> or
- <seealso marker="stdlib:gen_event#add_sup_handler-3"><c>stdlib:gen_event:add_sup_handler/3</c></seealso>.
+ <seealso marker="stdlib:gen_event#add_handler-3"><c>gen_event:add_handler/3</c></seealso> or
+ <seealso marker="stdlib:gen_event#add_sup_handler-3"><c>gen_event:add_sup_handler/3</c></seealso>.
In the latter scenario, the reference of the <c>Common Test</c> event manager is
required. To get it, call
<seealso marker="ct#get_event_mgr_ref-0"><c>ct:get_event_mgr_ref/0</c></seealso>
diff --git a/lib/common_test/doc/src/introduction.xml b/lib/common_test/doc/src/introduction.xml
index 40724f24e9..df12bea6dd 100644
--- a/lib/common_test/doc/src/introduction.xml
+++ b/lib/common_test/doc/src/introduction.xml
@@ -45,7 +45,7 @@
</list>
<p><c>Common Test</c> also integrates use of the OTP
<seealso marker="tools:cover">cover</seealso> tool in application
- <c>Tools</c> for code coverage analysis of Erlang/OTP programs.</p>
+ Tools for code coverage analysis of Erlang/OTP programs.</p>
<p><c>Common Test</c> executes test suite programs automatically,
without operator interaction. Test progress and results are
diff --git a/lib/common_test/doc/src/run_test_chapter.xml b/lib/common_test/doc/src/run_test_chapter.xml
index 43e36adfb6..76e306c4ed 100644
--- a/lib/common_test/doc/src/run_test_chapter.xml
+++ b/lib/common_test/doc/src/run_test_chapter.xml
@@ -274,7 +274,7 @@
<note><p>Directories passed to <c>Common Test</c> can have either relative or absolute paths.</p></note>
- <note><p>Any start flags to the Erlang runtime system (application <c>ERTS</c>) can also be passed as
+ <note><p>Any start flags to the Erlang runtime system (application ERTS) can also be passed as
parameters to <c>ct_run</c>. It is, for example, useful to be able to
pass directories to be added to the Erlang code server search path
with flag <c>-pa</c> or <c>-pz</c>. If you have common help- or library
@@ -286,7 +286,7 @@
<p>The absolute path of directory <c>chat_server/ebin</c>
is here passed to the code server. This is essential because relative
paths are stored by the code server as relative, and <c>Common Test</c> changes
- the current working directory of <c>ERTS</c> during the test run.</p>
+ the current working directory of ERTS during the test run.</p>
</note>
<p>The <c>ct_run</c> program sets the exit status before shutting down. The following values
@@ -1258,7 +1258,7 @@
<p>The minor log files contain full details of every single test
case, each in a separate file. This way, it is
straightforward to compare the latest results to that of previous
- test runs, even if the set of test cases changes. If application <c>SASL</c>
+ test runs, even if the set of test cases changes. If application SASL
is running, its logs are also printed to the current minor log file by the
<seealso marker="common_test:ct_hooks_chapter#builtin_cths">
cth_log_redirect built-in hook</seealso>.
diff --git a/lib/common_test/doc/src/write_test_chapter.xml b/lib/common_test/doc/src/write_test_chapter.xml
index 83daf771a6..7bd2ccf588 100644
--- a/lib/common_test/doc/src/write_test_chapter.xml
+++ b/lib/common_test/doc/src/write_test_chapter.xml
@@ -269,10 +269,10 @@
<p>As parameter <c>Config</c> is a list of key-value tuples, that is,
a data type called a property list, it can be handled by the
- <seealso marker="stdlib:proplists"><c>stdlib:proplists</c></seealso> module.
+ <seealso marker="stdlib:proplists"><c>proplists</c></seealso> module.
A value can, for example, be searched for and returned with function
<seealso marker="stdlib:proplists#get_value-2"><c>proplists:get_value/2</c></seealso>.
- Also, or alternatively, the general <seealso marker="stdlib:lists"><c>stdlib:lists</c></seealso>
+ Also, or alternatively, the general <seealso marker="stdlib:lists"><c>lists</c></seealso>
module contains useful functions. Normally, the only operations
performed on <c>Config</c> is insert (adding a tuple to the head of the list)
and lookup. <c>Common Test</c> provides a simple macro named <c>?config</c>,
@@ -652,7 +652,7 @@
<title>Parallel Test Cases and I/O</title>
<p>A parallel test case has a private I/O server as its group leader.
(For a description of the group leader concept, see
- <seealso marker="erts:index"><c>ERTS</c></seealso>).
+ <seealso marker="erts:index">ERTS</seealso>).
The central I/O server process, which handles the output from
regular test cases and configuration functions, does not respond to I/O messages
during execution of parallel groups. This is important to understand
@@ -1032,8 +1032,8 @@
6. Categorized error, importance = 99</pre>
<p>The arguments <c>Format</c> and <c>FormatArgs</c> in <c>ct:log/print/pal</c> are
- always passed on to the <c>stdlib</c> function <c>io:format/3</c> (For details,
- see the <seealso marker="stdlib:io"><c>stdlib:io</c></seealso> manual page).</p>
+ always passed on to the STDLIB function <c>io:format/3</c> (For details,
+ see the <seealso marker="stdlib:io"><c>io</c></seealso> manual page).</p>
<p><c>ct:pal/4</c> and <c>ct:log/5</c> add headers to strings being printed to the
log file. The strings are also wrapped in div tags with a CSS class
diff --git a/lib/common_test/test_server/ts_run.erl b/lib/common_test/test_server/ts_run.erl
index 66db1ff9a7..82ae44ec06 100644
--- a/lib/common_test/test_server/ts_run.erl
+++ b/lib/common_test/test_server/ts_run.erl
@@ -258,7 +258,7 @@ make_command(Vars, Spec, State) ->
run_batch(Vars, _Spec, State) ->
process_flag(trap_exit, true),
- Command = State#state.command ++ " -noinput -s erlang halt",
+ Command = State#state.command ++ " -noinput -eval \"erlang:halt(0,[{flush,false}]).\"",
ts_lib:progress(Vars, 1, "Command: ~ts~n", [Command]),
io:format(user, "Command: ~ts~n",[Command]),
Port = open_port({spawn, Command}, [stream, in, eof, exit_status]),
diff --git a/lib/compiler/doc/src/compile.xml b/lib/compiler/doc/src/compile.xml
index 61e214294e..3ce37b98e9 100644
--- a/lib/compiler/doc/src/compile.xml
+++ b/lib/compiler/doc/src/compile.xml
@@ -136,7 +136,7 @@
(see
<seealso marker="erts:absform">The Abstract Format</seealso>
in ERTS User's Guide) in the compiled beam module. Tools
- such as <c>Debugger</c>, <c>Xref</c>, and <c>Cover</c> require
+ such as Debugger, Xref, and Cover require
the debug information to be included.</p>
<p><em>Warning</em>: Source code can be reconstructed from
@@ -544,7 +544,7 @@ module.beam: module.erl \
compiler to be deprecated. Notice that the compiler does not know
about attribute <c>-deprecated()</c>, but uses an
assembled list of deprecated functions in Erlang/OTP. To
- do a more general check, the <c>Xref</c> tool can be used.
+ do a more general check, the Xref tool can be used.
See also
<seealso marker="tools:xref#deprecated_function">xref(3)</seealso>
and the function
@@ -846,7 +846,7 @@ pi() -> 3.1416.
<section>
<title>Inlining of List Functions</title>
<p>The compiler can also inline various list manipulation functions
- from the module <c>list</c> in <c>STDLIB</c>.</p>
+ from the module <c>list</c> in STDLIB.</p>
<p>This feature must be explicitly enabled with a compiler option or a
<c>-compile()</c> attribute in the source module.</p>
diff --git a/lib/compiler/doc/src/notes.xml b/lib/compiler/doc/src/notes.xml
index 92b3d809fc..dd6b132a92 100644
--- a/lib/compiler/doc/src/notes.xml
+++ b/lib/compiler/doc/src/notes.xml
@@ -280,7 +280,7 @@
<item>
<p>
The <c>cerl</c> and <c>cerl_trees</c> modules in the
- <c>compiler</c> application are now documented.</p>
+ Compiler application are now documented.</p>
<p>
Own Id: OTP-11978</p>
</item>
@@ -1982,7 +1982,7 @@
<c>RightExpr</c> or vice versa. The evaluation order is
only important if the expressions contains and/or depends
on operations with side-effects, such as message passing
- or <c>ets</c> operations.</p>
+ or ETS operations.</p>
<p>
Own Id: OTP-7206</p>
</item>
diff --git a/lib/compiler/doc/src/ref_man.xml b/lib/compiler/doc/src/ref_man.xml
index f5466553c0..c32c499008 100644
--- a/lib/compiler/doc/src/ref_man.xml
+++ b/lib/compiler/doc/src/ref_man.xml
@@ -30,7 +30,7 @@
<file>application.sgml</file>
</header>
<description>
- <p>The <c>Compiler</c> application compiles Erlang
+ <p>The Compiler application compiles Erlang
code to byte-code. The highly compact byte-code is executed by
the Erlang emulator.</p>
</description>
diff --git a/lib/crypto/doc/src/notes.xml b/lib/crypto/doc/src/notes.xml
index 7d3a85326f..56e165a1d1 100644
--- a/lib/crypto/doc/src/notes.xml
+++ b/lib/crypto/doc/src/notes.xml
@@ -815,7 +815,7 @@
also been extended. </item><item> The <c>configure</c>
scripts of <c>erl_interface</c> and <c>odbc</c> now
search for thread libraries and thread library quirks the
- same way as <c>erts</c> do. </item><item> The
+ same way as ERTS do. </item><item> The
<c>configure</c> script of the <c>odbc</c> application
now also looks for odbc libraries in <c>lib64</c> and
<c>lib/64</c> directories when building on a 64-bit
diff --git a/lib/debugger/doc/src/i.xml b/lib/debugger/doc/src/i.xml
index db89f23494..628b91e9e4 100644
--- a/lib/debugger/doc/src/i.xml
+++ b/lib/debugger/doc/src/i.xml
@@ -45,7 +45,7 @@
attached manually or automatically.</p>
<p>By preference, these functions can be included in module
- <seealso marker="stdlib:shell_default"><c>stdlib:shell_default</c></seealso>.
+ <seealso marker="stdlib:shell_default"><c>shell_default</c></seealso>.
By default, they are included in that module.</p>
</description>
@@ -372,7 +372,7 @@
</fsummary>
<desc>
<p>Returns the current version number of the interpreter.
- Same as the version number of the <c>Debugger</c> application.</p>
+ Same as the version number of the Debugger application.</p>
</desc>
</func>
diff --git a/lib/hipe/sparc/hipe_rtl_to_sparc.erl b/lib/hipe/sparc/hipe_rtl_to_sparc.erl
index eef5ba8d96..f9c043eafe 100644
--- a/lib/hipe/sparc/hipe_rtl_to_sparc.erl
+++ b/lib/hipe/sparc/hipe_rtl_to_sparc.erl
@@ -750,13 +750,25 @@ xaluop_commutes(XAluOp) ->
xaluop_is_shift(XAluOp) ->
case XAluOp of
+ 'add' -> false;
+ 'addcc' -> false;
+ 'and' -> false;
+ 'andcc' -> false;
+ 'cmpcc' -> false;
+ 'ldsb' -> false;
+ 'ldub' -> false;
+ 'lduw' -> false;
+ 'or' -> false;
'sll' -> true;
- 'srl' -> true;
+ %% 'sllx' -> true;
+ 'smul' -> false;
'sra' -> true;
- 'sllx' -> true;
- 'srlx' -> true;
- 'srax' -> true;
- _ -> false
+ %% 'srax' -> true;
+ 'srl' -> true;
+ %% 'srlx' -> true;
+ 'sub' -> false;
+ 'subcc' -> false;
+ 'xor' -> false
end.
%%% Convert an extended SPARC AluOp back to a plain AluOp.
@@ -764,9 +776,23 @@ xaluop_is_shift(XAluOp) ->
xaluop_normalise(XAluOp) ->
case XAluOp of
- 'cmp' -> 'sub';
+ 'add' -> 'add';
+ 'addcc' -> 'addcc';
+ 'and' -> 'and';
+ 'andcc' -> 'andcc';
+ %% 'cmp' -> 'sub';
'cmpcc' -> 'subcc';
- _ -> XAluOp
+ 'ldsb' -> 'ldsb';
+ 'ldub' -> 'ldub';
+ 'lduw' -> 'lduw';
+ 'or' -> 'or';
+ 'sll' -> 'sll';
+ 'smul' -> 'smul';
+ 'sra' -> 'sra';
+ 'srl' -> 'srl';
+ 'sub' -> 'sub';
+ 'subcc' -> 'subcc';
+ 'xor' -> 'xor'
end.
%%% Convert an RTL condition code.
diff --git a/lib/hipe/test/hipe_testsuite_driver.erl b/lib/hipe/test/hipe_testsuite_driver.erl
index 03ec7adfd0..a3048d907e 100644
--- a/lib/hipe/test/hipe_testsuite_driver.erl
+++ b/lib/hipe/test/hipe_testsuite_driver.erl
@@ -99,7 +99,7 @@ write_suite(Suite) ->
write_header(#suite{suitename = SuiteName, outputfile = OutputFile,
testcases = TestCases}) ->
Exports = format_export(TestCases),
- TimeLimit = 3, %% with 1 or 2 it fails on some slow machines...
+ TimeLimit = 5, %% with 1 or 2 it fails on some slow machines...
io:format(OutputFile,
"%% ATTENTION!\n"
"%% This is an automatically generated file. Do not edit.\n\n"
diff --git a/lib/inets/doc/src/http_server.xml b/lib/inets/doc/src/http_server.xml
index aeda961714..65b3dcde95 100644
--- a/lib/inets/doc/src/http_server.xml
+++ b/lib/inets/doc/src/http_server.xml
@@ -4,7 +4,7 @@
<chapter>
<header>
<copyright>
- <year>2004</year><year>2015</year>
+ <year>2004</year><year>2016</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -40,8 +40,8 @@
<item>Secure Sockets Layer (SSL)</item>
<item>Erlang Scripting Interface (ESI)</item>
<item>Common Gateway Interface (CGI)</item>
- <item>User Authentication (using <c>Mnesia</c>,
- <c>Dets</c> or plain text database)</item>
+ <item>User Authentication (using Mnesia,
+ Dets or plain text database)</item>
<item>Common Logfile Format (with or without disk_log(3) support)</item>
<item>URL Aliasing</item>
<item>Action Mappings</item>
@@ -563,7 +563,7 @@ http://your.server.org/eval?httpd_example:print(atom_to_list(apply(erlang,halt,[
<title>mod_auth - User Authentication</title>
<p>The <seealso marker="mod_auth">mod_auth(3)</seealso>
module provides for basic user authentication using
- textual files, <c>Dets</c> databases as well as <c>Mnesia</c> databases.</p>
+ textual files, Dets databases as well as Mnesia databases.</p>
<p>Uses the following Erlang Web Server API interaction data:
</p>
<list type="bulleted">
@@ -580,15 +580,15 @@ http://your.server.org/eval?httpd_example:print(atom_to_list(apply(erlang,halt,[
<section>
<title>Mnesia As Authentication Database</title>
- <p>If <c>Mnesia</c> is used as storage method, <c>Mnesia</c> must be
- started before the HTTP server. The first time <c>Mnesia</c> is
+ <p>If Mnesia is used as storage method, Mnesia must be
+ started before the HTTP server. The first time Mnesia is
started, the schema and the tables must be created before
- <c>Mnesia</c> is started. A simple example of a module with two
- functions that creates and start <c>Mnesia</c> is provided
+ Mnesia is started. A simple example of a module with two
+ functions that creates and start Mnesia is provided
here. Function <c>first_start/0</c> is to be used the first
time. It creates the schema and the tables.
<c>start/0</c> is to be used in consecutive startups.
- <c>start/0</c> starts <c>Mnesia</c> and waits for the tables to
+ <c>start/0</c> starts Mnesia and waits for the tables to
be initiated. This function must only be used when the
schema and the tables are already created.</p>
@@ -616,25 +616,25 @@ start() ->
mnesia:start(),
mnesia:wait_for_tables([httpd_user, httpd_group], 60000). </code>
- <p>To create the <c>Mnesia</c> tables, we use two records defined in
+ <p>To create the Mnesia tables, we use two records defined in
<c>mod_auth.hrl</c>, so that file must be included. <c>first_start/0</c>
creates a schema that specifies on which nodes the database is to reside.
- Then it starts <c>Mnesia</c> and creates the tables. The first argument
+ Then it starts Mnesia and creates the tables. The first argument
is the name of the tables, the second argument is a list of options of
how to create the table, see
- <seealso marker="mnesia:mnesia"><c>mnesia</c></seealso>, documentation for
+ <seealso marker="mnesia:mnesia"><c>mnesia(3)</c></seealso>, documentation for
more information. As the implementation of the <c>mod_auth_mnesia</c>
saves one row for each user, the type must be <c>bag</c>.
When the schema and the tables are created, function
<seealso marker="mnesia:mnesia#start-0">mnesia:start/0</seealso>
- is used to start <c>Mnesia</c> and
- waits for the tables to be loaded. <c>Mnesia</c> uses the
+ is used to start Mnesia and
+ waits for the tables to be loaded. Mnesia uses the
directory specified as <c>mnesia_dir</c> at startup if specified,
- otherwise <c>Mnesia</c> uses the current directory. For security
- reasons, ensure that the <c>Mnesia</c> tables are stored outside
+ otherwise Mnesia uses the current directory. For security
+ reasons, ensure that the Mnesia tables are stored outside
the document tree of the HTTP server. If they are placed in the
directory which it protects, clients can download the tables.
- Only the <c>Dets</c> and <c>Mnesia</c> storage
+ Only the Dets and Mnesia storage
methods allow writing of dynamic user data to disk. <c>plain</c> is
a read only method.</p>
</section>
@@ -669,7 +669,7 @@ start() ->
<section>
<title>mod_disk_log - Logging Using Disk_Log.</title>
<p>Standard logging using the "Common Logfile Format" and
- <seealso marker="kernel:disk_log">kernel:disk_log(3)</seealso>.</p>
+ <seealso marker="kernel:disk_log">disk_log(3)</seealso>.</p>
<p>Uses the following Erlang Web Server API interaction data:
</p>
<list type="bulleted">
diff --git a/lib/inets/doc/src/httpc.xml b/lib/inets/doc/src/httpc.xml
index ca9b268a03..13471aab2c 100644
--- a/lib/inets/doc/src/httpc.xml
+++ b/lib/inets/doc/src/httpc.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>2004</year><year>2015</year>
+ <year>2004</year><year>2016</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -72,7 +72,7 @@
<p><c>profile() = atom()</c></p>
<p><c>path() = string()</c> representing a file path or directory path</p>
<p><c>ip_address()</c> = See the
- <seealso marker="kernel:inet">inet(3)</seealso> manual page in <c>Kernel</c>.</p>
+ <seealso marker="kernel:inet">inet(3)</seealso> manual page in Kernel.</p>
<p><c>socket_opt()</c> = See the options used by
<seealso marker="kernel:gen_tcp">gen_tcp(3)</seealso> <c>gen_tcp(3)</c> and
<seealso marker="ssl:ssl">ssl(3)</seealso> connect(s)</p>
diff --git a/lib/inets/doc/src/httpd.xml b/lib/inets/doc/src/httpd.xml
index b05ae72983..d74635fc01 100644
--- a/lib/inets/doc/src/httpd.xml
+++ b/lib/inets/doc/src/httpd.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>1997</year><year>2015</year>
+ <year>1997</year><year>2016</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -711,7 +711,7 @@ text/plain asc txt</pre>
<item>
<p>Sets the type of authentication database that is used for the
directory. The key difference between the different methods is
- that dynamic data can be saved when <c>Mnesia</c> and <c>Dets</c>
+ that dynamic data can be saved when Mnesia and Dets
are used.
This property is called <c>AuthDbType</c> in the Apache-like
configuration files.</p>
@@ -731,10 +731,10 @@ text/plain asc txt</pre>
<code> ragnar:s7Xxv7
edward:wwjau8 </code>
- <p>If the <c>Dets</c> storage method is used, the user database is
- maintained by <c>Dets</c> and must not be edited by hand. Use the
+ <p>If the Dets storage method is used, the user database is
+ maintained by Dets and must not be edited by hand. Use the
API functions in module <c>mod_auth</c> to create/edit the user
- database. This directive is ignored if the <c>Mnesia</c>
+ database. This directive is ignored if the Mnesia
storage method is used. For security reasons, ensure that
<c>auth_user_file</c> is stored outside the document tree of the web
server. If it is placed in the directory that it protects,
@@ -753,10 +753,10 @@ text/plain asc txt</pre>
<code>group1: bob joe ante</code>
- <p>If the <c>Dets</c> storage method is used, the group database is
- maintained by <c>Dets</c> and must not be edited by hand. Use the
+ <p>If the Dets storage method is used, the group database is
+ maintained by Dets and must not be edited by hand. Use the
API for module <c>mod_auth</c> to create/edit the group database.
- This directive is ignored if the <c>Mnesia</c> storage method is used.
+ This directive is ignored if the Mnesia storage method is used.
For security reasons, ensure that the <c>auth_group_file</c> is
stored outside the document tree of the web server. If it is
placed in the directory that it protects, clients
diff --git a/lib/inets/doc/src/mod_auth.xml b/lib/inets/doc/src/mod_auth.xml
index 4b7088b2c5..c4f844622b 100644
--- a/lib/inets/doc/src/mod_auth.xml
+++ b/lib/inets/doc/src/mod_auth.xml
@@ -33,7 +33,7 @@
<modulesummary>User authentication using text files, Dets, or Mnesia database.</modulesummary>
<description>
<p>This module provides for basic user authentication using
- textual files, <c>Dets</c> databases, or <c>Mnesia</c> databases.</p>
+ textual files, Dets databases, or Mnesia databases.</p>
</description>
<funcs>
diff --git a/lib/inets/src/inets_app/inets.appup.src b/lib/inets/src/inets_app/inets.appup.src
index d4d21f6774..3a31daeb20 100644
--- a/lib/inets/src/inets_app/inets.appup.src
+++ b/lib/inets/src/inets_app/inets.appup.src
@@ -18,16 +18,10 @@
%% %CopyrightEnd%
{"%VSN%",
[
- {<<"6.3.1">>,
- [{load_module, mod_esi, soft_purge, soft_purge, []}
- ]},
{<<"6\\..*">>,[{restart_application, inets}]},
{<<"5\\..*">>,[{restart_application, inets}]}
],
[
- {<<"6.3.1">>,
- [{load_module, mod_esi, soft_purge, soft_purge, []}
- ]},
{<<"6\\..*">>,[{restart_application, inets}]},
{<<"5\\..*">>,[{restart_application, inets}]}
]
diff --git a/lib/inets/vsn.mk b/lib/inets/vsn.mk
index 747724a86b..f668ef106c 100644
--- a/lib/inets/vsn.mk
+++ b/lib/inets/vsn.mk
@@ -19,6 +19,6 @@
# %CopyrightEnd%
APPLICATION = inets
-INETS_VSN = 6.3.2
+INETS_VSN = 6.3.3
PRE_VSN =
APP_VSN = "$(APPLICATION)-$(INETS_VSN)$(PRE_VSN)"
diff --git a/lib/kernel/doc/src/app.xml b/lib/kernel/doc/src/app.xml
index 5e0da409a3..d2e9390d7e 100644
--- a/lib/kernel/doc/src/app.xml
+++ b/lib/kernel/doc/src/app.xml
@@ -151,7 +151,7 @@ ApplicationVersion = string()</code>
application is allowed to be started. <c>systools</c> uses
this list to generate correct start scripts. Defaults to
the empty list, but notice that all applications have
- dependencies to (at least) <c>Kernel</c> and <c>STDLIB</c>.</p>
+ dependencies to (at least) Kernel and STDLIB.</p>
</item>
<tag><c>env</c></tag>
<item>
@@ -171,7 +171,7 @@ ApplicationVersion = string()</code>
implemented as a supervision tree, otherwise the application
controller does not know how to start it. <c>mod</c>
can be omitted for applications without processes, typically
- code libraries, for example, <c>STDLIB</c>.</p>
+ code libraries, for example, STDLIB.</p>
</item>
<tag><c>start_phases</c></tag>
<item>
@@ -236,7 +236,7 @@ ApplicationVersion = string()</code>
<section>
<title>See Also</title>
<p><seealso marker="application"><c>application(3)</c></seealso>,
- <seealso marker="sasl:systools"><c>sasl:systools(3)</c></seealso></p>
+ <seealso marker="sasl:systools"><c>systools(3)</c></seealso></p>
</section>
</fileref>
diff --git a/lib/kernel/doc/src/application.xml b/lib/kernel/doc/src/application.xml
index 8d33aa86e7..886286b76d 100644
--- a/lib/kernel/doc/src/application.xml
+++ b/lib/kernel/doc/src/application.xml
@@ -200,7 +200,7 @@
<seealso marker="app"><c>app(4)</c></seealso>.</p>
<p>If <c><anno>Distributed</anno> == {<anno>Application</anno>,[<anno>Time</anno>,]<anno>Nodes</anno>}</c>,
the application becomes distributed. The argument overrides
- the value for the application in the <c>Kernel</c> configuration
+ the value for the application in the Kernel configuration
parameter <c>distributed</c>. <c><anno>Application</anno></c> must be
the application name (same as in the first argument).
If a node crashes and <c><anno>Time</anno></c> is specified,
@@ -221,7 +221,7 @@ Nodes = [cp1@cave, {cp2@cave, cp3@cave}]</code>
the application is to be started at <c>cp2@cave</c>
or <c>cp3@cave</c>.</p>
<p>If <c>Distributed == default</c>, the value for
- the application in the <c>Kernel</c> configuration parameter
+ the application in the Kernel configuration parameter
<c>distributed</c> is used.</p>
</desc>
</func>
@@ -267,7 +267,7 @@ Nodes = [cp1@cave, {cp2@cave, cp3@cave}]</code>
started, <c>Application</c> is started as well.</p>
<p>By default, all applications are loaded with permission
<c>true</c> on all nodes. The permission can be configured
- using the <c>Kernel</c> configuration parameter <c>permissions</c>.</p>
+ using the Kernel configuration parameter <c>permissions</c>.</p>
</desc>
</func>
<func>
diff --git a/lib/kernel/doc/src/auth.xml b/lib/kernel/doc/src/auth.xml
index 03f983b96d..5901446960 100644
--- a/lib/kernel/doc/src/auth.xml
+++ b/lib/kernel/doc/src/auth.xml
@@ -47,7 +47,7 @@
<desc>
<p>Use
<seealso marker="erts:erlang#erlang:get_cookie/0"><c>erlang:get_cookie()</c></seealso>
- in <c>ERTS</c> instead.</p>
+ in ERTS instead.</p>
</desc>
</func>
<func>
@@ -59,7 +59,7 @@
<desc>
<p>Use
<seealso marker="erts:erlang#erlang:set_cookie/2"><c>erlang:set_cookie(node(), <anno>Cookie</anno>)</c>
- in <c>ERTS</c></seealso> instead.</p>
+ in ERTS</seealso> instead.</p>
</desc>
</func>
<func>
diff --git a/lib/kernel/doc/src/code.xml b/lib/kernel/doc/src/code.xml
index 21f8a2d54a..4db377bcde 100644
--- a/lib/kernel/doc/src/code.xml
+++ b/lib/kernel/doc/src/code.xml
@@ -86,11 +86,11 @@
an <c>ebin</c> directory are ignored.</p>
<p>All application directories found in the additional directories
appears before the standard OTP applications, except for the
- <c>Kernel</c> and <c>STDLIB</c> applications, which are placed before
+ Kernel and STDLIB applications, which are placed before
any additional applications. In other words, modules found in any
of the additional library directories override modules with
- the same name in OTP, except for modules in <c>Kernel</c> and
- <c>STDLIB</c>.</p>
+ the same name in OTP, except for modules in Kernel and
+ STDLIB.</p>
<p>Environment variable <c>ERL_LIBS</c> (if defined) is to contain
a colon-separated (for Unix-like systems) or semicolon-separated
(for Windows) list of additional libraries.</p>
@@ -151,7 +151,7 @@ zip:create("mnesia-4.4.7.ez",
<c>$OTPROOT/lib/mnesia.ez/mnesia/ebin</c> or
<c>$OTPROOT/lib/mnesia-4.4.7.ez/mnesia-4.4.7/ebin</c>.</p>
- <p>The code server uses module <c>erl_prim_loader</c> in <c>ERTS</c>
+ <p>The code server uses module <c>erl_prim_loader</c> in ERTS
(possibly through <c>erl_boot_server</c>) to read code files from
archives. However, the functions in <c>erl_prim_loader</c> can also be
used by other applications to read files from archives. For
@@ -688,9 +688,9 @@ ok = code:finish_loading(Prepared),
<p>Normally, <c><anno>Loaded</anno></c> is the absolute filename
<c>Filename</c> from which the code is obtained. If the module
is preloaded (see
- <seealso marker="sasl:script"><c>sasl:script(4)</c></seealso>),
+ <seealso marker="sasl:script"><c>script(4)</c></seealso>),
<c>Loaded==preloaded</c>. If the module is Cover-compiled (see
- <seealso marker="tools:cover"><c>tools:cover(3)</c></seealso>),
+ <seealso marker="tools:cover"><c>cover(3)</c></seealso>),
<c>Loaded==cover_compiled</c>.</p>
</desc>
</func>
diff --git a/lib/kernel/doc/src/erl_boot_server.xml b/lib/kernel/doc/src/erl_boot_server.xml
index 897365f9b9..4109251387 100644
--- a/lib/kernel/doc/src/erl_boot_server.xml
+++ b/lib/kernel/doc/src/erl_boot_server.xml
@@ -38,13 +38,13 @@
command-line flag <c>-loader inet</c>. All hosts specified
with command-line flag <c>-hosts Host</c> must have one
instance of this server running.</p>
- <p>This server can be started with the <c>Kernel</c> configuration
+ <p>This server can be started with the Kernel configuration
parameter <c>start_boot_server</c>.</p>
<p>The <c>erl_boot_server</c> can read regular files and
files in archives. See <seealso marker="code"><c>code(3)</c></seealso>
and
<seealso marker="erts:erl_prim_loader"><c>erl_prim_loader(3)</c></seealso>
- in <c>ERTS</c>.</p>
+ in ERTS.</p>
<warning><p>The support for loading code from archive files is
experimental. It is released before it is ready
to obtain early feedback. The file format, semantics,
diff --git a/lib/kernel/doc/src/erl_ddll.xml b/lib/kernel/doc/src/erl_ddll.xml
index a5ce58ef3e..75114e015c 100644
--- a/lib/kernel/doc/src/erl_ddll.xml
+++ b/lib/kernel/doc/src/erl_ddll.xml
@@ -201,7 +201,7 @@
<desc>
<p>Removes a driver monitor in much the same way as
<seealso marker="erts:erlang#erlang:demonitor/1"><c>erlang:demonitor/1</c></seealso>
- in <c>ERTS</c>
+ in ERTS
does with process monitors. For details about how to create
driver monitors, see
<seealso marker="#monitor/2"><c>monitor/2</c></seealso>,
@@ -431,7 +431,7 @@
<p>Creates a driver monitor and works in many
ways as
<seealso marker="erts:erlang#erlang:monitor/2"><c>erlang:monitor/2</c></seealso>
- in <c>ERTS</c>,
+ in ERTS,
does for processes. When a driver changes state, the monitor
results in a monitor message that is sent to the calling
process. <c><anno>MonitorRef</anno></c> returned by this function is
@@ -745,7 +745,7 @@
<p>This parameter is the name of the driver
to be used in subsequent calls to function
<seealso marker="erts:erlang#open_port/2"><c>erlang:open_port</c></seealso>
- in <c>ERTS</c>.
+ in ERTS.
The name can be specified as an <c>iolist()</c> or
an <c>atom()</c>. The name specified when loading is used
to find the object file (with the help of <c><anno>Path</anno></c>
diff --git a/lib/kernel/doc/src/error_logger.xml b/lib/kernel/doc/src/error_logger.xml
index a8273e59e2..814e8eac46 100644
--- a/lib/kernel/doc/src/error_logger.xml
+++ b/lib/kernel/doc/src/error_logger.xml
@@ -33,7 +33,7 @@
<description>
<p>The Erlang <em>error logger</em> is an event manager (see
<seealso marker="doc/design_principles:des_princ">OTP Design Principles</seealso> and
- <seealso marker="stdlib:gen_event"><c>stdlib:gen_event(3)</c></seealso>),
+ <seealso marker="stdlib:gen_event"><c>gen_event(3)</c></seealso>),
registered as <c>error_logger</c>. Errors, warnings, and info events
are sent to the error logger from the Erlang runtime system and
the different Erlang/OTP applications. The events are, by default,
@@ -44,12 +44,12 @@
executing.</p>
<p>Initially, <c>error_logger</c> has only a primitive event
handler, which buffers and prints the raw event messages. During
- system startup, the <c>Kernel</c> application replaces this with a
+ system startup, the Kernel application replaces this with a
<em>standard event handler</em>, by default one that writes
- nicely formatted output to the terminal. <c>Kernel</c> can also be
+ nicely formatted output to the terminal. Kernel can also be
configured so that events are logged to a file instead, or not logged at all,
see <seealso marker="kernel_app"><c>kernel(6)</c></seealso>.</p>
- <p>Also the <c>SASL</c> application, if started, adds its own event
+ <p>Also the SASL application, if started, adds its own event
handler, which by default writes supervisor, crash, and progress
reports to the terminal. See
<seealso marker="sasl:sasl_app"><c>sasl(6)</c></seealso>.</p>
@@ -58,9 +58,9 @@
User-defined event handlers can be added to handle application-specific
events, see
<seealso marker="#add_report_handler/1"><c>add_report_handler/1,2</c></seealso>.
- Also, a useful event handler is provided in <c>STDLIB</c> for multi-file
+ Also, a useful event handler is provided in STDLIB for multi-file
logging of events, see
- <seealso marker="stdlib:log_mf_h"><c>stdlib:log_mf_h(3)</c></seealso>.</p>
+ <seealso marker="stdlib:log_mf_h"><c>log_mf_h(3)</c></seealso>.</p>
<p>Warning events were introduced in Erlang/OTP R9C and are enabled
by default as from Erlang/OTP 18.0. To retain backwards compatibility
with existing user-defined event handlers, the warning events can be
@@ -82,7 +82,7 @@
<p>Adds a new event handler to the error logger. The event
handler must be implemented as a <c>gen_event</c> callback
module, see
- <seealso marker="stdlib:gen_event"><c>stdlib:gen_event(3)</c></seealso>.</p>
+ <seealso marker="stdlib:gen_event"><c>gen_event(3)</c></seealso>.</p>
<p><c><anno>Handler</anno></c> is typically the name of the callback module
and <c><anno>Args</anno></c> is an optional term (defaults to []) passed
to the initialization callback function <c><anno>Handler</anno>:init/1</c>.
@@ -97,7 +97,7 @@
<desc>
<p>Deletes an event handler from the error logger by calling
<c>gen_event:delete_handler(error_logger, <anno>Handler</anno>, [])</c>,
- see <seealso marker="stdlib:gen_event"><c>stdlib:gen_event(3)</c></seealso>.</p>
+ see <seealso marker="stdlib:gen_event"><c>gen_event(3)</c></seealso>.</p>
</desc>
</func>
<func>
@@ -110,7 +110,7 @@
The <c><anno>Format</anno></c> and <c><anno>Data</anno></c> arguments
are the same as the arguments of
<seealso marker="stdlib:io#format/2"><c>io:format/2</c></seealso>
- in <c>STDLIB</c>.
+ in STDLIB.
The event is handled by the standard event handler.</p>
<p><em>Example:</em></p>
<pre>
@@ -171,7 +171,7 @@ ok</pre>
The <c><anno>Format</anno></c> and <c><anno>Data</anno></c> arguments
are the same as the arguments of
<seealso marker="stdlib:io#format/2"><c>io:format/2</c></seealso>
- in <c>STDLIB</c>. The event is handled by the standard event handler.</p>
+ in STDLIB. The event is handled by the standard event handler.</p>
<p><em>Example:</em></p>
<pre>
1> <input>error_logger:info_msg("Something happened in ~p~n", [a_module]).</input>
@@ -235,7 +235,7 @@ ok</pre>
<p>Enables or disables printout of standard events to a file.</p>
<p>This is done by adding or deleting the standard event handler
for output to file. Thus, calling this function overrides
- the value of the <c>Kernel</c> <c>error_logger</c> configuration
+ the value of the Kernel <c>error_logger</c> configuration
parameter.</p>
<p>Enabling file logging can be used together with calling
<c>tty(false)</c>, to have a silent system where
@@ -274,7 +274,7 @@ ok</pre>
to the terminal.</p>
<p>This is done by adding or deleting the standard event handler
for output to the terminal. Thus, calling this function overrides
- the value of the <c>Kernel</c> <c>error_logger</c> configuration parameter.</p>
+ the value of the Kernel <c>error_logger</c> configuration parameter.</p>
</desc>
</func>
<func>
@@ -323,7 +323,7 @@ ok</pre>
The <c><anno>Format</anno></c> and <c><anno>Data</anno></c> arguments
are the same as the arguments of
<seealso marker="stdlib:io#format/2"><c>io:format/2</c></seealso>
- in <c>STDLIB</c>.
+ in STDLIB.
The event is handled by the standard event handler. It is tagged
as an error, warning, or info, see
<seealso marker="#warning_map/0"><c>warning_map/0</c></seealso>.</p>
@@ -416,8 +416,8 @@ ok</pre>
</section>
<section>
<title>See Also</title>
- <p><seealso marker="stdlib:gen_event"><c>stdlib:gen_event(3)</c></seealso>,
- <seealso marker="stdlib:log_mf_h"><c>stdlib:log_mf_h(3)</c></seealso>
+ <p><seealso marker="stdlib:gen_event"><c>gen_event(3)</c></seealso>,
+ <seealso marker="stdlib:log_mf_h"><c>log_mf_h(3)</c></seealso>
<seealso marker="kernel_app"><c>kernel(6)</c></seealso>
<seealso marker="sasl:sasl_app"><c>sasl(6)</c></seealso></p>
</section>
diff --git a/lib/kernel/doc/src/file.xml b/lib/kernel/doc/src/file.xml
index 7d86c3ebcb..09497482cf 100644
--- a/lib/kernel/doc/src/file.xml
+++ b/lib/kernel/doc/src/file.xml
@@ -79,7 +79,7 @@
<seealso marker="#list_dir_all"><c>list_dir_all/1</c></seealso> and
<seealso marker="#read_link_all"><c>read_link_all/1</c></seealso>.</p>
- <p>See also section <seealso marker="stdlib:unicode_usage#notes-about-raw-filenames">Notes About Raw Filenames</seealso> in the <c>STDLIB</c> User´s Giude.</p>
+ <p>See also section <seealso marker="stdlib:unicode_usage#notes-about-raw-filenames">Notes About Raw Filenames</seealso> in the STDLIB User's Guide.</p>
</description>
@@ -277,7 +277,7 @@ f.txt: {person, "kalle", 25}.
{ok,[{person,"kalle",25},{person,"pelle",30}]}</pre>
<p>The encoding of <c><anno>Filename</anno></c> can be set
by a comment, as described in
- <seealso marker="stdlib:epp#encoding"><c>stdlib:epp(3)</c></seealso>.</p>
+ <seealso marker="stdlib:epp#encoding"><c>epp(3)</c></seealso>.</p>
</desc>
</func>
<func>
@@ -445,7 +445,7 @@ f.txt: {person, "kalle", 25}.
</taglist>
<p>The encoding of <c><anno>Filename</anno></c> can be set
by a comment, as described in
- <seealso marker="stdlib:epp#encoding"><c>stdlib:epp(3)</c></seealso>.</p>
+ <seealso marker="stdlib:epp#encoding"><c>epp(3)</c></seealso>.</p>
</desc>
</func>
<func>
@@ -455,7 +455,7 @@ f.txt: {person, "kalle", 25}.
<p>The same as <c>eval/1</c>, but the variable bindings
<c><anno>Bindings</anno></c> are used in the evaluation. For information
about the variable bindings, see
- <seealso marker="stdlib:erl_eval"><c>stdlib:erl_eval(3)</c></seealso>.</p>
+ <seealso marker="stdlib:erl_eval"><c>erl_eval(3)</c></seealso>.</p>
</desc>
</func>
<func>
@@ -830,7 +830,7 @@ f.txt: {person, "kalle", 25}.
this module (<c>file</c>) for reading and writing data as the interfaces
provided here work with byte-oriented data. Using other (Unicode)
encodings makes the
- <seealso marker="stdlib:io"><c>stdlib:io(3)</c></seealso> functions
+ <seealso marker="stdlib:io"><c>io(3)</c></seealso> functions
<c>get_chars</c>, <c>get_line</c>, and <c>put_chars</c> more suitable,
as they can work with the full Unicode range.</p>
<p>If data is sent to an <c>io_device()</c> in a format that cannot be
@@ -847,7 +847,7 @@ f.txt: {person, "kalle", 25}.
that is,
<seealso marker="#read/2"><c>read/2</c></seealso> are
returned "as is". If module
- <seealso marker="stdlib:io"><c>stdlib:io(3)</c></seealso> is used for
+ <seealso marker="stdlib:io"><c>io(3)</c></seealso> is used for
writing, the file can only cope with Unicode characters up to code point
255 (the ISO Latin-1 range).</p>
</item>
@@ -861,7 +861,7 @@ f.txt: {person, "kalle", 25}.
the file lies beyond the ISO Latin-1 range (0..255), but failure occurs
if the data contains Unicode code points beyond that range. The file is
best read with the functions in the Unicode aware module
- <seealso marker="stdlib:io"><c>stdlib:io(3)</c></seealso>.</p>
+ <seealso marker="stdlib:io"><c>io(3)</c></seealso>.</p>
<p>Bytes written to the file by any means are translated to UTF-8 encoding
before being stored on the disk file.</p>
</item>
@@ -891,7 +891,7 @@ f.txt: {person, "kalle", 25}.
So a file can be analyzed in latin1 encoding for, for example, a BOM,
positioned beyond the BOM and then be set for the right encoding before
further reading. For functions identifying BOMs, see module
- <seealso marker="stdlib:unicode"><c>stdlib:unicode(3)</c></seealso>. </p>
+ <seealso marker="stdlib:unicode"><c>unicode(3)</c></seealso>. </p>
<p>This option is not allowed on <c>raw</c> files.</p>
</item>
<tag><c>ram</c></tag>
@@ -932,7 +932,7 @@ f.txt: {person, "kalle", 25}.
closed and the process itself is terminated.
An <c><anno>IoDevice</anno></c> returned from this call can be used
as an argument to the I/O functions (see
- <seealso marker="stdlib:io"><c>stdlib:io(3)</c></seealso>).</p>
+ <seealso marker="stdlib:io"><c>io(3)</c></seealso>).</p>
<note>
<p>In previous versions of <c>file</c>, modes were specified
as one of the atoms <c>read</c>, <c>write</c>, or
@@ -1055,7 +1055,7 @@ f.txt: {person, "kalle", 25}.
</taglist>
<p>The encoding of <c><anno>Filename</anno></c> can be set
by a comment as described in
- <seealso marker="stdlib:epp#encoding"><c>stdlib:epp(3)</c></seealso>.</p>
+ <seealso marker="stdlib:epp#encoding"><c>epp(3)</c></seealso>.</p>
</desc>
</func>
<func>
@@ -1128,7 +1128,7 @@ f.txt: {person, "kalle", 25}.
</taglist>
<p>The encoding of <c><anno>Filename</anno></c> can be set
by a comment as described in
- <seealso marker="stdlib:epp#encoding"><c>stdlib:epp(3)</c></seealso>.</p>
+ <seealso marker="stdlib:epp#encoding"><c>epp(3)</c></seealso>.</p>
</desc>
</func>
<func>
@@ -1389,7 +1389,7 @@ f.txt: {person, "kalle", 25}.
<c>{ok, <anno>FileInfo</anno>}</c> if successful, otherwise
<c>{error, <anno>Reason</anno>}</c>. <c><anno>FileInfo</anno></c>
is a record
- <c>file_info</c>, defined in the <c>Kernel</c> include file
+ <c>file_info</c>, defined in the Kernel include file
<c>file.hrl</c>. Include the following directive in the module
from which the function is called:</p>
<code type="none">
@@ -1552,7 +1552,7 @@ f.txt: {person, "kalle", 25}.
raw line-oriented reading.</p>
<p>If <c>encoding</c> is set to something else than <c>latin1</c>, the
<c>read_line/1</c> call fails if the data contains characters larger than 255,
- why module <seealso marker="stdlib:io"><c>stdlib:io(3)</c></seealso> is to be
+ why module <seealso marker="stdlib:io"><c>io(3)</c></seealso> is to be
preferred when reading such a file.</p>
<p>The function returns:</p>
<taglist>
@@ -1970,7 +1970,7 @@ f.txt: {person, "kalle", 25}.
<p>Changes file information. Returns <c>ok</c> if successful,
otherwise <c>{error, <anno>Reason</anno>}</c>.
<c><anno>FileInfo</anno></c> is a record
- <c>file_info</c>, defined in the <c>Kernel</c> include file
+ <c>file_info</c>, defined in the Kernel include file
<c>file.hrl</c>. Include the following directive in the module
from which the function is called:</p>
<code type="none">
diff --git a/lib/kernel/doc/src/gen_tcp.xml b/lib/kernel/doc/src/gen_tcp.xml
index 83242c2df8..08454b9832 100644
--- a/lib/kernel/doc/src/gen_tcp.xml
+++ b/lib/kernel/doc/src/gen_tcp.xml
@@ -216,7 +216,7 @@ do_recv(Sock, Bs) ->
time-out in milliseconds. Defaults to <c>infinity</c>.</p>
<note>
<p>The default values for options specified to <c>connect</c> can
- be affected by the <c>Kernel</c> configuration parameter
+ be affected by the Kernel configuration parameter
<c>inet_default_connect_options</c>. For details, see
<seealso marker="inet"><c>inet(3)</c></seealso>.</p>
</note>
@@ -293,7 +293,7 @@ do_recv(Sock, Bs) ->
<seealso marker="#accept/1"><c>accept/1,2</c></seealso>.</p>
<note>
<p>The default values for options specified to <c>listen</c> can
- be affected by the <c>Kernel</c> configuration parameter
+ be affected by the Kernel configuration parameter
<c>inet_default_listen_options</c>. For details, see
<seealso marker="inet"><c>inet(3)</c></seealso>.</p>
</note>
@@ -307,7 +307,7 @@ do_recv(Sock, Bs) ->
<type_desc variable="HttpPacket">See the description of
<c>HttpPacket</c> in
<seealso marker="erts:erlang#decode_packet/3"><c>erlang:decode_packet/3</c></seealso>
- in <c>ERTS</c>.
+ in ERTS.
</type_desc>
<desc>
<p>Receives a packet from a socket in passive
diff --git a/lib/kernel/doc/src/inet.xml b/lib/kernel/doc/src/inet.xml
index 8cc21bf3e2..3f4e3684f4 100644
--- a/lib/kernel/doc/src/inet.xml
+++ b/lib/kernel/doc/src/inet.xml
@@ -36,7 +36,7 @@
<seealso marker="erts:inet_cfg">ERTS User's Guide:
Inet Configuration</seealso> for more information about how to
configure an Erlang runtime system for IP communication.</p>
- <p>The following two <c>Kernel</c> configuration parameters affect the
+ <p>The following two Kernel configuration parameters affect the
behavior of all sockets opened on an Erlang node:</p>
<list type="bulleted">
<item><p><c>inet_default_connect_options</c> can contain a list of
@@ -48,7 +48,7 @@
<p>When <c>accept</c> is issued, the values of the listening socket options
are inherited. No such application variable is therefore needed for
<c>accept</c>.</p>
- <p>Using the <c>Kernel</c> configuration parameters above, one
+ <p>Using the Kernel configuration parameters above, one
can set default options for all TCP sockets on a node, but use this
with care. Options such as <c>{delay_send,true}</c> can be
specified in this way. The following is an example of starting an Erlang
@@ -95,7 +95,7 @@ fe80::204:acff:fe17:bf38
<datatype>
<name name="hostent"/>
<desc>
- <p>The record is defined in the <c>Kernel</c> include file
+ <p>The record is defined in the Kernel include file
<c>"inet.hrl"</c>.</p>
<p>Add the following directive to the module:</p>
<code>
@@ -391,7 +391,7 @@ get_tcpi_sacked(Sock) ->
<<_:28/binary,TcpiSacked:32/native,_/binary>> = Info,
TcpiSacked.]]></code>
<p>Preferably, you would check the machine type, the operating system,
- and the <c>Kernel</c> version before executing anything similar to
+ and the Kernel version before executing anything similar to
this code.</p>
</desc>
</func>
@@ -661,7 +661,7 @@ get_tcpi_sacked(Sock) ->
<p>The size of the user-level software buffer used by
the driver. Not to be confused with options <c>sndbuf</c>
and <c>recbuf</c>, which correspond to the
- <c>Kernel</c> socket buffers. It is recommended
+ Kernel socket buffers. It is recommended
to have <c>val(buffer) &gt;= max(val(sndbuf),val(recbuf))</c> to
avoid performance issues because of unnecessary copying.
<c>val(buffer)</c> is automatically set to the above
@@ -720,7 +720,7 @@ get_tcpi_sacked(Sock) ->
<p>The socket message queue is set to a busy
state when the amount of data on the message
queue reaches this limit. Notice that this limit only
- concerns data that has not yet reached the <c>ERTS</c> internal
+ concerns data that has not yet reached the ERTS internal
socket implementation. Defaults to 8 kB.</p>
<p>Senders of data to the socket are suspended if
either the socket message queue is busy or the socket
@@ -736,7 +736,7 @@ get_tcpi_sacked(Sock) ->
<tag><c>{high_watermark, Size}</c> (TCP/IP sockets)</tag>
<item>
<p>The socket is set to a busy state when the amount
- of data queued internally by the <c>ERTS</c> socket implementation
+ of data queued internally by the ERTS socket implementation
reaches this limit. Defaults to 8 kB.</p>
<p>Senders of data to the socket are suspended if
either the socket message queue is busy or the socket
@@ -816,7 +816,7 @@ get_tcpi_sacked(Sock) ->
socket message queue is set in a not busy state when
the amount of data queued in the message queue falls
below this limit. Notice that this limit only concerns data
- that has not yet reached the <c>ERTS</c> internal socket
+ that has not yet reached the ERTS internal socket
implementation. Defaults to 4 kB.</p>
<p>Senders that are suspended because of either a
busy message queue or a busy socket are resumed
@@ -834,7 +834,7 @@ get_tcpi_sacked(Sock) ->
<item>
<p>If the socket is in a busy state, the socket is
set in a not busy state when the amount of data
- queued internally by the <c>ERTS</c> socket implementation
+ queued internally by the ERTS socket implementation
falls below this limit. Defaults to 4 kB.</p>
<p>Senders that are suspended because of a
busy message queue or a busy socket are resumed
@@ -954,7 +954,7 @@ setcap cap_sys_admin,cap_sys_ptrace,cap_dac_read_search+epi beam.smp</code>
are returned with the format according to <c>HttpPacket</c>
described in
<seealso marker="erts:erlang#decode_packet/3">
- <c>erlang:decode_packet/3</c></seealso> in <c>ERTS</c>.
+ <c>erlang:decode_packet/3</c></seealso> in ERTS.
A socket in passive
mode returns <c>{ok, HttpPacket}</c> from <c>gen_tcp:recv</c>
while an active socket sends messages like
@@ -1130,7 +1130,7 @@ inet:setopts(Sock,[{raw,6,8,<<30:32/native>>}]),]]></code>
can respond differently to this kind of option
manipulation. Use with care.</p>
<p>Notice that the default options for TCP/IP sockets can be
- changed with the <c>Kernel</c> configuration parameters mentioned in
+ changed with the Kernel configuration parameters mentioned in
the beginning of this manual page.</p>
</desc>
</func>
diff --git a/lib/kernel/doc/src/init_stub.xml b/lib/kernel/doc/src/init_stub.xml
index df89b174ca..1297c8264d 100644
--- a/lib/kernel/doc/src/init_stub.xml
+++ b/lib/kernel/doc/src/init_stub.xml
@@ -34,6 +34,6 @@
<modulesummary>Coordination of system startup.</modulesummary>
<description>
<p>This module is moved to the
- <seealso marker="erts:init"><c>ERTS</c></seealso> application.</p>
+ <seealso marker="erts:init">ERTS</seealso> application.</p>
</description>
</erlref>
diff --git a/lib/kernel/doc/src/kernel_app.xml b/lib/kernel/doc/src/kernel_app.xml
index fb6421e1c5..df681a505f 100644
--- a/lib/kernel/doc/src/kernel_app.xml
+++ b/lib/kernel/doc/src/kernel_app.xml
@@ -31,12 +31,12 @@
<app>kernel</app>
<appsummary>The Kernel application.</appsummary>
<description>
- <p>The <c>Kernel</c> application has all the code necessary to run
+ <p>The Kernel application has all the code necessary to run
the Erlang runtime system: file servers, code servers,
and so on.</p>
- <p>The <c>Kernel</c> application is the first application started. It is
+ <p>The Kernel application is the first application started. It is
mandatory in the sense that the minimal system based on
- Erlang/OTP consists of <c>Kernel</c> and <c>STDLIB</c>. <c>Kernel</c>
+ Erlang/OTP consists of Kernel and STDLIB. Kernel
contains the following functional areas:</p>
<list type="bulleted">
<item>Start, stop, supervision, configuration, and distribution of applications</item>
@@ -53,13 +53,13 @@
<section>
<title>Error Logger Event Handlers</title>
<p>Two standard error logger event handlers are defined in
- the <c>Kernel</c> application. These are described in
+ the Kernel application. These are described in
<seealso marker="error_logger"><c>error_logger(3)</c></seealso>.</p>
</section>
<section>
<title>Configuration</title>
- <p>The following configuration parameters are defined for the <c>Kernel</c>
+ <p>The following configuration parameters are defined for the Kernel
application. For more information about configuration parameters,
see file <seealso marker="app"><c>app(4)</c></seealso>.</p>
<taglist>
@@ -162,8 +162,8 @@
depth to which terms are printed by the error logger event
handlers included in OTP. This
configuration parameter is used by the two event handlers
- defined by the <c>Kernel</c> application and the two event
- handlers in the <c>SASL</c> application.
+ defined by the Kernel application and the two event
+ handlers in the SASL application.
(If you have implemented your own error handlers, this configuration
parameter has no effect on them.)</p>
@@ -173,7 +173,7 @@
<c>~P</c> and <c>~W</c>, respectively, and <c>Depth</c> is
used as the depth parameter. For details, see
<seealso marker="stdlib:io#format/2"><c>io:format/2</c></seealso>
- in <c>STDLIB</c>.</p>
+ in STDLIB.</p>
<note><p>A reasonable starting value for <c>Depth</c> is
<c>30</c>. We recommend to test crashing various processes in your
@@ -241,7 +241,7 @@
<p>The name (string) of an Inet user configuration file. For details,
see section
<seealso marker="erts:inet_cfg"><c>Inet Configuration</c></seealso>
- in the <c>ERTS</c> User's Guide.</p>
+ in the ERTS User's Guide.</p>
</item>
<tag><c>net_setuptime = SetupTime</c></tag>
<item>
@@ -360,7 +360,7 @@ MaxT = TickTime + TickTime / 4</code>
<tag><c>start_timer = true | false</c></tag>
<item>
<p>Starts the <c>timer_server</c> if the parameter is
- <c>true</c> (see <seealso marker="stdlib:timer"><c>stdlib:timer(3)</c></seealso>).
+ <c>true</c> (see <seealso marker="stdlib:timer"><c>timer(3)</c></seealso>).
This parameter is to be set to <c>true</c> in an embedded system
using this service.</p>
<p>Defaults to <c>false</c>.</p>
diff --git a/lib/kernel/doc/src/net_kernel.xml b/lib/kernel/doc/src/net_kernel.xml
index 3c1b3d5190..4e2b0c69db 100644
--- a/lib/kernel/doc/src/net_kernel.xml
+++ b/lib/kernel/doc/src/net_kernel.xml
@@ -55,7 +55,7 @@ $ <input>erl -sname foobar</input></pre>
<seealso marker="erts:erl"><c>erl</c></seealso>.</p>
<p>Normally, connections are established automatically when
another node is referenced. This functionality can be disabled
- by setting <c>Kernel</c> configuration parameter
+ by setting Kernel configuration parameter
<c>dist_auto_connect</c> to <c>false</c>, see
<seealso marker="kernel_app"><c>kernel(6)</c></seealso>. In this case,
connections must be established explicitly by calling
@@ -146,7 +146,7 @@ $ <input>erl -sname foobar</input></pre>
are stopped. Two
option lists are considered the same if they contain the same
set of options.</p>
- <p>As from <c>Kernel</c> version 2.11.4, and <c>ERTS</c> version
+ <p>As from Kernel version 2.11.4, and ERTS version
5.5.4, the following is guaranteed:</p>
<list type="bulleted">
<item><p><c>nodeup</c> messages are delivered before delivery
@@ -156,13 +156,13 @@ $ <input>erl -sname foobar</input></pre>
messages from the remote node that have been passed
through the connection have been delivered.</p></item>
</list>
- <p>Notice that this is <em>not</em> guaranteed for <c>Kernel</c>
+ <p>Notice that this is <em>not</em> guaranteed for Kernel
versions before 2.11.4.</p>
- <p>As from <c>Kernel</c> version 2.11.4, subscriptions can also be
+ <p>As from Kernel version 2.11.4, subscriptions can also be
made before the <c>net_kernel</c> server is started, that is,
<c>net_kernel:monitor_nodes/[1,2]</c> does not return
<c>ignored</c>.</p>
- <p>As from <c>Kernel</c> version 2.13, and <c>ERTS</c> version
+ <p>As from Kernel version 2.13, and ERTS version
5.7, the following is guaranteed:</p>
<list type="bulleted">
<item><p><c>nodeup</c> messages are delivered after the
@@ -172,7 +172,7 @@ $ <input>erl -sname foobar</input></pre>
corresponding node has disappeared in results from
<c>erlang:nodes/X</c>.</p></item>
</list>
- <p>Notice that this is <em>not</em> guaranteed for <c>Kernel</c>
+ <p>Notice that this is <em>not</em> guaranteed for Kernel
versions before 2.13.</p>
<p>The format of the node status change messages depends on
<c><anno>Options</anno></c>. If <c><anno>Options</anno></c> is
diff --git a/lib/kernel/doc/src/notes.xml b/lib/kernel/doc/src/notes.xml
index 3d35f6f57f..9e9be3f661 100644
--- a/lib/kernel/doc/src/notes.xml
+++ b/lib/kernel/doc/src/notes.xml
@@ -3482,7 +3482,7 @@
types (for instance, <c>ensure_loaded/1</c> now only
accepts an atom as documented; it used to accept a string
too).</p>
- <p><c>Dialyzer</c> will generally emit warnings for any
+ <p>Dialyzer will generally emit warnings for any
calls that use undocumented argument types. Even if the
call happens to still work in R12B, you should correct
your code. A future release will adhere to the
diff --git a/lib/kernel/doc/src/rpc.xml b/lib/kernel/doc/src/rpc.xml
index 8cad9fe4fc..5944e9321a 100644
--- a/lib/kernel/doc/src/rpc.xml
+++ b/lib/kernel/doc/src/rpc.xml
@@ -320,7 +320,7 @@
<fsummary>Information about a process.</fsummary>
<desc>
<p>Location transparent version of the BIF
- <seealso marker="erts:erlang#process_info/1"><c>erlang:process_info/1</c></seealso> in <c>ERTS</c>.</p>
+ <seealso marker="erts:erlang#process_info/1"><c>erlang:process_info/1</c></seealso> in ERTS.</p>
</desc>
</func>
@@ -330,7 +330,7 @@
<fsummary>Information about a process.</fsummary>
<desc>
<p>Location transparent version of the BIF
- <seealso marker="erts:erlang#process_info/2"><c>erlang:process_info/2</c></seealso> in <c>ERTS</c>.</p>
+ <seealso marker="erts:erlang#process_info/2"><c>erlang:process_info/2</c></seealso> in ERTS.</p>
</desc>
</func>
diff --git a/lib/kernel/doc/src/zlib_stub.xml b/lib/kernel/doc/src/zlib_stub.xml
index b111581b10..9ab9c4eb62 100644
--- a/lib/kernel/doc/src/zlib_stub.xml
+++ b/lib/kernel/doc/src/zlib_stub.xml
@@ -34,6 +34,6 @@
<modulesummary>Zlib compression interface.</modulesummary>
<description>
<p>This module is moved to the
- <seealso marker="erts:zlib"><c>ERTS</c></seealso> application.</p>
+ <seealso marker="erts:zlib">ERTS</seealso> application.</p>
</description>
</erlref>
diff --git a/lib/kernel/src/os.erl b/lib/kernel/src/os.erl
index 05bbf1069e..f8519d3a5e 100644
--- a/lib/kernel/src/os.erl
+++ b/lib/kernel/src/os.erl
@@ -254,7 +254,19 @@ mk_cmd(_,Cmd) ->
{"/bin/sh -s unix:cmd", [out],
%% We insert a new line after the command, in case the command
%% contains a comment character.
- ["(", unicode:characters_to_binary(Cmd), "\n); echo \"\^D\"\n"],
+ %%
+ %% The </dev/null closes stdin, which means that programs
+ %% that use a closed stdin as an termination indicator works.
+ %% An example of such a program is 'more'.
+ %%
+ %% The "echo ^D" is used to indicate that the program has executed
+ %% and we should return any output we have gotten. We cannot use
+ %% termination of the child or closing of stdin/stdout as then
+ %% starting background jobs from os:cmd will block os:cmd.
+ %%
+ %% I tried changing this to be "better", but got bombarded with
+ %% backwards incompatibility bug reports, so leave this as it is.
+ ["(", unicode:characters_to_binary(Cmd), "\n) </dev/null; echo \"\^D\"\n"],
<<$\^D>>}.
validate(Atom) when is_atom(Atom) ->
diff --git a/lib/kernel/test/os_SUITE.erl b/lib/kernel/test/os_SUITE.erl
index 19ab3713a1..e76d6ec482 100644
--- a/lib/kernel/test/os_SUITE.erl
+++ b/lib/kernel/test/os_SUITE.erl
@@ -25,7 +25,7 @@
-export([space_in_cwd/1, quoting/1, cmd_unicode/1, space_in_name/1, bad_command/1,
find_executable/1, unix_comment_in_command/1, deep_list_command/1,
large_output_command/1, background_command/0, background_command/1,
- message_leak/1, perf_counter_api/1]).
+ message_leak/1, close_stdin/0, close_stdin/1, perf_counter_api/1]).
-include_lib("common_test/include/ct.hrl").
@@ -37,7 +37,7 @@ all() ->
[space_in_cwd, quoting, cmd_unicode, space_in_name, bad_command,
find_executable, unix_comment_in_command, deep_list_command,
large_output_command, background_command, message_leak,
- perf_counter_api].
+ close_stdin, perf_counter_api].
groups() ->
[].
@@ -54,7 +54,8 @@ init_per_group(_GroupName, Config) ->
end_per_group(_GroupName, Config) ->
Config.
-init_per_testcase(background_command, Config) ->
+init_per_testcase(TC, Config)
+ when TC =:= background_command; TC =:= close_stdin ->
case os:type() of
{win32, _} ->
{skip,"Should not work on windows"};
@@ -294,7 +295,7 @@ message_leak(_Config) ->
case os:type() of
{unix, _} ->
- os:cmd("while true; do echo hello; done&"),
+ os:cmd("for i in $(seq 1 100); do echo hello; done&"),
[] = receive_all();
_ ->
ok % Cannot background on non-unix
@@ -302,6 +303,16 @@ message_leak(_Config) ->
process_flag(trap_exit, false).
+%% Test that os:cmd closes stdin of the program that is executed
+close_stdin() ->
+ [{timetrap, {seconds, 5}}].
+close_stdin(Config) ->
+ DataDir = proplists:get_value(data_dir, Config),
+ Fds = filename:join(DataDir, "my_fds"),
+
+ "-1" = os:cmd(Fds).
+
+
%% Test that the os:perf_counter api works as expected
perf_counter_api(_Config) ->
diff --git a/lib/kernel/test/os_SUITE_data/Makefile.src b/lib/kernel/test/os_SUITE_data/Makefile.src
index 912d0cbcb1..f83f781411 100644
--- a/lib/kernel/test/os_SUITE_data/Makefile.src
+++ b/lib/kernel/test/os_SUITE_data/Makefile.src
@@ -3,7 +3,7 @@ LD = @LD@
CFLAGS = @CFLAGS@ -I@erl_include@ @DEFS@
CROSSLDFLAGS = @CROSSLDFLAGS@
-PROGS = my_echo@exe@
+PROGS = my_echo@exe@ my_fds@exe@
all: $(PROGS)
@@ -12,3 +12,9 @@ my_echo@exe@: my_echo@obj@
my_echo@obj@: my_echo.c
$(CC) -c -o my_echo@obj@ $(CFLAGS) my_echo.c
+
+my_fds@exe@: my_fds@obj@
+ $(LD) $(CROSSLDFLAGS) -o my_fds my_fds@obj@ @LIBS@
+
+my_fds@obj@: my_fds.c
+ $(CC) -c -o my_fds@obj@ $(CFLAGS) my_fds.c
diff --git a/lib/kernel/test/os_SUITE_data/my_fds.c b/lib/kernel/test/os_SUITE_data/my_fds.c
new file mode 100644
index 0000000000..704a4d1e1d
--- /dev/null
+++ b/lib/kernel/test/os_SUITE_data/my_fds.c
@@ -0,0 +1,9 @@
+#include <stdio.h>
+
+int
+main(int argc, char** argv)
+{
+ char buff[1];
+ int res = read(stdin, buff, 1);
+ printf("%d", res);
+}
diff --git a/lib/mnesia/doc/src/Mnesia_chap1.xml b/lib/mnesia/doc/src/Mnesia_chap1.xml
index 9dfeb5efe4..035e934ed2 100644
--- a/lib/mnesia/doc/src/Mnesia_chap1.xml
+++ b/lib/mnesia/doc/src/Mnesia_chap1.xml
@@ -32,38 +32,38 @@
<rev>C</rev>
<file>Mnesia_chap1.xml</file>
</header>
- <p>The <c>Mnesia</c> application provides a heavy duty real-time
+ <p>The Mnesia application provides a heavy duty real-time
distributed database.</p>
<section>
<title>Scope</title>
<p>This User's Guide describes how to
- build <c>Mnesia</c> database applications, and how to integrate
- and use the <c>Mnesia</c> database management system with
+ build Mnesia database applications, and how to integrate
+ and use the Mnesia database management system with
OTP. Programming constructs are described, and numerous
programming examples are included to illustrate the use of
- <c>Mnesia</c>.</p>
+ Mnesia.</p>
<p>This User's Guide is organized as follows:</p>
<list type="bulleted">
<item><seealso marker="Mnesia_overview">Mnesia</seealso>
provides an introduction to
- <c>Mnesia</c>.
+ Mnesia.
</item>
<item><seealso marker="Mnesia_chap2">Getting Started</seealso>
- introduces <c>Mnesia</c> with an example database. Examples
+ introduces Mnesia with an example database. Examples
are included how to start an Erlang session, specify a
- <c>Mnesia</c> database directory, initialize a database
- schema, start <c>Mnesia</c>, and create tables. Initial
+ Mnesia database directory, initialize a database
+ schema, start Mnesia, and create tables. Initial
prototyping of record definitions is also discussed.
</item>
<item><seealso marker="Mnesia_chap3">Build a Mnesia
Database</seealso> more formally describes the steps
- introduced in the previous section, namely the <c>Mnesia</c>
- functions that define a database schema, start <c>Mnesia</c>,
+ introduced in the previous section, namely the Mnesia
+ functions that define a database schema, start Mnesia,
and create the required tables.
</item>
<item><seealso marker="Mnesia_chap4">Transactions and Other Access Contexts</seealso>
- describes the transactions properties that make <c>Mnesia</c> into
+ describes the transactions properties that make Mnesia into
a fault tolerant, real-time distributed database management
system. This section also describes the concept of locking
to ensure consistency in tables, and "dirty
@@ -76,16 +76,16 @@
features include indexing, checkpoints, distribution and fault
tolerance, disc-less nodes, replication manipulation, local
content tables, concurrency, and object-based programming in
- <c>Mnesia</c>.
+ Mnesia.
</item>
<item><seealso marker="Mnesia_chap7">Mnesia System
Information</seealso> describes the files contained in the
- <c>Mnesia</c> database directory, database configuration data,
+ Mnesia database directory, database configuration data,
core and table dumps, as well as the important subject of
backup, fall-back, and disaster recovery principles.
</item>
<item><seealso marker="Mnesia_chap8">Combine Mnesia with
- SNMP</seealso> is a short section that outlines <c>Mnesia</c>
+ SNMP</seealso> is a short section that outlines Mnesia
integrated with SNMP.
</item>
<item><seealso marker="Mnesia_App_A">Appendix A: Backup
diff --git a/lib/mnesia/doc/src/Mnesia_chap8.xml b/lib/mnesia/doc/src/Mnesia_chap8.xml
index f1a469e315..4a2eed84d7 100644
--- a/lib/mnesia/doc/src/Mnesia_chap8.xml
+++ b/lib/mnesia/doc/src/Mnesia_chap8.xml
@@ -51,11 +51,11 @@
</item>
</list>
<p>All these approaches have different advantages and
- disadvantages. <c>Mnesia</c> applications can easily be opened to
+ disadvantages. Mnesia applications can easily be opened to
the SNMP protocol. A direct 1-to-1 mapping can be established
- between <c>Mnesia</c> tables and SNMP tables. This means
- that a <c>Mnesia</c> table can be configured to be <em>both</em>
- a <c>Mnesia</c> table and an SNMP table. A number of functions to
+ between Mnesia tables and SNMP tables. This means
+ that a Mnesia table can be configured to be <em>both</em>
+ a Mnesia table and an SNMP table. A number of functions to
control this behavior are described in the Reference Manual.</p>
</section>
</chapter>
diff --git a/lib/mnesia/doc/src/Mnesia_overview.xml b/lib/mnesia/doc/src/Mnesia_overview.xml
index d2d597b85d..63f2309284 100644
--- a/lib/mnesia/doc/src/Mnesia_overview.xml
+++ b/lib/mnesia/doc/src/Mnesia_overview.xml
@@ -39,14 +39,14 @@
high level of fault tolerance that is required in many nonstop
systems, combined with requirements on the DBMS to run in the same
address space as the application, have led us to implement a new
- DBMS, called <c>Mnesia</c>.</p>
- <p><c>Mnesia</c> is implemented in, and tightly connected to Erlang.
+ DBMS, called Mnesia.</p>
+ <p>Mnesia is implemented in, and tightly connected to Erlang.
It provides the functionality that is necessary for the
implementation of fault tolerant telecommunications systems.</p>
- <p><c>Mnesia</c> is a multiuser distributed DBMS specially made for
+ <p>Mnesia is a multiuser distributed DBMS specially made for
industrial telecommunications applications written in Erlang,
which is also the intended target language.
- <c>Mnesia</c> tries to address all the data
+ Mnesia tries to address all the data
management issues required for typical telecommunications systems.
It has a number of features that are not normally found in traditional
databases.</p>
@@ -54,7 +54,7 @@
from the features provided by traditional DBMSs. The applications now
implemented in Erlang need a mixture of a broad range
of features, which generally are not satisfied by traditional DBMSs.
- <c>Mnesia</c> is designed with requirements like the following in
+ Mnesia is designed with requirements like the following in
mind:</p>
<list type="ordered">
<item>Fast real-time key/value lookup
@@ -71,9 +71,9 @@
<item>Complex objects
</item>
</list>
- <p><c>Mnesia</c> is designed with the typical data management problems
- of telecommunications applications in mind. This sets <c>Mnesia</c>
- apart from most other DBMS. Hence <c>Mnesia</c>
+ <p>Mnesia is designed with the typical data management problems
+ of telecommunications applications in mind. This sets Mnesia
+ apart from most other DBMS. Hence Mnesia
combines many concepts found in traditional databases such as
transactions and queries with concepts found in data management
systems for telecommunications applications, for example:</p>
@@ -86,7 +86,7 @@
suspending it.
</item>
</list>
- <p><c>Mnesia</c> is also interesting because of its tight coupling to
+ <p>Mnesia is also interesting because of its tight coupling to
Erlang, thus almost turning Erlang into a database programming
language. This has many benefits, the foremost is that
the impedance mismatch between the data format used by the DBMS
@@ -97,7 +97,7 @@
<title>Mnesia Database Management System (DBMS)</title>
<section>
<title>Features</title>
- <p><c>Mnesia</c> contains the following features that combine to
+ <p>Mnesia contains the following features that combine to
produce a fault-tolerant, distributed DBMS written in Erlang:
</p>
<list type="bulleted">
@@ -118,7 +118,7 @@
functions can be called within one transaction.
</item>
<item>Several transactions can run concurrently, and their execution
- is fully synchronized by the DBMS. <c>Mnesia</c> ensures that no
+ is fully synchronized by the DBMS. Mnesia ensures that no
two processes manipulate data simultaneously.
</item>
<item>Transactions can be assigned the property of being executed on
@@ -132,29 +132,29 @@
<section>
<title>Add-On Application</title>
- <p>Query List Comprehension (QLC) can be used with <c>Mnesia</c>
+ <p>Query List Comprehension (QLC) can be used with Mnesia
to produce specialized functions that enhance the operational
- ability of <c>Mnesia</c>. QLC has its own documentation as part
+ ability of Mnesia. QLC has its own documentation as part
of the OTP documentation set. The main features of QLC
- when used with <c>Mnesia</c> are as follows:</p>
+ when used with Mnesia are as follows:</p>
<list type="bulleted">
- <item>QLC can optimize the query compiler for the <c>Mnesia</c>
+ <item>QLC can optimize the query compiler for the Mnesia
DBMS, essentially making the DBMS more efficient.
</item>
<item>QLC can be used as a database programming
- language for <c>Mnesia</c>. It includes a notation called "list
+ language for Mnesia. It includes a notation called "list
comprehensions" and can be used to make complex database
queries over a set of tables.
</item>
</list>
<p>For information about QLC, see the
<seealso marker="stdlib:qlc">qlc</seealso> manual page
- in <c>STDLIB</c>.</p>
+ in STDLIB.</p>
</section>
<section>
<title>When to Use Mnesia</title>
- <p>Use <c>Mnesia</c> with the following types of applications:</p>
+ <p>Use Mnesia with the following types of applications:</p>
<list type="bulleted">
<item>Applications that need to replicate data.
</item>
@@ -166,7 +166,7 @@
<item>Applications that use soft real-time characteristics.
</item>
</list>
- <p><c>Mnesia</c> is not as appropriate with the
+ <p>Mnesia is not as appropriate with the
following types of applications:</p>
<list type="bulleted">
<item>Programs that process plain text or binary data files.
@@ -176,14 +176,14 @@
library module <c>dets</c>, which is a disc-based version
of the module <c>ets</c>. For information about <c>dets</c>,
see the <seealso marker="stdlib:dets">dets</seealso>
- manual page in <c>STDLIB</c>.
+ manual page in STDLIB.
</item>
<item>Applications that need disc logging facilities.
Those applications can
use the module <c>disk_log</c> by preference. For
information about <c>disk_log</c>, see the
<seealso marker="kernel:disk_log">disk_log</seealso>
- manual page in <c>Kernel</c>.
+ manual page in Kernel.
</item>
<item>Hard real-time systems.
</item>
diff --git a/lib/mnesia/doc/src/mnesia.xml b/lib/mnesia/doc/src/mnesia.xml
index b35214cde9..621b6047ee 100644
--- a/lib/mnesia/doc/src/mnesia.xml
+++ b/lib/mnesia/doc/src/mnesia.xml
@@ -37,7 +37,7 @@
<description>
<p>The following are some of the most important and attractive
- capabilities provided by <c>Mnesia</c>:</p>
+ capabilities provided by Mnesia:</p>
<list type="bulleted">
<item>A relational/object hybrid data model that is suitable
for telecommunications applications.
@@ -62,15 +62,15 @@
reconfigured at runtime without stopping the system.
</item>
</list>
- <p>This Reference Manual describes the <c>Mnesia</c> API. This
- includes functions that define and manipulate <c>Mnesia</c>
+ <p>This Reference Manual describes the Mnesia API. This
+ includes functions that define and manipulate Mnesia
tables.</p>
<p>All functions in this Reference Manual can be used in any
combination with queries using the list comprehension notation.
For information about the query notation, see the
<seealso marker="stdlib:qlc">qlc</seealso>
- manual page in <c>STDLIB</c>.</p>
- <p>Data in <c>Mnesia</c> is organized as a set of tables. Each table
+ manual page in STDLIB.</p>
+ <p>Data in Mnesia is organized as a set of tables. Each table
has a name that must be an atom. Each table is made up of
Erlang records. The user is responsible for the record
definitions. Each table also has a set of properties. The
@@ -121,14 +121,14 @@
<item>
<p><c>index</c>. This is a list of attribute names, or
integers, which specify the tuple positions on which
- <c>Mnesia</c> is to build and maintain an extra index
+ Mnesia is to build and maintain an extra index
table.</p>
</item>
<item>
<p><c>local_content</c>. When an application requires
tables whose contents are local to each node,
<c>local_content</c> tables can be used. The table name
- is known to all <c>Mnesia</c> nodes, but its content is
+ is known to all Mnesia nodes, but its content is
unique on each node. This means that access to such a table
must be done locally. Set field <c>local_content</c> to
<c>true</c> to enable the <c>local_content</c>
@@ -143,7 +143,7 @@
avoid inconsistencies because of network splits.</p>
</item>
<item>
- <p><c>snmp</c>. Each (set-based) <c>Mnesia</c> table can be
+ <p><c>snmp</c>. Each (set-based) Mnesia table can be
automatically turned into a Simple Network Management
Protocol (SNMP) ordered table as well.
This property specifies the types of the SNMP keys.</p>
@@ -174,7 +174,7 @@
copy of each modified record during the transaction. During
iteration, that is, <c>mnesia:fold[lr]/4</c>,
<c>mnesia:next/2</c>, <c>mnesia:prev/2</c>, and
- <c>mnesia:snmp_get_next_index/2</c>, <c>Mnesia</c>
+ <c>mnesia:snmp_get_next_index/2</c>, Mnesia
compensates for every written or deleted record, which can
reduce the performance.</p>
<p>If possible, avoid writing or deleting records in the same
@@ -188,7 +188,7 @@
<desc>
<p>Makes the transaction silently
return the tuple <c>{aborted, Reason}</c>.
- Termination of a <c>Mnesia</c> transaction means that
+ Termination of a Mnesia transaction means that
an exception is thrown to an enclosing <c>catch</c>.
Thus, the expression <c>catch mnesia:abort(x)</c> does
not terminate the transaction.</p>
@@ -324,7 +324,7 @@
<c>mnesia:ets</c>. Argument <c>AccessMod</c>
is the name of a callback module, which implements the
<c>mnesia_access</c> behavior.</p>
- <p><c>Mnesia</c> forwards calls to the following functions:</p>
+ <p>Mnesia forwards calls to the following functions:</p>
<list type="bulleted">
<item>mnesia:lock/2 (read_lock_table/1, write_lock_table/1)
</item>
@@ -391,15 +391,15 @@
</item>
</list>
<p><c>ActivityId</c> is a record that represents the identity
- of the enclosing <c>Mnesia</c> activity. The first field
+ of the enclosing Mnesia activity. The first field
(obtained with <c>element(1, ActivityId)</c>) contains an
atom, which can be interpreted as the activity type:
<c>ets</c>, <c>async_dirty</c>, <c>sync_dirty</c>, or
<c>tid</c>. <c>tid</c> means that the activity is a
transaction. The structure of the rest of the identity
- record is internal to <c>Mnesia</c>.</p>
+ record is internal to Mnesia.</p>
<p><c>Opaque</c> is an opaque data structure that is internal
- to <c>Mnesia</c>.</p>
+ to Mnesia.</p>
</desc>
</func>
<func>
@@ -458,7 +458,7 @@ mnesia:add_table_index(person, age)</code>
<desc>
<marker id="async_dirty"></marker>
<p>Calls the <c>Fun</c> in a context that is not protected by
- a transaction. The <c>Mnesia</c> function calls performed in
+ a transaction. The Mnesia function calls performed in
the <c>Fun</c> are mapped to the corresponding dirty
functions. This still involves logging, replication, and
subscriptions, but there is no locking, local transaction
@@ -467,7 +467,7 @@ mnesia:add_table_index(person, age)</code>
for normal <c>mnesia:dirty_*</c> operations, the operations
are performed semi-asynchronously. For details, see
<c>mnesia:activity/4</c> and the User's Guide.</p>
- <p>The <c>Mnesia</c> tables can be manipulated without
+ <p>The Mnesia tables can be manipulated without
using transactions. This has some serious disadvantages, but
is considerably faster, as the transaction manager is not
involved and no locks are set. A dirty operation does,
@@ -480,7 +480,7 @@ mnesia:add_table_index(person, age)</code>
read records dirty than within a transaction.</p>
<p>Depending on the application, it can be a good idea to use
the dirty functions for certain operations. Almost all
- <c>Mnesia</c> functions that can be called within
+ Mnesia functions that can be called within
transactions have a dirty equivalent, which is much more
efficient.</p>
<p>However, notice that there is a risk that the database can
@@ -497,7 +497,7 @@ mnesia:add_table_index(person, age)</code>
<fsummary>Backs up all tables in the database.</fsummary>
<desc>
<marker id="backup"></marker>
- <p>Activates a new checkpoint covering all <c>Mnesia</c> tables,
+ <p>Activates a new checkpoint covering all Mnesia tables,
including the schema, with maximum degree of redundancy, and
performs a backup using <c>backup_checkpoint/2/3</c>. The
default value of the backup callback module <c>BackupMod</c>
@@ -529,16 +529,16 @@ mnesia:add_table_index(person, age)</code>
<taglist>
<tag><c>extra_db_nodes</c></tag>
<item>
- <p><c>Value</c> is a list of nodes that <c>Mnesia</c>
+ <p><c>Value</c> is a list of nodes that Mnesia
is to try to connect to. <c>ReturnValue</c> is those
- nodes in <c>Value</c> that <c>Mnesia</c> is connected
+ nodes in <c>Value</c> that Mnesia is connected
to.</p>
<p>Notice that this function must only be used to connect
to newly started RAM nodes (N.D.R.S.N.) with an empty
schema. If, for example, this function is used after
the network has been partitioned, it can lead to
inconsistent tables.</p>
- <p>Notice that <c>Mnesia</c> can be connected to other
+ <p>Notice that Mnesia can be connected to other
nodes than those returned in <c>ReturnValue</c>.</p>
</item>
<tag><c>dc_dump_limit</c></tag>
@@ -548,7 +548,7 @@ mnesia:add_table_index(person, age)</code>
Configuration Parameters</seealso>. <c>ReturnValue</c>
is the new value. Notice that this configuration
parameter is not persistent. It is lost when
- <c>Mnesia</c> has stopped.</p>
+ Mnesia has stopped.</p>
</item>
</taglist>
</desc>
@@ -562,9 +562,9 @@ mnesia:add_table_index(person, age)</code>
<c>read_write</c> but it can also be set to the atom
<c>read_only</c>. If <c>AccessMode</c> is set to
<c>read_only</c>, updates to the table cannot be
- performed. At startup, <c>Mnesia</c> always loads
+ performed. At startup, Mnesia always loads
<c>read_only</c> tables locally regardless of when and if
- <c>Mnesia</c> is terminated on other nodes.</p>
+ Mnesia is terminated on other nodes.</p>
</desc>
</func>
<func>
@@ -620,13 +620,13 @@ mnesia:change_table_copy_type(person, node(), disc_copies)</code>
<desc>
<marker id="create_schema"></marker>
<p>Creates a new database on disc. Various files are
- created in the local <c>Mnesia</c> directory of each node.
+ created in the local Mnesia directory of each node.
Notice that the directory must be unique for each node.
Two nodes must never share the same directory. If possible,
use a local disc device to improve performance.</p>
<p><c>mnesia:create_schema/1</c> fails if any of the
Erlang nodes given as <c>DiscNodes</c> are not alive, if
- <c>Mnesia</c> is running on any of the nodes, or if any
+ Mnesia is running on any of the nodes, or if any
of the nodes already have a schema. Use
<c>mnesia:delete_schema/1</c> to get rid of old faulty
schemas.</p>
@@ -638,10 +638,10 @@ mnesia:change_table_copy_type(person, node(), disc_copies)</code>
</func>
<func>
<name>create_table(Name, TabDef) -> {atomic, ok} | {aborted, Reason}</name>
- <fsummary>Creates a <c>Mnesia</c> table called <c>Name</c>with properties as described by argument <c>TabDef</c>.</fsummary>
+ <fsummary>Creates a Mnesia table called <c>Name</c>with properties as described by argument <c>TabDef</c>.</fsummary>
<desc>
<marker id="create_table"></marker>
- <p>Creates a <c>Mnesia</c> table called
+ <p>Creates a Mnesia table called
<c>Name</c> according to argument <c>TabDef</c>. This
list must be a list of <c>{Item, Value}</c> tuples,
where the following values are allowed:</p>
@@ -652,8 +652,8 @@ mnesia:change_table_copy_type(person, node(), disc_copies)</code>
set to the atom <c>read_only</c>. If <c>AccessMode</c>
is set to <c>read_only</c>, updates to the table
cannot be performed.</p>
- <p>At startup, <c>Mnesia</c> always loads <c>read_only</c>
- table locally regardless of when and if <c>Mnesia</c> is
+ <p>At startup, Mnesia always loads <c>read_only</c>
+ table locally regardless of when and if Mnesia is
terminated on other nodes. This argument returns the
access mode of the table. The access mode can be
<c>read_only</c> or <c>read_write</c>.</p>
@@ -693,7 +693,7 @@ mnesia:change_table_copy_type(person, node(), disc_copies)</code>
<item>
<p><c>{index, Intlist}</c>, where
<c>Intlist</c> is a list of attribute names (atoms) or
- record fields for which <c>Mnesia</c> is to build and
+ record fields for which Mnesia is to build and
maintain an extra index table. The <c>qlc</c> query
compiler <em>may</em> be able to optimize queries
if there are indexes available.</p>
@@ -735,10 +735,10 @@ mnesia:change_table_copy_type(person, node(), disc_copies)</code>
<c>mnesia:create_table/2</c>, the table is immediately
accessible by SNMP. Therefore applications that use
SNMP to manipulate and control the system can be
- designed easily, since <c>Mnesia</c> provides a
+ designed easily, since Mnesia provides a
direct mapping between the logical tables that make up
an SNMP control application and the physical data that
- makes up a <c>Mnesia</c> table.</p>
+ makes up a Mnesia table.</p>
</item>
<item>
<p><c>{storage_properties, [{Backend, Properties}]</c>
@@ -746,7 +746,7 @@ mnesia:change_table_copy_type(person, node(), disc_copies)</code>
<c>Backend</c> can currently be <c>ets</c> or <c>dets</c>.
<c>Properties</c> is a list of options sent to the
back end storage during table creation. <c>Properties</c>
- cannot contain properties already used by <c>Mnesia</c>,
+ cannot contain properties already used by Mnesia,
such as <c>type</c> or <c>named_table</c>.</p>
<p>For example:</p>
<code type="none">
@@ -776,7 +776,7 @@ mnesia:create_table(table, [{ram_copies, [node()]}, {disc_only_copies, nodes()},
mnesia:create_table(person,
[{ram_copies, [N1, N2]},
{attributes, record_info(fields, person)}]).</code>
- <p>If it is required that <c>Mnesia</c> must build and
+ <p>If it is required that Mnesia must build and
maintain an extra index table on attribute <c>address</c>
of all the <c>person</c> records that are inserted in the
table, the following code would be issued:</p>
@@ -819,8 +819,8 @@ mnesia:create_table(person,
When the last replica is deleted with this
function, the table disappears entirely.</p>
<p>This function can also be used to delete a replica of
- the table named <c>schema</c>. The <c>Mnesia</c> node is
- then removed. Notice that <c>Mnesia</c> must be
+ the table named <c>schema</c>. The Mnesia node is
+ then removed. Notice that Mnesia must be
stopped on the node first.</p>
</desc>
</func>
@@ -891,9 +891,9 @@ mnesia:create_table(person,
<c>mnesia:create_schema/1</c>.
<c>mnesia:delete_schema/1</c> fails if any of the Erlang
nodes given as <c>DiscNodes</c> are not alive, or if
- <c>Mnesia</c> is running on any of the nodes.</p>
+ Mnesia is running on any of the nodes.</p>
<p>After the database is deleted, it can still be possible
- to start <c>Mnesia</c> as a disc-less node. This depends
+ to start Mnesia as a disc-less node. This depends
on how configuration parameter <c>schema_location</c> is
set.</p>
<warning>
@@ -1100,7 +1100,7 @@ mnesia:create_table(person,
<name>dirty_update_counter(Tab, Key, Incr) -> NewVal | exit({aborted, Reason})</name>
<fsummary>Dirty update of a counter record.</fsummary>
<desc>
- <p><c>Mnesia</c> has no special counter records. However,
+ <p>Mnesia has no special counter records. However,
records of the form <c>{Tab, Key, Integer}</c> can be used
as (possibly disc-resident) counters when <c>Tab</c> is a
<c>set</c>. This function updates a counter with a positive
@@ -1147,7 +1147,7 @@ mnesia:create_table(person,
<desc>
<marker id="dump_log"></marker>
<p>Performs a user-initiated dump of the local log file.
- This is usually not necessary, as <c>Mnesia</c> by default
+ This is usually not necessary, as Mnesia by default
manages this automatically. See configuration parameters
<seealso marker="#dump_log_time_threshold">dump_log_time_threshold</seealso>
and
@@ -1172,7 +1172,7 @@ mnesia:create_table(person,
<fsummary>Dumps local tables into a text file.</fsummary>
<desc>
<marker id="dump_to_textfile"></marker>
- <p>Dumps all local tables of a <c>Mnesia</c> system into a
+ <p>Dumps all local tables of a Mnesia system into a
text file, which can be edited (by a normal text editor)
and then be reloaded with
<c>mnesia:load_textfile/1</c>. Only use this function for
@@ -1182,10 +1182,10 @@ mnesia:create_table(person,
</func>
<func>
<name>error_description(Error) -> String</name>
- <fsummary>Returns a string describing a particular <c>Mnesia</c> error.</fsummary>
+ <fsummary>Returns a string describing a particular Mnesia error.</fsummary>
<desc>
<marker id="error_description"></marker>
- <p>All <c>Mnesia</c> transactions, including all the schema
+ <p>All Mnesia transactions, including all the schema
update functions, either return value <c>{atomic, Val}</c>
or the tuple <c>{aborted, Reason}</c>. <c>Reason</c> can
be either of the atoms in the following list. The
@@ -1264,8 +1264,8 @@ mnesia:create_table(person,
<desc>
<marker id="ets"></marker>
<p>Calls the <c>Fun</c> in a raw context that is not protected by
- a transaction. The <c>Mnesia</c> function call is performed in
- the <c>Fun</c> and performed directly on the local <c>ets</c>
+ a transaction. The Mnesia function call is performed in
+ the <c>Fun</c> and performed directly on the local ETS
tables on the assumption that the local storage type is
<c>ram_copies</c> and the tables are not replicated to other
nodes. Subscriptions are not triggered and checkpoints are
@@ -1321,13 +1321,13 @@ mnesia:create_table(person,
<fsummary>Forces a table to be loaded into the system.</fsummary>
<desc>
<marker id="force_load_table"></marker>
- <p>The <c>Mnesia</c> algorithm for table load can lead to a
+ <p>The Mnesia algorithm for table load can lead to a
situation where a table cannot be loaded. This situation
- occurs when a node is started and <c>Mnesia</c> concludes, or
+ occurs when a node is started and Mnesia concludes, or
suspects, that another copy of the table was active after
this local copy became inactive because of a system crash.</p>
<p>If this situation is not acceptable, this function can be
- used to override the strategy of the <c>Mnesia</c> table
+ used to override the strategy of the Mnesia table
load algorithm. This can lead to a situation where some
transaction effects are lost with an inconsistent database as
result, but for some applications high availability is more
@@ -1402,9 +1402,9 @@ mnesia:create_table(person,
<desc>
<marker id="info"></marker>
<p>Prints system information on the terminal.
- This function can be used even if <c>Mnesia</c> is not
+ This function can be used even if Mnesia is not
started. However, more information is displayed if
- <c>Mnesia</c> is started.</p>
+ Mnesia is started.</p>
</desc>
</func>
<func>
@@ -1431,7 +1431,7 @@ mnesia:create_table(person,
<p>Installs a backup as fallback. The fallback is used to
restore the database at the next startup. Installation of
fallbacks requires Erlang to be operational on all the
- involved nodes, but it does not matter if <c>Mnesia</c>
+ involved nodes, but it does not matter if Mnesia
is running or not. The installation of the fallback fails
if the local node is not one of the disc-resident nodes
in the backup.</p>
@@ -1465,14 +1465,14 @@ mnesia:create_table(person,
<p><c>{mnesia_dir, AlternateDir}</c>.
This argument is only valid if the scope of the
installation is <c>local</c>. Normally the installation
- of a fallback is targeted to the <c>Mnesia</c> directory,
+ of a fallback is targeted to the Mnesia directory,
as configured with configuration parameter
<c>-mnesia dir</c>. But by explicitly supplying an
<c>AlternateDir</c>, the fallback is installed there
- regardless of the <c>Mnesia</c> directory configuration
+ regardless of the Mnesia directory configuration
parameter setting. After installation of a fallback on
- an alternative <c>Mnesia</c> directory, that directory
- is fully prepared for use as an active <c>Mnesia</c>
+ an alternative Mnesia directory, that directory
+ is fully prepared for use as an active Mnesia
directory.</p>
<p>This is a dangerous feature that must be
used with care. By unintentional mixing of directories,
@@ -1509,7 +1509,7 @@ mnesia:create_table(person,
<marker id="load_textfile"></marker>
<p>Loads a series of definitions and data found in the
text file (generated with <c>mnesia:dump_to_textfile/1</c>)
- into <c>Mnesia</c>. This function also starts <c>Mnesia</c>
+ into Mnesia. This function also starts Mnesia
and possibly creates a new schema. This function is
intended for educational purposes only. It is recommended
to use other functions to deal with real backups.</p>
@@ -1558,7 +1558,7 @@ mnesia:create_table(person,
</taglist>
<p>Conflicting lock requests are automatically queued if there
is no risk of a deadlock. Otherwise the transaction must be
- terminated and executed again. <c>Mnesia</c> does this
+ terminated and executed again. Mnesia does this
automatically as long as the upper limit of the maximum
<c>retries</c> is not reached. For details, see
<c>mnesia:transaction/3</c>.</p>
@@ -1726,19 +1726,19 @@ mnesia:create_table(person,
</func>
<func>
<name>report_event(Event) -> ok</name>
- <fsummary>Reports a user event to the <c>Mnesia</c> event handler.</fsummary>
+ <fsummary>Reports a user event to the Mnesia event handler.</fsummary>
<desc>
<marker id="report_event"></marker>
- <p>When tracing a system of <c>Mnesia</c> applications it is
- useful to be able to interleave <c>Mnesia</c> own events with
+ <p>When tracing a system of Mnesia applications it is
+ useful to be able to interleave Mnesia own events with
application-related events that give information about the
application context.</p>
<p>Whenever the application begins a
- new and demanding <c>Mnesia</c> task, or if it enters a new
+ new and demanding Mnesia task, or if it enters a new
interesting phase in its execution, it can be a good idea to
use <c>mnesia:report_event/1</c>. <c>Event</c> can be
any term and generates a <c>{mnesia_user, Event}</c> event
- for any processes that subscribe to <c>Mnesia</c> system
+ for any processes that subscribe to Mnesia system
events.</p>
</desc>
</func>
@@ -1748,7 +1748,7 @@ mnesia:create_table(person,
<desc>
<marker id="restore"></marker>
<p>With this function, tables can be restored online from a
- backup without restarting <c>Mnesia</c>.
+ backup without restarting Mnesia.
<c>Opaque</c> is forwarded to the backup module.
<c>Args</c> is a list of the following tuples:</p>
<list type="bulleted">
@@ -1873,7 +1873,7 @@ mnesia:create_table(person,
<p>For a complete description of <c>select</c>, see the
<seealso marker="erts:index">ERTS</seealso> User's Guide and the
<seealso marker="stdlib:ets">ets</seealso> manual page in
- <c>STDLIB</c>.</p>
+ STDLIB.</p>
<p>For example, to find the names of all male persons older
than 30 in table <c>Tab</c>:</p>
<code type="none">
@@ -1920,10 +1920,10 @@ mnesia:select(Tab,[{MatchHead, [Guard], [Result]}]),</code>
</func>
<func>
<name>set_debug_level(Level) -> OldLevel</name>
- <fsummary>Changes the internal debug level of <c>Mnesia</c>.</fsummary>
+ <fsummary>Changes the internal debug level of Mnesia.</fsummary>
<desc>
<marker id="set_debug_level"></marker>
- <p>Changes the internal debug level of <c>Mnesia</c>.
+ <p>Changes the internal debug level of Mnesia.
For details, see
<seealso marker="#configuration_parameters">Section
Configuration Parameters</seealso>.</p>
@@ -1934,7 +1934,7 @@ mnesia:select(Tab,[{MatchHead, [Guard], [Result]}]),</code>
<fsummary>Sets the master nodes for all tables.</fsummary>
<desc>
<marker id="set_master_nodes_1"></marker>
- <p>For each table <c>Mnesia</c> determines its replica nodes
+ <p>For each table Mnesia determines its replica nodes
(<c>TabNodes</c>) and starts
<c>mnesia:set_master_nodes(Tab, TabMasterNodes)</c>. where
<c>TabMasterNodes</c> is the intersection of
@@ -1952,16 +1952,16 @@ mnesia:select(Tab,[{MatchHead, [Guard], [Result]}]),</code>
that can have caused an inconsistent database, it can use the
function <c>mnesia:set_master_nodes(Tab, MasterNodes)</c> to
define from which nodes each table is to be loaded.
- At startup, the <c>Mnesia</c> normal table load algorithm is
+ At startup, the Mnesia normal table load algorithm is
bypassed and the table is loaded from one of the master nodes
- defined for the table, regardless of when and if <c>Mnesia</c>
+ defined for the table, regardless of when and if Mnesia
terminated on other nodes. <c>MasterNodes</c> can only
contain nodes where the table has a replica. If the
<c>MasterNodes</c> list is empty, the master node recovery
mechanism for the particular table is reset, and the
normal load mechanism is used at the next restart.</p>
<p>The master node setting is always local. It can be
- changed regardless if <c>Mnesia</c> is started or not.</p>
+ changed regardless if Mnesia is started or not.</p>
<p>The database can also become inconsistent if
configuration parameter <c>max_wait_for_decision</c> is used
or if <c>mnesia:force_load_table/1</c> is used.</p>
@@ -1976,7 +1976,7 @@ mnesia:select(Tab,[{MatchHead, [Guard], [Result]}]),</code>
</func>
<func>
<name>snmp_get_mnesia_key(Tab, RowIndex) -> {ok, Key} | undefined</name>
- <fsummary>Gets the corresponding <c>Mnesia</c> key from an SNMP index.</fsummary>
+ <fsummary>Gets the corresponding Mnesia key from an SNMP index.</fsummary>
<type>
<v>Tab ::= atom()</v>
<v>RowIndex ::= [integer()]</v>
@@ -1984,7 +1984,7 @@ mnesia:select(Tab,[{MatchHead, [Guard], [Result]}]),</code>
<v>key() ::= integer() | string() | [integer()]</v>
</type>
<desc>
- <p>Transforms an SNMP index to the corresponding <c>Mnesia</c>
+ <p>Transforms an SNMP index to the corresponding Mnesia
key. If the SNMP table has multiple keys, the key is a tuple
of the key columns.</p>
</desc>
@@ -2020,7 +2020,7 @@ mnesia:select(Tab,[{MatchHead, [Guard], [Result]}]),</code>
</func>
<func>
<name>snmp_open_table(Tab, SnmpStruct) -> {aborted, R} | {atomic, ok}</name>
- <fsummary>Organizes a <c>Mnesia</c> table as an SNMP table.</fsummary>
+ <fsummary>Organizes a Mnesia table as an SNMP table.</fsummary>
<type>
<v>Tab ::= atom()</v>
<v>SnmpStruct ::= [{key, type()}]</v>
@@ -2029,14 +2029,14 @@ mnesia:select(Tab,[{MatchHead, [Guard], [Result]}]),</code>
</type>
<desc>
<p>A direct one-to-one mapping can be established between
- <c>Mnesia</c> tables and SNMP tables. Many telecommunication
+ Mnesia tables and SNMP tables. Many telecommunication
applications are controlled and monitored by the SNMP
- protocol. This connection between <c>Mnesia</c> and SNMP
+ protocol. This connection between Mnesia and SNMP
makes it simple and convenient to achieve this mapping.</p>
<p>Argument <c>SnmpStruct</c> is a list of SNMP
information. Currently, the only information needed is
information about the key types in the table. Multiple
- keys cannot be handled in <c>Mnesia</c>, but many SNMP
+ keys cannot be handled in Mnesia, but many SNMP
tables have multiple keys. Therefore, the following
convention is used: if a table has multiple keys, these must
always be stored as a tuple of the keys. Information about
@@ -2069,39 +2069,39 @@ mnesia:create_table(employee,
<p>When a table is SNMP ordered, modifications are more
expensive than usual, O(logN). Also, more memory is used.</p>
<p>Notice that only the lexicographical SNMP ordering is
- implemented in <c>Mnesia</c>, not the actual SNMP monitoring.</p>
+ implemented in Mnesia, not the actual SNMP monitoring.</p>
</desc>
</func>
<func>
<name>start() -> ok | {error, Reason}</name>
- <fsummary>Starts a local <c>Mnesia</c> system.</fsummary>
+ <fsummary>Starts a local Mnesia system.</fsummary>
<desc>
<marker id="start"></marker>
- <p>The startup procedure for a set of <c>Mnesia</c> nodes is a
- fairly complicated operation. A <c>Mnesia</c> system consists
- of a set of nodes, with <c>Mnesia</c> started locally on all
+ <p>The startup procedure for a set of Mnesia nodes is a
+ fairly complicated operation. A Mnesia system consists
+ of a set of nodes, with Mnesia started locally on all
participating nodes. Normally, each node has a directory where
- all the <c>Mnesia</c> files are written. This directory is
- referred to as the <c>Mnesia</c> directory. <c>Mnesia</c> can
+ all the Mnesia files are written. This directory is
+ referred to as the Mnesia directory. Mnesia can
also be started on disc-less nodes. For more information
about disc-less nodes, see <c>mnesia:create_schema/1</c>
and the User's Guide.</p>
- <p>The set of nodes that makes up a <c>Mnesia</c> system is kept
- in a schema. <c>Mnesia</c> nodes can be added to or removed
+ <p>The set of nodes that makes up a Mnesia system is kept
+ in a schema. Mnesia nodes can be added to or removed
from the schema. The initial schema is normally created on
disc with the function <c>mnesia:create_schema/1</c>. On
disc-less nodes, a tiny default schema is generated each time
- <c>Mnesia</c> is started. During the startup procedure,
- <c>Mnesia</c> exchanges schema information between the nodes
+ Mnesia is started. During the startup procedure,
+ Mnesia exchanges schema information between the nodes
to verify that the table definitions are compatible.</p>
<p>Each schema has a unique cookie, which can be regarded as a
unique schema identifier. The cookie must be the same on all
- nodes where <c>Mnesia</c> is supposed to run. For details,
+ nodes where Mnesia is supposed to run. For details,
see the User's Guide.</p>
- <p>The schema file and all other files that <c>Mnesia</c>
- needs are kept in the <c>Mnesia</c> directory. The
+ <p>The schema file and all other files that Mnesia
+ needs are kept in the Mnesia directory. The
command-line option <c>-mnesia dir Dir</c> can be used to
- specify the location of this directory to the <c>Mnesia</c>
+ specify the location of this directory to the Mnesia
system. If no such command-line option is found, the name
of the directory defaults to <c>Mnesia.Node</c>.</p>
<p><c>application:start(mnesia)</c> can also be used.</p>
@@ -2109,10 +2109,10 @@ mnesia:create_table(employee,
</func>
<func>
<name>stop() -> stopped</name>
- <fsummary>Stops <c>Mnesia</c> locally.</fsummary>
+ <fsummary>Stops Mnesia locally.</fsummary>
<desc>
<marker id="stop"></marker>
- <p>Stops <c>Mnesia</c> locally on the current node.</p>
+ <p>Stops Mnesia locally on the current node.</p>
<p><c>application:stop(mnesia)</c> can also be used.</p>
</desc>
</func>
@@ -2132,7 +2132,7 @@ mnesia:create_table(employee,
<desc>
<marker id="sync_dirty"></marker>
<p>Calls the <c>Fun</c> in a context that is not protected by
- a transaction. The <c>Mnesia</c> function calls performed in
+ a transaction. The Mnesia function calls performed in
the <c>Fun</c> are mapped to the corresponding dirty functions.
It is performed in almost the same context as
<c>mnesia:async_dirty/1,2</c>. The difference is that the
@@ -2167,10 +2167,10 @@ mnesia:create_table(employee,
</func>
<func>
<name>system_info(InfoKey) -> Info | exit({aborted, Reason})</name>
- <fsummary>Returns information about the <c>Mnesia</c> system.</fsummary>
+ <fsummary>Returns information about the Mnesia system.</fsummary>
<desc>
<marker id="system_info"></marker>
- <p>Returns information about the <c>Mnesia</c> system, such as
+ <p>Returns information about the Mnesia system, such as
transaction statistics, <c>db_nodes</c>, and configuration
parameters. The valid keys are as follows:</p>
<list type="bulleted">
@@ -2188,7 +2188,7 @@ mnesia:create_table(employee,
</item>
<item>
<p><c>auto_repair</c>. Returns <c>true</c> or <c>false</c>
- to indicate if <c>Mnesia</c> is configured to start the
+ to indicate if Mnesia is configured to start the
auto-repair facility on corrupted disc files.</p>
</item>
<item>
@@ -2209,20 +2209,20 @@ mnesia:create_table(employee,
in the list of nodes if they explicitly have been added
to the schema, for example, with
<c>mnesia:add_table_copy/3</c>. The function can be
- started even if <c>Mnesia</c> is not yet running.</p>
+ started even if Mnesia is not yet running.</p>
</item>
<item>
<p><c>debug</c>. Returns the current debug level of
- <c>Mnesia</c>.</p>
+ Mnesia.</p>
</item>
<item>
- <p><c>directory</c>. Returns the name of the <c>Mnesia</c>
- directory. It can be called even if <c>Mnesia</c> is
+ <p><c>directory</c>. Returns the name of the Mnesia
+ directory. It can be called even if Mnesia is
not yet running.</p>
</item>
<item>
<p><c>dump_log_load_regulation</c>. Returns a boolean that
- tells if <c>Mnesia</c> is configured to regulate the
+ tells if Mnesia is configured to regulate the
dumper process load.</p>
<p>This feature is temporary and will be removed in future
releases.</p>
@@ -2233,9 +2233,9 @@ mnesia:create_table(employee,
</item>
<item>
<p><c>dump_log_update_in_place</c>. Returns a boolean that
- tells if <c>Mnesia</c> is configured to perform the
- updates in the <c>dets</c> files directly, or if the
- updates are to be performed in a copy of the <c>dets</c>
+ tells if Mnesia is configured to perform the
+ updates in the Dets files directly, or if the
+ updates are to be performed in a copy of the Dets
files.</p>
</item>
<item>
@@ -2253,13 +2253,13 @@ mnesia:create_table(employee,
</item>
<item>
<p><c>held_locks</c>. Returns a list of all
- locks held by the local <c>Mnesia</c> lock manager.</p>
+ locks held by the local Mnesia lock manager.</p>
</item>
<item>
<p><c>is_running</c>. Returns <c>yes</c> or <c>no</c> to
- indicate if <c>Mnesia</c> is running. It can
+ indicate if Mnesia is running. It can
also return <c>starting</c> or <c>stopping</c>. Can be
- called even if <c>Mnesia</c> is not yet running.</p>
+ called even if Mnesia is not yet running.</p>
</item>
<item>
<p><c>local_tables</c>. Returns a list
@@ -2272,7 +2272,7 @@ mnesia:create_table(employee,
</item>
<item>
<p><c>log_version</c>. Returns the version
- number of the <c>Mnesia</c> transaction log format.</p>
+ number of the Mnesia transaction log format.</p>
</item>
<item>
<p><c>master_node_tables</c>. Returns a
@@ -2280,25 +2280,25 @@ mnesia:create_table(employee,
</item>
<item>
<p><c>protocol_version</c>. Returns the version number of
- the <c>Mnesia</c> inter-process communication protocol.</p>
+ the Mnesia inter-process communication protocol.</p>
</item>
<item>
<p><c>running_db_nodes</c>. Returns a list of nodes where
- <c>Mnesia</c> currently is running. This function can be
- called even if <c>Mnesia</c> is not yet running, but it
+ Mnesia currently is running. This function can be
+ called even if Mnesia is not yet running, but it
then has slightly different semantics.</p>
- <p>If <c>Mnesia</c> is down on the local node, the function
+ <p>If Mnesia is down on the local node, the function
returns those other <c>db_nodes</c> and
<c>extra_db_nodes</c> that for the moment are
operational.</p>
- <p>If <c>Mnesia</c> is started, the function returns
- those nodes that <c>Mnesia</c> on the local node is fully
- connected to. Only those nodes that <c>Mnesia</c> has
+ <p>If Mnesia is started, the function returns
+ those nodes that Mnesia on the local node is fully
+ connected to. Only those nodes that Mnesia has
exchanged schema information with are included as
<c>running_db_nodes</c>. After the merge of schemas, the
- local <c>Mnesia</c> system is fully operable and
+ local Mnesia system is fully operable and
applications can perform access of remote replicas.
- Before the schema merge, <c>Mnesia</c> only operates
+ Before the schema merge, Mnesia only operates
locally. Sometimes there are more nodes included in the
<c>running_db_nodes</c> list than all <c>db_nodes</c>
and <c>extra_db_nodes</c> together.</p>
@@ -2322,17 +2322,17 @@ mnesia:create_table(employee,
<item>
<p><c>transaction_failures</c>. Returns a
number that indicates how many transactions have
- failed since <c>Mnesia</c> was started.</p>
+ failed since Mnesia was started.</p>
</item>
<item>
<p><c>transaction_commits</c>. Returns a
number that indicates how many transactions have
- terminated successfully since <c>Mnesia</c> was started.</p>
+ terminated successfully since Mnesia was started.</p>
</item>
<item>
<p><c>transaction_restarts</c>. Returns a
number that indicates how many transactions have been
- restarted since <c>Mnesia</c> was started.</p>
+ restarted since Mnesia was started.</p>
</item>
<item>
<p><c>transaction_log_writes</c>.
@@ -2342,12 +2342,12 @@ mnesia:create_table(employee,
</item>
<item>
<p><c>use_dir</c>. Returns a boolean that indicates if
- the <c>Mnesia</c> directory is used or not. Can be
- started even if <c>Mnesia</c> is not yet running.</p>
+ the Mnesia directory is used or not. Can be
+ started even if Mnesia is not yet running.</p>
</item>
<item>
<p><c>version</c>. Returns the current
- version number of <c>Mnesia</c>.</p>
+ version number of Mnesia.</p>
</item>
</list>
</desc>
@@ -2359,13 +2359,13 @@ mnesia:create_table(employee,
<marker id="table"></marker>
<p>Returns a Query List Comprehension (QLC) query handle,
see the <seealso marker="stdlib:qlc">qlc(3)</seealso>
- manual page in <c>STDLIB</c>. The module <c>qlc</c>
- implements a query language that can use <c>Mnesia</c>
+ manual page in STDLIB. The module <c>qlc</c>
+ implements a query language that can use Mnesia
tables as sources of data. Calling
<c>mnesia:table/1,2</c> is the means to make the
<c>mnesia</c> table <c>Tab</c> usable to QLC.</p>
- <p><c>Option</c> can contain <c>Mnesia</c>
- options or QLC options. <c>Mnesia</c> recognizes the
+ <p><c>Option</c> can contain Mnesia
+ options or QLC options. Mnesia recognizes the
following options (any other option is forwarded to
QLC).</p>
<list type="bulleted">
@@ -2374,7 +2374,7 @@ mnesia:create_table(employee,
</item>
<item><c>{n_objects,Number}</c>, where <c>n_objects</c>
specifies (roughly) the number of objects returned
- from <c>Mnesia</c> to QLC. Queries to remote tables
+ from Mnesia to QLC. Queries to remote tables
can need a larger chunk to reduce network overhead.
By default, <c>100</c> objects at a time are returned.
</item>
@@ -2413,7 +2413,7 @@ mnesia:create_table(employee,
<desc>
<marker id="table_info"></marker>
<p>The <c>table_info/2</c> function takes two arguments.
- The first is the name of a <c>Mnesia</c> table.
+ The first is the name of a Mnesia table.
The second is one of the following keys:</p>
<list type="bulleted">
<item>
@@ -2465,7 +2465,7 @@ mnesia:create_table(employee,
</item>
<item>
<p><c>load_node</c>. Returns the name of
- the node that <c>Mnesia</c> loaded the table from. The
+ the node that Mnesia loaded the table from. The
structure of the returned value is unspecified, but
can be useful for debugging purposes.</p>
</item>
@@ -2476,7 +2476,7 @@ mnesia:create_table(employee,
</item>
<item>
<p><c>load_reason</c>. Returns the
- reason of why <c>Mnesia</c> decided to load the table.
+ reason of why Mnesia decided to load the table.
The structure of the returned value is unspecified, but
can be useful for debugging purposes.</p>
</item>
@@ -2620,7 +2620,7 @@ raise(Name, Amount) ->
several processes running on different nodes can concurrently
execute the function <c>raise/2</c> without interfering
with each other.</p>
- <p>Since <c>Mnesia</c> detects deadlocks, a transaction can be
+ <p>Since Mnesia detects deadlocks, a transaction can be
restarted any number of times. This function attempts a
restart as specified in <c>Retries</c>. <c>Retries</c> must
be an integer greater than 0 or the atom <c>infinity</c>.
@@ -2643,7 +2643,7 @@ raise(Name, Amount) ->
<p><c>NewAttributeList</c> and <c>NewRecordName</c>
specify the attributes and the new record type of the
converted table. Table name always remains unchanged. If
- <c>record_name</c> is changed, only the <c>Mnesia</c>
+ <c>record_name</c> is changed, only the Mnesia
functions that use table identifiers work, for example,
<c>mnesia:write/3</c> works, but not <c>mnesia:write/1</c>.</p>
</desc>
@@ -2706,7 +2706,7 @@ raise(Name, Amount) ->
distributed operation that is either performed on all
nodes with disc resident schema, or none. Uninstallation of
fallbacks requires Erlang to be operational on all
- involved nodes, but it does not matter if <c>Mnesia</c> is
+ involved nodes, but it does not matter if Mnesia is
running or not. Which nodes that are considered as
disc-resident nodes is determined from the schema
information in the local fallback.</p>
@@ -2792,28 +2792,28 @@ raise(Name, Amount) ->
<section>
<title>Configuration Parameters</title>
<marker id="configuration_parameters"></marker>
- <p><c>Mnesia</c> reads the following application configuration
+ <p>Mnesia reads the following application configuration
parameters:</p>
<list type="bulleted">
<item>
<p><c>-mnesia access_module Module</c>. The name of the
- <c>Mnesia</c> activity access callback module. Default is
+ Mnesia activity access callback module. Default is
<c>mnesia</c>.</p>
</item>
<item>
<p><c>-mnesia auto_repair true | false</c>. This flag
- controls if <c>Mnesia</c> automatically tries to repair
+ controls if Mnesia automatically tries to repair
files that have not been properly closed. Default is
<c>true</c>.</p>
</item>
<item>
<p><c>-mnesia backup_module Module</c>. The name of the
- <c>Mnesia</c> backup callback module. Default is
+ Mnesia backup callback module. Default is
<c>mnesia_backup</c>.</p>
</item>
<item>
<p><c>-mnesia debug Level</c>. Controls the debug level
- of <c>Mnesia</c>. The possible values are as follows:</p>
+ of Mnesia. The possible values are as follows:</p>
<taglist>
<tag><c>none</c></tag>
<item>
@@ -2825,7 +2825,7 @@ raise(Name, Amount) ->
events generate <c>{mnesia_info, Format, Args}</c>
system events. Processes can subscribe to these events with
<c>mnesia:subscribe/1</c>. The events are always sent to
- the <c>Mnesia</c> event handler.</p>
+ the Mnesia event handler.</p>
</item>
<tag><c>debug</c></tag>
<item>
@@ -2834,15 +2834,15 @@ raise(Name, Amount) ->
<c>{mnesia_info, Format, Args}</c> system events.
Processes can subscribe to these events with
<c>mnesia:subscribe/1</c>. The events are always sent to
- the <c>Mnesia</c> event handler. On this debug level,
- the <c>Mnesia</c> event handler starts subscribing to
+ the Mnesia event handler. On this debug level,
+ the Mnesia event handler starts subscribing to
updates in the schema table.</p>
</item>
<tag><c>trace</c></tag>
<item>
<p>Activates all events at the debug level. On this
- level, the <c>Mnesia</c> event handler starts subscribing
- to updates on all <c>Mnesia</c> tables. This level is
+ level, the Mnesia event handler starts subscribing
+ to updates on all Mnesia tables. This level is
intended only for debugging small toy systems, as many
large events can be generated.</p>
</item>
@@ -2856,7 +2856,7 @@ raise(Name, Amount) ->
</item>
<item>
<p><c>-mnesia core_dir Directory</c>. The name of the
- directory where <c>Mnesia</c> core files is stored, or
+ directory where Mnesia core files is stored, or
false. Setting it implies that also RAM-only nodes
generate a core file if a crash occurs.</p>
</item>
@@ -2870,9 +2870,9 @@ raise(Name, Amount) ->
</item>
<item>
<p><c>-mnesia dir Directory</c>. The name of the directory
- where all <c>Mnesia</c> data is stored. The directory name
+ where all Mnesia data is stored. The directory name
must be unique for the current node. Two nodes must never
- share the the same <c>Mnesia</c> directory. The results
+ share the the same Mnesia directory. The results
are unpredictable.</p>
</item>
<item>
@@ -2915,44 +2915,44 @@ raise(Name, Amount) ->
</item>
<item>
<p><c>-mnesia event_module Module</c>. The name of the
- <c>Mnesia</c> event handler callback module. Default is
+ Mnesia event handler callback module. Default is
<c>mnesia_event</c>.</p>
</item>
<item>
<p><c>-mnesia extra_db_nodes Nodes</c> specifies a list of
nodes, in addition to the ones found in the schema, with
- which <c>Mnesia</c> is also to establish contact. Default
+ which Mnesia is also to establish contact. Default
is <c>[]</c> (empty list).</p>
</item>
<item>
<p><c>-mnesia fallback_error_function {UserModule, UserFunc}</c>.
Specifies a user-supplied callback function, which is
- called if a fallback is installed and <c>Mnesia</c> goes
- down on another node. <c>Mnesia</c> calls the function
+ called if a fallback is installed and Mnesia goes
+ down on another node. Mnesia calls the function
with one argument, the name of the dying node, for example,
- <c>UserModule:UserFunc(DyingNode)</c>. <c>Mnesia</c> must
+ <c>UserModule:UserFunc(DyingNode)</c>. Mnesia must
be restarted, otherwise the database can be inconsistent.
- The default behavior is to terminate <c>Mnesia</c>.</p>
+ The default behavior is to terminate Mnesia.</p>
</item>
<item>
<p><c>-mnesia max_wait_for_decision Timeout</c>. Specifies
- how long <c>Mnesia</c> waits for other nodes to share their
+ how long Mnesia waits for other nodes to share their
knowledge about the outcome of an unclear transaction. By
default, <c>Timeout</c> is set to the atom <c>infinity</c>.
- This implies that if <c>Mnesia</c> upon startup detects
+ This implies that if Mnesia upon startup detects
a "heavyweight transaction" whose outcome is unclear, the
- local <c>Mnesia</c> waits until <c>Mnesia</c> is started
+ local Mnesia waits until Mnesia is started
on some (in the worst case all) of the other nodes that were
involved in the interrupted transaction. This is a rare
- situation, but if it occurs, <c>Mnesia</c> does not guess if
+ situation, but if it occurs, Mnesia does not guess if
the transaction on the other nodes was committed or
- terminated. <c>Mnesia</c> waits until it knows the outcome
+ terminated. Mnesia waits until it knows the outcome
and then acts accordingly.</p>
<p>If <c>Timeout</c> is set to an integer value in
- milliseconds, <c>Mnesia</c> forces "heavyweight transactions"
+ milliseconds, Mnesia forces "heavyweight transactions"
to be finished, even if the outcome of the transaction for
the moment is unclear. After <c>Timeout</c> milliseconds,
- <c>Mnesia</c> commits or terminates the transaction and
+ Mnesia commits or terminates the transaction and
continues with the startup. This can lead to a situation
where the transaction is committed on some nodes and
terminated on other nodes. If the transaction is a
@@ -2976,14 +2976,14 @@ raise(Name, Amount) ->
</item>
<item>
<p><c>-mnesia schema_location Loc</c>. Controls where
- <c>Mnesia</c> looks for its schema. Parameter
+ Mnesia looks for its schema. Parameter
<c>Loc</c> can be one of the following atoms:</p>
<taglist>
<tag><c>disc</c></tag>
<item>
<p>Mandatory disc. The schema is assumed to be located
- in the <c>Mnesia</c> directory. If the schema cannot
- be found, <c>Mnesia</c> refuses to start. This is the
+ in the Mnesia directory. If the schema cannot
+ be found, Mnesia refuses to start. This is the
old behavior.</p>
</item>
<tag><c>ram</c></tag>
@@ -3001,10 +3001,10 @@ raise(Name, Amount) ->
<tag><c>opt_disc</c></tag>
<item>
<p>Optional disc. The schema can reside on disc or in
- RAM. If the schema is found on disc, <c>Mnesia</c>
+ RAM. If the schema is found on disc, Mnesia
starts as a disc-based node and the storage type of
the schema table is <c>disc_copies</c>. If no schema is
- found on disc, <c>Mnesia</c> starts as a disc-less node
+ found on disc, Mnesia starts as a disc-less node
and the storage type of the schema table is
<c>ram_copies</c>. Default value for the application
parameter is <c>opt_disc</c>.</p>
@@ -3012,7 +3012,7 @@ raise(Name, Amount) ->
</taglist>
</item>
</list>
- <p>First, the <c>SASL</c> application parameters are checked,
+ <p>First, the SASL application parameters are checked,
then the command-line flags are checked, and finally, the
default value is chosen.</p>
</section>
diff --git a/lib/mnesia/doc/src/mnesia_frag_hash.xml b/lib/mnesia/doc/src/mnesia_frag_hash.xml
index 95f5f8aa07..51b32129b6 100644
--- a/lib/mnesia/doc/src/mnesia_frag_hash.xml
+++ b/lib/mnesia/doc/src/mnesia_frag_hash.xml
@@ -87,13 +87,13 @@
the new one.</p>
<p><c>NewState</c> is stored as <c>hash_state</c> among the
other <c>frag_properties</c>.</p>
- <p>As a part of the <c>add_frag</c> procedure, <c>Mnesia</c> iterates
+ <p>As a part of the <c>add_frag</c> procedure, Mnesia iterates
over all fragments corresponding to the <c>IterFrags</c> numbers
and starts <c>key_to_frag_number(NewState,RecordKey)</c> for
each record. If the new fragment differs from the old
fragment, the record is moved to the new fragment.</p>
<p>As the <c>add_frag</c> procedure is a part of a schema
- transaction, <c>Mnesia</c> acquires write locks on the
+ transaction, Mnesia acquires write locks on the
affected tables. That is, both the fragments corresponding
to <c>IterFrags</c> and those corresponding to
<c>AdditionalLockFrags</c>.</p>
@@ -112,7 +112,7 @@
<desc>
<p><c>NewState</c> is stored as <c>hash_state</c> among the
other <c>frag_properties</c>.</p>
- <p>As a part of the <c>del_frag</c> procedure, <c>Mnesia</c> iterates
+ <p>As a part of the <c>del_frag</c> procedure, Mnesia iterates
over all fragments corresponding to the <c>IterFrags</c> numbers
and starts <c>key_to_frag_number(NewState,RecordKey)</c> for
each record. If the new fragment differs from the old
@@ -120,7 +120,7 @@
<p>Notice that all records in the last fragment must be moved to
another fragment, as the entire fragment is deleted.</p>
<p>As the <c>del_frag</c> procedure is a part of a schema
- transaction, <c>Mnesia</c> acquires write locks on the
+ transaction, Mnesia acquires write locks on the
affected tables. That is, both the fragments corresponding
to <c>IterFrags</c> and those corresponding to
<c>AdditionalLockFrags</c>.</p>
@@ -134,7 +134,7 @@
<v>Reason = term()</v>
</type>
<desc>
- <p>Starts whenever <c>Mnesia</c> needs to determine
+ <p>Starts whenever Mnesia needs to determine
which fragment a certain record belongs to. It is typically
started at <c>read</c>, <c>write</c>, and <c>delete</c>.</p>
</desc>
@@ -149,7 +149,7 @@
<v>Reason = term()</v>
</type>
<desc>
- <p>This function is called whenever <c>Mnesia</c> needs to determine
+ <p>This function is called whenever Mnesia needs to determine
which fragments that need to be searched for a <c>MatchSpec</c>.
It is typically called by <c>select</c> and
<c>match_object</c>.</p>
diff --git a/lib/mnesia/doc/src/mnesia_registry.xml b/lib/mnesia/doc/src/mnesia_registry.xml
index cd778ae072..a76f716981 100644
--- a/lib/mnesia/doc/src/mnesia_registry.xml
+++ b/lib/mnesia/doc/src/mnesia_registry.xml
@@ -38,20 +38,20 @@
<modulesummary>Dump support for registries in erl_interface.</modulesummary>
<description>
<p>This module is usually part of the <c>erl_interface</c>
- application, but is currently part of the <c>Mnesia</c>
+ application, but is currently part of the Mnesia
application.</p>
<p>This module is mainly intended for internal use within OTP,
but it has two functions that are exported for public use.</p>
<p>On C-nodes, <c>erl_interface</c> has support for registry
tables. These tables reside in RAM on the C-node, but can also
- be dumped into <c>Mnesia</c> tables. By default, the dumping
+ be dumped into Mnesia tables. By default, the dumping
of registry tables through <c>erl_interface</c> causes a
- corresponding <c>Mnesia</c> table to be created with
+ corresponding Mnesia table to be created with
<c>mnesia_registry:create_table/1</c>, if necessary.</p>
<p>Tables that are created with these functions can be
- administered as all other <c>Mnesia</c> tables. They can be
+ administered as all other Mnesia tables. They can be
included in backups, replicas can be added, and so on.
- The tables are normal <c>Mnesia</c> tables owned by the user
+ The tables are normal Mnesia tables owned by the user
of the corresponding <c>erl_interface</c> registries.</p>
</description>
@@ -68,7 +68,7 @@
that is, <c>{ram_copies,[node()]}</c> or
<c>{disc_copies,[node()]}</c>.</p>
<p>This function is used by <c>erl_interface</c> to
- create the <c>Mnesia</c> table if it does not already
+ create the Mnesia table if it does not already
exist.</p>
</desc>
</func>
diff --git a/lib/mnesia/doc/src/part.xml b/lib/mnesia/doc/src/part.xml
index 101bdb29d4..d3ffe93937 100644
--- a/lib/mnesia/doc/src/part.xml
+++ b/lib/mnesia/doc/src/part.xml
@@ -30,7 +30,7 @@
<file>part.sgml</file>
</header>
<description>
- <p>The <c>Mnesia</c> application is a distributed Database Management
+ <p>The Mnesia application is a distributed Database Management
System (DBMS), appropriate for telecommunications applications and other
Erlang applications, which require continuous operation and exhibit soft
real-time properties.</p>
diff --git a/lib/mnesia/doc/src/ref_man.xml b/lib/mnesia/doc/src/ref_man.xml
index 662f0d61d6..7fb71b9c45 100644
--- a/lib/mnesia/doc/src/ref_man.xml
+++ b/lib/mnesia/doc/src/ref_man.xml
@@ -33,7 +33,7 @@
<file>refman.sgml</file>
</header>
<description>
- <p>The <c>Mnesia</c> application is a distributed Database Management
+ <p>The Mnesia application is a distributed Database Management
System (DBMS), appropriate for telecommunications applications and other
Erlang applications, which require continuous operation and exhibit soft
real-time properties.</p>
diff --git a/lib/observer/doc/src/ttb.xml b/lib/observer/doc/src/ttb.xml
index 94ecef24b4..42b0fa1d8a 100644
--- a/lib/observer/doc/src/ttb.xml
+++ b/lib/observer/doc/src/ttb.xml
@@ -485,7 +485,7 @@ ttb:p(all, call).</input></pre>
<p>For a description of the <c>match_spec()</c> syntax,
see section
<seealso marker="erts:match_spec"><c>Match Specifications in Erlang</c></seealso>
- in <c>ERTS</c>, which explains the general match specification "language".
+ in ERTS, which explains the general match specification "language".
</p>
<note>
<p>The <em>system tracer</em> for sequential tracing is
diff --git a/lib/observer/src/observer_tv_wx.erl b/lib/observer/src/observer_tv_wx.erl
index 59f6443551..968a7620aa 100644
--- a/lib/observer/src/observer_tv_wx.erl
+++ b/lib/observer/src/observer_tv_wx.erl
@@ -124,6 +124,8 @@ handle_event(#wx{id=Id}, State = #state{node=Node, grid=Grid, opt=Opt0})
end,
case get_tables2(Node, Opt) of
Error = {error, _} ->
+ Id =:= ?ID_MNESIA andalso
+ wxMenuBar:check(observer_wx:get_menubar(), ?ID_ETS, true),
self() ! Error,
{noreply, State};
Tables ->
@@ -217,22 +219,32 @@ handle_info(refresh_interval, State = #state{node=Node, grid=Grid, opt=Opt,
{noreply, State#state{tabs=Tabs}}
end;
-handle_info({active, Node}, State = #state{parent=Parent, grid=Grid, opt=Opt,
+handle_info({active, Node}, State = #state{parent=Parent, grid=Grid, opt=Opt0,
timer=Timer0}) ->
- Tables = get_tables(Node, Opt),
+ {Tables, Opt} = case Opt0#opt.type =:= mnesia andalso get_tables2(Node, Opt0) of
+ Ts when is_list(Ts) ->
+ {Ts, Opt0};
+ _ -> % false or error getting mnesia tables
+ Opt1 = Opt0#opt{type=ets},
+ {get_tables(Node, Opt1), Opt1}
+ end,
Tabs = update_grid(Grid, Opt, Tables),
wxWindow:setFocus(Grid),
create_menus(Parent, Opt),
Timer = observer_lib:start_timer(Timer0),
- {noreply, State#state{node=Node, tabs=Tabs, timer=Timer}};
+ {noreply, State#state{node=Node, tabs=Tabs, timer=Timer, opt=Opt}};
handle_info(not_active, State = #state{timer = Timer0}) ->
Timer = observer_lib:stop_timer(Timer0),
{noreply, State#state{timer=Timer}};
-handle_info({error, Error}, State) ->
+handle_info({error, Error}, #state{opt=Opt}=State) ->
handle_error(Error),
- {noreply, State};
+ case Opt#opt.type of
+ mnesia -> wxMenuBar:check(observer_wx:get_menubar(), ?ID_ETS, true);
+ _ -> ok
+ end,
+ {noreply, State#state{opt=Opt#opt{type=ets}}};
handle_info(_Event, State) ->
{noreply, State}.
diff --git a/lib/observer/src/observer_wx.erl b/lib/observer/src/observer_wx.erl
index 301bb4b32f..5732c12006 100644
--- a/lib/observer/src/observer_wx.erl
+++ b/lib/observer/src/observer_wx.erl
@@ -21,7 +21,7 @@
-behaviour(wx_object).
-export([start/0, stop/0]).
--export([create_menus/2, get_attrib/1, get_tracer/0, get_active_node/0,
+-export([create_menus/2, get_attrib/1, get_tracer/0, get_active_node/0, get_menubar/0,
set_status/1, create_txt_dialog/4, try_rpc/4, return_to_localnode/2]).
-export([init/1, handle_event/2, handle_cast/2, terminate/2, code_change/3,
@@ -94,6 +94,9 @@ get_tracer() ->
get_active_node() ->
wx_object:call(observer, get_active_node).
+get_menubar() ->
+ wx_object:call(observer, get_menubar).
+
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
init(_Args) ->
@@ -391,6 +394,9 @@ handle_call(get_tracer, _From, State=#state{trace_panel=TraceP}) ->
handle_call(get_active_node, _From, State=#state{node=Node}) ->
{reply, Node, State};
+handle_call(get_menubar, _From, State=#state{menubar=MenuBar}) ->
+ {reply, MenuBar, State};
+
handle_call(stop, From, State) ->
stop_servers(State),
{noreply, State#state{reply_to=From}};
diff --git a/lib/odbc/doc/src/notes.xml b/lib/odbc/doc/src/notes.xml
index d3dd39616f..40f9339028 100644
--- a/lib/odbc/doc/src/notes.xml
+++ b/lib/odbc/doc/src/notes.xml
@@ -585,7 +585,7 @@
also been extended. </item><item> The <c>configure</c>
scripts of <c>erl_interface</c> and <c>odbc</c> now
search for thread libraries and thread library quirks the
- same way as <c>erts</c> do. </item><item> The
+ same way as ERTS do. </item><item> The
<c>configure</c> script of the <c>odbc</c> application
now also looks for odbc libraries in <c>lib64</c> and
<c>lib/64</c> directories when building on a 64-bit
diff --git a/lib/parsetools/doc/src/yecc.xml b/lib/parsetools/doc/src/yecc.xml
index 6ec9fb5f0e..9188bd2a22 100644
--- a/lib/parsetools/doc/src/yecc.xml
+++ b/lib/parsetools/doc/src/yecc.xml
@@ -201,7 +201,7 @@
<p>The grammar starts with an optional <c>header</c> section. The
header is put first in the generated file, before the module
declaration. The purpose of the header is to provide a means to
- make the documentation generated by <c>EDoc</c> look nicer. Each
+ make the documentation generated by EDoc look nicer. Each
header line should be enclosed in double quotes, and newlines
will be inserted between the lines. For example:</p>
<code>
diff --git a/lib/reltool/doc/src/notes.xml b/lib/reltool/doc/src/notes.xml
index 6df4924d0a..25d983afd3 100644
--- a/lib/reltool/doc/src/notes.xml
+++ b/lib/reltool/doc/src/notes.xml
@@ -546,8 +546,8 @@
<p>The handling of applications included in releases has
been improved. Applications that are required to be
started before other applications in a release are now
- automatically included in the release. The <c>kernel</c>
- and <c>stdlib</c> applications are always included as
+ automatically included in the release. The Kernel
+ and STDLIB applications are always included as
they are mandatory.</p>
<p>Applications that are (explicitly or implicitly)
included in a release are now automatically included as
diff --git a/lib/reltool/doc/src/part.xml b/lib/reltool/doc/src/part.xml
index 5904084879..e608d548ea 100644
--- a/lib/reltool/doc/src/part.xml
+++ b/lib/reltool/doc/src/part.xml
@@ -31,7 +31,7 @@
<rev>%VSN%</rev>
</header>
<description>
- <p><c>Reltool</c> is a release management tool. It analyses a given
+ <p>Reltool is a release management tool. It analyses a given
Erlang/OTP installation and determines various dependencies
between applications. The <c>graphical</c> frontend depicts the
dependencies and enables interactive customization of a
diff --git a/lib/reltool/doc/src/ref_man.xml b/lib/reltool/doc/src/ref_man.xml
index 38f270b79a..1684f075ff 100644
--- a/lib/reltool/doc/src/ref_man.xml
+++ b/lib/reltool/doc/src/ref_man.xml
@@ -31,7 +31,7 @@
<rev>%VSN%</rev>
</header>
<description>
- <p><c>Reltool</c> is a release management tool. It analyses a given
+ <p>Reltool is a release management tool. It analyses a given
Erlang/OTP installation and determines various dependencies
between applications. The <c>graphical</c> frontend depicts the
dependencies and enables interactive customization of a
diff --git a/lib/reltool/doc/src/reltool.xml b/lib/reltool/doc/src/reltool.xml
index 38448e7961..5bfbee966b 100644
--- a/lib/reltool/doc/src/reltool.xml
+++ b/lib/reltool/doc/src/reltool.xml
@@ -47,7 +47,7 @@
<p>The tool uses an installed Erlang/OTP system as input.
<c>root_dir</c> is the root directory of the analysed system and
- it defaults to the system executing <c>reltool</c>. Applications
+ it defaults to the system executing Reltool. Applications
may also be located outside <c>root_dir</c>. <c>lib_dirs</c>
defines library directories where additional applications
may reside and it defaults to the directories
@@ -56,7 +56,7 @@
<p>An application directory <c>AppDir</c> under a library
directory is recognized by the existence of an <c>AppDir/ebin</c>
- directory. If this does not exist, <c>reltool</c> will not
+ directory. If this does not exist, Reltool will not
consider <c>AppDir</c> at all when looking for applications.</p>
<p>It is recommended that application directories are named as the
@@ -81,14 +81,14 @@
<tag><c>config</c></tag>
<item>
<p>This is the main option and it controls the configuration
- of <c>reltool</c>. It can either be a <c>sys</c> tuple or
+ of Reltool. It can either be a <c>sys</c> tuple or
a name of a <c>file</c> containing a sys tuple.</p>
</item>
<tag><c>trap_exit</c></tag>
<item>
<p>This option controls the error handling behavior of
- <c>reltool</c>. By default the window processes traps
+ Reltool. By default the window processes traps
exit, but this behavior can altered by setting
<c>trap_exit</c> to <c>false</c>.</p>
</item>
diff --git a/lib/reltool/doc/src/reltool_intro.xml b/lib/reltool/doc/src/reltool_intro.xml
index 8e232b8838..2980ad7977 100644
--- a/lib/reltool/doc/src/reltool_intro.xml
+++ b/lib/reltool/doc/src/reltool_intro.xml
@@ -34,7 +34,7 @@
<rev>%VSN%</rev>
<file>reltool_intro.xml</file>
</header>
- <p><c>Reltool</c> is a release management tool. It analyses a given
+ <p>Reltool is a release management tool. It analyses a given
Erlang/OTP installation and determines various dependencies between
applications. The <c>graphical</c> frontend depicts the dependencies and
enables interactive customization of a target system. The backend provides a
@@ -82,7 +82,7 @@
and about the Erlang/OTP development system:</p>
<list type="bulleted">
<item>
- <p>the Reference Manual of <c>Reltool</c></p>
+ <p>the Reference Manual of Reltool</p>
</item>
<item>
<p>the Erlang/OTP <c>System Principles</c></p>
diff --git a/lib/runtime_tools/doc/src/dbg.xml b/lib/runtime_tools/doc/src/dbg.xml
index 14a81b2293..db04bfdf7b 100644
--- a/lib/runtime_tools/doc/src/dbg.xml
+++ b/lib/runtime_tools/doc/src/dbg.xml
@@ -78,7 +78,7 @@
<p>Pseudo function that by means of a <c>parse_transform</c>
translates the <em>literal</em><c>fun()</c> typed as parameter in
the function call to a match specification as described in
- the <c>match_spec</c> manual of <c>ERTS</c> users guide.
+ the <c>match_spec</c> manual of ERTS users guide.
(with literal I mean that the <c>fun()</c> needs to
textually be written as the parameter of the function, it
cannot be held in a variable which in turn is passed to the
diff --git a/lib/runtime_tools/doc/src/notes.xml b/lib/runtime_tools/doc/src/notes.xml
index 6bec7cb9ca..b6dfb2dd28 100644
--- a/lib/runtime_tools/doc/src/notes.xml
+++ b/lib/runtime_tools/doc/src/notes.xml
@@ -668,7 +668,7 @@
also been extended. </item><item> The <c>configure</c>
scripts of <c>erl_interface</c> and <c>odbc</c> now
search for thread libraries and thread library quirks the
- same way as <c>erts</c> do. </item><item> The
+ same way as ERTS do. </item><item> The
<c>configure</c> script of the <c>odbc</c> application
now also looks for odbc libraries in <c>lib64</c> and
<c>lib/64</c> directories when building on a 64-bit
diff --git a/lib/sasl/doc/src/alarm_handler.xml b/lib/sasl/doc/src/alarm_handler.xml
index 8550a88b28..4160757164 100644
--- a/lib/sasl/doc/src/alarm_handler.xml
+++ b/lib/sasl/doc/src/alarm_handler.xml
@@ -54,7 +54,7 @@
format is defined by the user. For example, an event handler
for SNMP can be defined, together with an alarm Management
Information Base (MIB).</p>
- <p>The alarm handler is part of the <c>SASL</c> application.</p>
+ <p>The alarm handler is part of the SASL application.</p>
<p>When writing new event handlers for the alarm handler, the
following events must be handled:</p>
<taglist>
@@ -76,7 +76,7 @@
{NewHandler, Args})</c>. <c>NewHandler:init({Args, {alarm_handler,
Alarms}})</c> is called. For more details, see
<seealso marker="stdlib:gen_event"><c>gen_event(3)</c></seealso>
- in <c>STDLIB</c>.</p>
+ in STDLIB.</p>
</description>
<funcs>
diff --git a/lib/sasl/doc/src/appup.xml b/lib/sasl/doc/src/appup.xml
index 6fbdcb9f5b..a43a966dcb 100644
--- a/lib/sasl/doc/src/appup.xml
+++ b/lib/sasl/doc/src/appup.xml
@@ -362,12 +362,12 @@ point_of_no_return</pre>
system is restarted.</p>
<pre>
restart_new_emulator</pre>
- <p>This instruction is used when the application <c>ERTS</c>,
- <c>Kernel</c>, <c>STDLIB</c>, or <c>SASL</c> is
+ <p>This instruction is used when the application ERTS,
+ Kernel, STDLIB, or SASL is
upgraded. It shuts down the current emulator and starts a new
one. All processes are terminated gracefully, and the new
- version of <c>ERTS</c>, <c>Kernel</c>, <c>STDLIB</c>, and
- <c>SASL</c> are used when the emulator restarts.
+ version of ERTS, Kernel, STDLIB, and
+ SASL are used when the emulator restarts.
Only one <c>restart_new_emulator</c> instruction is allowed
in the <c>relup</c> file, and it must be placed first.
<seealso marker="systools#make_relup/3"><c>systools:make_relup/3,4</c></seealso>
@@ -385,7 +385,7 @@ restart_new_emulator</pre>
<warning>
<p>As stated earlier, instruction <c>restart_new_emulator</c>
causes the emulator to be restarted with new versions of
- <c>ERTS</c>, <c>Kernel</c>, <c>STDLIB</c>, and <c>SASL</c>.
+ ERTS>, Kernel, STDLIB, and SASL.
However, all other applications do at startup run their old
versions in this new emulator. This is usually no problem,
but every now and then incompatible changes occur to the
diff --git a/lib/sasl/doc/src/error_logging.xml b/lib/sasl/doc/src/error_logging.xml
index 8464a41ff9..4b2c960bbb 100644
--- a/lib/sasl/doc/src/error_logging.xml
+++ b/lib/sasl/doc/src/error_logging.xml
@@ -32,20 +32,20 @@
<rev>B</rev>
<file>error_logging.xml</file>
</header>
- <p>The <c>SASL</c> application introduces three types of reports:</p>
+ <p>The SASL application introduces three types of reports:</p>
<list type="bulleted">
<item>Supervisor report</item>
<item>Progress report</item>
<item>Crash report</item>
</list>
- <p>When the <c>SASL</c> application is started, it adds a handler that
+ <p>When the SASL application is started, it adds a handler that
formats and writes these reports, as specified in the configuration
- parameters for <c>SASL</c>, that is, the environment variables
- in the <c>SASL</c> application specification, which is found in the
- <c>.app</c> file of <c>SASL</c>. For details, see the
+ parameters for SASL, that is, the environment variables
+ in the SASL application specification, which is found in the
+ <c>.app</c> file of SASL. For details, see the
<seealso marker="sasl_app"><c>sasl(6)</c></seealso> application in the
Reference Manual and the <seealso marker="kernel:app"><c>app(4)</c></seealso>
- file in the <c>Kernel</c> Reference Manual.</p>
+ file in the Kernel Reference Manual.</p>
<section>
<title>Supervisor Report</title>
@@ -180,14 +180,14 @@
<p>The report browser is used to browse and format error reports
written by the error logger handler
<seealso marker="stdlib:log_mf_h"><c>log_mf_h</c></seealso>
- defined in <c>STDLIB</c>.</p>
+ defined in STDLIB.</p>
<p>The <c>log_mf_h</c> handler writes all reports to a
report logging directory, which is specified when
- configuring the <c>SASL</c> application.</p>
+ configuring the SASL application.</p>
<p>If the report browser is
used offline, the reports can be copied to another directory
specified when starting the browser. If no such directory
- is specified, the browser reads reports from the <c>SASL</c>
+ is specified, the browser reads reports from the SASL
<c>error_logger_mf_dir</c>.</p>
<section>
diff --git a/lib/sasl/doc/src/notes.xml b/lib/sasl/doc/src/notes.xml
index dae73f8b23..bd713af932 100644
--- a/lib/sasl/doc/src/notes.xml
+++ b/lib/sasl/doc/src/notes.xml
@@ -824,7 +824,7 @@
<list>
<item>
<p>Use an infinity timeout in all calls to
- <c>gen_server:call()</c> in the <c>sasl</c>
+ <c>gen_server:call()</c> in the SASL
application.</p>
<p>
Own Id: OTP-8506 Aux Id: seq11509 </p>
diff --git a/lib/sasl/doc/src/part.xml b/lib/sasl/doc/src/part.xml
index f531ed2dea..659710487e 100644
--- a/lib/sasl/doc/src/part.xml
+++ b/lib/sasl/doc/src/part.xml
@@ -30,7 +30,7 @@
<file>part.xml</file>
</header>
<description>
- <p>The System Architecture Support Libraries <c>SASL</c> application
+ <p>The System Architecture Support Libraries SASL application
provides support for alarm handling, release handling, and
related functions.</p>
</description>
diff --git a/lib/sasl/doc/src/rb.xml b/lib/sasl/doc/src/rb.xml
index 1ce19046eb..d5df4fd345 100644
--- a/lib/sasl/doc/src/rb.xml
+++ b/lib/sasl/doc/src/rb.xml
@@ -38,7 +38,7 @@
<p>The Report Browser (RB) tool is used to browse and
format error reports written by the error logger handler
<seealso marker="stdlib:log_mf_h"><c>log_mf_h</c></seealso>
- in <c>STDLIB</c>.</p>
+ in STDLIB.</p>
</description>
<funcs>
@@ -62,7 +62,7 @@
reports that match that filter.</p>
<p>The reports are matched using the
<seealso marker="stdlib:proplists"><c>proplists</c></seealso>
- module in <c>STDLIB</c>. The report must be a proplist
+ module in STDLIB. The report must be a proplist
to be matched against any of the filters.</p>
<p>If the filter has the form <c>{Key, RegExp, re}</c>, the
report must contain an element with key equal to <c>Key</c> and
@@ -102,7 +102,7 @@
</list>
<p>For a definition of valid regular expressions and options, see
the <seealso marker="stdlib:re"><c>re</c></seealso> module in
- <c>STDLIB</c> and in particular function <c>re:run/3</c>.</p>
+ STDLIB and in particular function <c>re:run/3</c>.</p>
<p>For details about data type <c>mp()</c>, see
<seealso marker="stdlib:re#type-mp"><c>re:mp()</c></seealso>.</p>
</desc>
diff --git a/lib/sasl/doc/src/ref_man.xml b/lib/sasl/doc/src/ref_man.xml
index 42045df5ec..78cf1eb26e 100644
--- a/lib/sasl/doc/src/ref_man.xml
+++ b/lib/sasl/doc/src/ref_man.xml
@@ -30,7 +30,7 @@
<file>application.xml</file>
</header>
<description>
- <p>The <c>SASL</c> application provides support for alarm handling,
+ <p>The SASL application provides support for alarm handling,
release handling, and related functions.</p>
</description>
<xi:include href="sasl_app.xml"/>
diff --git a/lib/sasl/doc/src/rel.xml b/lib/sasl/doc/src/rel.xml
index d6558c06b4..9356b2cd47 100644
--- a/lib/sasl/doc/src/rel.xml
+++ b/lib/sasl/doc/src/rel.xml
@@ -59,7 +59,7 @@
<tag><c>Vsn = string()</c></tag>
<item><p>Release version.</p></item>
<tag><c>EVsn = string()</c></tag>
- <item><p><c>ERTS</c> version the release is intended for.</p></item>
+ <item><p>ERTS version the release is intended for.</p></item>
<tag><c>Application = atom()</c></tag>
<item><p>Name of an application included in the release.</p></item>
<tag><c>AppVsn = string()</c></tag>
@@ -82,8 +82,8 @@
to the same value as in the application resource file.</p></item>
</taglist>
<note>
- <p>The list of applications must contain the <c>Kernel</c> and
- <c>STDLIB</c> applications.</p>
+ <p>The list of applications must contain the Kernel and
+ STDLIB applications.</p>
</note>
</section>
diff --git a/lib/sasl/doc/src/release_handler.xml b/lib/sasl/doc/src/release_handler.xml
index bcbc5f5339..8f073807fb 100644
--- a/lib/sasl/doc/src/release_handler.xml
+++ b/lib/sasl/doc/src/release_handler.xml
@@ -31,7 +31,7 @@
<module>release_handler</module>
<modulesummary>Unpacking and Installation of Release Packages</modulesummary>
<description>
- <p>The <em>release handler</em> process belongs to the <c>SASL</c>
+ <p>The <em>release handler</em> process belongs to the SASL
application, which is responsible for <em>release handling</em>,
that is, unpacking, installation, and removal of release packages.</p>
<p>An introduction to release handling and an example is provided in
@@ -44,7 +44,7 @@
directory of the previous version of the release, where
<c>$ROOT</c> is the installation root directory,
<seealso marker="kernel:code#root_dir/0"><c>code:root_dir()</c></seealso>.
- Another <c>releases</c> directory can be specified using the <c>SASL</c>
+ Another <c>releases</c> directory can be specified using the SASL
configuration parameter <c>releases_dir</c> or the OS environment
variable <c>RELDIR</c>. The release handler must have write access
to this directory to install the new release.
@@ -56,7 +56,7 @@
<item>A boot script, <c>Name.boot</c></item>
</list>
<p>The <c>.rel</c> file contains information about the release: its name,
- version, and which <c>ERTS</c> and application versions it uses.</p>
+ version, and which ERTS and application versions it uses.</p>
<p>A release package can also contain:</p>
<list type="bulleted">
<item>A release upgrade file, <c>relup</c></item>
@@ -115,7 +115,7 @@
<em>System Documentation</em>. In this case, the system
configuration file <c>sys.config</c> is mandatory.</p>
<p>The installation of a new release can restart the system. Which
- program to use is specified by the <c>SASL</c> configuration
+ program to use is specified by the SASL configuration
parameter <c>start_prg</c>, which defaults
to <c>$ROOT/bin/start</c>.</p>
<p>The emulator restart on Windows NT expects that the system is
@@ -132,7 +132,7 @@
is made permanent.</p>
<p>The release handler at a node running on a diskless machine,
or with a read-only file system, must be configured accordingly
- using the following <c>SASL</c> configuration parameters (for
+ using the following SASL configuration parameters (for
details, see <seealso marker="sasl_app">sasl(6)</seealso>):</p>
<taglist>
<tag><c>masters</c></tag>
@@ -287,7 +287,7 @@
returned, the emulator is restarted
before the upgrade instructions are executed. This
occurs if the emulator or any of the applications
- <c>Kernel</c>, <c>STDLIB</c>, or <c>SASL</c>
+ Kernel, STDLIB, or SASL
are updated. The new emulator version
and these core applications execute after the restart.
For all other applications the old versions are
@@ -310,13 +310,13 @@
<tag><c>code_change_timeout</c></tag>
<item><p>Defines the time-out
for all calls to
- <seealso marker="stdlib:sys#change_code/4"><c>stdlib:sys:change_code</c></seealso>.
+ <seealso marker="stdlib:sys#change_code/4"><c>sys:change_code</c></seealso>.
If no value is specified or <c>default</c> is specified, the
default value defined in <c>sys</c> is used.</p></item>
<tag><c>suspend_timeout</c></tag>
<item><p>Defines the time-out for
all calls to
- <seealso marker="stdlib:sys#suspend/1"><c>stdlib:sys:suspend</c></seealso>.
+ <seealso marker="stdlib:sys#suspend/1"><c>sys:suspend</c></seealso>.
If no value is specified, the values defined by the <c>Timeout</c>
parameter of the <c>upgrade</c> or <c>suspend</c> instructions are used.
If <c>default</c> is specified, the default value defined in
@@ -342,7 +342,7 @@ release_handler:set_unpacked(RelFile, [{myapp,"1.0","/home/user"},...]).
=> {ok,NewVsn}</code>
<p>If <c>NewVsn</c> is installed with option
<c>{update_paths,true}</c>, then
- <seealso marker="kernel:code#lib_dir/1"><c>kernel:code:lib_dir(myapp)</c></seealso>
+ <seealso marker="kernel:code#lib_dir/1"><c>code:lib_dir(myapp)</c></seealso>
returns <c>/home/user/myapp-1.0</c>.</p></item>
</taglist>
<note>
@@ -801,7 +801,7 @@ release_handler:set_unpacked(RelFile, [{myapp,"1.0","/home/user"},...]).
is an atom named from the Posix error codes, such as
<c>enoent</c>, <c>eacces</c>, or <c>eisdir</c>. See
<seealso marker="kernel:file"><c>file(3)</c></seealso>
- in <c>Kernel</c>.</p></item>
+ in Kernel.</p></item>
<tag><c>Posix</c></tag>
<item><p>Some file operation failed, as for the previous item in
the list.</p></item>
diff --git a/lib/sasl/doc/src/sasl_app.xml b/lib/sasl/doc/src/sasl_app.xml
index 52f449c2a8..0576397f9b 100644
--- a/lib/sasl/doc/src/sasl_app.xml
+++ b/lib/sasl/doc/src/sasl_app.xml
@@ -31,17 +31,17 @@
<app>sasl</app>
<appsummary>The SASL application</appsummary>
<description>
- <p>The <c>SASL</c> application provides the following services:</p>
+ <p>The SASL application provides the following services:</p>
<list type="bulleted">
<item><c>alarm_handler</c></item>
<item><c>rb</c></item>
<item><c>release_handler</c></item>
<item><c>systools</c></item>
</list>
- <p>The <c>SASL</c> application also includes <c>error_logger</c> event
- handlers for formatting <c>SASL</c> error and crash reports.</p>
+ <p>The SASL application also includes <c>error_logger</c> event
+ handlers for formatting SASL error and crash reports.</p>
<note>
- <p>The <c>SASL</c> application in OTP has nothing to do with
+ <p>The SASL application in OTP has nothing to do with
"Simple Authentication and Security Layer" (RFC 4422).</p>
</note>
</description>
@@ -49,7 +49,7 @@
<section>
<title>Error Logger Event Handlers</title>
<p>The following error logger event handlers are used by
- the <c>SASL</c> application.</p>
+ the SASL application.</p>
<taglist>
<tag><c>sasl_report_tty_h</c></tag>
<item>
@@ -57,7 +57,7 @@
reports</em>, and <em>progress reports</em> to <c>stdio</c>.
This error logger event handler uses
<seealso marker="kernel:kernel_app#error_logger_format_depth">error_logger_format_depth</seealso>
- in the <c>Kernel</c> application to limit how much detail is
+ in the Kernel application to limit how much detail is
printed in crash and supervisor reports.</p>
</item>
<tag><c>sasl_report_file_h</c></tag>
@@ -66,7 +66,7 @@
report</em>, and <em>progress report</em> to a single file.
This error logger event handler uses
<seealso marker="kernel:kernel_app#error_logger_format_depth">error_logger_format_depth</seealso>
- in the <c>Kernel</c> application to limit the details
+ in the Kernel application to limit the details
printed in crash and supervisor reports.</p>
</item>
<tag><c>log_mf_h</c></tag>
@@ -75,9 +75,9 @@
error logger to disk. Multiple files and log rotation are
used. For efficiency reasons, each event is written as a
binary. For more information about this handler,
- see <seealso marker="stdlib:log_mf_h">the <c>STDLIB</c> Reference
+ see <seealso marker="stdlib:log_mf_h">the STDLIB Reference
Manual</seealso>.</p>
- <p>To activate this event handler, three <c>SASL</c>
+ <p>To activate this event handler, three SASL
configuration parameters must be set,
<c>error_logger_mf_dir</c>, <c>error_logger_mf_maxbytes</c>,
and <c>error_logger_mf_maxfiles</c>. The next section provides
@@ -88,9 +88,9 @@
<section>
<title>Configuration</title>
- <p>The following configuration parameters are defined for the <c>SASL</c>
+ <p>The following configuration parameters are defined for the SASL
application. For more information about configuration parameters, see
- <seealso marker="kernel:app"><c>app(4)</c></seealso> in <c>Kernel</c>.</p>
+ <seealso marker="kernel:app"><c>app(4)</c></seealso> in Kernel.</p>
<p>All configuration parameters are optional.</p>
<taglist>
<tag><c><![CDATA[sasl_error_logger = Value ]]></c></tag>
@@ -112,7 +112,7 @@
Use <c>[append]</c> to have the <c>FileName</c> open in append mode.
<c>FileName</c> is a string.</p></item>
<tag><c>false</c></tag>
- <item><p>No <c>SASL</c> error logger handler is installed.</p></item>
+ <item><p>No SASL error logger handler is installed.</p></item>
</taglist>
</item>
<tag><c><![CDATA[errlog_type = error | progress | all ]]></c></tag>
diff --git a/lib/sasl/doc/src/sasl_intro.xml b/lib/sasl/doc/src/sasl_intro.xml
index b71dafb192..f74a7c1db8 100644
--- a/lib/sasl/doc/src/sasl_intro.xml
+++ b/lib/sasl/doc/src/sasl_intro.xml
@@ -32,7 +32,7 @@
<section>
<title>Scope</title>
- <p>The <c>SASL</c> application provides support for:</p>
+ <p>The SASL application provides support for:</p>
<list type="bulleted">
<item>Error logging</item>
<item>Alarm handling</item>
diff --git a/lib/sasl/doc/src/systools.xml b/lib/sasl/doc/src/systools.xml
index 7446762de4..fa503fa573 100644
--- a/lib/sasl/doc/src/systools.xml
+++ b/lib/sasl/doc/src/systools.xml
@@ -85,7 +85,7 @@
</item>
<item>
<p>If the emulator needs to be restarted after upgrading or
- downgrading, that is, if the <c>ERTS</c> version differs
+ downgrading, that is, if the ERTS version differs
between <c>Name.rel</c> and <c>Name2.rel</c></p>
</item>
</list>
@@ -201,10 +201,10 @@
between the applications. Where there are no dependencies,
the order in the <c>.rel</c> file is kept.</p>
<p>The function fails if the mandatory
- applications <c>Kernel</c> and <c>STDLIB</c> are not
+ applications Kernel and STDLIB are not
included in the <c>.rel</c> file and have start
type <c>permanent</c> (which is default).</p>
- <p>If <c>SASL</c> is not included as an application in
+ <p>If SASL is not included as an application in
the <c>.rel</c> file, a warning is issued because such a
release cannot be used in an upgrade. To turn off this
warning, add option <c>no_warn_sasl</c>.</p>
diff --git a/lib/ssh/doc/src/ssh.xml b/lib/ssh/doc/src/ssh.xml
index e6c54d27bf..ef9f7cbd9b 100644
--- a/lib/ssh/doc/src/ssh.xml
+++ b/lib/ssh/doc/src/ssh.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>2004</year><year>2015</year>
+ <year>2004</year><year>2016</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -756,7 +756,7 @@
<p>Utility function that starts the applications <c>crypto</c>, <c>public_key</c>,
and <c>ssh</c>. Default type is <c>temporary</c>.
For more information, see the <seealso marker="kernel:application">application(3)</seealso>
- manual page in <c>kernel</c>.</p>
+ manual page in Kernel.</p>
</desc>
</func>
@@ -769,7 +769,7 @@
<desc>
<p>Stops the <c>ssh</c> application.
For more information, see the <seealso marker="kernel:application">application(3)</seealso>
- manual page in <c>kernel</c>.</p>
+ manual page in Kernel.</p>
</desc>
</func>
diff --git a/lib/ssh/doc/src/ssh_app.xml b/lib/ssh/doc/src/ssh_app.xml
index f6ce44c015..5cc4c24889 100644
--- a/lib/ssh/doc/src/ssh_app.xml
+++ b/lib/ssh/doc/src/ssh_app.xml
@@ -4,7 +4,7 @@
<appref>
<header>
<copyright>
- <year>2012</year><year>2015</year>
+ <year>2012</year><year>2016</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -203,7 +203,7 @@
<section>
<title>Unicode support</title>
<p>Unicode filenames are supported if the emulator and the underlaying OS support it. See section DESCRIPTION in the
- <seealso marker="kernel:file">file</seealso> manual page in <c>kernel</c> for information about this subject.
+ <seealso marker="kernel:file">file</seealso> manual page in Kernel for information about this subject.
</p>
<p>The shell and the cli both support unicode.
</p>
diff --git a/lib/ssh/doc/src/ssh_channel.xml b/lib/ssh/doc/src/ssh_channel.xml
index 907b0b3bec..7b598494f7 100644
--- a/lib/ssh/doc/src/ssh_channel.xml
+++ b/lib/ssh/doc/src/ssh_channel.xml
@@ -139,7 +139,7 @@
enters the <c>ssh_channel</c> process receive loop and become an
<c>ssh_channel process</c>. The process must have been started using
one of the start functions in <c>proc_lib</c>, see the <seealso
- marker="stdlib:proc_lib">proc_lib(3)</seealso> manual page in <c>stdlib</c>.
+ marker="stdlib:proc_lib">proc_lib(3)</seealso> manual page in STDLIB.
The user is responsible for any initialization of the process
and must call <seealso marker = "#init-1">ssh_channel:init/1</seealso>.
</p>
diff --git a/lib/ssh/src/ssh_auth.erl b/lib/ssh/src/ssh_auth.erl
index 1dcf5d0708..ac35b70209 100644
--- a/lib/ssh/src/ssh_auth.erl
+++ b/lib/ssh/src/ssh_auth.erl
@@ -140,7 +140,7 @@ publickey_msg([Alg, #ssh{user = User,
session_id = SessionId,
service = Service,
opts = Opts} = Ssh]) ->
- Hash = sha, %% Maybe option?!
+ Hash = ssh_transport:sha(Alg),
KeyCb = proplists:get_value(key_cb, Opts, ssh_file),
case KeyCb:user_key(Alg, Opts) of
{ok, PrivKey} ->
@@ -260,43 +260,54 @@ handle_userauth_request(#ssh_msg_userauth_request{user = User,
handle_userauth_request(#ssh_msg_userauth_request{user = User,
service = "ssh-connection",
method = "publickey",
- data = Data},
- SessionId,
+ data = <<?BYTE(?FALSE),
+ ?UINT32(ALen), BAlg:ALen/binary,
+ ?UINT32(KLen), KeyBlob:KLen/binary,
+ _/binary
+ >>
+ },
+ _SessionId,
#ssh{opts = Opts,
userauth_supported_methods = Methods} = Ssh) ->
- <<?BYTE(HaveSig),
- ?UINT32(ALen), BAlg:ALen/binary,
- Rest/binary>> = Data,
-
- {KeyBlob, SigWLen} =
- case Rest of
- <<?UINT32(KLen0), KeyBlob0:KLen0/binary, SigWLen0/binary>> ->
- {KeyBlob0, SigWLen0};
- <<>> ->
- {<<>>, <<>>}
- end,
-
- case HaveSig of
- ?TRUE ->
- case verify_sig(SessionId, User, "ssh-connection",
- binary_to_list(BAlg),
- KeyBlob, SigWLen, Opts) of
- true ->
- {authorized, User,
- ssh_transport:ssh_packet(
- #ssh_msg_userauth_success{}, Ssh)};
- false ->
- {not_authorized, {User, undefined},
- ssh_transport:ssh_packet(#ssh_msg_userauth_failure{
- authentications = Methods,
- partial_success = false}, Ssh)}
- end;
- ?FALSE ->
+ case pre_verify_sig(User, binary_to_list(BAlg),
+ KeyBlob, Opts) of
+ true ->
{not_authorized, {User, undefined},
ssh_transport:ssh_packet(
#ssh_msg_userauth_pk_ok{algorithm_name = binary_to_list(BAlg),
- key_blob = KeyBlob}, Ssh)}
+ key_blob = KeyBlob}, Ssh)};
+ false ->
+ {not_authorized, {User, undefined},
+ ssh_transport:ssh_packet(#ssh_msg_userauth_failure{
+ authentications = Methods,
+ partial_success = false}, Ssh)}
+ end;
+
+handle_userauth_request(#ssh_msg_userauth_request{user = User,
+ service = "ssh-connection",
+ method = "publickey",
+ data = <<?BYTE(?TRUE),
+ ?UINT32(ALen), BAlg:ALen/binary,
+ ?UINT32(KLen), KeyBlob:KLen/binary,
+ SigWLen/binary>>
+ },
+ SessionId,
+ #ssh{opts = Opts,
+ userauth_supported_methods = Methods} = Ssh) ->
+
+ case verify_sig(SessionId, User, "ssh-connection",
+ binary_to_list(BAlg),
+ KeyBlob, SigWLen, Opts) of
+ true ->
+ {authorized, User,
+ ssh_transport:ssh_packet(
+ #ssh_msg_userauth_success{}, Ssh)};
+ false ->
+ {not_authorized, {User, undefined},
+ ssh_transport:ssh_packet(#ssh_msg_userauth_failure{
+ authentications = Methods,
+ partial_success = false}, Ssh)}
end;
handle_userauth_request(#ssh_msg_userauth_request{user = User,
@@ -395,10 +406,22 @@ handle_userauth_info_response(#ssh_msg_userauth_info_response{num_responses = 1,
kb_tries_left = KbTriesLeft,
user = User,
userauth_supported_methods = Methods} = Ssh) ->
+ SendOneEmpty = proplists:get_value(tstflg, Opts) == one_empty,
case check_password(User, unicode:characters_to_list(Password), Opts, Ssh) of
+ {true,Ssh1} when SendOneEmpty==true ->
+ Msg = #ssh_msg_userauth_info_request{name = "",
+ instruction = "",
+ language_tag = "",
+ num_prompts = 0,
+ data = <<?BOOLEAN(?FALSE)>>
+ },
+ {authorized_but_one_more, User,
+ ssh_transport:ssh_packet(Msg, Ssh1)};
+
{true,Ssh1} ->
{authorized, User,
ssh_transport:ssh_packet(#ssh_msg_userauth_success{}, Ssh1)};
+
{false,Ssh1} ->
{not_authorized, {User, {error,"Bad user or password"}},
ssh_transport:ssh_packet(#ssh_msg_userauth_failure{
@@ -408,6 +431,11 @@ handle_userauth_info_response(#ssh_msg_userauth_info_response{num_responses = 1,
)}
end;
+handle_userauth_info_response({extra,#ssh_msg_userauth_info_response{}},
+ #ssh{user = User} = Ssh) ->
+ {authorized, User,
+ ssh_transport:ssh_packet(#ssh_msg_userauth_success{}, Ssh)};
+
handle_userauth_info_response(#ssh_msg_userauth_info_response{},
_Auth) ->
ssh_connection_handler:disconnect(
@@ -484,19 +512,34 @@ get_password_option(Opts, User) ->
false -> proplists:get_value(password, Opts, false)
end.
-verify_sig(SessionId, User, Service, Alg, KeyBlob, SigWLen, Opts) ->
- {ok, Key} = decode_public_key_v2(KeyBlob, Alg),
- KeyCb = proplists:get_value(key_cb, Opts, ssh_file),
+pre_verify_sig(User, Alg, KeyBlob, Opts) ->
+ try
+ {ok, Key} = decode_public_key_v2(KeyBlob, Alg),
+ KeyCb = proplists:get_value(key_cb, Opts, ssh_file),
+ KeyCb:is_auth_key(Key, User, Opts)
+ catch
+ _:_ ->
+ false
+ end.
- case KeyCb:is_auth_key(Key, User, Opts) of
- true ->
- PlainText = build_sig_data(SessionId, User,
- Service, KeyBlob, Alg),
- <<?UINT32(AlgSigLen), AlgSig:AlgSigLen/binary>> = SigWLen,
- <<?UINT32(AlgLen), _Alg:AlgLen/binary,
- ?UINT32(SigLen), Sig:SigLen/binary>> = AlgSig,
- ssh_transport:verify(PlainText, sha, Sig, Key);
- false ->
+verify_sig(SessionId, User, Service, Alg, KeyBlob, SigWLen, Opts) ->
+ try
+ {ok, Key} = decode_public_key_v2(KeyBlob, Alg),
+ KeyCb = proplists:get_value(key_cb, Opts, ssh_file),
+
+ case KeyCb:is_auth_key(Key, User, Opts) of
+ true ->
+ PlainText = build_sig_data(SessionId, User,
+ Service, KeyBlob, Alg),
+ <<?UINT32(AlgSigLen), AlgSig:AlgSigLen/binary>> = SigWLen,
+ <<?UINT32(AlgLen), _Alg:AlgLen/binary,
+ ?UINT32(SigLen), Sig:SigLen/binary>> = AlgSig,
+ ssh_transport:verify(PlainText, ssh_transport:sha(list_to_atom(Alg)), Sig, Key);
+ false ->
+ false
+ end
+ catch
+ _:_ ->
false
end.
diff --git a/lib/ssh/src/ssh_connection_handler.erl b/lib/ssh/src/ssh_connection_handler.erl
index 2eb29c9b32..facf6b561a 100644
--- a/lib/ssh/src/ssh_connection_handler.erl
+++ b/lib/ssh/src/ssh_connection_handler.erl
@@ -822,9 +822,21 @@ handle_event(_, #ssh_msg_userauth_info_response{} = Msg, {userauth_keyboard_inte
{not_authorized, {User, Reason}, {Reply, Ssh}} ->
retry_fun(User, Reason, D),
send_bytes(Reply, D),
- {next_state, {userauth,server}, D#data{ssh_params = Ssh}}
+ {next_state, {userauth,server}, D#data{ssh_params = Ssh}};
+
+ {authorized_but_one_more, _User, {Reply, Ssh}} ->
+ send_bytes(Reply, D),
+ {next_state, {userauth_keyboard_interactive_extra,server}, D#data{ssh_params = Ssh}}
end;
+handle_event(_, #ssh_msg_userauth_info_response{} = Msg, {userauth_keyboard_interactive_extra, server}, D) ->
+ {authorized, User, {Reply, Ssh}} = ssh_auth:handle_userauth_info_response({extra,Msg}, D#data.ssh_params),
+ send_bytes(Reply, D),
+ D#data.starter ! ssh_connected,
+ connected_fun(User, "keyboard-interactive", D),
+ {next_state, {connected,server}, D#data{auth_user = User,
+ ssh_params = Ssh#ssh{authenticated = true}}};
+
handle_event(_, Msg = #ssh_msg_userauth_failure{}, {userauth_keyboard_interactive, client},
#data{ssh_params = Ssh0} = D0) ->
Prefs = [{Method,M,F,A} || {Method,M,F,A} <- Ssh0#ssh.userauth_preference,
@@ -1238,9 +1250,12 @@ handle_event(internal, prepare_next_packet, _, D) ->
handle_event(info, {CloseTag,Socket}, StateName,
D = #data{socket = Socket,
transport_close_tag = CloseTag}) ->
- disconnect(#ssh_msg_disconnect{code = ?SSH_DISCONNECT_BY_APPLICATION,
- description = "Connection closed"},
- StateName, D);
+ %% Simulate a disconnect from the peer
+ handle_event(info,
+ #ssh_msg_disconnect{code = ?SSH_DISCONNECT_BY_APPLICATION,
+ description = "Connection closed"},
+ StateName,
+ D);
handle_event(info, {timeout, {_, From} = Request}, _,
#data{connection_state = #connection{requests = Requests} = C0} = D) ->
diff --git a/lib/ssh/src/ssh_transport.erl b/lib/ssh/src/ssh_transport.erl
index 7cb3b75ac0..15b80de30a 100644
--- a/lib/ssh/src/ssh_transport.erl
+++ b/lib/ssh/src/ssh_transport.erl
@@ -46,7 +46,7 @@
handle_kex_ecdh_reply/2,
extract_public_key/1,
ssh_packet/2, pack/2,
- sign/3, verify/4]).
+ sha/1, sign/3, verify/4]).
%%% For test suites
-export([pack/3]).
@@ -1619,6 +1619,11 @@ kex_h(SSH, Key, Min, NBits, Max, Prime, Gen, E, F, K) ->
crypto:hash(sha((SSH#ssh.algorithms)#alg.kex), L).
+sha('ssh-rsa') -> sha;
+sha('ssh-dss') -> sha;
+sha('ecdsa-sha2-nistp256') -> sha(secp256r1);
+sha('ecdsa-sha2-nistp384') -> sha(secp384r1);
+sha('ecdsa-sha2-nistp521') -> sha(secp521r1);
sha(secp256r1) -> sha256;
sha(secp384r1) -> sha384;
sha(secp521r1) -> sha512;
diff --git a/lib/ssl/doc/src/ssl_distribution.xml b/lib/ssl/doc/src/ssl_distribution.xml
index 4bd5f67202..1150043e76 100644
--- a/lib/ssl/doc/src/ssl_distribution.xml
+++ b/lib/ssl/doc/src/ssl_distribution.xml
@@ -71,8 +71,8 @@
<section>
<title>Building Boot Scripts Including the ssl Application</title>
<p>Boot scripts are built using the <c>systools</c> utility in the
- <c>sasl</c> application. For more information on <c>systools</c>,
- see the <c>sasl</c> documentation. This is only an example of
+ SASL application. For more information on <c>systools</c>,
+ see the SASL documentation. This is only an example of
what can be done.</p>
<p>The simplest boot script possible includes only the Kernel
diff --git a/lib/ssl/src/dtls_connection.erl b/lib/ssl/src/dtls_connection.erl
index a0d9982aaa..479f68f4bb 100644
--- a/lib/ssl/src/dtls_connection.erl
+++ b/lib/ssl/src/dtls_connection.erl
@@ -42,22 +42,17 @@
-export([next_record/1, next_event/3]).
%% Handshake handling
--export([%%renegotiate/2,
- send_handshake/2, queue_handshake/2, queue_change_cipher/2]).
+-export([renegotiate/2,
+ reinit_handshake_data/1,
+ send_handshake/2, queue_handshake/2, queue_change_cipher/2,
+ select_sni_extension/1]).
%% Alert and close handling
--export([%%send_alert/2, handle_own_alert/4, handle_close_alert/3,
- handle_normal_shutdown/3 %%, close/5
- %%alert_user/6, alert_user/9
- ]).
+-export([send_alert/2, close/5]).
%% Data handling
--export([%%write_application_data/3,
- read_application_data/2,
- passive_receive/2, next_record_if_active/1%,
- %%handle_common_event/4,
- %handle_packet/3
+-export([passive_receive/2, next_record_if_active/1, handle_common_event/4
]).
%% gen_statem state functions
@@ -102,10 +97,11 @@ send_handshake(Handshake, State) ->
send_handshake_flight(queue_handshake(Handshake, State)).
queue_flight_buffer(Msg, #state{negotiated_version = Version,
- connection_states = #connection_states{
- current_write =
- #connection_state{epoch = Epoch}},
+ connection_states = ConnectionStates,
flight_buffer = Flight} = State) ->
+ ConnectionState =
+ ssl_record:current_connection_state(ConnectionStates, write),
+ Epoch = maps:get(epoch, ConnectionState),
State#state{flight_buffer = Flight ++ [{Version, Epoch, Msg}]}.
queue_handshake(Handshake, #state{negotiated_version = Version,
@@ -139,6 +135,25 @@ send_alert(Alert, #state{negotiated_version = Version,
Transport:send(Socket, BinMsg),
State0#state{connection_states = ConnectionStates}.
+close(downgrade, _,_,_,_) ->
+ ok;
+%% Other
+close(_, Socket, Transport, _,_) ->
+ Transport:close(Socket).
+
+reinit_handshake_data(#state{protocol_buffers = Buffers} = State) ->
+ State#state{premaster_secret = undefined,
+ public_key_info = undefined,
+ tls_handshake_history = ssl_handshake:init_handshake_history(),
+ protocol_buffers =
+ Buffers#protocol_buffers{dtls_fragment_state =
+ dtls_handshake:dtls_handshake_new_flight(0)}}.
+
+select_sni_extension(#client_hello{extensions = HelloExtensions}) ->
+ HelloExtensions#hello_extensions.sni;
+select_sni_extension(_) ->
+ undefined.
+
%%====================================================================
%% tls_connection_sup API
%%====================================================================
@@ -232,7 +247,7 @@ hello(internal, #client_hello{client_version = ClientVersion,
case dtls_handshake:hello(Hello, SslOpts, {Port, Session0, Cache, CacheCb,
ConnectionStates0, Cert, KeyExAlg}, Renegotiation) of
#alert{} = Alert ->
- handle_own_alert(Alert, ClientVersion, hello, State);
+ ssl_connection:handle_own_alert(Alert, ClientVersion, hello, State);
{Version, {Type, Session},
ConnectionStates, Protocol0, ServerHelloExt, HashSign} ->
Protocol = case Protocol0 of
@@ -256,7 +271,7 @@ hello(internal, #server_hello{} = Hello,
ssl_options = SslOptions} = State) ->
case dtls_handshake:hello(Hello, SslOptions, ConnectionStates0, Renegotiation) of
#alert{} = Alert ->
- handle_own_alert(Alert, ReqVersion, hello, State);
+ ssl_connection:handle_own_alert(Alert, ReqVersion, hello, State);
{Version, NewId, ConnectionStates, ProtoExt, Protocol} ->
ssl_connection:handle_session(Hello,
Version, NewId, ConnectionStates, ProtoExt, Protocol, State)
@@ -335,7 +350,7 @@ handle_info({Protocol, _, Data}, StateName,
{Record, State} ->
next_event(StateName, Record, State);
#alert{} = Alert ->
- handle_normal_shutdown(Alert, StateName, State0),
+ ssl_connection:handle_normal_shutdown(Alert, StateName, State0),
{stop, {shutdown, own_alert}}
end;
handle_info({CloseTag, Socket}, StateName,
@@ -355,7 +370,7 @@ handle_info({CloseTag, Socket}, StateName,
%%invalidate_session(Role, Host, Port, Session)
ok
end,
- handle_normal_shutdown(?ALERT_REC(?FATAL, ?CLOSE_NOTIFY), StateName, State),
+ ssl_connection:handle_normal_shutdown(?ALERT_REC(?FATAL, ?CLOSE_NOTIFY), StateName, State),
{stop, {shutdown, transport_closed}};
handle_info(Msg, StateName, State) ->
ssl_connection:handle_info(Msg, StateName, State).
@@ -363,6 +378,51 @@ handle_info(Msg, StateName, State) ->
handle_call(Event, From, StateName, State) ->
ssl_connection:handle_call(Event, From, StateName, State, ?MODULE).
+handle_common_event(internal, #alert{} = Alert, StateName,
+ #state{negotiated_version = Version} = State) ->
+ ssl_connection:handle_own_alert(Alert, Version, StateName, State);
+
+%%% DTLS record protocol level handshake messages
+handle_common_event(internal, #ssl_tls{type = ?HANDSHAKE} = Record,
+ StateName,
+ #state{protocol_buffers =
+ #protocol_buffers{dtls_packets = Packets0,
+ dtls_fragment_state = HsState0} = Buffers,
+ negotiated_version = Version} = State0) ->
+ try
+ {Packets1, HsState} = dtls_handshake:get_dtls_handshake(Record, HsState0),
+ State =
+ State0#state{protocol_buffers =
+ Buffers#protocol_buffers{dtls_fragment_state = HsState}},
+ Events = dtls_handshake_events(Packets0 ++ Packets1),
+ case StateName of
+ connection ->
+ ssl_connection:hibernate_after(StateName, State, Events);
+ _ ->
+ {next_state, StateName, State, Events}
+ end
+ catch throw:#alert{} = Alert ->
+ ssl_connection:handle_own_alert(Alert, Version, StateName, State0)
+ end;
+%%% DTLS record protocol level application data messages
+handle_common_event(internal, #ssl_tls{type = ?APPLICATION_DATA, fragment = Data}, StateName, State) ->
+ {next_state, StateName, State, [{next_event, internal, {application_data, Data}}]};
+%%% DTLS record protocol level change cipher messages
+handle_common_event(internal, #ssl_tls{type = ?CHANGE_CIPHER_SPEC, fragment = Data}, StateName, State) ->
+ {next_state, StateName, State, [{next_event, internal, #change_cipher_spec{type = Data}}]};
+%%% DTLS record protocol level Alert messages
+handle_common_event(internal, #ssl_tls{type = ?ALERT, fragment = EncAlerts}, StateName,
+ #state{negotiated_version = Version} = State) ->
+ case decode_alerts(EncAlerts) of
+ Alerts = [_|_] ->
+ handle_alerts(Alerts, {next_state, StateName, State});
+ #alert{} = Alert ->
+ ssl_connection:handle_own_alert(Alert, Version, StateName, State)
+ end;
+%% Ignore unknown TLS record level protocol messages
+handle_common_event(internal, #ssl_tls{type = _Unknown}, StateName, State) ->
+ {next_state, StateName, State}.
+
%%--------------------------------------------------------------------
%% Description:This function is called by a gen_fsm when it is about
%% to terminate. It should be the opposite of Module:init/1 and do any
@@ -385,10 +445,21 @@ format_status(Type, Data) ->
%%--------------------------------------------------------------------
%%% Internal functions
%%--------------------------------------------------------------------
+
+dtls_handshake_events([]) ->
+ throw(?ALERT_REC(?FATAL, ?HANDSHAKE_FAILURE, malformed_handshake));
+dtls_handshake_events(Packets) ->
+ lists:map(fun(Packet) ->
+ {next_event, internal, {handshake, Packet}}
+ end, Packets).
+
+
encode_handshake(Handshake, Version, ConnectionStates0, Hist0) ->
{Seq, ConnectionStates} = sequence(ConnectionStates0),
{EncHandshake, Frag} = dtls_handshake:encode_handshake(Handshake, Version, Seq),
- Hist = ssl_handshake:update_handshake_history(Hist0, EncHandshake),
+ %% DTLS does not have an equivalent version to SSLv2. So v2 hello compatibility
+ %% will always be false
+ Hist = ssl_handshake:update_handshake_history(Hist0, EncHandshake, false),
{Frag, ConnectionStates, Hist}.
encode_change_cipher(#change_cipher_spec{}, Version, ConnectionStates) ->
@@ -424,12 +495,12 @@ encode_handshake_record(_Version, _Epoch, _Space, _MsgType, _MsgSeq, _Len, <<>>,
encode_handshake_record(Version, Epoch, Space, MsgType, MsgSeq, Len, Bin,
Offset, MRS, Encoded0, CS0) ->
MaxFragmentLen = Space - 25,
- case Bin of
- <<BinFragment:MaxFragmentLen/bytes, Rest/binary>> ->
- ok;
+ {BinFragment, Rest} =
+ case Bin of
+ <<BinFragment0:MaxFragmentLen/bytes, Rest0/binary>> ->
+ {BinFragment0, Rest0};
_ ->
- BinFragment = Bin,
- Rest = <<>>
+ {Bin, <<>>}
end,
FragLength = byte_size(BinFragment),
Frag = [MsgType, ?uint24(Len), ?uint16(MsgSeq), ?uint24(Offset), ?uint24(FragLength), BinFragment],
@@ -460,13 +531,13 @@ finish_pack_records({[], Acc}) ->
finish_pack_records({Buf, Acc}) ->
lists:reverse([lists:reverse(Buf)|Acc]).
-%% decode_alerts(Bin) ->
-%% ssl_alert:decode(Bin).
+decode_alerts(Bin) ->
+ ssl_alert:decode(Bin).
initial_state(Role, Host, Port, Socket, {SSLOptions, SocketOptions}, User,
{CbModule, DataTag, CloseTag, ErrorTag}) ->
#ssl_options{beast_mitigation = BeastMitigation} = SSLOptions,
- ConnectionStates = ssl_record:init_connection_states(Role, BeastMitigation),
+ ConnectionStates = dtls_record:init_connection_states(Role, BeastMitigation),
SessionCacheCb = case application:get_env(ssl, session_cb) of
{ok, Cb} when is_atom(Cb) ->
@@ -549,7 +620,7 @@ passive_receive(State0 = #state{user_data_buffer = Buffer}, StateName) ->
{Record, State} = next_record(State0),
next_event(StateName, Record, State);
_ ->
- {Record, State} = read_application_data(<<>>, State0),
+ {Record, State} = ssl_connection:read_application_data(<<>>, State0),
next_event(StateName, Record, State)
end.
@@ -561,7 +632,7 @@ next_event(connection = StateName, no_record, State0, Actions) ->
{no_record, State} ->
ssl_connection:hibernate_after(StateName, State, Actions);
{#ssl_tls{} = Record, State} ->
- {next_state, StateName, State, [{next_event, internal, {dtls_record, Record}} | Actions]};
+ {next_state, StateName, State, [{next_event, internal, {protocol_record, Record}} | Actions]};
{#alert{} = Alert, State} ->
{next_state, StateName, State, [{next_event, internal, Alert} | Actions]}
end;
@@ -570,20 +641,11 @@ next_event(StateName, Record, State, Actions) ->
no_record ->
{next_state, StateName, State, Actions};
#ssl_tls{} = Record ->
- {next_state, StateName, State, [{next_event, internal, {dtls_record, Record}} | Actions]};
+ {next_state, StateName, State, [{next_event, internal, {protocol_record, Record}} | Actions]};
#alert{} = Alert ->
{next_state, StateName, State, [{next_event, internal, Alert} | Actions]}
end.
-read_application_data(_,State) ->
- {#ssl_tls{fragment = <<"place holder">>}, State}.
-
-handle_own_alert(_,_,_, State) -> %% Place holder
- {stop, {shutdown, own_alert}, State}.
-
-handle_normal_shutdown(_, _, _State) -> %% Place holder
- ok.
-
%% TODO This generates dialyzer warnings, has to be handled differently.
%% handle_packet(Address, Port, Packet) ->
%% try dtls_record:get_dtls_records(Packet, <<>>) of
@@ -632,5 +694,34 @@ handle_normal_shutdown(_, _, _State) -> %% Place holder
%% address_to_bin({A,B,C,D,E,F,G,H}, Port) ->
%% <<A:16,B:16,C:16,D:16,E:16,F:16,G:16,H:16,Port:16>>.
-sequence(#connection_states{dtls_write_msg_seq = Seq} = CS) ->
- {Seq, CS#connection_states{dtls_write_msg_seq = Seq + 1}}.
+sequence(#{write_msg_seq := Seq} = ConnectionState) ->
+ {Seq, ConnectionState#{write_msg_seq => Seq + 1}}.
+
+renegotiate(#state{role = client} = State, Actions) ->
+ %% Handle same way as if server requested
+ %% the renegotiation
+ Hs0 = ssl_handshake:init_handshake_history(),
+ {next_state, connection, State#state{tls_handshake_history = Hs0,
+ protocol_buffers = #protocol_buffers{}},
+ [{next_event, internal, #hello_request{}} | Actions]};
+
+renegotiate(#state{role = server,
+ connection_states = CS0} = State0, Actions) ->
+ HelloRequest = ssl_handshake:hello_request(),
+ CS = CS0#{write_msg_seq => 0},
+ State1 = send_handshake(HelloRequest,
+ State0#state{connection_states =
+ CS}),
+ Hs0 = ssl_handshake:init_handshake_history(),
+ {Record, State} = next_record(State1#state{tls_handshake_history = Hs0,
+ protocol_buffers = #protocol_buffers{}}),
+ next_event(hello, Record, State, Actions).
+
+handle_alerts([], Result) ->
+ Result;
+handle_alerts(_, {stop,_} = Stop) ->
+ Stop;
+handle_alerts([Alert | Alerts], {next_state, StateName, State}) ->
+ handle_alerts(Alerts, ssl_connection:handle_alert(Alert, StateName, State));
+handle_alerts([Alert | Alerts], {next_state, StateName, State, _Actions}) ->
+ handle_alerts(Alerts, ssl_connection:handle_alert(Alert, StateName, State)).
diff --git a/lib/ssl/src/dtls_handshake.erl b/lib/ssl/src/dtls_handshake.erl
index 5a799cf441..c6535d5928 100644
--- a/lib/ssl/src/dtls_handshake.erl
+++ b/lib/ssl/src/dtls_handshake.erl
@@ -35,7 +35,7 @@
%% Internal application API
%%====================================================================
%%--------------------------------------------------------------------
--spec client_hello(host(), inet:port_number(), #connection_states{},
+-spec client_hello(host(), inet:port_number(), ssl_record:connection_states(),
#ssl_options{}, integer(), atom(), boolean(), der_cert()) ->
#client_hello{}.
%%
@@ -48,7 +48,7 @@ client_hello(Host, Port, ConnectionStates, SslOpts,
Cache, CacheCb, Renegotiation, OwnCert).
%%--------------------------------------------------------------------
--spec client_hello(host(), inet:port_number(), term(), #connection_states{},
+-spec client_hello(host(), inet:port_number(), term(), ssl_record:connection_states(),
#ssl_options{}, integer(), atom(), boolean(), der_cert()) ->
#client_hello{}.
%%
@@ -61,7 +61,7 @@ client_hello(Host, Port, Cookie, ConnectionStates,
Cache, CacheCb, Renegotiation, OwnCert) ->
Version = dtls_record:highest_protocol_version(Versions),
Pending = ssl_record:pending_connection_state(ConnectionStates, read),
- SecParams = Pending#connection_state.security_parameters,
+ SecParams = maps:get(security_parameters, Pending),
CipherSuites = ssl_handshake:available_suites(UserSuites, Version),
Extensions = ssl_handshake:client_hello_extensions(Host, dtls_v1:corresponding_tls_version(Version), CipherSuites,
@@ -445,29 +445,23 @@ enc_handshake(#client_hello{client_version = {Major, Minor},
cookie = Cookie,
cipher_suites = CipherSuites,
compression_methods = CompMethods,
- extensions = HelloExtensions}, Version) ->
+ extensions = HelloExtensions}, _Version) ->
SIDLength = byte_size(SessionID),
- BinCookie = enc_client_hello_cookie(Version, Cookie),
+ CookieLength = byte_size(Cookie),
BinCompMethods = list_to_binary(CompMethods),
CmLength = byte_size(BinCompMethods),
BinCipherSuites = list_to_binary(CipherSuites),
CsLength = byte_size(BinCipherSuites),
ExtensionsBin = ssl_handshake:encode_hello_extensions(HelloExtensions),
-
+
{?CLIENT_HELLO, <<?BYTE(Major), ?BYTE(Minor), Random:32/binary,
?BYTE(SIDLength), SessionID/binary,
- BinCookie/binary,
+ ?BYTE(CookieLength), Cookie/binary,
?UINT16(CsLength), BinCipherSuites/binary,
?BYTE(CmLength), BinCompMethods/binary, ExtensionsBin/binary>>};
enc_handshake(HandshakeMsg, Version) ->
ssl_handshake:encode_handshake(HandshakeMsg, Version).
-enc_client_hello_cookie(_, <<>>) ->
- <<>>;
-enc_client_hello_cookie(_, Cookie) ->
- CookieLength = byte_size(Cookie),
- <<?BYTE(CookieLength), Cookie/binary>>.
-
decode_handshake(_Version, ?CLIENT_HELLO, <<?BYTE(Major), ?BYTE(Minor), Random:32/binary,
?BYTE(SID_length), Session_ID:SID_length/binary,
?BYTE(Cookie_length), Cookie:Cookie_length/binary,
diff --git a/lib/ssl/src/dtls_record.erl b/lib/ssl/src/dtls_record.erl
index 5387fcafa8..8a6e2d315c 100644
--- a/lib/ssl/src/dtls_record.erl
+++ b/lib/ssl/src/dtls_record.erl
@@ -30,7 +30,7 @@
-include("ssl_cipher.hrl").
%% Handling of incoming data
--export([get_dtls_records/2]).
+-export([get_dtls_records/2, init_connection_states/2]).
%% Decoding
-export([decode_cipher_text/2]).
@@ -58,7 +58,26 @@
%%====================================================================
%% Internal application API
%%====================================================================
-
+%%--------------------------------------------------------------------
+-spec init_connection_states(client | server, one_n_minus_one | zero_n | disabled) ->
+ ssl_record:connection_states().
+%% %
+ %
+%% Description: Creates a connection_states record with appropriate
+%% values for the initial SSL connection setup.
+%%--------------------------------------------------------------------
+init_connection_states(Role, BeastMitigation) ->
+ ConnectionEnd = ssl_record:record_protocol_role(Role),
+ Current = initial_connection_state(ConnectionEnd, BeastMitigation),
+ Pending = ssl_record:empty_connection_state(ConnectionEnd, BeastMitigation),
+ #{write_msg_seq => 0,
+ prvious_read => undefined,
+ current_read => Current,
+ pending_read => Pending,
+ prvious_write => undefined,
+ current_write => Current,
+ pending_write => Pending}.
+
%%--------------------------------------------------------------------
-spec get_dtls_records(binary(), binary()) -> {[binary()], binary()} | #alert{}.
%%
@@ -122,63 +141,59 @@ get_dtls_records_aux(Data, Acc) ->
end.
encode_plain_text(Type, Version, Data,
- #connection_states{current_write =
- #connection_state{
- epoch = Epoch,
- sequence_number = Seq,
- compression_state=CompS0,
- security_parameters=
- #security_parameters{
- cipher_type = ?AEAD,
- compression_algorithm=CompAlg}
- }= WriteState0} = ConnectionStates) ->
+ #{current_write :=
+ #{epoch := Epoch,
+ sequence_number := Seq,
+ compression_state := CompS0,
+ security_parameters :=
+ #security_parameters{
+ cipher_type = ?AEAD,
+ compression_algorithm = CompAlg}
+ }= WriteState0} = ConnectionStates) ->
{Comp, CompS1} = ssl_record:compress(CompAlg, Data, CompS0),
- WriteState1 = WriteState0#connection_state{compression_state = CompS1},
+ WriteState1 = WriteState0#{compression_state => CompS1},
AAD = calc_aad(Type, Version, Epoch, Seq),
{CipherFragment, WriteState} = ssl_record:cipher_aead(dtls_v1:corresponding_tls_version(Version),
Comp, WriteState1, AAD),
CipherText = encode_tls_cipher_text(Type, Version, Epoch, Seq, CipherFragment),
- {CipherText, ConnectionStates#connection_states{current_write =
- WriteState#connection_state{sequence_number = Seq +1}}};
+ {CipherText, ConnectionStates#{current_write => WriteState#{sequence_number => Seq +1}}};
encode_plain_text(Type, Version, Data,
- #connection_states{current_write=#connection_state{
- epoch = Epoch,
- sequence_number = Seq,
- compression_state=CompS0,
- security_parameters=
- #security_parameters{compression_algorithm=CompAlg}
- }= WriteState0} = ConnectionStates) ->
+ #{current_write :=
+ #{epoch := Epoch,
+ sequence_number := Seq,
+ compression_state := CompS0,
+ security_parameters :=
+ #security_parameters{compression_algorithm = CompAlg}
+ }= WriteState0} = ConnectionStates) ->
{Comp, CompS1} = ssl_record:compress(CompAlg, Data, CompS0),
- WriteState1 = WriteState0#connection_state{compression_state = CompS1},
+ WriteState1 = WriteState0#{compression_state => CompS1},
MacHash = calc_mac_hash(WriteState1, Type, Version, Epoch, Seq, Comp),
{CipherFragment, WriteState} = ssl_record:cipher(dtls_v1:corresponding_tls_version(Version),
Comp, WriteState1, MacHash),
CipherText = encode_tls_cipher_text(Type, Version, Epoch, Seq, CipherFragment),
- {CipherText, ConnectionStates#connection_states{current_write =
- WriteState#connection_state{sequence_number = Seq +1}}}.
+ {CipherText, ConnectionStates#{current_write => WriteState#{sequence_number => Seq +1}}}.
decode_cipher_text(#ssl_tls{type = Type, version = Version,
epoch = Epoch,
sequence_number = Seq,
fragment = CipherFragment} = CipherText,
- #connection_states{current_read =
- #connection_state{
- compression_state = CompressionS0,
- security_parameters=
- #security_parameters{
- cipher_type = ?AEAD,
- compression_algorithm=CompAlg}
- } = ReadState0}= ConnnectionStates0) ->
+ #{current_read :=
+ #{compression_state := CompressionS0,
+ security_parameters :=
+ #security_parameters{
+ cipher_type = ?AEAD,
+ compression_algorithm = CompAlg}
+ } = ReadState0} = ConnnectionStates0) ->
AAD = calc_aad(Type, Version, Epoch, Seq),
case ssl_record:decipher_aead(dtls_v1:corresponding_tls_version(Version),
CipherFragment, ReadState0, AAD) of
{PlainFragment, ReadState1} ->
{Plain, CompressionS1} = ssl_record:uncompress(CompAlg,
PlainFragment, CompressionS0),
- ConnnectionStates = ConnnectionStates0#connection_states{
- current_read = ReadState1#connection_state{
- compression_state = CompressionS1}},
+ ConnnectionStates = ConnnectionStates0#{
+ current_read => ReadState1#{
+ compression_state => CompressionS1}},
{CipherText#ssl_tls{fragment = Plain}, ConnnectionStates};
#alert{} = Alert ->
Alert
@@ -188,13 +203,12 @@ decode_cipher_text(#ssl_tls{type = Type, version = Version,
epoch = Epoch,
sequence_number = Seq,
fragment = CipherFragment} = CipherText,
- #connection_states{current_read =
- #connection_state{
- compression_state = CompressionS0,
- security_parameters=
- #security_parameters{
- compression_algorithm=CompAlg}
- } = ReadState0}= ConnnectionStates0) ->
+ #{current_read :=
+ #{compression_state := CompressionS0,
+ security_parameters :=
+ #security_parameters{
+ compression_algorithm = CompAlg}
+ } = ReadState0}= ConnnectionStates0) ->
{PlainFragment, Mac, ReadState1} = ssl_record:decipher(dtls_v1:corresponding_tls_version(Version),
CipherFragment, ReadState0, true),
MacHash = calc_mac_hash(ReadState1, Type, Version, Epoch, Seq, PlainFragment),
@@ -202,17 +216,17 @@ decode_cipher_text(#ssl_tls{type = Type, version = Version,
true ->
{Plain, CompressionS1} = ssl_record:uncompress(CompAlg,
PlainFragment, CompressionS0),
- ConnnectionStates = ConnnectionStates0#connection_states{
- current_read = ReadState1#connection_state{
- compression_state = CompressionS1}},
+ ConnnectionStates = ConnnectionStates0#{
+ current_read => ReadState1#{
+ compression_state => CompressionS1}},
{CipherText#ssl_tls{fragment = Plain}, ConnnectionStates};
false ->
?ALERT_REC(?FATAL, ?BAD_RECORD_MAC)
end.
%%--------------------------------------------------------------------
--spec encode_change_cipher_spec(dtls_version(), #connection_states{}) ->
- {iolist(), #connection_states{}}.
+-spec encode_change_cipher_spec(dtls_version(), ssl_record:connection_states()) ->
+ {iolist(), ssl_record:connection_states()}.
%%
%% Description: Encodes a change_cipher_spec-message to send on the ssl socket.
%%--------------------------------------------------------------------
@@ -352,92 +366,87 @@ is_acceptable_version(Version, Versions) ->
%%--------------------------------------------------------------------
--spec init_connection_state_seq(dtls_version(), #connection_states{}) ->
- #connection_state{}.
+-spec init_connection_state_seq(dtls_version(), ssl_record:connection_states()) ->
+ ssl_record:connection_state().
%%
%% Description: Copy the read sequence number to the write sequence number
%% This is only valid for DTLS in the first client_hello
%%--------------------------------------------------------------------
init_connection_state_seq({254, _},
- #connection_states{
- current_read = Read = #connection_state{epoch = 0},
- current_write = Write = #connection_state{epoch = 0}} = CS0) ->
- CS0#connection_states{current_write =
- Write#connection_state{
- sequence_number = Read#connection_state.sequence_number}};
+ #{current_read := #{epoch := 0} = Read,
+ current_write := #{epoch := 0} = Write} = CS0) ->
+ Seq = maps:get(sequence_number, Read),
+ CS0#{current_write => Write#{sequence_number => Seq}};
init_connection_state_seq(_, CS) ->
CS.
%%--------------------------------------------------------
--spec current_connection_state_epoch(#connection_states{}, read | write) ->
+-spec current_connection_state_epoch(ssl_record:connection_states(), read | write) ->
integer().
%%
%% Description: Returns the epoch the connection_state record
%% that is currently defined as the current conection state.
%%--------------------------------------------------------------------
-current_connection_state_epoch(#connection_states{current_read = Current},
+current_connection_state_epoch(#{current_read := Current},
read) ->
- Current#connection_state.epoch;
-current_connection_state_epoch(#connection_states{current_write = Current},
+ maps:get(epoch, Current);
+current_connection_state_epoch(#{current_write := Current},
write) ->
- Current#connection_state.epoch.
+ maps:get(epoch, Current).
%%--------------------------------------------------------------------
--spec connection_state_by_epoch(#connection_states{}, integer(), read | write) ->
- #connection_state{}.
+-spec connection_state_by_epoch(ssl_record:connection_states(), integer(), read | write) ->
+ ssl_record:connection_state().
%%
%% Description: Returns the instance of the connection_state record
%% that is defined by the Epoch.
%%--------------------------------------------------------------------
-connection_state_by_epoch(#connection_states{current_read = CS}, Epoch, read)
- when CS#connection_state.epoch == Epoch ->
+connection_state_by_epoch(#{current_read := #{epoch := Epoch}} = CS, Epoch, read) ->
CS;
-connection_state_by_epoch(#connection_states{pending_read = CS}, Epoch, read)
- when CS#connection_state.epoch == Epoch ->
+connection_state_by_epoch(#{pending_read := #{epoch := Epoch}} = CS, Epoch, read) ->
CS;
-connection_state_by_epoch(#connection_states{current_write = CS}, Epoch, write)
- when CS#connection_state.epoch == Epoch ->
+connection_state_by_epoch(#{current_write := #{epoch := Epoch}} = CS, Epoch, write) ->
CS;
-connection_state_by_epoch(#connection_states{pending_write = CS}, Epoch, write)
- when CS#connection_state.epoch == Epoch ->
+connection_state_by_epoch(#{pending_write := #{epoch := Epoch}} = CS, Epoch, write) ->
CS.
%%--------------------------------------------------------------------
--spec set_connection_state_by_epoch(#connection_states{},
- #connection_state{}, read | write)
- -> #connection_states{}.
+-spec set_connection_state_by_epoch(ssl_record:connection_states(),
+ ssl_record:connection_state(), read | write)
+ -> ssl_record:connection_states().
%%
%% Description: Returns the instance of the connection_state record
%% that is defined by the Epoch.
%%--------------------------------------------------------------------
-set_connection_state_by_epoch(ConnectionStates0 =
- #connection_states{current_read = CS},
- NewCS = #connection_state{epoch = Epoch}, read)
- when CS#connection_state.epoch == Epoch ->
- ConnectionStates0#connection_states{current_read = NewCS};
-
-set_connection_state_by_epoch(ConnectionStates0 =
- #connection_states{pending_read = CS},
- NewCS = #connection_state{epoch = Epoch}, read)
- when CS#connection_state.epoch == Epoch ->
- ConnectionStates0#connection_states{pending_read = NewCS};
-
-set_connection_state_by_epoch(ConnectionStates0 =
- #connection_states{current_write = CS},
- NewCS = #connection_state{epoch = Epoch}, write)
- when CS#connection_state.epoch == Epoch ->
- ConnectionStates0#connection_states{current_write = NewCS};
-
-set_connection_state_by_epoch(ConnectionStates0 =
- #connection_states{pending_write = CS},
- NewCS = #connection_state{epoch = Epoch}, write)
- when CS#connection_state.epoch == Epoch ->
- ConnectionStates0#connection_states{pending_write = NewCS}.
+set_connection_state_by_epoch(#{current_read := #{epoch := Epoch}} = ConnectionStates0,
+ NewCS = #{epoch := Epoch}, read) ->
+ ConnectionStates0#{current_read => NewCS};
+set_connection_state_by_epoch(#{pending_read := #{epoch := Epoch}} = ConnectionStates0,
+ NewCS = #{epoch := Epoch}, read) ->
+ ConnectionStates0#{pending_read => NewCS};
+set_connection_state_by_epoch(#{current_write := #{epoch := Epoch}} = ConnectionStates0,
+ NewCS = #{epoch := Epoch}, write) ->
+ ConnectionStates0#{current_write => NewCS};
+set_connection_state_by_epoch(#{pending_write := #{epoch := Epoch}} = ConnectionStates0,
+NewCS = #{epoch := Epoch}, write) ->
+ ConnectionStates0#{pending_write => NewCS}.
%%--------------------------------------------------------------------
%%% Internal functions
%%--------------------------------------------------------------------
-
+initial_connection_state(ConnectionEnd, BeastMitigation) ->
+ #{security_parameters =>
+ ssl_record:initial_security_params(ConnectionEnd),
+ epoch => 0,
+ sequence_number => 1,
+ beast_mitigation => BeastMitigation,
+ compression_state => undefined,
+ cipher_state => undefined,
+ mac_secret => undefined,
+ secure_renegotiation => undefined,
+ client_verify_data => undefined,
+ server_verify_data => undefined
+ }.
lowest_list_protocol_version(Ver, []) ->
Ver;
@@ -454,8 +463,8 @@ encode_tls_cipher_text(Type, {MajVer, MinVer}, Epoch, Seq, Fragment) ->
[<<?BYTE(Type), ?BYTE(MajVer), ?BYTE(MinVer), ?UINT16(Epoch),
?UINT48(Seq), ?UINT16(Length)>>, Fragment].
-calc_mac_hash(#connection_state{mac_secret = MacSecret,
- security_parameters = #security_parameters{mac_algorithm = MacAlg}},
+calc_mac_hash(#{mac_secret := MacSecret,
+ security_parameters := #security_parameters{mac_algorithm = MacAlg}},
Type, Version, Epoch, SeqNo, Fragment) ->
Length = erlang:iolist_size(Fragment),
NewSeq = (Epoch bsl 48) + SeqNo,
diff --git a/lib/ssl/src/ssl.appup.src b/lib/ssl/src/ssl.appup.src
index 22e24af0a8..32252386b4 100644
--- a/lib/ssl/src/ssl.appup.src
+++ b/lib/ssl/src/ssl.appup.src
@@ -7,5 +7,5 @@
[
{<<"^8[.]0([.][0-9]+)?$">>, [{restart_application, ssl}]},
{<<"^[3-7][.][^.].*">>, [{restart_application, ssl}]}
- ]
+ ]
}.
diff --git a/lib/ssl/src/ssl.erl b/lib/ssl/src/ssl.erl
index d2aeb3258f..27b753af2e 100644
--- a/lib/ssl/src/ssl.erl
+++ b/lib/ssl/src/ssl.erl
@@ -43,7 +43,7 @@
renegotiate/1, prf/5, negotiated_protocol/1, negotiated_next_protocol/1,
connection_information/1, connection_information/2]).
%% Misc
--export([handle_options/2]).
+-export([handle_options/2, tls_version/1]).
-deprecated({negotiated_next_protocol, 1, next_major_release}).
-deprecated({connection_info, 1, next_major_release}).
@@ -607,6 +607,11 @@ format_error(Error) ->
Other
end.
+tls_version({3, _} = Version) ->
+ Version;
+tls_version({254, _} = Version) ->
+ dtls_v1:corresponding_tls_version(Version).
+
%%%--------------------------------------------------------------
%%% Internal functions
%%%--------------------------------------------------------------------
diff --git a/lib/ssl/src/ssl_alert.erl b/lib/ssl/src/ssl_alert.erl
index db71b16d80..05dfb4c1b3 100644
--- a/lib/ssl/src/ssl_alert.erl
+++ b/lib/ssl/src/ssl_alert.erl
@@ -39,8 +39,8 @@
%%====================================================================
%%--------------------------------------------------------------------
--spec encode(#alert{}, ssl_record:ssl_version(), #connection_states{}) ->
- {iolist(), #connection_states{}}.
+-spec encode(#alert{}, ssl_record:ssl_version(), ssl_record:connection_states()) ->
+ {iolist(), ssl_record:connection_states()}.
%%
%% Description: Encodes an alert
%%--------------------------------------------------------------------
diff --git a/lib/ssl/src/ssl_connection.erl b/lib/ssl/src/ssl_connection.erl
index 8a990870e8..304d1706f5 100644
--- a/lib/ssl/src/ssl_connection.erl
+++ b/lib/ssl/src/ssl_connection.erl
@@ -58,6 +58,13 @@
-export([handle_info/3, handle_call/5, handle_session/7, ssl_config/3,
prepare_connection/2, hibernate_after/3]).
+%% Alert and close handling
+-export([handle_own_alert/4,handle_alert/3,
+ handle_normal_shutdown/3
+ ]).
+
+%% Data handling
+-export([write_application_data/3, read_application_data/2]).
%%====================================================================
%% Internal application API
@@ -264,7 +271,7 @@ prf(ConnectionPid, Secret, Label, Seed, WantedLength) ->
%%--------------------------------------------------------------------
-spec handle_session(#server_hello{}, ssl_record:ssl_version(),
- binary(), #connection_states{}, _,_, #state{}) ->
+ binary(), ssl_record:connection_states(), _,_, #state{}) ->
gen_statem:state_function_result().
%%--------------------------------------------------------------------
handle_session(#server_hello{cipher_suite = CipherSuite,
@@ -272,19 +279,21 @@ handle_session(#server_hello{cipher_suite = CipherSuite,
Version, NewId, ConnectionStates, ProtoExt, Protocol0,
#state{session = #session{session_id = OldId},
negotiated_version = ReqVersion,
- negotiated_protocol = CurrentProtocol} = State0) ->
+ negotiated_protocol = CurrentProtocol} = State0) ->
{KeyAlgorithm, _, _, _} =
ssl_cipher:suite_definition(CipherSuite),
PremasterSecret = make_premaster_secret(ReqVersion, KeyAlgorithm),
- {ExpectNPN, Protocol} = case Protocol0 of
- undefined -> {false, CurrentProtocol};
- _ -> {ProtoExt =:= npn, Protocol0}
- end,
+ {ExpectNPN, Protocol} = case Protocol0 of
+ undefined ->
+ {false, CurrentProtocol};
+ _ ->
+ {ProtoExt =:= npn, Protocol0}
+ end,
State = State0#state{key_algorithm = KeyAlgorithm,
- negotiated_version = Version,
+ negotiated_version = Version,
connection_states = ConnectionStates,
premaster_secret = PremasterSecret,
expecting_next_protocol_negotiation = ExpectNPN,
@@ -382,7 +391,7 @@ abbreviated(internal, #finished{verify_data = Data} = Finished,
session = #session{master_secret = MasterSecret},
connection_states = ConnectionStates0} =
State0, Connection) ->
- case ssl_handshake:verify_connection(Version, Finished, client,
+ case ssl_handshake:verify_connection(ssl:tls_version(Version), Finished, client,
get_current_prf(ConnectionStates0, write),
MasterSecret, Handshake) of
verified ->
@@ -392,7 +401,7 @@ abbreviated(internal, #finished{verify_data = Data} = Finished,
expecting_finished = false}, Connection),
Connection:next_event(connection, Record, State);
#alert{} = Alert ->
- Connection:handle_own_alert(Alert, Version, abbreviated, State0)
+ handle_own_alert(Alert, Version, abbreviated, State0)
end;
abbreviated(internal, #finished{verify_data = Data} = Finished,
@@ -400,7 +409,7 @@ abbreviated(internal, #finished{verify_data = Data} = Finished,
session = #session{master_secret = MasterSecret},
negotiated_version = Version,
connection_states = ConnectionStates0} = State0, Connection) ->
- case ssl_handshake:verify_connection(Version, Finished, server,
+ case ssl_handshake:verify_connection(ssl:tls_version(Version), Finished, server,
get_pending_prf(ConnectionStates0, write),
MasterSecret, Handshake0) of
verified ->
@@ -412,7 +421,7 @@ abbreviated(internal, #finished{verify_data = Data} = Finished,
{Record, State} = prepare_connection(State1#state{expecting_finished = false}, Connection),
Connection:next_event(connection, Record, State);
#alert{} = Alert ->
- Connection:handle_own_alert(Alert, Version, abbreviated, State0)
+ handle_own_alert(Alert, Version, abbreviated, State0)
end;
%% only allowed to send next_protocol message after change cipher spec
@@ -452,9 +461,9 @@ certify(internal, #certificate{asn1_certificates = []},
#state{role = server, negotiated_version = Version,
ssl_options = #ssl_options{verify = verify_peer,
fail_if_no_peer_cert = true}} =
- State, Connection) ->
+ State, _Connection) ->
Alert = ?ALERT_REC(?FATAL,?HANDSHAKE_FAILURE),
- Connection:handle_own_alert(Alert, Version, certify, State);
+ handle_own_alert(Alert, Version, certify, State);
certify(internal, #certificate{asn1_certificates = []},
#state{role = server,
@@ -469,9 +478,9 @@ certify(internal, #certificate{},
#state{role = server,
negotiated_version = Version,
ssl_options = #ssl_options{verify = verify_none}} =
- State, Connection) ->
+ State, _Connection) ->
Alert = ?ALERT_REC(?FATAL,?UNEXPECTED_MESSAGE, unrequested_certificate),
- Connection:handle_own_alert(Alert, Version, certify, State);
+ handle_own_alert(Alert, Version, certify, State);
certify(internal, #certificate{} = Cert,
#state{negotiated_version = Version,
@@ -492,7 +501,7 @@ certify(internal, #certificate{} = Cert,
handle_peer_cert(Role, PeerCert, PublicKeyInfo,
State#state{client_certificate_requested = false}, Connection);
#alert{} = Alert ->
- Connection:handle_own_alert(Alert, Version, certify, State)
+ handle_own_alert(Alert, Version, certify, State)
end;
certify(internal, #server_key_exchange{exchange_keys = Keys},
@@ -506,10 +515,10 @@ certify(internal, #server_key_exchange{exchange_keys = Keys},
Alg == psk; Alg == dhe_psk; Alg == rsa_psk;
Alg == srp_dss; Alg == srp_rsa; Alg == srp_anon ->
- Params = ssl_handshake:decode_server_key(Keys, Alg, Version),
+ Params = ssl_handshake:decode_server_key(Keys, Alg, ssl:tls_version(Version)),
%% Use negotiated value if TLS-1.2 otherwhise return default
- HashSign = negotiated_hashsign(Params#server_key_params.hashsign, Alg, PubKeyInfo, Version),
+ HashSign = negotiated_hashsign(Params#server_key_params.hashsign, Alg, PubKeyInfo, ssl:tls_version(Version)),
case is_anonymous(Alg) of
true ->
@@ -517,13 +526,13 @@ certify(internal, #server_key_exchange{exchange_keys = Keys},
State#state{hashsign_algorithm = HashSign}, Connection);
false ->
case ssl_handshake:verify_server_key(Params, HashSign,
- ConnectionStates, Version, PubKeyInfo) of
+ ConnectionStates, ssl:tls_version(Version), PubKeyInfo) of
true ->
calculate_secret(Params#server_key_params.params,
State#state{hashsign_algorithm = HashSign},
Connection);
false ->
- Connection:handle_own_alert(?ALERT_REC(?FATAL, ?DECRYPT_ERROR),
+ handle_own_alert(?ALERT_REC(?FATAL, ?DECRYPT_ERROR),
Version, certify, State)
end
end;
@@ -533,9 +542,9 @@ certify(internal, #certificate_request{} = CertRequest,
role = client,
ssl_options = #ssl_options{signature_algs = SupportedHashSigns},
negotiated_version = Version} = State0, Connection) ->
- case ssl_handshake:select_hashsign(CertRequest, Cert, SupportedHashSigns, Version) of
+ case ssl_handshake:select_hashsign(CertRequest, Cert, SupportedHashSigns, ssl:tls_version(Version)) of
#alert {} = Alert ->
- Connection:handle_own_alert(Alert, Version, certify, State0);
+ handle_own_alert(Alert, Version, certify, State0);
NegotiatedHashSign ->
{Record, State} = Connection:next_record(State0#state{client_certificate_requested = true}),
Connection:next_event(certify, Record,
@@ -554,7 +563,7 @@ certify(internal, #server_hello_done{},
when Alg == psk ->
case ssl_handshake:premaster_secret({Alg, PSKIdentity}, PSKLookup) of
#alert{} = Alert ->
- Connection:handle_own_alert(Alert, Version, certify, State0);
+ handle_own_alert(Alert, Version, certify, State0);
PremasterSecret ->
State = master_secret(PremasterSecret,
State0#state{premaster_secret = PremasterSecret}),
@@ -575,7 +584,7 @@ certify(internal, #server_hello_done{},
case ssl_handshake:premaster_secret({Alg, PSKIdentity}, PSKLookup,
RSAPremasterSecret) of
#alert{} = Alert ->
- Connection:handle_own_alert(Alert, Version, certify, State0);
+ handle_own_alert(Alert, Version, certify, State0);
PremasterSecret ->
State = master_secret(PremasterSecret,
State0#state{premaster_secret = RSAPremasterSecret}),
@@ -589,13 +598,13 @@ certify(internal, #server_hello_done{},
negotiated_version = Version,
premaster_secret = undefined,
role = client} = State0, Connection) ->
- case ssl_handshake:master_secret(record_cb(Connection), Version, Session,
+ case ssl_handshake:master_secret(ssl:tls_version(Version), Session,
ConnectionStates0, client) of
{MasterSecret, ConnectionStates} ->
State = State0#state{connection_states = ConnectionStates},
client_certify_and_key_exchange(State, Connection);
#alert{} = Alert ->
- Connection:handle_own_alert(Alert, Version, certify, State0)
+ handle_own_alert(Alert, Version, certify, State0)
end;
%% Master secret is calculated from premaster_secret
@@ -605,7 +614,7 @@ certify(internal, #server_hello_done{},
negotiated_version = Version,
premaster_secret = PremasterSecret,
role = client} = State0, Connection) ->
- case ssl_handshake:master_secret(record_cb(Connection), Version, PremasterSecret,
+ case ssl_handshake:master_secret(ssl:tls_version(Version), PremasterSecret,
ConnectionStates0, client) of
{MasterSecret, ConnectionStates} ->
Session = Session0#session{master_secret = MasterSecret},
@@ -613,7 +622,7 @@ certify(internal, #server_hello_done{},
session = Session},
client_certify_and_key_exchange(State, Connection);
#alert{} = Alert ->
- Connection:handle_own_alert(Alert, Version, certify, State0)
+ handle_own_alert(Alert, Version, certify, State0)
end;
certify(internal = Type, #client_key_exchange{} = Msg,
@@ -627,11 +636,11 @@ certify(internal = Type, #client_key_exchange{} = Msg,
certify(internal, #client_key_exchange{exchange_keys = Keys},
State = #state{key_algorithm = KeyAlg, negotiated_version = Version}, Connection) ->
try
- certify_client_key_exchange(ssl_handshake:decode_client_key(Keys, KeyAlg, Version),
+ certify_client_key_exchange(ssl_handshake:decode_client_key(Keys, KeyAlg, ssl:tls_version(Version)),
State, Connection)
catch
#alert{} = Alert ->
- Connection:handle_own_alert(Alert, Version, certify, State)
+ handle_own_alert(Alert, Version, certify, State)
end;
certify(Type, Msg, State, Connection) ->
@@ -662,21 +671,21 @@ cipher(internal, #certificate_verify{signature = Signature,
%% Use negotiated value if TLS-1.2 otherwhise return default
HashSign = negotiated_hashsign(CertHashSign, KexAlg, PublicKeyInfo, Version),
case ssl_handshake:certificate_verify(Signature, PublicKeyInfo,
- Version, HashSign, MasterSecret, Handshake) of
+ ssl:tls_version(Version), HashSign, MasterSecret, Handshake) of
valid ->
{Record, State} = Connection:next_record(State0),
Connection:next_event(cipher, Record,
State#state{cert_hashsign_algorithm = HashSign});
#alert{} = Alert ->
- Connection:handle_own_alert(Alert, Version, cipher, State0)
+ handle_own_alert(Alert, Version, cipher, State0)
end;
%% client must send a next protocol message if we are expecting it
cipher(internal, #finished{},
#state{role = server, expecting_next_protocol_negotiation = true,
negotiated_protocol = undefined, negotiated_version = Version} = State0,
- Connection) ->
- Connection:handle_own_alert(?ALERT_REC(?FATAL,?UNEXPECTED_MESSAGE), Version, cipher, State0);
+ _Connection) ->
+ handle_own_alert(?ALERT_REC(?FATAL,?UNEXPECTED_MESSAGE), Version, cipher, State0);
cipher(internal, #finished{verify_data = Data} = Finished,
#state{negotiated_version = Version,
@@ -688,7 +697,7 @@ cipher(internal, #finished{verify_data = Data} = Finished,
= Session0,
connection_states = ConnectionStates0,
tls_handshake_history = Handshake0} = State, Connection) ->
- case ssl_handshake:verify_connection(Version, Finished,
+ case ssl_handshake:verify_connection(ssl:tls_version(Version), Finished,
opposite_role(Role),
get_current_prf(ConnectionStates0, read),
MasterSecret, Handshake0) of
@@ -697,7 +706,7 @@ cipher(internal, #finished{verify_data = Data} = Finished,
cipher_role(Role, Data, Session,
State#state{expecting_finished = false}, Connection);
#alert{} = Alert ->
- Connection:handle_own_alert(Alert, Version, cipher, State)
+ handle_own_alert(Alert, Version, cipher, State)
end;
%% only allowed to send next_protocol message after change cipher spec
@@ -730,7 +739,7 @@ connection({call, From}, {application_data, Data},
%% parallize send and receive decoding and not block the receiver
%% if sending is overloading the socket.
try
- Connection:write_application_data(Data, From, State)
+ write_application_data(Data, From, State)
catch throw:Error ->
hibernate_after(connection, State, [{reply, From, Error}])
end;
@@ -801,33 +810,37 @@ handle_common_event(internal, {handshake, {#hello_request{}, _}}, StateName, #st
when StateName =/= connection ->
{keep_state_and_data};
handle_common_event(internal, {handshake, {Handshake, Raw}}, StateName,
- #state{tls_handshake_history = Hs0} = State0, Connection) ->
+ #state{tls_handshake_history = Hs0,
+ ssl_options = #ssl_options{v2_hello_compatible = V2HComp}} = State0,
+ Connection) ->
+
+ PossibleSNI = Connection:select_sni_extension(Handshake),
%% This function handles client SNI hello extension when Handshake is
%% a client_hello, which needs to be determined by the connection callback.
%% In other cases this is a noop
- State = Connection:handle_sni_extension(Handshake, State0),
- HsHist = ssl_handshake:update_handshake_history(Hs0, Raw),
+ State = handle_sni_extension(PossibleSNI, State0),
+ HsHist = ssl_handshake:update_handshake_history(Hs0, Raw, V2HComp),
{next_state, StateName, State#state{tls_handshake_history = HsHist},
[{next_event, internal, Handshake}]};
-handle_common_event(internal, {tls_record, TLSRecord}, StateName, State, Connection) ->
- Connection:handle_common_event(internal, TLSRecord, StateName, State);
+handle_common_event(internal, {protocol_record, TLSorDTLSRecord}, StateName, State, Connection) ->
+ Connection:handle_common_event(internal, TLSorDTLSRecord, StateName, State);
handle_common_event(timeout, hibernate, _, _, _) ->
{keep_state_and_data, [hibernate]};
handle_common_event(internal, {application_data, Data}, StateName, State0, Connection) ->
- case Connection:read_application_data(Data, State0) of
+ case read_application_data(Data, State0) of
{stop, Reason, State} ->
{stop, Reason, State};
{Record, State} ->
Connection:next_event(StateName, Record, State)
end;
handle_common_event(internal, #change_cipher_spec{type = <<1>>}, StateName,
- #state{negotiated_version = Version} = State, Connection) ->
- Connection:handle_own_alert(?ALERT_REC(?FATAL, ?HANDSHAKE_FAILURE), Version,
+ #state{negotiated_version = Version} = State, _) ->
+ handle_own_alert(?ALERT_REC(?FATAL, ?HANDSHAKE_FAILURE), Version,
StateName, State);
handle_common_event(_Type, Msg, StateName, #state{negotiated_version = Version} = State,
- Connection) ->
+ _) ->
Alert = ?ALERT_REC(?FATAL,?UNEXPECTED_MESSAGE),
- Connection:handle_own_alert(Alert, Version, {StateName, Msg}, State).
+ handle_own_alert(Alert, Version, {StateName, Msg}, State).
handle_call({application_data, _Data}, _, _, _, _) ->
%% In renegotiation priorities handshake, send data when handshake is finished
@@ -905,9 +918,8 @@ handle_call(renegotiate, From, StateName, _, _) when StateName =/= connection ->
handle_call({prf, Secret, Label, Seed, WantedLength}, From, _,
#state{connection_states = ConnectionStates,
negotiated_version = Version}, _) ->
- ConnectionState =
+ #{security_parameters := SecParams} =
ssl_record:current_connection_state(ConnectionStates, read),
- SecParams = ConnectionState#connection_state.security_parameters,
#security_parameters{master_secret = MasterSecret,
client_random = ClientRandom,
server_random = ServerRandom,
@@ -922,7 +934,7 @@ handle_call({prf, Secret, Label, Seed, WantedLength}, From, _,
(client_random, Acc) -> [ClientRandom|Acc];
(server_random, Acc) -> [ServerRandom|Acc]
end, [], Seed)),
- ssl_handshake:prf(Version, PRFAlgorithm, SecretToUse, Label, SeedToUse, WantedLength)
+ ssl_handshake:prf(ssl:tls_version(Version), PRFAlgorithm, SecretToUse, Label, SeedToUse, WantedLength)
catch
exit:_ -> {error, badarg};
error:Reason -> {error, Reason}
@@ -933,20 +945,19 @@ handle_call(_,_,_,_,_) ->
handle_info({ErrorTag, Socket, econnaborted}, StateName,
#state{socket = Socket, transport_cb = Transport,
- start_or_recv_from = StartFrom, role = Role,
protocol_cb = Connection,
+ start_or_recv_from = StartFrom, role = Role,
error_tag = ErrorTag,
tracker = Tracker} = State) when StateName =/= connection ->
- Connection:alert_user(Transport, Tracker,Socket,
- StartFrom, ?ALERT_REC(?FATAL, ?CLOSE_NOTIFY), Role),
+ alert_user(Transport, Tracker,Socket,
+ StartFrom, ?ALERT_REC(?FATAL, ?CLOSE_NOTIFY), Role, Connection),
{stop, normal, State};
handle_info({ErrorTag, Socket, Reason}, StateName, #state{socket = Socket,
- protocol_cb = Connection,
error_tag = ErrorTag} = State) ->
Report = io_lib:format("SSL: Socket error: ~p ~n", [Reason]),
error_logger:info_report(Report),
- Connection:handle_normal_shutdown(?ALERT_REC(?FATAL, ?CLOSE_NOTIFY), StateName, State),
+ handle_normal_shutdown(?ALERT_REC(?FATAL, ?CLOSE_NOTIFY), StateName, State),
{stop, normal, State};
handle_info({'DOWN', MonitorRef, _, _, _}, _,
@@ -1049,13 +1060,124 @@ format_status(terminate, [_, StateName, State]) ->
ssl_options = NewOptions,
flight_buffer = ?SECRET_PRINTOUT}
}}]}].
+
+%%--------------------------------------------------------------------
+%%%
+%%--------------------------------------------------------------------
+write_application_data(Data0, From,
+ #state{socket = Socket,
+ negotiated_version = Version,
+ protocol_cb = Connection,
+ transport_cb = Transport,
+ connection_states = ConnectionStates0,
+ socket_options = SockOpts,
+ ssl_options = #ssl_options{renegotiate_at = RenegotiateAt}} = State) ->
+ Data = encode_packet(Data0, SockOpts),
+
+ case time_to_renegotiate(Data, ConnectionStates0, RenegotiateAt) of
+ true ->
+ Connection:renegotiate(State#state{renegotiation = {true, internal}},
+ [{next_event, {call, From}, {application_data, Data0}}]);
+ false ->
+ {Msgs, ConnectionStates} = ssl_record:encode_data(Data, Version, ConnectionStates0),
+ Result = Transport:send(Socket, Msgs),
+ ssl_connection:hibernate_after(connection, State#state{connection_states = ConnectionStates},
+ [{reply, From, Result}])
+ end.
+
+read_application_data(Data, #state{user_application = {_Mon, Pid},
+ socket = Socket,
+ protocol_cb = Connection,
+ transport_cb = Transport,
+ socket_options = SOpts,
+ bytes_to_read = BytesToRead,
+ start_or_recv_from = RecvFrom,
+ timer = Timer,
+ user_data_buffer = Buffer0,
+ tracker = Tracker} = State0) ->
+ Buffer1 = if
+ Buffer0 =:= <<>> -> Data;
+ Data =:= <<>> -> Buffer0;
+ true -> <<Buffer0/binary, Data/binary>>
+ end,
+ case get_data(SOpts, BytesToRead, Buffer1) of
+ {ok, ClientData, Buffer} -> % Send data
+ SocketOpt = deliver_app_data(Transport, Socket, SOpts,
+ ClientData, Pid, RecvFrom, Tracker, Connection),
+ cancel_timer(Timer),
+ State = State0#state{user_data_buffer = Buffer,
+ start_or_recv_from = undefined,
+ timer = undefined,
+ bytes_to_read = undefined,
+ socket_options = SocketOpt
+ },
+ if
+ SocketOpt#socket_options.active =:= false; Buffer =:= <<>> ->
+ %% Passive mode, wait for active once or recv
+ %% Active and empty, get more data
+ Connection:next_record_if_active(State);
+ true -> %% We have more data
+ read_application_data(<<>>, State)
+ end;
+ {more, Buffer} -> % no reply, we need more data
+ Connection:next_record(State0#state{user_data_buffer = Buffer});
+ {passive, Buffer} ->
+ Connection:next_record_if_active(State0#state{user_data_buffer = Buffer});
+ {error,_Reason} -> %% Invalid packet in packet mode
+ deliver_packet_error(Transport, Socket, SOpts, Buffer1, Pid, RecvFrom, Tracker, Connection),
+ {stop, normal, State0}
+ end.
+%%--------------------------------------------------------------------
+%%%
+%%--------------------------------------------------------------------
+handle_alert(#alert{level = ?FATAL} = Alert, StateName,
+ #state{socket = Socket, transport_cb = Transport,
+ protocol_cb = Connection,
+ ssl_options = SslOpts, start_or_recv_from = From, host = Host,
+ port = Port, session = Session, user_application = {_Mon, Pid},
+ role = Role, socket_options = Opts, tracker = Tracker}) ->
+ invalidate_session(Role, Host, Port, Session),
+ log_alert(SslOpts#ssl_options.log_alert, StateName, Alert),
+ alert_user(Transport, Tracker, Socket, StateName, Opts, Pid, From, Alert, Role, Connection),
+ {stop, normal};
+
+handle_alert(#alert{level = ?WARNING, description = ?CLOSE_NOTIFY} = Alert,
+ StateName, State) ->
+ handle_normal_shutdown(Alert, StateName, State),
+ {stop, {shutdown, peer_close}};
+
+handle_alert(#alert{level = ?WARNING, description = ?NO_RENEGOTIATION} = Alert, StateName,
+ #state{ssl_options = SslOpts, renegotiation = {true, internal}} = State) ->
+ log_alert(SslOpts#ssl_options.log_alert, StateName, Alert),
+ handle_normal_shutdown(Alert, StateName, State),
+ {stop, {shutdown, peer_close}};
+
+handle_alert(#alert{level = ?WARNING, description = ?NO_RENEGOTIATION} = Alert, StateName,
+ #state{ssl_options = SslOpts, renegotiation = {true, From},
+ protocol_cb = Connection} = State0) ->
+ log_alert(SslOpts#ssl_options.log_alert, StateName, Alert),
+ gen_statem:reply(From, {error, renegotiation_rejected}),
+ {Record, State} = Connection:next_record(State0),
+ %% Go back to connection!
+ Connection:next_event(connection, Record, State);
+
+%% Gracefully log and ignore all other warning alerts
+handle_alert(#alert{level = ?WARNING} = Alert, StateName,
+ #state{ssl_options = SslOpts, protocol_cb = Connection} = State0) ->
+ log_alert(SslOpts#ssl_options.log_alert, StateName, Alert),
+ {Record, State} = Connection:next_record(State0),
+ Connection:next_event(StateName, Record, State).
+
%%--------------------------------------------------------------------
%%% Internal functions
%%--------------------------------------------------------------------
connection_info(#state{sni_hostname = SNIHostname,
session = #session{cipher_suite = CipherSuite},
- negotiated_version = Version, ssl_options = Opts}) ->
- [{protocol, tls_record:protocol_version(Version)},
+ protocol_cb = Connection,
+ negotiated_version = {_,_} = Version,
+ ssl_options = Opts}) ->
+ RecordCB = record_cb(Connection),
+ [{protocol, RecordCB:protocol_version(Version)},
{cipher_suite, ssl_cipher:erl_suite_definition(CipherSuite)},
{sni_hostname, SNIHostname}] ++ ssl_options_list(Opts).
@@ -1067,7 +1189,7 @@ do_server_hello(Type, #hello_extensions{next_protocol_negotiation = NextProtocol
= State0, Connection) when is_atom(Type) ->
ServerHello =
- ssl_handshake:server_hello(SessId, Version, ConnectionStates0, ServerHelloExt),
+ ssl_handshake:server_hello(SessId, ssl:tls_version(Version), ConnectionStates0, ServerHelloExt),
State = server_hello(ServerHello,
State0#state{expecting_next_protocol_negotiation =
NextProtocols =/= undefined}, Connection),
@@ -1094,14 +1216,14 @@ new_server_hello(#server_hello{cipher_suite = CipherSuite,
Connection:next_event(certify, Record, State)
catch
#alert{} = Alert ->
- Connection:handle_own_alert(Alert, Version, hello, State0)
+ handle_own_alert(Alert, Version, hello, State0)
end.
resumed_server_hello(#state{session = Session,
connection_states = ConnectionStates0,
negotiated_version = Version} = State0, Connection) ->
- case ssl_handshake:master_secret(record_cb(Connection), Version, Session,
+ case ssl_handshake:master_secret(ssl:tls_version(Version), Session,
ConnectionStates0, server) of
{_, ConnectionStates1} ->
State1 = State0#state{connection_states = ConnectionStates1,
@@ -1111,7 +1233,7 @@ resumed_server_hello(#state{session = Session,
{Record, State} = Connection:next_record(State2),
Connection:next_event(abbreviated, Record, State);
#alert{} = Alert ->
- Connection:handle_own_alert(Alert, Version, hello, State0)
+ handle_own_alert(Alert, Version, hello, State0)
end.
server_hello(ServerHello, State0, Connection) ->
@@ -1177,7 +1299,7 @@ verify_client_cert(#state{client_certificate_requested = true, role = client,
tls_handshake_history = Handshake0} = State, Connection) ->
case ssl_handshake:client_certificate_verify(OwnCert, MasterSecret,
- Version, HashSign, PrivateKey, Handshake0) of
+ ssl:tls_version(Version), HashSign, PrivateKey, Handshake0) of
#certificate_verify{} = Verified ->
Connection:queue_handshake(Verified, State);
ignore ->
@@ -1200,7 +1322,7 @@ client_certify_and_key_exchange(#state{negotiated_version = Version} =
Connection:next_event(cipher, Record, State)
catch
throw:#alert{} = Alert ->
- Connection:handle_own_alert(Alert, Version, certify, State0)
+ handle_own_alert(Alert, Version, certify, State0)
end.
do_client_certify_and_key_exchange(State0, Connection) ->
@@ -1291,12 +1413,11 @@ key_exchange(#state{role = server, key_algorithm = Algo,
Algo == dhe_rsa;
Algo == dh_anon ->
DHKeys = public_key:generate_key(Params),
- ConnectionState =
+ #{security_parameters := SecParams} =
ssl_record:pending_connection_state(ConnectionStates0, read),
- SecParams = ConnectionState#connection_state.security_parameters,
#security_parameters{client_random = ClientRandom,
server_random = ServerRandom} = SecParams,
- Msg = ssl_handshake:key_exchange(server, Version, {dh, DHKeys, Params,
+ Msg = ssl_handshake:key_exchange(server, ssl:tls_version(Version), {dh, DHKeys, Params,
HashSignAlgo, ClientRandom,
ServerRandom,
PrivateKey}),
@@ -1316,15 +1437,15 @@ key_exchange(#state{role = server, key_algorithm = Algo,
Algo == ecdh_anon ->
ECDHKeys = public_key:generate_key(select_curve(State0)),
- ConnectionState =
+ #{security_parameters := SecParams} =
ssl_record:pending_connection_state(ConnectionStates0, read),
- SecParams = ConnectionState#connection_state.security_parameters,
#security_parameters{client_random = ClientRandom,
server_random = ServerRandom} = SecParams,
- Msg = ssl_handshake:key_exchange(server, Version, {ecdh, ECDHKeys,
- HashSignAlgo, ClientRandom,
- ServerRandom,
- PrivateKey}),
+ Msg = ssl_handshake:key_exchange(server, ssl:tls_version(Version),
+ {ecdh, ECDHKeys,
+ HashSignAlgo, ClientRandom,
+ ServerRandom,
+ PrivateKey}),
State = Connection:queue_handshake(Msg, State0),
State#state{diffie_hellman_keys = ECDHKeys};
@@ -1338,14 +1459,14 @@ key_exchange(#state{role = server, key_algorithm = psk,
connection_states = ConnectionStates0,
negotiated_version = Version
} = State0, Connection) ->
- ConnectionState =
+ #{security_parameters := SecParams} =
ssl_record:pending_connection_state(ConnectionStates0, read),
- SecParams = ConnectionState#connection_state.security_parameters,
#security_parameters{client_random = ClientRandom,
server_random = ServerRandom} = SecParams,
- Msg = ssl_handshake:key_exchange(server, Version, {psk, PskIdentityHint,
- HashSignAlgo, ClientRandom,
- ServerRandom,
+ Msg = ssl_handshake:key_exchange(server, ssl:tls_version(Version),
+ {psk, PskIdentityHint,
+ HashSignAlgo, ClientRandom,
+ ServerRandom,
PrivateKey}),
Connection:queue_handshake(Msg, State0);
@@ -1358,16 +1479,16 @@ key_exchange(#state{role = server, key_algorithm = dhe_psk,
negotiated_version = Version
} = State0, Connection) ->
DHKeys = public_key:generate_key(Params),
- ConnectionState =
+ #{security_parameters := SecParams} =
ssl_record:pending_connection_state(ConnectionStates0, read),
- SecParams = ConnectionState#connection_state.security_parameters,
#security_parameters{client_random = ClientRandom,
server_random = ServerRandom} = SecParams,
- Msg = ssl_handshake:key_exchange(server, Version, {dhe_psk,
- PskIdentityHint, DHKeys, Params,
- HashSignAlgo, ClientRandom,
- ServerRandom,
- PrivateKey}),
+ Msg = ssl_handshake:key_exchange(server, ssl:tls_version(Version),
+ {dhe_psk,
+ PskIdentityHint, DHKeys, Params,
+ HashSignAlgo, ClientRandom,
+ ServerRandom,
+ PrivateKey}),
State = Connection:queue_handshake(Msg, State0),
State#state{diffie_hellman_keys = DHKeys};
@@ -1381,15 +1502,15 @@ key_exchange(#state{role = server, key_algorithm = rsa_psk,
connection_states = ConnectionStates0,
negotiated_version = Version
} = State0, Connection) ->
- ConnectionState =
+ #{security_parameters := SecParams} =
ssl_record:pending_connection_state(ConnectionStates0, read),
- SecParams = ConnectionState#connection_state.security_parameters,
#security_parameters{client_random = ClientRandom,
server_random = ServerRandom} = SecParams,
- Msg = ssl_handshake:key_exchange(server, Version, {psk, PskIdentityHint,
- HashSignAlgo, ClientRandom,
- ServerRandom,
- PrivateKey}),
+ Msg = ssl_handshake:key_exchange(server, ssl:tls_version(Version),
+ {psk, PskIdentityHint,
+ HashSignAlgo, ClientRandom,
+ ServerRandom,
+ PrivateKey}),
Connection:queue_handshake(Msg, State0);
key_exchange(#state{role = server, key_algorithm = Algo,
@@ -1410,15 +1531,15 @@ key_exchange(#state{role = server, key_algorithm = Algo,
Keys0 = {_,_} ->
Keys0
end,
- ConnectionState =
+ #{security_parameters := SecParams} =
ssl_record:pending_connection_state(ConnectionStates0, read),
- SecParams = ConnectionState#connection_state.security_parameters,
#security_parameters{client_random = ClientRandom,
server_random = ServerRandom} = SecParams,
- Msg = ssl_handshake:key_exchange(server, Version, {srp, Keys, SrpParams,
- HashSignAlgo, ClientRandom,
- ServerRandom,
- PrivateKey}),
+ Msg = ssl_handshake:key_exchange(server, ssl:tls_version(Version),
+ {srp, Keys, SrpParams,
+ HashSignAlgo, ClientRandom,
+ ServerRandom,
+ PrivateKey}),
State = Connection:queue_handshake(Msg, State0),
State#state{srp_params = SrpParams,
srp_keys = Keys};
@@ -1428,7 +1549,7 @@ key_exchange(#state{role = client,
public_key_info = PublicKeyInfo,
negotiated_version = Version,
premaster_secret = PremasterSecret} = State0, Connection) ->
- Msg = rsa_key_exchange(Version, PremasterSecret, PublicKeyInfo),
+ Msg = rsa_key_exchange(ssl:tls_version(Version), PremasterSecret, PublicKeyInfo),
Connection:queue_handshake(Msg, State0);
key_exchange(#state{role = client,
@@ -1439,7 +1560,7 @@ key_exchange(#state{role = client,
when Algorithm == dhe_dss;
Algorithm == dhe_rsa;
Algorithm == dh_anon ->
- Msg = ssl_handshake:key_exchange(client, Version, {dh, DhPubKey}),
+ Msg = ssl_handshake:key_exchange(client, ssl:tls_version(Version), {dh, DhPubKey}),
Connection:queue_handshake(Msg, State0);
key_exchange(#state{role = client,
@@ -1449,14 +1570,14 @@ key_exchange(#state{role = client,
when Algorithm == ecdhe_ecdsa; Algorithm == ecdhe_rsa;
Algorithm == ecdh_ecdsa; Algorithm == ecdh_rsa;
Algorithm == ecdh_anon ->
- Msg = ssl_handshake:key_exchange(client, Version, {ecdh, Keys}),
+ Msg = ssl_handshake:key_exchange(client, ssl:tls_version(Version), {ecdh, Keys}),
Connection:queue_handshake(Msg, State0);
key_exchange(#state{role = client,
ssl_options = SslOpts,
key_algorithm = psk,
negotiated_version = Version} = State0, Connection) ->
- Msg = ssl_handshake:key_exchange(client, Version,
+ Msg = ssl_handshake:key_exchange(client, ssl:tls_version(Version),
{psk, SslOpts#ssl_options.psk_identity}),
Connection:queue_handshake(Msg, State0);
@@ -1465,7 +1586,7 @@ key_exchange(#state{role = client,
key_algorithm = dhe_psk,
negotiated_version = Version,
diffie_hellman_keys = {DhPubKey, _}} = State0, Connection) ->
- Msg = ssl_handshake:key_exchange(client, Version,
+ Msg = ssl_handshake:key_exchange(client, ssl:tls_version(Version),
{dhe_psk,
SslOpts#ssl_options.psk_identity, DhPubKey}),
Connection:queue_handshake(Msg, State0);
@@ -1476,7 +1597,7 @@ key_exchange(#state{role = client,
negotiated_version = Version,
premaster_secret = PremasterSecret}
= State0, Connection) ->
- Msg = rsa_psk_key_exchange(Version, SslOpts#ssl_options.psk_identity,
+ Msg = rsa_psk_key_exchange(ssl:tls_version(Version), SslOpts#ssl_options.psk_identity,
PremasterSecret, PublicKeyInfo),
Connection:queue_handshake(Msg, State0);
@@ -1488,7 +1609,7 @@ key_exchange(#state{role = client,
when Algorithm == srp_dss;
Algorithm == srp_rsa;
Algorithm == srp_anon ->
- Msg = ssl_handshake:key_exchange(client, Version, {srp, ClientPubKey}),
+ Msg = ssl_handshake:key_exchange(client, ssl:tls_version(Version), {srp, ClientPubKey}),
Connection:queue_handshake(Msg, State0).
rsa_key_exchange(Version, PremasterSecret, PublicKeyInfo = {Algorithm, _, _})
@@ -1501,7 +1622,7 @@ rsa_key_exchange(Version, PremasterSecret, PublicKeyInfo = {Algorithm, _, _})
Algorithm == ?sha384WithRSAEncryption;
Algorithm == ?sha512WithRSAEncryption
->
- ssl_handshake:key_exchange(client, Version,
+ ssl_handshake:key_exchange(client, ssl:tls_version(Version),
{premaster_secret, PremasterSecret,
PublicKeyInfo});
rsa_key_exchange(_, _, _) ->
@@ -1518,7 +1639,7 @@ rsa_psk_key_exchange(Version, PskIdentity, PremasterSecret,
Algorithm == ?sha384WithRSAEncryption;
Algorithm == ?sha512WithRSAEncryption
->
- ssl_handshake:key_exchange(client, Version,
+ ssl_handshake:key_exchange(client, ssl:tls_version(Version),
{psk_premaster_secret, PskIdentity, PremasterSecret,
PublicKeyInfo});
rsa_psk_key_exchange(_, _, _, _) ->
@@ -1530,12 +1651,14 @@ request_client_cert(#state{ssl_options = #ssl_options{verify = verify_peer,
cert_db = CertDbHandle,
cert_db_ref = CertDbRef,
negotiated_version = Version} = State0, Connection) ->
- #connection_state{security_parameters =
- #security_parameters{cipher_suite = CipherSuite}} =
+ #{security_parameters :=
+ #security_parameters{cipher_suite = CipherSuite}} =
ssl_record:pending_connection_state(ConnectionStates0, read),
- HashSigns = ssl_handshake:available_signature_algs(SupportedHashSigns, Version, [Version]),
+ TLSVersion = ssl:tls_version(Version),
+ HashSigns = ssl_handshake:available_signature_algs(SupportedHashSigns,
+ TLSVersion, [TLSVersion]),
Msg = ssl_handshake:certificate_request(CipherSuite, CertDbHandle, CertDbRef,
- HashSigns, Version),
+ HashSigns, TLSVersion),
State = Connection:queue_handshake(Msg, State0),
State#state{client_certificate_requested = true};
@@ -1548,7 +1671,7 @@ calculate_master_secret(PremasterSecret,
connection_states = ConnectionStates0,
session = Session0} = State0, Connection,
_Current, Next) ->
- case ssl_handshake:master_secret(record_cb(Connection), Version, PremasterSecret,
+ case ssl_handshake:master_secret(ssl:tls_version(Version), PremasterSecret,
ConnectionStates0, server) of
{MasterSecret, ConnectionStates} ->
Session = Session0#session{master_secret = MasterSecret},
@@ -1557,7 +1680,7 @@ calculate_master_secret(PremasterSecret,
{Record, State} = Connection:next_record(State1),
Connection:next_event(Next, Record, State);
#alert{} = Alert ->
- Connection:handle_own_alert(Alert, Version, certify, State0)
+ handle_own_alert(Alert, Version, certify, State0)
end.
finalize_handshake(State0, StateName, Connection) ->
@@ -1590,7 +1713,7 @@ finished(#state{role = Role, negotiated_version = Version,
connection_states = ConnectionStates0,
tls_handshake_history = Handshake0} = State0, StateName, Connection) ->
MasterSecret = Session#session.master_secret,
- Finished = ssl_handshake:finished(Version, Role,
+ Finished = ssl_handshake:finished(ssl:tls_version(Version), Role,
get_current_prf(ConnectionStates0, write),
MasterSecret, Handshake0),
ConnectionStates = save_verify_data(Role, Finished, ConnectionStates0, StateName),
@@ -1655,7 +1778,7 @@ master_secret(#alert{} = Alert, _) ->
master_secret(PremasterSecret, #state{session = Session,
negotiated_version = Version, role = Role,
connection_states = ConnectionStates0} = State) ->
- case ssl_handshake:master_secret(tls_record, Version, PremasterSecret,
+ case ssl_handshake:master_secret(ssl:tls_version(Version), PremasterSecret,
ConnectionStates0, Role) of
{MasterSecret, ConnectionStates} ->
State#state{
@@ -1738,11 +1861,11 @@ is_anonymous(_) ->
false.
get_current_prf(CStates, Direction) ->
- CS = ssl_record:current_connection_state(CStates, Direction),
- CS#connection_state.security_parameters#security_parameters.prf_algorithm.
+ #{security_parameters := SecParams} = ssl_record:current_connection_state(CStates, Direction),
+ SecParams#security_parameters.prf_algorithm.
get_pending_prf(CStates, Direction) ->
- CS = ssl_record:pending_connection_state(CStates, Direction),
- CS#connection_state.security_parameters#security_parameters.prf_algorithm.
+ #{security_parameters := SecParams} = ssl_record:pending_connection_state(CStates, Direction),
+ SecParams#security_parameters.prf_algorithm.
opposite_role(client) ->
server;
@@ -1964,7 +2087,7 @@ handle_resumed_session(SessId, #state{connection_states = ConnectionStates0,
session_cache = Cache,
session_cache_cb = CacheCb} = State0) ->
Session = CacheCb:lookup(Cache, {{Host, Port}, SessId}),
- case ssl_handshake:master_secret(tls_record, Version, Session,
+ case ssl_handshake:master_secret(ssl:tls_version(Version), Session,
ConnectionStates0, client) of
{_, ConnectionStates} ->
{Record, State} =
@@ -1973,7 +2096,7 @@ handle_resumed_session(SessId, #state{connection_states = ConnectionStates0,
session = Session}),
Connection:next_event(abbreviated, Record, State);
#alert{} = Alert ->
- Connection:handle_own_alert(Alert, Version, hello, State0)
+ handle_own_alert(Alert, Version, hello, State0)
end.
make_premaster_secret({MajVer, MinVer}, rsa) ->
@@ -2040,7 +2163,7 @@ handle_active_option(_, StateName, To, Reply, #state{user_data_buffer = <<>>} =
%% user_data_buffer =/= <<>>
handle_active_option(_, StateName0, To, Reply, #state{protocol_cb = Connection} = State0) ->
- case Connection:read_application_data(<<>>, State0) of
+ case read_application_data(<<>>, State0) of
{stop, Reason, State} ->
{stop, Reason, State};
{Record, State1} ->
@@ -2054,3 +2177,264 @@ handle_active_option(_, StateName0, To, Reply, #state{protocol_cb = Connection}
Stop
end
end.
+
+encode_packet(Data, #socket_options{packet=Packet}) ->
+ case Packet of
+ 1 -> encode_size_packet(Data, 8, (1 bsl 8) - 1);
+ 2 -> encode_size_packet(Data, 16, (1 bsl 16) - 1);
+ 4 -> encode_size_packet(Data, 32, (1 bsl 32) - 1);
+ _ -> Data
+ end.
+
+encode_size_packet(Bin, Size, Max) ->
+ Len = erlang:byte_size(Bin),
+ case Len > Max of
+ true -> throw({error, {badarg, {packet_to_large, Len, Max}}});
+ false -> <<Len:Size, Bin/binary>>
+ end.
+
+time_to_renegotiate(_Data,
+ #{current_write := #{sequence_number := Num}},
+ RenegotiateAt) ->
+
+ %% We could do test:
+ %% is_time_to_renegotiate((erlang:byte_size(_Data) div ?MAX_PLAIN_TEXT_LENGTH) + 1, RenegotiateAt),
+ %% but we chose to have a some what lower renegotiateAt and a much cheaper test
+ is_time_to_renegotiate(Num, RenegotiateAt).
+
+is_time_to_renegotiate(N, M) when N < M->
+ false;
+is_time_to_renegotiate(_,_) ->
+ true.
+
+
+%% Picks ClientData
+get_data(_, _, <<>>) ->
+ {more, <<>>};
+%% Recv timed out save buffer data until next recv
+get_data(#socket_options{active=false}, undefined, Buffer) ->
+ {passive, Buffer};
+get_data(#socket_options{active=Active, packet=Raw}, BytesToRead, Buffer)
+ when Raw =:= raw; Raw =:= 0 -> %% Raw Mode
+ if
+ Active =/= false orelse BytesToRead =:= 0 ->
+ %% Active true or once, or passive mode recv(0)
+ {ok, Buffer, <<>>};
+ byte_size(Buffer) >= BytesToRead ->
+ %% Passive Mode, recv(Bytes)
+ <<Data:BytesToRead/binary, Rest/binary>> = Buffer,
+ {ok, Data, Rest};
+ true ->
+ %% Passive Mode not enough data
+ {more, Buffer}
+ end;
+get_data(#socket_options{packet=Type, packet_size=Size}, _, Buffer) ->
+ PacketOpts = [{packet_size, Size}],
+ case decode_packet(Type, Buffer, PacketOpts) of
+ {more, _} ->
+ {more, Buffer};
+ Decoded ->
+ Decoded
+ end.
+
+decode_packet({http, headers}, Buffer, PacketOpts) ->
+ decode_packet(httph, Buffer, PacketOpts);
+decode_packet({http_bin, headers}, Buffer, PacketOpts) ->
+ decode_packet(httph_bin, Buffer, PacketOpts);
+decode_packet(Type, Buffer, PacketOpts) ->
+ erlang:decode_packet(Type, Buffer, PacketOpts).
+
+%% Just like with gen_tcp sockets, an ssl socket that has been configured with
+%% {packet, http} (or {packet, http_bin}) will automatically switch to expect
+%% HTTP headers after it sees a HTTP Request or HTTP Response line. We
+%% represent the current state as follows:
+%% #socket_options.packet =:= http: Expect a HTTP Request/Response line
+%% #socket_options.packet =:= {http, headers}: Expect HTTP Headers
+%% Note that if the user has explicitly configured the socket to expect
+%% HTTP headers using the {packet, httph} option, we don't do any automatic
+%% switching of states.
+deliver_app_data(Transport, Socket, SOpts = #socket_options{active=Active, packet=Type},
+ Data, Pid, From, Tracker, Connection) ->
+ send_or_reply(Active, Pid, From, format_reply(Transport, Socket, SOpts, Data, Tracker, Connection)),
+ SO = case Data of
+ {P, _, _, _} when ((P =:= http_request) or (P =:= http_response)),
+ ((Type =:= http) or (Type =:= http_bin)) ->
+ SOpts#socket_options{packet={Type, headers}};
+ http_eoh when tuple_size(Type) =:= 2 ->
+ % End of headers - expect another Request/Response line
+ {Type1, headers} = Type,
+ SOpts#socket_options{packet=Type1};
+ _ ->
+ SOpts
+ end,
+ case Active of
+ once ->
+ SO#socket_options{active=false};
+ _ ->
+ SO
+ end.
+
+format_reply(_, _,#socket_options{active = false, mode = Mode, packet = Packet,
+ header = Header}, Data, _, _) ->
+ {ok, do_format_reply(Mode, Packet, Header, Data)};
+format_reply(Transport, Socket, #socket_options{active = _, mode = Mode, packet = Packet,
+ header = Header}, Data, Tracker, Connection) ->
+ {ssl, ssl_socket:socket(self(), Transport, Socket, Connection, Tracker),
+ do_format_reply(Mode, Packet, Header, Data)}.
+
+deliver_packet_error(Transport, Socket, SO= #socket_options{active = Active}, Data, Pid, From, Tracker, Connection) ->
+ send_or_reply(Active, Pid, From, format_packet_error(Transport, Socket, SO, Data, Tracker, Connection)).
+
+format_packet_error(_, _,#socket_options{active = false, mode = Mode}, Data, _, _) ->
+ {error, {invalid_packet, do_format_reply(Mode, raw, 0, Data)}};
+format_packet_error(Transport, Socket, #socket_options{active = _, mode = Mode}, Data, Tracker, Connection) ->
+ {ssl_error, ssl_socket:socket(self(), Transport, Socket, Connection, Tracker),
+ {invalid_packet, do_format_reply(Mode, raw, 0, Data)}}.
+
+do_format_reply(binary, _, N, Data) when N > 0 -> % Header mode
+ header(N, Data);
+do_format_reply(binary, _, _, Data) ->
+ Data;
+do_format_reply(list, Packet, _, Data)
+ when Packet == http; Packet == {http, headers};
+ Packet == http_bin; Packet == {http_bin, headers};
+ Packet == httph; Packet == httph_bin ->
+ Data;
+do_format_reply(list, _,_, Data) ->
+ binary_to_list(Data).
+
+header(0, <<>>) ->
+ <<>>;
+header(_, <<>>) ->
+ [];
+header(0, Binary) ->
+ Binary;
+header(N, Binary) ->
+ <<?BYTE(ByteN), NewBinary/binary>> = Binary,
+ [ByteN | header(N-1, NewBinary)].
+
+send_or_reply(false, _Pid, From, Data) when From =/= undefined ->
+ gen_statem:reply(From, Data);
+%% Can happen when handling own alert or tcp error/close and there is
+%% no outstanding gen_fsm sync events
+send_or_reply(false, no_pid, _, _) ->
+ ok;
+send_or_reply(_, Pid, _From, Data) ->
+ send_user(Pid, Data).
+
+send_user(Pid, Msg) ->
+ Pid ! Msg.
+
+alert_user(Transport, Tracker, Socket, connection, Opts, Pid, From, Alert, Role, Connection) ->
+ alert_user(Transport, Tracker, Socket, Opts#socket_options.active, Pid, From, Alert, Role, Connection);
+alert_user(Transport, Tracker, Socket,_, _, _, From, Alert, Role, Connection) ->
+ alert_user(Transport, Tracker, Socket, From, Alert, Role, Connection).
+
+alert_user(Transport, Tracker, Socket, From, Alert, Role, Connection) ->
+ alert_user(Transport, Tracker, Socket, false, no_pid, From, Alert, Role, Connection).
+
+alert_user(_, _, _, false = Active, Pid, From, Alert, Role, _) when From =/= undefined ->
+ %% If there is an outstanding ssl_accept | recv
+ %% From will be defined and send_or_reply will
+ %% send the appropriate error message.
+ ReasonCode = ssl_alert:reason_code(Alert, Role),
+ send_or_reply(Active, Pid, From, {error, ReasonCode});
+alert_user(Transport, Tracker, Socket, Active, Pid, From, Alert, Role, Connection) ->
+ case ssl_alert:reason_code(Alert, Role) of
+ closed ->
+ send_or_reply(Active, Pid, From,
+ {ssl_closed, ssl_socket:socket(self(),
+ Transport, Socket, Connection, Tracker)});
+ ReasonCode ->
+ send_or_reply(Active, Pid, From,
+ {ssl_error, ssl_socket:socket(self(),
+ Transport, Socket, Connection, Tracker), ReasonCode})
+ end.
+
+log_alert(true, Info, Alert) ->
+ Txt = ssl_alert:alert_txt(Alert),
+ error_logger:format("SSL: ~p: ~s\n", [Info, Txt]);
+log_alert(false, _, _) ->
+ ok.
+
+handle_own_alert(Alert, Version, StateName,
+ #state{transport_cb = Transport,
+ socket = Socket,
+ connection_states = ConnectionStates,
+ ssl_options = SslOpts} = State) ->
+ try %% Try to tell the other side
+ {BinMsg, _} =
+ ssl_alert:encode(Alert, Version, ConnectionStates),
+ Transport:send(Socket, BinMsg)
+ catch _:_ -> %% Can crash if we are in a uninitialized state
+ ignore
+ end,
+ try %% Try to tell the local user
+ log_alert(SslOpts#ssl_options.log_alert, StateName, Alert),
+ handle_normal_shutdown(Alert,StateName, State)
+ catch _:_ ->
+ ok
+ end,
+ {stop, {shutdown, own_alert}}.
+
+handle_normal_shutdown(Alert, _, #state{socket = Socket,
+ transport_cb = Transport,
+ protocol_cb = Connection,
+ start_or_recv_from = StartFrom,
+ tracker = Tracker,
+ role = Role, renegotiation = {false, first}}) ->
+ alert_user(Transport, Tracker,Socket, StartFrom, Alert, Role, Connection);
+
+handle_normal_shutdown(Alert, StateName, #state{socket = Socket,
+ socket_options = Opts,
+ transport_cb = Transport,
+ protocol_cb = Connection,
+ user_application = {_Mon, Pid},
+ tracker = Tracker,
+ start_or_recv_from = RecvFrom, role = Role}) ->
+ alert_user(Transport, Tracker, Socket, StateName, Opts, Pid, RecvFrom, Alert, Role, Connection).
+
+invalidate_session(client, Host, Port, Session) ->
+ ssl_manager:invalidate_session(Host, Port, Session);
+invalidate_session(server, _, Port, Session) ->
+ ssl_manager:invalidate_session(Port, Session).
+
+handle_sni_extension(undefined, State) ->
+ State;
+handle_sni_extension(#sni{hostname = Hostname}, State0) ->
+ NewOptions = update_ssl_options_from_sni(State0#state.ssl_options, Hostname),
+ case NewOptions of
+ undefined ->
+ State0;
+ _ ->
+ {ok, Ref, CertDbHandle, FileRefHandle, CacheHandle, CRLDbHandle, OwnCert, Key, DHParams} =
+ ssl_config:init(NewOptions, State0#state.role),
+ State0#state{
+ session = State0#state.session#session{own_certificate = OwnCert},
+ file_ref_db = FileRefHandle,
+ cert_db_ref = Ref,
+ cert_db = CertDbHandle,
+ crl_db = CRLDbHandle,
+ session_cache = CacheHandle,
+ private_key = Key,
+ diffie_hellman_params = DHParams,
+ ssl_options = NewOptions,
+ sni_hostname = Hostname
+ }
+ end.
+
+update_ssl_options_from_sni(OrigSSLOptions, SNIHostname) ->
+ SSLOption =
+ case OrigSSLOptions#ssl_options.sni_fun of
+ undefined ->
+ proplists:get_value(SNIHostname,
+ OrigSSLOptions#ssl_options.sni_hosts);
+ SNIFun ->
+ SNIFun(SNIHostname)
+ end,
+ case SSLOption of
+ undefined ->
+ undefined;
+ _ ->
+ ssl:handle_options(SSLOption, OrigSSLOptions)
+ end.
diff --git a/lib/ssl/src/ssl_connection.hrl b/lib/ssl/src/ssl_connection.hrl
index 4b54943ddf..f1e612a41b 100644
--- a/lib/ssl/src/ssl_connection.hrl
+++ b/lib/ssl/src/ssl_connection.hrl
@@ -46,7 +46,7 @@
socket :: port(),
ssl_options :: #ssl_options{},
socket_options :: #socket_options{},
- connection_states :: #connection_states{} | secret_printout(),
+ connection_states :: ssl_record:connection_states() | secret_printout(),
protocol_buffers :: term() | secret_printout() , %% #protocol_buffers{} from tls_record.hrl or dtls_recor.hrl
tls_handshake_history :: ssl_handshake:ssl_handshake_history() | secret_printout()
| 'undefined',
diff --git a/lib/ssl/src/ssl_handshake.erl b/lib/ssl/src/ssl_handshake.erl
index 081efda768..36d533cd4e 100644
--- a/lib/ssl/src/ssl_handshake.erl
+++ b/lib/ssl/src/ssl_handshake.erl
@@ -51,8 +51,8 @@
%% Handle handshake messages
-export([certify/10, client_certificate_verify/6, certificate_verify/6, verify_signature/5,
- master_secret/5, server_key_exchange_hash/2, verify_connection/6,
- init_handshake_history/0, update_handshake_history/2, verify_server_key/5
+ master_secret/4, server_key_exchange_hash/2, verify_connection/6,
+ init_handshake_history/0, update_handshake_history/3, verify_server_key/5
]).
%% Encode/Decode
@@ -94,15 +94,14 @@ hello_request() ->
#hello_request{}.
%%--------------------------------------------------------------------
--spec server_hello(#session{}, ssl_record:ssl_version(), #connection_states{},
+-spec server_hello(#session{}, ssl_record:ssl_version(), ssl_record:connection_states(),
#hello_extensions{}) -> #server_hello{}.
%%
%% Description: Creates a server hello message.
%%--------------------------------------------------------------------
server_hello(SessionId, Version, ConnectionStates, Extensions) ->
- Pending = ssl_record:pending_connection_state(ConnectionStates, read),
- SecParams = Pending#connection_state.security_parameters,
-
+ #{security_parameters := SecParams} =
+ ssl_record:pending_connection_state(ConnectionStates, read),
#server_hello{server_version = Version,
cipher_suite = SecParams#security_parameters.cipher_suite,
compression_method =
@@ -335,9 +334,8 @@ verify_server_key(#server_key_params{params_bin = EncParams,
signature = Signature},
HashSign = {HashAlgo, _},
ConnectionStates, Version, PubKeyInfo) ->
- ConnectionState =
+ #{security_parameters := SecParams} =
ssl_record:pending_connection_state(ConnectionStates, read),
- SecParams = ConnectionState#connection_state.security_parameters,
#security_parameters{client_random = ClientRandom,
server_random = ServerRandom} = SecParams,
Hash = server_key_exchange_hash(HashAlgo,
@@ -447,7 +445,7 @@ init_handshake_history() ->
{[], []}.
%%--------------------------------------------------------------------
--spec update_handshake_history(ssl_handshake:ssl_handshake_history(), Data ::term()) ->
+-spec update_handshake_history(ssl_handshake:ssl_handshake_history(), Data ::term(), boolean()) ->
ssl_handshake:ssl_handshake_history().
%%
%% Description: Update the handshake history buffer with Data.
@@ -457,14 +455,14 @@ update_handshake_history(Handshake, % special-case SSL2 client hello
?UINT16(CSLength), ?UINT16(0),
?UINT16(CDLength),
CipherSuites:CSLength/binary,
- ChallengeData:CDLength/binary>>) ->
+ ChallengeData:CDLength/binary>>, true) ->
update_handshake_history(Handshake,
<<?CLIENT_HELLO, ?BYTE(Major), ?BYTE(Minor),
?UINT16(CSLength), ?UINT16(0),
?UINT16(CDLength),
CipherSuites:CSLength/binary,
- ChallengeData:CDLength/binary>>);
-update_handshake_history({Handshake0, _Prev}, Data) ->
+ ChallengeData:CDLength/binary>>, true);
+update_handshake_history({Handshake0, _Prev}, Data, _) ->
{[Data|Handshake0], Handshake0}.
%% %%--------------------------------------------------------------------
@@ -696,33 +694,32 @@ select_hashsign_algs(undefined, ?'id-dsa', _) ->
%%--------------------------------------------------------------------
--spec master_secret(atom(), ssl_record:ssl_version(), #session{} | binary(), #connection_states{},
- client | server) -> {binary(), #connection_states{}} | #alert{}.
+-spec master_secret(ssl_record:ssl_version(), #session{} | binary(), ssl_record:connection_states(),
+ client | server) -> {binary(), ssl_record:connection_states()} | #alert{}.
%%
%% Description: Sets or calculates the master secret and calculate keys,
%% updating the pending connection states. The Mastersecret and the update
%% connection states are returned or an alert if the calculation fails.
%%-------------------------------------------------------------------
-master_secret(RecordCB, Version, #session{master_secret = Mastersecret},
+master_secret(Version, #session{master_secret = Mastersecret},
ConnectionStates, Role) ->
- ConnectionState =
+ #{security_parameters := SecParams} =
ssl_record:pending_connection_state(ConnectionStates, read),
- SecParams = ConnectionState#connection_state.security_parameters,
- try master_secret(RecordCB, Version, Mastersecret, SecParams,
+ try master_secret(Version, Mastersecret, SecParams,
ConnectionStates, Role)
catch
exit:_ ->
?ALERT_REC(?FATAL, ?HANDSHAKE_FAILURE, key_calculation_failure)
end;
-master_secret(RecordCB, Version, PremasterSecret, ConnectionStates, Role) ->
- ConnectionState =
+master_secret(Version, PremasterSecret, ConnectionStates, Role) ->
+ #{security_parameters := SecParams} =
ssl_record:pending_connection_state(ConnectionStates, read),
- SecParams = ConnectionState#connection_state.security_parameters,
+
#security_parameters{prf_algorithm = PrfAlgo,
client_random = ClientRandom,
server_random = ServerRandom} = SecParams,
- try master_secret(RecordCB, Version,
+ try master_secret(Version,
calc_master_secret(Version,PrfAlgo,PremasterSecret,
ClientRandom, ServerRandom),
SecParams, ConnectionStates, Role)
@@ -1343,29 +1340,29 @@ do_select_version(
renegotiation_info(_, client, _, false) ->
#renegotiation_info{renegotiated_connection = undefined};
renegotiation_info(_RecordCB, server, ConnectionStates, false) ->
- CS = ssl_record:current_connection_state(ConnectionStates, read),
- case CS#connection_state.secure_renegotiation of
+ ConnectionState = ssl_record:current_connection_state(ConnectionStates, read),
+ case maps:get(secure_renegotiation, ConnectionState) of
true ->
#renegotiation_info{renegotiated_connection = ?byte(0)};
false ->
#renegotiation_info{renegotiated_connection = undefined}
end;
renegotiation_info(_RecordCB, client, ConnectionStates, true) ->
- CS = ssl_record:current_connection_state(ConnectionStates, read),
- case CS#connection_state.secure_renegotiation of
+ ConnectionState = ssl_record:current_connection_state(ConnectionStates, read),
+ case maps:get(secure_renegotiation, ConnectionState) of
true ->
- Data = CS#connection_state.client_verify_data,
+ Data = maps:get(client_verify_data, ConnectionState),
#renegotiation_info{renegotiated_connection = Data};
false ->
#renegotiation_info{renegotiated_connection = undefined}
end;
renegotiation_info(_RecordCB, server, ConnectionStates, true) ->
- CS = ssl_record:current_connection_state(ConnectionStates, read),
- case CS#connection_state.secure_renegotiation of
+ ConnectionState = ssl_record:current_connection_state(ConnectionStates, read),
+ case maps:get(secure_renegotiation, ConnectionState) of
true ->
- CData = CS#connection_state.client_verify_data,
- SData =CS#connection_state.server_verify_data,
+ CData = maps:get(client_verify_data, ConnectionState),
+ SData = maps:get(server_verify_data, ConnectionState),
#renegotiation_info{renegotiated_connection = <<CData/binary, SData/binary>>};
false ->
#renegotiation_info{renegotiated_connection = undefined}
@@ -1388,9 +1385,9 @@ handle_renegotiation_info(_RecordCB, _, undefined, ConnectionStates, false, _, _
handle_renegotiation_info(_RecordCB, client, #renegotiation_info{renegotiated_connection = ClientServerVerify},
ConnectionStates, true, _, _) ->
- CS = ssl_record:current_connection_state(ConnectionStates, read),
- CData = CS#connection_state.client_verify_data,
- SData = CS#connection_state.server_verify_data,
+ ConnectionState = ssl_record:current_connection_state(ConnectionStates, read),
+ CData = maps:get(client_verify_data, ConnectionState),
+ SData = maps:get(server_verify_data, ConnectionState),
case <<CData/binary, SData/binary>> == ClientServerVerify of
true ->
{ok, ConnectionStates};
@@ -1404,8 +1401,8 @@ handle_renegotiation_info(_RecordCB, server, #renegotiation_info{renegotiated_co
true ->
?ALERT_REC(?FATAL, ?HANDSHAKE_FAILURE, {server_renegotiation, empty_renegotiation_info_scsv});
false ->
- CS = ssl_record:current_connection_state(ConnectionStates, read),
- Data = CS#connection_state.client_verify_data,
+ ConnectionState = ssl_record:current_connection_state(ConnectionStates, read),
+ Data = maps:get(client_verify_data, ConnectionState),
case Data == ClientVerify of
true ->
{ok, ConnectionStates};
@@ -1426,8 +1423,8 @@ handle_renegotiation_info(RecordCB, server, undefined, ConnectionStates, true, S
end.
handle_renegotiation_info(_RecordCB, ConnectionStates, SecureRenegotation) ->
- CS = ssl_record:current_connection_state(ConnectionStates, read),
- case {SecureRenegotation, CS#connection_state.secure_renegotiation} of
+ ConnectionState = ssl_record:current_connection_state(ConnectionStates, read),
+ case {SecureRenegotation, maps:get(secure_renegotiation, ConnectionState)} of
{_, true} ->
?ALERT_REC(?FATAL, ?HANDSHAKE_FAILURE, already_secure);
{true, false} ->
@@ -1645,7 +1642,7 @@ calc_finished({3, 0}, Role, _PrfAlgo, MasterSecret, Handshake) ->
calc_finished({3, N}, Role, PrfAlgo, MasterSecret, Handshake) ->
tls_v1:finished(Role, N, PrfAlgo, MasterSecret, lists:reverse(Handshake)).
-master_secret(_RecordCB, Version, MasterSecret,
+master_secret(Version, MasterSecret,
#security_parameters{
bulk_cipher_algorithm = BCA,
client_random = ClientRandom,
@@ -1728,18 +1725,16 @@ hello_pending_connection_states(_RecordCB, Role, Version, CipherSuite, Random, C
NewWriteSecParams,
ConnectionStates).
-hello_security_parameters(client, Version, ConnectionState, CipherSuite, Random,
+hello_security_parameters(client, Version, #{security_parameters := SecParams}, CipherSuite, Random,
Compression) ->
- SecParams = ConnectionState#connection_state.security_parameters,
NewSecParams = ssl_cipher:security_parameters(Version, CipherSuite, SecParams),
NewSecParams#security_parameters{
server_random = Random,
compression_algorithm = Compression
};
-hello_security_parameters(server, Version, ConnectionState, CipherSuite, Random,
+hello_security_parameters(server, Version, #{security_parameters := SecParams}, CipherSuite, Random,
Compression) ->
- SecParams = ConnectionState#connection_state.security_parameters,
NewSecParams = ssl_cipher:security_parameters(Version, CipherSuite, SecParams),
NewSecParams#security_parameters{
client_random = Random,
diff --git a/lib/ssl/src/ssl_record.erl b/lib/ssl/src/ssl_record.erl
index 5bb1c92c2d..71cd0279f3 100644
--- a/lib/ssl/src/ssl_record.erl
+++ b/lib/ssl/src/ssl_record.erl
@@ -30,8 +30,7 @@
-include("ssl_alert.hrl").
%% Connection state handling
--export([init_connection_states/2,
- current_connection_state/2, pending_connection_state/2,
+-export([initial_security_params/1, current_connection_state/2, pending_connection_state/2,
activate_pending_connection_state/2,
set_security_params/3,
set_mac_secret/4,
@@ -39,7 +38,8 @@
set_pending_cipher_state/4,
set_renegotiation_flag/2,
set_client_verify_data/3,
- set_server_verify_data/3]).
+ set_server_verify_data/3,
+ empty_connection_state/2, initial_connection_state/2, record_protocol_role/1]).
%% Encoding records
-export([encode_handshake/3, encode_alert_record/3,
@@ -52,122 +52,92 @@
-export([cipher/4, decipher/4, is_correct_mac/2,
cipher_aead/4, decipher_aead/4]).
--export_type([ssl_version/0, ssl_atom_version/0]).
+-export_type([ssl_version/0, ssl_atom_version/0, connection_states/0, connection_state/0]).
-type ssl_version() :: {integer(), integer()}.
-type ssl_atom_version() :: tls_record:tls_atom_version().
-
+-type connection_states() :: term(). %% Map
+-type connection_state() :: term(). %% Map
%%====================================================================
%% Internal application API
%%====================================================================
+
%%--------------------------------------------------------------------
--spec init_connection_states(client | server, one_n_minus_one | zero_n | disabled ) ->
- #connection_states{}.
-%%
-%% Description: Creates a connection_states record with appropriate
-%% values for the initial SSL connection setup.
-%%--------------------------------------------------------------------
-init_connection_states(Role, BeastMitigation) ->
- ConnectionEnd = record_protocol_role(Role),
- Current = initial_connection_state(ConnectionEnd, BeastMitigation),
- Pending = empty_connection_state(ConnectionEnd, BeastMitigation),
- #connection_states{dtls_write_msg_seq = 1, % only used by dtls
- current_read = Current,
- pending_read = Pending,
- current_write = Current,
- pending_write = Pending
- }.
-
-%%--------------------------------------------------------------------
--spec current_connection_state(#connection_states{}, read | write) ->
- #connection_state{}.
+-spec current_connection_state(connection_states(), read | write) ->
+ connection_state().
%%
-%% Description: Returns the instance of the connection_state record
+%% Description: Returns the instance of the connection_state map
%% that is currently defined as the current conection state.
%%--------------------------------------------------------------------
-current_connection_state(#connection_states{current_read = Current},
- read) ->
- Current;
-current_connection_state(#connection_states{current_write = Current},
- write) ->
- Current.
+current_connection_state(ConnectionStates, read) ->
+ maps:get(current_read, ConnectionStates);
+current_connection_state(ConnectionStates, write) ->
+ maps:get(current_write, ConnectionStates).
%%--------------------------------------------------------------------
--spec pending_connection_state(#connection_states{}, read | write) ->
- term().
+-spec pending_connection_state(connection_states(), read | write) ->
+ connection_state().
%%
-%% Description: Returns the instance of the connection_state record
-%% that is currently defined as the pending conection state.
+%% Description: Returns the instance of the connection_state map
+%% that is pendingly defined as the pending conection state.
%%--------------------------------------------------------------------
-pending_connection_state(#connection_states{pending_read = Pending},
- read) ->
- Pending;
-pending_connection_state(#connection_states{pending_write = Pending},
- write) ->
- Pending.
-
+pending_connection_state(ConnectionStates, read) ->
+ maps:get(pending_read, ConnectionStates);
+pending_connection_state(ConnectionStates, write) ->
+ maps:get(pending_write, ConnectionStates).
%%--------------------------------------------------------------------
--spec activate_pending_connection_state(#connection_states{}, read | write) ->
- #connection_states{}.
+-spec activate_pending_connection_state(connection_states(), read | write) ->
+ connection_states().
%%
%% Description: Creates a new instance of the connection_states record
%% where the pending state of <Type> has been activated.
%%--------------------------------------------------------------------
-activate_pending_connection_state(States =
- #connection_states{current_read = Current,
- pending_read = Pending},
+activate_pending_connection_state(#{current_read := Current,
+ pending_read := Pending} = States,
read) ->
- NewCurrent = Pending#connection_state{epoch = dtls_next_epoch(Current),
- sequence_number = 0},
- BeastMitigation = Pending#connection_state.beast_mitigation,
- SecParams = Pending#connection_state.security_parameters,
+ #{secure_renegotiation := SecureRenegotation} = Current,
+ #{beast_mitigation := BeastMitigation,
+ security_parameters := SecParams} = Pending,
+ NewCurrent = Pending#{sequence_number => 0},
ConnectionEnd = SecParams#security_parameters.connection_end,
EmptyPending = empty_connection_state(ConnectionEnd, BeastMitigation),
- SecureRenegotation = NewCurrent#connection_state.secure_renegotiation,
- NewPending = EmptyPending#connection_state{secure_renegotiation = SecureRenegotation},
- States#connection_states{current_read = NewCurrent,
- pending_read = NewPending
- };
-
-activate_pending_connection_state(States =
- #connection_states{current_write = Current,
- pending_write = Pending},
+ NewPending = EmptyPending#{secure_renegotiation => SecureRenegotation},
+ States#{current_read => NewCurrent,
+ pending_read => NewPending
+ };
+
+activate_pending_connection_state(#{current_write := Current,
+ pending_write := Pending} = States,
write) ->
- NewCurrent = Pending#connection_state{epoch = dtls_next_epoch(Current),
- sequence_number = 0},
- BeastMitigation = Pending#connection_state.beast_mitigation,
- SecParams = Pending#connection_state.security_parameters,
+ NewCurrent = Pending#{sequence_number => 0},
+ #{secure_renegotiation := SecureRenegotation} = Current,
+ #{beast_mitigation := BeastMitigation,
+ security_parameters := SecParams} = Pending,
ConnectionEnd = SecParams#security_parameters.connection_end,
EmptyPending = empty_connection_state(ConnectionEnd, BeastMitigation),
- SecureRenegotation = NewCurrent#connection_state.secure_renegotiation,
- NewPending = EmptyPending#connection_state{secure_renegotiation = SecureRenegotation},
- States#connection_states{current_write = NewCurrent,
- pending_write = NewPending
- }.
-
+ NewPending = EmptyPending#{secure_renegotiation => SecureRenegotation},
+ States#{current_write => NewCurrent,
+ pending_write => NewPending
+ }.
%%--------------------------------------------------------------------
-spec set_security_params(#security_parameters{}, #security_parameters{},
- #connection_states{}) -> #connection_states{}.
+ connection_states()) -> connection_states().
%%
%% Description: Creates a new instance of the connection_states record
%% where the pending states gets its security parameters updated.
%%--------------------------------------------------------------------
-set_security_params(ReadParams, WriteParams, States =
- #connection_states{pending_read = Read,
- pending_write = Write}) ->
- States#connection_states{pending_read =
- Read#connection_state{security_parameters =
- ReadParams},
- pending_write =
- Write#connection_state{security_parameters =
- WriteParams}
- }.
+set_security_params(ReadParams, WriteParams,
+ #{pending_read := Read,
+ pending_write := Write} = States) ->
+ States#{pending_read => Read#{security_parameters => ReadParams},
+ pending_write => Write#{security_parameters => WriteParams}
+ }.
%%--------------------------------------------------------------------
-spec set_mac_secret(binary(), binary(), client | server,
- #connection_states{}) -> #connection_states{}.
+ connection_states()) -> connection_states().
%%
%% Description: update the mac_secret field in pending connection states
%%--------------------------------------------------------------------
@@ -177,152 +147,145 @@ set_mac_secret(ClientWriteMacSecret, ServerWriteMacSecret, server, States) ->
set_mac_secret(ClientWriteMacSecret, ServerWriteMacSecret, States).
set_mac_secret(ReadMacSecret, WriteMacSecret,
- States = #connection_states{pending_read = Read,
- pending_write = Write}) ->
- States#connection_states{
- pending_read = Read#connection_state{mac_secret = ReadMacSecret},
- pending_write = Write#connection_state{mac_secret = WriteMacSecret}
+ States = #{pending_read := Read,
+ pending_write := Write}) ->
+ States#{pending_read => Read#{mac_secret => ReadMacSecret},
+ pending_write => Write#{mac_secret => WriteMacSecret}
}.
%%--------------------------------------------------------------------
--spec set_master_secret(binary(), #connection_states{}) -> #connection_states{}.
+-spec set_master_secret(binary(), connection_states()) -> connection_states().
%%
%% Description: Set master_secret in pending connection states
%%--------------------------------------------------------------------
set_master_secret(MasterSecret,
- States = #connection_states{pending_read = Read,
- pending_write = Write}) ->
- ReadSecPar = Read#connection_state.security_parameters,
- Read1 = Read#connection_state{
- security_parameters = ReadSecPar#security_parameters{
- master_secret = MasterSecret}},
- WriteSecPar = Write#connection_state.security_parameters,
- Write1 = Write#connection_state{
- security_parameters = WriteSecPar#security_parameters{
- master_secret = MasterSecret}},
- States#connection_states{pending_read = Read1, pending_write = Write1}.
-
-%%--------------------------------------------------------------------
--spec set_renegotiation_flag(boolean(), #connection_states{}) -> #connection_states{}.
+ States = #{pending_read := Read = #{security_parameters := ReadSecPar},
+ pending_write := Write = #{security_parameters := WriteSecPar}}) ->
+ Read1 = Read#{security_parameters => ReadSecPar#security_parameters{
+ master_secret = MasterSecret}},
+ Write1 = Write#{security_parameters => WriteSecPar#security_parameters{
+ master_secret = MasterSecret}},
+ States#{pending_read => Read1, pending_write => Write1}.
+
+%%--------------------------------------------------------------------
+-spec set_renegotiation_flag(boolean(), connection_states()) -> connection_states().
%%
%% Description: Set secure_renegotiation in pending connection states
%%--------------------------------------------------------------------
-set_renegotiation_flag(Flag, #connection_states{
- current_read = CurrentRead0,
- current_write = CurrentWrite0,
- pending_read = PendingRead0,
- pending_write = PendingWrite0}
+set_renegotiation_flag(Flag, #{current_read := CurrentRead0,
+ current_write := CurrentWrite0,
+ pending_read := PendingRead0,
+ pending_write := PendingWrite0}
= ConnectionStates) ->
- CurrentRead = CurrentRead0#connection_state{secure_renegotiation = Flag},
- CurrentWrite = CurrentWrite0#connection_state{secure_renegotiation = Flag},
- PendingRead = PendingRead0#connection_state{secure_renegotiation = Flag},
- PendingWrite = PendingWrite0#connection_state{secure_renegotiation = Flag},
- ConnectionStates#connection_states{current_read = CurrentRead,
- current_write = CurrentWrite,
- pending_read = PendingRead,
- pending_write = PendingWrite}.
+ CurrentRead = CurrentRead0#{secure_renegotiation => Flag},
+ CurrentWrite = CurrentWrite0#{secure_renegotiation => Flag},
+ PendingRead = PendingRead0#{secure_renegotiation => Flag},
+ PendingWrite = PendingWrite0#{secure_renegotiation => Flag},
+ ConnectionStates#{current_read => CurrentRead,
+ current_write => CurrentWrite,
+ pending_read => PendingRead,
+ pending_write => PendingWrite}.
%%--------------------------------------------------------------------
-spec set_client_verify_data(current_read | current_write | current_both,
- binary(), #connection_states{})->
- #connection_states{}.
+ binary(), connection_states())->
+ connection_states().
%%
%% Description: Set verify data in connection states.
%%--------------------------------------------------------------------
set_client_verify_data(current_read, Data,
- #connection_states{current_read = CurrentRead0,
- pending_write = PendingWrite0}
+ #{current_read := CurrentRead0,
+ pending_write := PendingWrite0}
= ConnectionStates) ->
- CurrentRead = CurrentRead0#connection_state{client_verify_data = Data},
- PendingWrite = PendingWrite0#connection_state{client_verify_data = Data},
- ConnectionStates#connection_states{current_read = CurrentRead,
- pending_write = PendingWrite};
+ CurrentRead = CurrentRead0#{client_verify_data => Data},
+ PendingWrite = PendingWrite0#{client_verify_data => Data},
+ ConnectionStates#{current_read => CurrentRead,
+ pending_write => PendingWrite};
set_client_verify_data(current_write, Data,
- #connection_states{pending_read = PendingRead0,
- current_write = CurrentWrite0}
+ #{pending_read := PendingRead0,
+ current_write := CurrentWrite0}
= ConnectionStates) ->
- PendingRead = PendingRead0#connection_state{client_verify_data = Data},
- CurrentWrite = CurrentWrite0#connection_state{client_verify_data = Data},
- ConnectionStates#connection_states{pending_read = PendingRead,
- current_write = CurrentWrite};
+ PendingRead = PendingRead0#{client_verify_data => Data},
+ CurrentWrite = CurrentWrite0#{client_verify_data => Data},
+ ConnectionStates#{pending_read => PendingRead,
+ current_write => CurrentWrite};
set_client_verify_data(current_both, Data,
- #connection_states{current_read = CurrentRead0,
- current_write = CurrentWrite0}
+ #{current_read := CurrentRead0,
+ current_write := CurrentWrite0}
= ConnectionStates) ->
- CurrentRead = CurrentRead0#connection_state{client_verify_data = Data},
- CurrentWrite = CurrentWrite0#connection_state{client_verify_data = Data},
- ConnectionStates#connection_states{current_read = CurrentRead,
- current_write = CurrentWrite}.
+ CurrentRead = CurrentRead0#{client_verify_data => Data},
+ CurrentWrite = CurrentWrite0#{client_verify_data => Data},
+ ConnectionStates#{current_read => CurrentRead,
+ current_write => CurrentWrite}.
%%--------------------------------------------------------------------
-spec set_server_verify_data(current_read | current_write | current_both,
- binary(), #connection_states{})->
- #connection_states{}.
+ binary(), connection_states())->
+ connection_states().
%%
%% Description: Set verify data in pending connection states.
%%--------------------------------------------------------------------
set_server_verify_data(current_write, Data,
- #connection_states{pending_read = PendingRead0,
- current_write = CurrentWrite0}
+ #{pending_read := PendingRead0,
+ current_write := CurrentWrite0}
= ConnectionStates) ->
- PendingRead = PendingRead0#connection_state{server_verify_data = Data},
- CurrentWrite = CurrentWrite0#connection_state{server_verify_data = Data},
- ConnectionStates#connection_states{pending_read = PendingRead,
- current_write = CurrentWrite};
+ PendingRead = PendingRead0#{server_verify_data => Data},
+ CurrentWrite = CurrentWrite0#{server_verify_data => Data},
+ ConnectionStates#{pending_read => PendingRead,
+ current_write => CurrentWrite};
set_server_verify_data(current_read, Data,
- #connection_states{current_read = CurrentRead0,
- pending_write = PendingWrite0}
+ #{current_read := CurrentRead0,
+ pending_write := PendingWrite0}
= ConnectionStates) ->
- CurrentRead = CurrentRead0#connection_state{server_verify_data = Data},
- PendingWrite = PendingWrite0#connection_state{server_verify_data = Data},
- ConnectionStates#connection_states{current_read = CurrentRead,
- pending_write = PendingWrite};
+ CurrentRead = CurrentRead0#{server_verify_data => Data},
+ PendingWrite = PendingWrite0#{server_verify_data => Data},
+ ConnectionStates#{current_read => CurrentRead,
+ pending_write => PendingWrite};
set_server_verify_data(current_both, Data,
- #connection_states{current_read = CurrentRead0,
- current_write = CurrentWrite0}
+ #{current_read := CurrentRead0,
+ current_write := CurrentWrite0}
= ConnectionStates) ->
- CurrentRead = CurrentRead0#connection_state{server_verify_data = Data},
- CurrentWrite = CurrentWrite0#connection_state{server_verify_data = Data},
- ConnectionStates#connection_states{current_read = CurrentRead,
- current_write = CurrentWrite}.
+ CurrentRead = CurrentRead0#{server_verify_data => Data},
+ CurrentWrite = CurrentWrite0#{server_verify_data => Data},
+ ConnectionStates#{current_read => CurrentRead,
+ current_write => CurrentWrite}.
%%--------------------------------------------------------------------
--spec set_pending_cipher_state(#connection_states{}, #cipher_state{},
+-spec set_pending_cipher_state(connection_states(), #cipher_state{},
#cipher_state{}, client | server) ->
- #connection_states{}.
+ connection_states().
%%
%% Description: Set the cipher state in the specified pending connection state.
%%--------------------------------------------------------------------
-set_pending_cipher_state(#connection_states{pending_read = Read,
- pending_write = Write} = States,
+set_pending_cipher_state(#{pending_read := Read,
+ pending_write := Write} = States,
ClientState, ServerState, server) ->
- States#connection_states{
- pending_read = Read#connection_state{cipher_state = ClientState},
- pending_write = Write#connection_state{cipher_state = ServerState}};
+ States#{
+ pending_read => Read#{cipher_state => ClientState},
+ pending_write => Write#{cipher_state => ServerState}};
-set_pending_cipher_state(#connection_states{pending_read = Read,
- pending_write = Write} = States,
+set_pending_cipher_state(#{pending_read := Read,
+ pending_write := Write} = States,
ClientState, ServerState, client) ->
- States#connection_states{
- pending_read = Read#connection_state{cipher_state = ServerState},
- pending_write = Write#connection_state{cipher_state = ClientState}}.
+ States#{
+ pending_read => Read#{cipher_state => ServerState},
+ pending_write => Write#{cipher_state => ClientState}}.
%%--------------------------------------------------------------------
--spec encode_handshake(iolist(), ssl_version(), #connection_states{}) ->
- {iolist(), #connection_states{}}.
+-spec encode_handshake(iolist(), ssl_version(), connection_states()) ->
+ {iolist(), connection_states()}.
%%
%% Description: Encodes a handshake message to send on the ssl-socket.
%%--------------------------------------------------------------------
encode_handshake(Frag, Version,
- #connection_states{current_write =
- #connection_state{
- beast_mitigation = BeastMitigation,
- security_parameters =
- #security_parameters{bulk_cipher_algorithm = BCA}}} =
+ #{current_write :=
+ #{beast_mitigation := BeastMitigation,
+ security_parameters :=
+ #security_parameters{bulk_cipher_algorithm = BCA}}} =
ConnectionStates)
-when is_list(Frag) ->
+ when is_list(Frag) ->
case iolist_size(Frag) of
N when N > ?MAX_PLAIN_TEXT_LENGTH ->
Data = split_bin(iolist_to_binary(Frag), ?MAX_PLAIN_TEXT_LENGTH, Version, BCA, BeastMitigation),
@@ -341,8 +304,8 @@ encode_handshake(Frag, Version, ConnectionStates) ->
encode_plain_text(?HANDSHAKE, Version, Frag, ConnectionStates).
%%--------------------------------------------------------------------
--spec encode_alert_record(#alert{}, ssl_version(), #connection_states{}) ->
- {iolist(), #connection_states{}}.
+-spec encode_alert_record(#alert{}, ssl_version(), connection_states()) ->
+ {iolist(), connection_states()}.
%%
%% Description: Encodes an alert message to send on the ssl-socket.
%%--------------------------------------------------------------------
@@ -352,8 +315,8 @@ encode_alert_record(#alert{level = Level, description = Description},
ConnectionStates).
%%--------------------------------------------------------------------
--spec encode_change_cipher_spec(ssl_version(), #connection_states{}) ->
- {iolist(), #connection_states{}}.
+-spec encode_change_cipher_spec(ssl_version(), connection_states()) ->
+ {iolist(), connection_states()}.
%%
%% Description: Encodes a change_cipher_spec-message to send on the ssl socket.
%%--------------------------------------------------------------------
@@ -361,15 +324,14 @@ encode_change_cipher_spec(Version, ConnectionStates) ->
encode_plain_text(?CHANGE_CIPHER_SPEC, Version, <<1:8>>, ConnectionStates).
%%--------------------------------------------------------------------
--spec encode_data(binary(), ssl_version(), #connection_states{}) ->
- {iolist(), #connection_states{}}.
+-spec encode_data(binary(), ssl_version(), connection_states()) ->
+ {iolist(), connection_states()}.
%%
%% Description: Encodes data to send on the ssl-socket.
%%--------------------------------------------------------------------
encode_data(Frag, Version,
- #connection_states{current_write = #connection_state{
- beast_mitigation = BeastMitigation,
- security_parameters =
+ #{current_write := #{beast_mitigation := BeastMitigation,
+ security_parameters :=
#security_parameters{bulk_cipher_algorithm = BCA}}} =
ConnectionStates) ->
Data = split_bin(Frag, ?MAX_PLAIN_TEXT_LENGTH, Version, BCA, BeastMitigation),
@@ -390,73 +352,74 @@ compressions() ->
[?byte(?NULL)].
%%--------------------------------------------------------------------
--spec cipher(ssl_version(), iodata(), #connection_state{}, MacHash::binary()) ->
- {CipherFragment::binary(), #connection_state{}}.
+-spec cipher(ssl_version(), iodata(), connection_state(), MacHash::binary()) ->
+ {CipherFragment::binary(), connection_state()}.
%%
%% Description: Payload encryption
%%--------------------------------------------------------------------
cipher(Version, Fragment,
- #connection_state{cipher_state = CipherS0,
- security_parameters=
- #security_parameters{bulk_cipher_algorithm =
- BulkCipherAlgo}
- } = WriteState0, MacHash) ->
-
+ #{cipher_state := CipherS0,
+ security_parameters :=
+ #security_parameters{bulk_cipher_algorithm =
+ BulkCipherAlgo}
+ } = WriteState0, MacHash) ->
+
{CipherFragment, CipherS1} =
ssl_cipher:cipher(BulkCipherAlgo, CipherS0, MacHash, Fragment, Version),
- {CipherFragment, WriteState0#connection_state{cipher_state = CipherS1}}.
+ {CipherFragment, WriteState0#{cipher_state => CipherS1}}.
%%--------------------------------------------------------------------
--spec cipher_aead(ssl_version(), iodata(), #connection_state{}, MacHash::binary()) ->
- {CipherFragment::binary(), #connection_state{}}.
+-spec cipher_aead(ssl_version(), iodata(), connection_state(), MacHash::binary()) ->
+ {CipherFragment::binary(), connection_state()}.
%%
%% Description: Payload encryption
%%--------------------------------------------------------------------
cipher_aead(Version, Fragment,
- #connection_state{cipher_state = CipherS0,
- sequence_number = SeqNo,
- security_parameters=
- #security_parameters{bulk_cipher_algorithm =
- BulkCipherAlgo}
- } = WriteState0, AAD) ->
-
+ #{cipher_state := CipherS0,
+ sequence_number := SeqNo,
+ security_parameters :=
+ #security_parameters{bulk_cipher_algorithm =
+ BulkCipherAlgo}
+ } = WriteState0, AAD) ->
+
{CipherFragment, CipherS1} =
ssl_cipher:cipher_aead(BulkCipherAlgo, CipherS0, SeqNo, AAD, Fragment, Version),
- {CipherFragment, WriteState0#connection_state{cipher_state = CipherS1}}.
+ {CipherFragment, WriteState0#{cipher_state => CipherS1}}.
%%--------------------------------------------------------------------
--spec decipher(ssl_version(), binary(), #connection_state{}, boolean()) -> {binary(), binary(), #connection_state{}} | #alert{}.
+-spec decipher(ssl_version(), binary(), connection_state(), boolean()) -> {binary(), binary(), connection_state} | #alert{}.
%%
%% Description: Payload decryption
%%--------------------------------------------------------------------
decipher(Version, CipherFragment,
- #connection_state{security_parameters =
- #security_parameters{bulk_cipher_algorithm =
- BulkCipherAlgo,
- hash_size = HashSz},
- cipher_state = CipherS0
- } = ReadState, PaddingCheck) ->
+ #{security_parameters :=
+ #security_parameters{bulk_cipher_algorithm =
+ BulkCipherAlgo,
+ hash_size = HashSz},
+ cipher_state := CipherS0
+ } = ReadState, PaddingCheck) ->
case ssl_cipher:decipher(BulkCipherAlgo, HashSz, CipherS0, CipherFragment, Version, PaddingCheck) of
{PlainFragment, Mac, CipherS1} ->
- CS1 = ReadState#connection_state{cipher_state = CipherS1},
+ CS1 = ReadState#{cipher_state => CipherS1},
{PlainFragment, Mac, CS1};
#alert{} = Alert ->
Alert
end.
%%--------------------------------------------------------------------
--spec decipher_aead(ssl_version(), binary(), #connection_state{}, binary()) -> {binary(), binary(), #connection_state{}} | #alert{}.
+-spec decipher_aead(ssl_version(), binary(), connection_state(), binary()) ->
+ {binary(), binary(), connection_state()} | #alert{}.
%%
%% Description: Payload decryption
%%--------------------------------------------------------------------
decipher_aead(Version, CipherFragment,
- #connection_state{sequence_number = SeqNo,
- security_parameters =
- #security_parameters{bulk_cipher_algorithm =
- BulkCipherAlgo},
- cipher_state = CipherS0
- } = ReadState, AAD) ->
+ #{sequence_number := SeqNo,
+ security_parameters :=
+ #security_parameters{bulk_cipher_algorithm =
+ BulkCipherAlgo},
+ cipher_state := CipherS0
+ } = ReadState, AAD) ->
case ssl_cipher:decipher_aead(BulkCipherAlgo, CipherS0, SeqNo, AAD, CipherFragment, Version) of
{PlainFragment, CipherS1} ->
- CS1 = ReadState#connection_state{cipher_state = CipherS1},
+ CS1 = ReadState#{cipher_state => CipherS1},
{PlainFragment, CS1};
#alert{} = Alert ->
Alert
@@ -466,8 +429,15 @@ decipher_aead(Version, CipherFragment,
%%--------------------------------------------------------------------
empty_connection_state(ConnectionEnd, BeastMitigation) ->
SecParams = empty_security_params(ConnectionEnd),
- #connection_state{security_parameters = SecParams,
- beast_mitigation = BeastMitigation}.
+ #{security_parameters => SecParams,
+ beast_mitigation => BeastMitigation,
+ compression_state => undefined,
+ cipher_state => undefined,
+ mac_secret => undefined,
+ secure_renegotiation => undefined,
+ client_verify_data => undefined,
+ server_verify_data => undefined
+ }.
empty_security_params(ConnectionEnd = ?CLIENT) ->
#security_parameters{connection_end = ConnectionEnd,
@@ -481,10 +451,10 @@ random() ->
Random_28_bytes = ssl_cipher:random_bytes(28),
<<?UINT32(Secs_since_1970), Random_28_bytes/binary>>.
-dtls_next_epoch(#connection_state{epoch = undefined}) -> %% SSL/TLS
- undefined;
-dtls_next_epoch(#connection_state{epoch = Epoch}) -> %% DTLS
- Epoch + 1.
+%% dtls_next_epoch(#connection_state{epoch = undefined}) -> %% SSL/TLS
+%% undefined;
+%% dtls_next_epoch(#connection_state{epoch = Epoch}) -> %% DTLS
+%% Epoch + 1.
is_correct_mac(Mac, Mac) ->
true;
@@ -497,11 +467,17 @@ record_protocol_role(server) ->
?SERVER.
initial_connection_state(ConnectionEnd, BeastMitigation) ->
- #connection_state{security_parameters =
- initial_security_params(ConnectionEnd),
- sequence_number = 0,
- beast_mitigation = BeastMitigation
- }.
+ #{security_parameters =>
+ initial_security_params(ConnectionEnd),
+ sequence_number => 0,
+ beast_mitigation => BeastMitigation,
+ compression_state => undefined,
+ cipher_state => undefined,
+ mac_secret => undefined,
+ secure_renegotiation => undefined,
+ client_verify_data => undefined,
+ server_verify_data => undefined
+ }.
initial_security_params(ConnectionEnd) ->
SecParams = #security_parameters{connection_end = ConnectionEnd,
diff --git a/lib/ssl/src/ssl_record.hrl b/lib/ssl/src/ssl_record.hrl
index a41264ff9b..ed007f58d7 100644
--- a/lib/ssl/src/ssl_record.hrl
+++ b/lib/ssl/src/ssl_record.hrl
@@ -30,29 +30,27 @@
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%% Connection states - RFC 4346 section 6.1
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
--record(connection_state, {
- security_parameters,
- compression_state,
- cipher_state,
- mac_secret,
- epoch, %% Only used by DTLS
- sequence_number,
- %% RFC 5746
- secure_renegotiation,
- client_verify_data,
- server_verify_data,
- %% How to do BEAST mitigation?
- beast_mitigation
- }).
-
--record(connection_states, {
- dtls_write_msg_seq, %% Only used by DTLS
+%% For documentation purposes are now maps in implementation
+%% -record(connection_state, {
+%% security_parameters,
+%% compression_state,
+%% cipher_state,
+%% mac_secret,
+%% sequence_number,
+%% %% RFC 5746
+%% secure_renegotiation,
+%% client_verify_data,
+%% server_verify_data,
+%% %% How to do BEAST mitigation?
+%% beast_mitigation
+%% }).
- current_read,
- pending_read,
- current_write,
- pending_write
- }).
+%% -record(connection_states, {
+%% current_read,
+%% pending_read,
+%% current_write,
+%% pending_write,
+%% }).
-record(security_parameters, {
cipher_suite,
diff --git a/lib/ssl/src/ssl_sup.erl b/lib/ssl/src/ssl_sup.erl
index 7fa1f7dc9e..ba20f65f44 100644
--- a/lib/ssl/src/ssl_sup.erl
+++ b/lib/ssl/src/ssl_sup.erl
@@ -47,11 +47,13 @@ init([]) ->
SessionCertManager = session_and_cert_manager_child_spec(),
TLSConnetionManager = tls_connection_manager_child_spec(),
%% Not supported yet
- %%DTLSConnetionManager = tls_connection_manager_child_spec(),
+ %%DTLSConnetionManager = dtls_connection_manager_child_spec(),
%% Handles emulated options so that they inherited by the accept socket, even when setopts is performed on
%% the listen socket
ListenOptionsTracker = listen_options_tracker_child_spec(),
- {ok, {{one_for_all, 10, 3600}, [SessionCertManager, TLSConnetionManager, ListenOptionsTracker]}}.
+ {ok, {{one_for_all, 10, 3600}, [SessionCertManager, TLSConnetionManager,
+ %%DTLSConnetionManager,
+ ListenOptionsTracker]}}.
manager_opts() ->
@@ -93,15 +95,14 @@ tls_connection_manager_child_spec() ->
{Name, StartFunc, Restart, Shutdown, Type, Modules}.
%% dtls_connection_manager_child_spec() ->
-%% Name = dtls_connection,
+%% Name = dtls_connection,
%% StartFunc = {dtls_connection_sup, start_link, []},
-%% Restart = permanent,
+%% Restart = permanent,
%% Shutdown = 4000,
%% Modules = [dtls_connection, ssl_connection],
%% Type = supervisor,
%% {Name, StartFunc, Restart, Shutdown, Type, Modules}.
-
listen_options_tracker_child_spec() ->
Name = ssl_socket,
StartFunc = {ssl_listen_tracker_sup, start_link, []},
diff --git a/lib/ssl/src/tls_connection.erl b/lib/ssl/src/tls_connection.erl
index 8b828f3421..9b9031473a 100644
--- a/lib/ssl/src/tls_connection.erl
+++ b/lib/ssl/src/tls_connection.erl
@@ -51,17 +51,13 @@
%% Handshake handling
-export([renegotiate/2, send_handshake/2,
queue_handshake/2, queue_change_cipher/2,
- reinit_handshake_data/1, handle_sni_extension/2]).
+ reinit_handshake_data/1, select_sni_extension/1]).
%% Alert and close handling
--export([send_alert/2, handle_own_alert/4, handle_close_alert/3,
- handle_normal_shutdown/3,
- close/5, alert_user/6, alert_user/9
- ]).
+-export([send_alert/2, close/5]).
%% Data handling
--export([write_application_data/3, read_application_data/2,
- passive_receive/2, next_record_if_active/1, handle_common_event/4]).
+-export([passive_receive/2, next_record_if_active/1, handle_common_event/4]).
%% gen_statem state functions
-export([init/3, error/3, downgrade/3, %% Initiation and take down states
@@ -107,9 +103,10 @@ send_handshake(Handshake, State) ->
queue_handshake(Handshake, #state{negotiated_version = Version,
tls_handshake_history = Hist0,
flight_buffer = Flight0,
+ ssl_options = #ssl_options{v2_hello_compatible = V2HComp},
connection_states = ConnectionStates0} = State0) ->
{BinHandshake, ConnectionStates, Hist} =
- encode_handshake(Handshake, Version, ConnectionStates0, Hist0),
+ encode_handshake(Handshake, Version, ConnectionStates0, Hist0, V2HComp),
State0#state{connection_states = ConnectionStates,
tls_handshake_history = Hist,
flight_buffer = Flight0 ++ [BinHandshake]}.
@@ -147,6 +144,11 @@ reinit_handshake_data(State) ->
tls_handshake_history = ssl_handshake:init_handshake_history()
}.
+select_sni_extension(#client_hello{extensions = HelloExtensions}) ->
+ HelloExtensions#hello_extensions.sni;
+select_sni_extension(_) ->
+ undefined.
+
%%====================================================================
%% tls_connection_sup API
%%====================================================================
@@ -186,7 +188,7 @@ callback_mode() ->
init({call, From}, {start, Timeout},
#state{host = Host, port = Port, role = client,
- ssl_options = SslOpts,
+ ssl_options = #ssl_options{v2_hello_compatible = V2HComp} = SslOpts,
session = #session{own_certificate = Cert} = Session0,
transport_cb = Transport, socket = Socket,
connection_states = ConnectionStates0,
@@ -202,7 +204,7 @@ init({call, From}, {start, Timeout},
HelloVersion = tls_record:lowest_protocol_version(SslOpts#ssl_options.versions),
Handshake0 = ssl_handshake:init_handshake_history(),
{BinMsg, ConnectionStates, Handshake} =
- encode_handshake(Hello, HelloVersion, ConnectionStates0, Handshake0),
+ encode_handshake(Hello, HelloVersion, ConnectionStates0, Handshake0, V2HComp),
Transport:send(Socket, BinMsg),
State1 = State0#state{connection_states = ConnectionStates,
negotiated_version = Version, %% Requested version
@@ -250,7 +252,7 @@ hello(internal, #client_hello{client_version = ClientVersion,
case tls_handshake:hello(Hello, SslOpts, {Port, Session0, Cache, CacheCb,
ConnectionStates0, Cert, KeyExAlg}, Renegotiation) of
#alert{} = Alert ->
- handle_own_alert(Alert, ClientVersion, hello, State);
+ ssl_connection:handle_own_alert(Alert, ClientVersion, hello, State);
{Version, {Type, Session},
ConnectionStates, Protocol0, ServerHelloExt, HashSign} ->
Protocol = case Protocol0 of
@@ -274,7 +276,7 @@ hello(internal, #server_hello{} = Hello,
ssl_options = SslOptions} = State) ->
case tls_handshake:hello(Hello, SslOptions, ConnectionStates0, Renegotiation) of
#alert{} = Alert ->
- handle_own_alert(Alert, ReqVersion, hello, State);
+ ssl_connection:handle_own_alert(Alert, ReqVersion, hello, State);
{Version, NewId, ConnectionStates, ProtoExt, Protocol} ->
ssl_connection:handle_session(Hello,
Version, NewId, ConnectionStates, ProtoExt, Protocol, State)
@@ -374,7 +376,7 @@ handle_info({Protocol, _, Data}, StateName,
{Record, State} ->
next_event(StateName, Record, State);
#alert{} = Alert ->
- handle_normal_shutdown(Alert, StateName, State0),
+ ssl_connection:handle_normal_shutdown(Alert, StateName, State0),
{stop, {shutdown, own_alert}}
end;
handle_info({CloseTag, Socket}, StateName,
@@ -394,14 +396,14 @@ handle_info({CloseTag, Socket}, StateName,
%%invalidate_session(Role, Host, Port, Session)
ok
end,
- handle_normal_shutdown(?ALERT_REC(?FATAL, ?CLOSE_NOTIFY), StateName, State),
+ ssl_connection:handle_normal_shutdown(?ALERT_REC(?FATAL, ?CLOSE_NOTIFY), StateName, State),
{stop, {shutdown, transport_closed}};
handle_info(Msg, StateName, State) ->
ssl_connection:handle_info(Msg, StateName, State).
handle_common_event(internal, #alert{} = Alert, StateName,
#state{negotiated_version = Version} = State) ->
- handle_own_alert(Alert, Version, StateName, State);
+ ssl_connection:handle_own_alert(Alert, Version, StateName, State);
%%% TLS record protocol level handshake messages
handle_common_event(internal, #ssl_tls{type = ?HANDSHAKE, fragment = Data},
@@ -422,7 +424,7 @@ handle_common_event(internal, #ssl_tls{type = ?HANDSHAKE, fragment = Data},
{next_state, StateName, State, Events}
end
catch throw:#alert{} = Alert ->
- handle_own_alert(Alert, Version, StateName, State0)
+ ssl_connection:handle_own_alert(Alert, Version, StateName, State0)
end;
%%% TLS record protocol level application data messages
handle_common_event(internal, #ssl_tls{type = ?APPLICATION_DATA, fragment = Data}, StateName, State) ->
@@ -437,12 +439,15 @@ handle_common_event(internal, #ssl_tls{type = ?ALERT, fragment = EncAlerts}, Sta
Alerts = [_|_] ->
handle_alerts(Alerts, {next_state, StateName, State});
[] ->
- handle_own_alert(?ALERT_REC(?FATAL, ?HANDSHAKE_FAILURE, empty_alert), Version, StateName, State);
+ ssl_connection:handle_own_alert(?ALERT_REC(?FATAL, ?HANDSHAKE_FAILURE, empty_alert),
+ Version, StateName, State);
#alert{} = Alert ->
- handle_own_alert(Alert, Version, StateName, State)
+ ssl_connection:handle_own_alert(Alert, Version, StateName, State)
catch
_:_ ->
- handle_own_alert(?ALERT_REC(?FATAL, ?HANDSHAKE_FAILURE, alert_decode_error), Version, StateName, State)
+ ssl_connection:handle_own_alert(?ALERT_REC(?FATAL, ?HANDSHAKE_FAILURE, alert_decode_error),
+ Version, StateName, State)
+
end;
%% Ignore unknown TLS record level protocol messages
handle_common_event(internal, #ssl_tls{type = _Unknown}, StateName, State) ->
@@ -470,9 +475,9 @@ code_change(_OldVsn, StateName, State, _) ->
%%--------------------------------------------------------------------
%%% Internal functions
%%--------------------------------------------------------------------
-encode_handshake(Handshake, Version, ConnectionStates0, Hist0) ->
+encode_handshake(Handshake, Version, ConnectionStates0, Hist0, V2HComp) ->
Frag = tls_handshake:encode_handshake(Handshake, Version),
- Hist = ssl_handshake:update_handshake_history(Hist0, Frag),
+ Hist = ssl_handshake:update_handshake_history(Hist0, Frag, V2HComp),
{Encoded, ConnectionStates} =
ssl_record:encode_handshake(Frag, Version, ConnectionStates0),
{Encoded, ConnectionStates, Hist}.
@@ -486,7 +491,7 @@ decode_alerts(Bin) ->
initial_state(Role, Host, Port, Socket, {SSLOptions, SocketOptions, Tracker}, User,
{CbModule, DataTag, CloseTag, ErrorTag}) ->
#ssl_options{beast_mitigation = BeastMitigation} = SSLOptions,
- ConnectionStates = ssl_record:init_connection_states(Role, BeastMitigation),
+ ConnectionStates = tls_record:init_connection_states(Role, BeastMitigation),
SessionCacheCb = case application:get_env(ssl, session_cb) of
{ok, Cb} when is_atom(Cb) ->
@@ -521,23 +526,6 @@ initial_state(Role, Host, Port, Socket, {SSLOptions, SocketOptions, Tracker}, Us
flight_buffer = []
}.
-
-update_ssl_options_from_sni(OrigSSLOptions, SNIHostname) ->
- SSLOption =
- case OrigSSLOptions#ssl_options.sni_fun of
- undefined ->
- proplists:get_value(SNIHostname,
- OrigSSLOptions#ssl_options.sni_hosts);
- SNIFun ->
- SNIFun(SNIHostname)
- end,
- case SSLOption of
- undefined ->
- undefined;
- _ ->
- ssl:handle_options(SSLOption, OrigSSLOptions)
- end.
-
next_tls_record(Data, #state{protocol_buffers = #protocol_buffers{tls_record_buffer = Buf0,
tls_cipher_texts = CT0} = Buffers} = State0) ->
case tls_record:get_tls_records(Data, Buf0) of
@@ -585,7 +573,7 @@ passive_receive(State0 = #state{user_data_buffer = Buffer}, StateName) ->
{Record, State} = next_record(State0),
next_event(StateName, Record, State);
_ ->
- {Record, State} = read_application_data(<<>>, State0),
+ {Record, State} = ssl_connection:read_application_data(<<>>, State0),
next_event(StateName, Record, State)
end.
@@ -597,7 +585,7 @@ next_event(connection = StateName, no_record, State0, Actions) ->
{no_record, State} ->
ssl_connection:hibernate_after(StateName, State, Actions);
{#ssl_tls{} = Record, State} ->
- {next_state, StateName, State, [{next_event, internal, {tls_record, Record}} | Actions]};
+ {next_state, StateName, State, [{next_event, internal, {protocol_record, Record}} | Actions]};
{#alert{} = Alert, State} ->
{next_state, StateName, State, [{next_event, internal, Alert} | Actions]}
end;
@@ -606,169 +594,11 @@ next_event(StateName, Record, State, Actions) ->
no_record ->
{next_state, StateName, State, Actions};
#ssl_tls{} = Record ->
- {next_state, StateName, State, [{next_event, internal, {tls_record, Record}} | Actions]};
+ {next_state, StateName, State, [{next_event, internal, {protocol_record, Record}} | Actions]};
#alert{} = Alert ->
{next_state, StateName, State, [{next_event, internal, Alert} | Actions]}
end.
-read_application_data(Data, #state{user_application = {_Mon, Pid},
- socket = Socket,
- transport_cb = Transport,
- socket_options = SOpts,
- bytes_to_read = BytesToRead,
- start_or_recv_from = RecvFrom,
- timer = Timer,
- user_data_buffer = Buffer0,
- tracker = Tracker} = State0) ->
- Buffer1 = if
- Buffer0 =:= <<>> -> Data;
- Data =:= <<>> -> Buffer0;
- true -> <<Buffer0/binary, Data/binary>>
- end,
- case get_data(SOpts, BytesToRead, Buffer1) of
- {ok, ClientData, Buffer} -> % Send data
- SocketOpt = deliver_app_data(Transport, Socket, SOpts, ClientData, Pid, RecvFrom, Tracker),
- cancel_timer(Timer),
- State = State0#state{user_data_buffer = Buffer,
- start_or_recv_from = undefined,
- timer = undefined,
- bytes_to_read = undefined,
- socket_options = SocketOpt
- },
- if
- SocketOpt#socket_options.active =:= false; Buffer =:= <<>> ->
- %% Passive mode, wait for active once or recv
- %% Active and empty, get more data
- next_record_if_active(State);
- true -> %% We have more data
- read_application_data(<<>>, State)
- end;
- {more, Buffer} -> % no reply, we need more data
- next_record(State0#state{user_data_buffer = Buffer});
- {passive, Buffer} ->
- next_record_if_active(State0#state{user_data_buffer = Buffer});
- {error,_Reason} -> %% Invalid packet in packet mode
- deliver_packet_error(Transport, Socket, SOpts, Buffer1, Pid, RecvFrom, Tracker),
- {stop, normal, State0}
- end.
-
-%% Picks ClientData
-get_data(_, _, <<>>) ->
- {more, <<>>};
-%% Recv timed out save buffer data until next recv
-get_data(#socket_options{active=false}, undefined, Buffer) ->
- {passive, Buffer};
-get_data(#socket_options{active=Active, packet=Raw}, BytesToRead, Buffer)
- when Raw =:= raw; Raw =:= 0 -> %% Raw Mode
- if
- Active =/= false orelse BytesToRead =:= 0 ->
- %% Active true or once, or passive mode recv(0)
- {ok, Buffer, <<>>};
- byte_size(Buffer) >= BytesToRead ->
- %% Passive Mode, recv(Bytes)
- <<Data:BytesToRead/binary, Rest/binary>> = Buffer,
- {ok, Data, Rest};
- true ->
- %% Passive Mode not enough data
- {more, Buffer}
- end;
-get_data(#socket_options{packet=Type, packet_size=Size}, _, Buffer) ->
- PacketOpts = [{packet_size, Size}],
- case decode_packet(Type, Buffer, PacketOpts) of
- {more, _} ->
- {more, Buffer};
- Decoded ->
- Decoded
- end.
-
-decode_packet({http, headers}, Buffer, PacketOpts) ->
- decode_packet(httph, Buffer, PacketOpts);
-decode_packet({http_bin, headers}, Buffer, PacketOpts) ->
- decode_packet(httph_bin, Buffer, PacketOpts);
-decode_packet(Type, Buffer, PacketOpts) ->
- erlang:decode_packet(Type, Buffer, PacketOpts).
-
-%% Just like with gen_tcp sockets, an ssl socket that has been configured with
-%% {packet, http} (or {packet, http_bin}) will automatically switch to expect
-%% HTTP headers after it sees a HTTP Request or HTTP Response line. We
-%% represent the current state as follows:
-%% #socket_options.packet =:= http: Expect a HTTP Request/Response line
-%% #socket_options.packet =:= {http, headers}: Expect HTTP Headers
-%% Note that if the user has explicitly configured the socket to expect
-%% HTTP headers using the {packet, httph} option, we don't do any automatic
-%% switching of states.
-deliver_app_data(Transport, Socket, SOpts = #socket_options{active=Active, packet=Type},
- Data, Pid, From, Tracker) ->
- send_or_reply(Active, Pid, From, format_reply(Transport, Socket, SOpts, Data, Tracker)),
- SO = case Data of
- {P, _, _, _} when ((P =:= http_request) or (P =:= http_response)),
- ((Type =:= http) or (Type =:= http_bin)) ->
- SOpts#socket_options{packet={Type, headers}};
- http_eoh when tuple_size(Type) =:= 2 ->
- % End of headers - expect another Request/Response line
- {Type1, headers} = Type,
- SOpts#socket_options{packet=Type1};
- _ ->
- SOpts
- end,
- case Active of
- once ->
- SO#socket_options{active=false};
- _ ->
- SO
- end.
-
-format_reply(_, _,#socket_options{active = false, mode = Mode, packet = Packet,
- header = Header}, Data, _) ->
- {ok, do_format_reply(Mode, Packet, Header, Data)};
-format_reply(Transport, Socket, #socket_options{active = _, mode = Mode, packet = Packet,
- header = Header}, Data, Tracker) ->
- {ssl, ssl_socket:socket(self(), Transport, Socket, ?MODULE, Tracker),
- do_format_reply(Mode, Packet, Header, Data)}.
-
-deliver_packet_error(Transport, Socket, SO= #socket_options{active = Active}, Data, Pid, From, Tracker) ->
- send_or_reply(Active, Pid, From, format_packet_error(Transport, Socket, SO, Data, Tracker)).
-
-format_packet_error(_, _,#socket_options{active = false, mode = Mode}, Data, _) ->
- {error, {invalid_packet, do_format_reply(Mode, raw, 0, Data)}};
-format_packet_error(Transport, Socket, #socket_options{active = _, mode = Mode}, Data, Tracker) ->
- {ssl_error, ssl_socket:socket(self(), Transport, Socket, ?MODULE, Tracker),
- {invalid_packet, do_format_reply(Mode, raw, 0, Data)}}.
-
-do_format_reply(binary, _, N, Data) when N > 0 -> % Header mode
- header(N, Data);
-do_format_reply(binary, _, _, Data) ->
- Data;
-do_format_reply(list, Packet, _, Data)
- when Packet == http; Packet == {http, headers};
- Packet == http_bin; Packet == {http_bin, headers};
- Packet == httph; Packet == httph_bin ->
- Data;
-do_format_reply(list, _,_, Data) ->
- binary_to_list(Data).
-
-header(0, <<>>) ->
- <<>>;
-header(_, <<>>) ->
- [];
-header(0, Binary) ->
- Binary;
-header(N, Binary) ->
- <<?BYTE(ByteN), NewBinary/binary>> = Binary,
- [ByteN | header(N-1, NewBinary)].
-
-send_or_reply(false, _Pid, From, Data) when From =/= undefined ->
- gen_statem:reply(From, Data);
-%% Can happen when handling own alert or tcp error/close and there is
-%% no outstanding gen_fsm sync events
-send_or_reply(false, no_pid, _, _) ->
- ok;
-send_or_reply(_, Pid, _From, Data) ->
- send_user(Pid, Data).
-
-send_user(Pid, Msg) ->
- Pid ! Msg.
-
tls_handshake_events([]) ->
throw(?ALERT_REC(?FATAL, ?HANDSHAKE_FAILURE, malformed_handshake));
tls_handshake_events(Packets) ->
@@ -776,55 +606,7 @@ tls_handshake_events(Packets) ->
{next_event, internal, {handshake, Packet}}
end, Packets).
-write_application_data(Data0, From,
- #state{socket = Socket,
- negotiated_version = Version,
- transport_cb = Transport,
- connection_states = ConnectionStates0,
- socket_options = SockOpts,
- ssl_options = #ssl_options{renegotiate_at = RenegotiateAt}} = State) ->
- Data = encode_packet(Data0, SockOpts),
-
- case time_to_renegotiate(Data, ConnectionStates0, RenegotiateAt) of
- true ->
- renegotiate(State#state{renegotiation = {true, internal}},
- [{next_event, {call, From}, {application_data, Data0}}]);
- false ->
- {Msgs, ConnectionStates} = ssl_record:encode_data(Data, Version, ConnectionStates0),
- Result = Transport:send(Socket, Msgs),
- ssl_connection:hibernate_after(connection, State#state{connection_states = ConnectionStates},
- [{reply, From, Result}])
- end.
-
-encode_packet(Data, #socket_options{packet=Packet}) ->
- case Packet of
- 1 -> encode_size_packet(Data, 8, (1 bsl 8) - 1);
- 2 -> encode_size_packet(Data, 16, (1 bsl 16) - 1);
- 4 -> encode_size_packet(Data, 32, (1 bsl 32) - 1);
- _ -> Data
- end.
-
-encode_size_packet(Bin, Size, Max) ->
- Len = erlang:byte_size(Bin),
- case Len > Max of
- true -> throw({error, {badarg, {packet_to_large, Len, Max}}});
- false -> <<Len:Size, Bin/binary>>
- end.
-time_to_renegotiate(_Data,
- #connection_states{current_write =
- #connection_state{sequence_number = Num}},
- RenegotiateAt) ->
-
- %% We could do test:
- %% is_time_to_renegotiate((erlang:byte_size(_Data) div ?MAX_PLAIN_TEXT_LENGTH) + 1, RenegotiateAt),
- %% but we chose to have a some what lower renegotiateAt and a much cheaper test
- is_time_to_renegotiate(Num, RenegotiateAt).
-
-is_time_to_renegotiate(N, M) when N < M->
- false;
-is_time_to_renegotiate(_,_) ->
- true.
renegotiate(#state{role = client} = State, Actions) ->
%% Handle same way as if server requested
%% the renegotiation
@@ -854,131 +636,10 @@ handle_alerts([], Result) ->
handle_alerts(_, {stop,_} = Stop) ->
Stop;
handle_alerts([Alert | Alerts], {next_state, StateName, State}) ->
- handle_alerts(Alerts, handle_alert(Alert, StateName, State));
+ handle_alerts(Alerts, ssl_connection:handle_alert(Alert, StateName, State));
handle_alerts([Alert | Alerts], {next_state, StateName, State, _Actions}) ->
- handle_alerts(Alerts, handle_alert(Alert, StateName, State)).
-handle_alert(#alert{level = ?FATAL} = Alert, StateName,
- #state{socket = Socket, transport_cb = Transport,
- ssl_options = SslOpts, start_or_recv_from = From, host = Host,
- port = Port, session = Session, user_application = {_Mon, Pid},
- role = Role, socket_options = Opts, tracker = Tracker}) ->
- invalidate_session(Role, Host, Port, Session),
- log_alert(SslOpts#ssl_options.log_alert, StateName, Alert),
- alert_user(Transport, Tracker, Socket, StateName, Opts, Pid, From, Alert, Role),
- {stop, normal};
-
-handle_alert(#alert{level = ?WARNING, description = ?CLOSE_NOTIFY} = Alert,
- StateName, State) ->
- handle_normal_shutdown(Alert, StateName, State),
- {stop, {shutdown, peer_close}};
-
-handle_alert(#alert{level = ?WARNING, description = ?NO_RENEGOTIATION} = Alert, StateName,
- #state{ssl_options = SslOpts, renegotiation = {true, internal}} = State) ->
- log_alert(SslOpts#ssl_options.log_alert, StateName, Alert),
- handle_normal_shutdown(Alert, StateName, State),
- {stop, {shutdown, peer_close}};
-
-handle_alert(#alert{level = ?WARNING, description = ?NO_RENEGOTIATION} = Alert, StateName,
- #state{ssl_options = SslOpts, renegotiation = {true, From}} = State0) ->
- log_alert(SslOpts#ssl_options.log_alert, StateName, Alert),
- gen_statem:reply(From, {error, renegotiation_rejected}),
- {Record, State} = next_record(State0),
- %% Go back to connection!
- next_event(connection, Record, State);
-
-%% Gracefully log and ignore all other warning alerts
-handle_alert(#alert{level = ?WARNING} = Alert, StateName,
- #state{ssl_options = SslOpts} = State0) ->
- log_alert(SslOpts#ssl_options.log_alert, StateName, Alert),
- {Record, State} = next_record(State0),
- next_event(StateName, Record, State).
+ handle_alerts(Alerts, ssl_connection:handle_alert(Alert, StateName, State)).
-alert_user(Transport, Tracker, Socket, connection, Opts, Pid, From, Alert, Role) ->
- alert_user(Transport, Tracker, Socket, Opts#socket_options.active, Pid, From, Alert, Role);
-alert_user(Transport, Tracker, Socket,_, _, _, From, Alert, Role) ->
- alert_user(Transport, Tracker, Socket, From, Alert, Role).
-
-alert_user(Transport, Tracker, Socket, From, Alert, Role) ->
- alert_user(Transport, Tracker, Socket, false, no_pid, From, Alert, Role).
-
-alert_user(_, _, _, false = Active, Pid, From, Alert, Role) when From =/= undefined ->
- %% If there is an outstanding ssl_accept | recv
- %% From will be defined and send_or_reply will
- %% send the appropriate error message.
- ReasonCode = ssl_alert:reason_code(Alert, Role),
- send_or_reply(Active, Pid, From, {error, ReasonCode});
-alert_user(Transport, Tracker, Socket, Active, Pid, From, Alert, Role) ->
- case ssl_alert:reason_code(Alert, Role) of
- closed ->
- send_or_reply(Active, Pid, From,
- {ssl_closed, ssl_socket:socket(self(),
- Transport, Socket, ?MODULE, Tracker)});
- ReasonCode ->
- send_or_reply(Active, Pid, From,
- {ssl_error, ssl_socket:socket(self(),
- Transport, Socket, ?MODULE, Tracker), ReasonCode})
- end.
-
-log_alert(true, Info, Alert) ->
- Txt = ssl_alert:alert_txt(Alert),
- error_logger:format("SSL: ~p: ~s\n", [Info, Txt]);
-log_alert(false, _, _) ->
- ok.
-
-handle_own_alert(Alert, Version, StateName,
- #state{transport_cb = Transport,
- socket = Socket,
- connection_states = ConnectionStates,
- ssl_options = SslOpts} = State) ->
- try %% Try to tell the other side
- {BinMsg, _} =
- ssl_alert:encode(Alert, Version, ConnectionStates),
- Transport:send(Socket, BinMsg)
- catch _:_ -> %% Can crash if we are in a uninitialized state
- ignore
- end,
- try %% Try to tell the local user
- log_alert(SslOpts#ssl_options.log_alert, StateName, Alert),
- handle_normal_shutdown(Alert,StateName, State)
- catch _:_ ->
- ok
- end,
- {stop, {shutdown, own_alert}}.
-
-handle_normal_shutdown(Alert, _, #state{socket = Socket,
- transport_cb = Transport,
- start_or_recv_from = StartFrom,
- tracker = Tracker,
- role = Role, renegotiation = {false, first}}) ->
- alert_user(Transport, Tracker,Socket, StartFrom, Alert, Role);
-
-handle_normal_shutdown(Alert, StateName, #state{socket = Socket,
- socket_options = Opts,
- transport_cb = Transport,
- user_application = {_Mon, Pid},
- tracker = Tracker,
- start_or_recv_from = RecvFrom, role = Role}) ->
- alert_user(Transport, Tracker, Socket, StateName, Opts, Pid, RecvFrom, Alert, Role).
-
-handle_close_alert(Data, StateName, State0) ->
- case next_tls_record(Data, State0) of
- {#ssl_tls{type = ?ALERT, fragment = EncAlerts}, State} ->
- [Alert|_] = decode_alerts(EncAlerts),
- handle_normal_shutdown(Alert, StateName, State);
- _ ->
- ok
- end.
-
-cancel_timer(undefined) ->
- ok;
-cancel_timer(Timer) ->
- erlang:cancel_timer(Timer),
- ok.
-
-invalidate_session(client, Host, Port, Session) ->
- ssl_manager:invalidate_session(Host, Port, Session);
-invalidate_session(server, _, Port, Session) ->
- ssl_manager:invalidate_session(Port, Session).
%% User closes or recursive call!
close({close, Timeout}, Socket, Transport = gen_tcp, _,_) ->
@@ -1017,42 +678,16 @@ convert_options_partial_chain(Options, up) ->
convert_options_partial_chain(Options, down) ->
list_to_tuple(proplists:delete(partial_chain, tuple_to_list(Options))).
-handle_sni_extension(#client_hello{extensions = HelloExtensions}, State0) ->
- case HelloExtensions#hello_extensions.sni of
- undefined ->
- State0;
- #sni{hostname = Hostname} ->
- NewOptions = update_ssl_options_from_sni(State0#state.ssl_options, Hostname),
- case NewOptions of
- undefined ->
- State0;
- _ ->
- {ok, Ref, CertDbHandle, FileRefHandle, CacheHandle, CRLDbHandle, OwnCert, Key, DHParams} =
- ssl_config:init(NewOptions, State0#state.role),
- State0#state{
- session = State0#state.session#session{own_certificate = OwnCert},
- file_ref_db = FileRefHandle,
- cert_db_ref = Ref,
- cert_db = CertDbHandle,
- crl_db = CRLDbHandle,
- session_cache = CacheHandle,
- private_key = Key,
- diffie_hellman_params = DHParams,
- ssl_options = NewOptions,
- sni_hostname = Hostname
- }
- end
- end;
-handle_sni_extension(_, State) ->
- State.
-
-gen_handshake(GenConnection, StateName, Type, Event, #state{negotiated_version = Version} = State) ->
+gen_handshake(GenConnection, StateName, Type, Event,
+ #state{negotiated_version = Version} = State) ->
try GenConnection:StateName(Type, Event, State, ?MODULE) of
Result ->
Result
catch
_:_ ->
- handle_own_alert(?ALERT_REC(?FATAL, ?HANDSHAKE_FAILURE, malformed_handshake_data), Version, StateName, State)
+ ssl_connection:handle_own_alert(?ALERT_REC(?FATAL, ?HANDSHAKE_FAILURE,
+ malformed_handshake_data),
+ Version, StateName, State)
end.
gen_info(Event, connection = StateName, #state{negotiated_version = Version} = State) ->
@@ -1061,7 +696,9 @@ gen_info(Event, connection = StateName, #state{negotiated_version = Version} =
Result
catch
_:_ ->
- handle_own_alert(?ALERT_REC(?FATAL, ?INTERNAL_ERROR, malformed_data), Version, StateName, State)
+ ssl_connection:handle_own_alert(?ALERT_REC(?FATAL, ?INTERNAL_ERROR,
+ malformed_data),
+ Version, StateName, State)
end;
gen_info(Event, StateName, #state{negotiated_version = Version} = State) ->
@@ -1070,6 +707,8 @@ gen_info(Event, StateName, #state{negotiated_version = Version} = State) ->
Result
catch
_:_ ->
- handle_own_alert(?ALERT_REC(?FATAL, ?HANDSHAKE_FAILURE, malformed_handshake_data), Version, StateName, State)
+ ssl_connection:handle_own_alert(?ALERT_REC(?FATAL, ?HANDSHAKE_FAILURE,
+ malformed_handshake_data),
+ Version, StateName, State)
end.
diff --git a/lib/ssl/src/tls_handshake.erl b/lib/ssl/src/tls_handshake.erl
index 6e593950d9..a2486bf752 100644
--- a/lib/ssl/src/tls_handshake.erl
+++ b/lib/ssl/src/tls_handshake.erl
@@ -41,7 +41,7 @@
%% Internal application API
%%====================================================================
%%--------------------------------------------------------------------
--spec client_hello(host(), inet:port_number(), #connection_states{},
+-spec client_hello(host(), inet:port_number(), ssl_record:connection_states(),
#ssl_options{}, integer(), atom(), boolean(), der_cert()) ->
#client_hello{}.
%%
@@ -54,8 +54,7 @@ client_hello(Host, Port, ConnectionStates,
} = SslOpts,
Cache, CacheCb, Renegotiation, OwnCert) ->
Version = tls_record:highest_protocol_version(Versions),
- Pending = ssl_record:pending_connection_state(ConnectionStates, read),
- SecParams = Pending#connection_state.security_parameters,
+ #{security_parameters := SecParams} = ssl_record:pending_connection_state(ConnectionStates, read),
AvailableCipherSuites = ssl_handshake:available_suites(UserSuites, Version),
Extensions = ssl_handshake:client_hello_extensions(Host, Version,
AvailableCipherSuites,
@@ -78,14 +77,14 @@ client_hello(Host, Port, ConnectionStates,
%%--------------------------------------------------------------------
-spec hello(#server_hello{} | #client_hello{}, #ssl_options{},
- #connection_states{} | {inet:port_number(), #session{}, db_handle(),
- atom(), #connection_states{},
+ ssl_record:connection_states() | {inet:port_number(), #session{}, db_handle(),
+ atom(), ssl_record:connection_states(),
binary() | undefined, ssl_cipher:key_algo()},
boolean()) ->
{tls_record:tls_version(), session_id(),
- #connection_states{}, alpn | npn, binary() | undefined}|
+ ssl_record:connection_states(), alpn | npn, binary() | undefined}|
{tls_record:tls_version(), {resumed | new, #session{}},
- #connection_states{}, binary() | undefined,
+ ssl_record:connection_states(), binary() | undefined,
#hello_extensions{}, {ssl_cipher:hash(), ssl_cipher:sign_algo()} | undefined} |
#alert{}.
%%
diff --git a/lib/ssl/src/tls_record.erl b/lib/ssl/src/tls_record.erl
index 9348c8bbdd..5331dd1303 100644
--- a/lib/ssl/src/tls_record.erl
+++ b/lib/ssl/src/tls_record.erl
@@ -32,7 +32,7 @@
-include("ssl_cipher.hrl").
%% Handling of incoming data
--export([get_tls_records/2]).
+-export([get_tls_records/2, init_connection_states/2]).
%% Decoding
-export([decode_cipher_text/3]).
@@ -56,12 +56,28 @@
%%====================================================================
%% Internal application API
%%====================================================================
+%%--------------------------------------------------------------------
+-spec init_connection_states(client | server, one_n_minus_one | zero_n | disabled) ->
+ ssl_record:connection_states().
+%% %
+ %
+%% Description: Creates a connection_states record with appropriate
+%% values for the initial SSL connection setup.
+%%--------------------------------------------------------------------
+init_connection_states(Role, BeastMitigation) ->
+ ConnectionEnd = ssl_record:record_protocol_role(Role),
+ Current = initial_connection_state(ConnectionEnd, BeastMitigation),
+ Pending = ssl_record:empty_connection_state(ConnectionEnd, BeastMitigation),
+ #{current_read => Current,
+ pending_read => Pending,
+ current_write => Current,
+ pending_write => Pending}.
%%--------------------------------------------------------------------
-spec get_tls_records(binary(), binary()) -> {[binary()], binary()} | #alert{}.
%%
-%% Description: Given old buffer and new data from TCP, packs up a records
%% and returns it as a list of tls_compressed binaries also returns leftover
+%% Description: Given old buffer and new data from TCP, packs up a records
%% data
%%--------------------------------------------------------------------
get_tls_records(Data, <<>>) ->
@@ -129,63 +145,61 @@ get_tls_records_aux(Data, Acc) ->
end.
encode_plain_text(Type, Version, Data,
- #connection_states{current_write =
- #connection_state{
- sequence_number = Seq,
- compression_state=CompS0,
- security_parameters=
- #security_parameters{
- cipher_type = ?AEAD,
- compression_algorithm=CompAlg}
- }= WriteState0} = ConnectionStates) ->
+ #{current_write :=
+ #{sequence_number := Seq,
+ compression_state := CompS0,
+ security_parameters :=
+ #security_parameters{
+ cipher_type = ?AEAD,
+ compression_algorithm = CompAlg}
+ }= WriteState0} = ConnectionStates) ->
{Comp, CompS1} = ssl_record:compress(CompAlg, Data, CompS0),
- WriteState1 = WriteState0#connection_state{compression_state = CompS1},
+ WriteState1 = WriteState0#{compression_state => CompS1},
AAD = calc_aad(Type, Version, WriteState1),
{CipherFragment, WriteState} = ssl_record:cipher_aead(Version, Comp, WriteState1, AAD),
CipherText = encode_tls_cipher_text(Type, Version, CipherFragment),
- {CipherText, ConnectionStates#connection_states{current_write = WriteState#connection_state{sequence_number = Seq +1}}};
+ {CipherText, ConnectionStates#{current_write => WriteState#{sequence_number => Seq +1}}};
encode_plain_text(Type, Version, Data,
- #connection_states{current_write =
- #connection_state{
- sequence_number = Seq,
- compression_state=CompS0,
- security_parameters=
- #security_parameters{compression_algorithm=CompAlg}
- }= WriteState0} = ConnectionStates) ->
+ #{current_write :=
+ #{sequence_number := Seq,
+ compression_state := CompS0,
+ security_parameters :=
+ #security_parameters{compression_algorithm = CompAlg}
+ }= WriteState0} = ConnectionStates) ->
{Comp, CompS1} = ssl_record:compress(CompAlg, Data, CompS0),
- WriteState1 = WriteState0#connection_state{compression_state = CompS1},
+ WriteState1 = WriteState0#{compression_state => CompS1},
MacHash = calc_mac_hash(Type, Version, Comp, WriteState1),
{CipherFragment, WriteState} = ssl_record:cipher(Version, Comp, WriteState1, MacHash),
CipherText = encode_tls_cipher_text(Type, Version, CipherFragment),
- {CipherText, ConnectionStates#connection_states{current_write = WriteState#connection_state{sequence_number = Seq +1}}}.
+ {CipherText, ConnectionStates#{current_write => WriteState#{sequence_number => Seq +1}}};
+encode_plain_text(_,_,_, CS) ->
+ exit({cs, CS}).
%%--------------------------------------------------------------------
--spec decode_cipher_text(#ssl_tls{}, #connection_states{}, boolean()) ->
- {#ssl_tls{}, #connection_states{}}| #alert{}.
+-spec decode_cipher_text(#ssl_tls{}, ssl_record:connection_states(), boolean()) ->
+ {#ssl_tls{}, ssl_record:connection_states()}| #alert{}.
%%
%% Description: Decode cipher text
%%--------------------------------------------------------------------
decode_cipher_text(#ssl_tls{type = Type, version = Version,
fragment = CipherFragment} = CipherText,
- #connection_states{current_read =
- #connection_state{
- compression_state = CompressionS0,
- sequence_number = Seq,
- security_parameters=
- #security_parameters{
- cipher_type = ?AEAD,
- compression_algorithm=CompAlg}
- } = ReadState0} = ConnnectionStates0, _) ->
+ #{current_read :=
+ #{compression_state := CompressionS0,
+ sequence_number := Seq,
+ security_parameters :=
+ #security_parameters{
+ cipher_type = ?AEAD,
+ compression_algorithm = CompAlg}
+ } = ReadState0} = ConnnectionStates0, _) ->
AAD = calc_aad(Type, Version, ReadState0),
case ssl_record:decipher_aead(Version, CipherFragment, ReadState0, AAD) of
{PlainFragment, ReadState1} ->
{Plain, CompressionS1} = ssl_record:uncompress(CompAlg,
PlainFragment, CompressionS0),
- ConnnectionStates = ConnnectionStates0#connection_states{
- current_read = ReadState1#connection_state{
- sequence_number = Seq + 1,
- compression_state = CompressionS1}},
+ ConnnectionStates = ConnnectionStates0#{
+ current_read => ReadState1#{sequence_number => Seq + 1,
+ compression_state => CompressionS1}},
{CipherText#ssl_tls{fragment = Plain}, ConnnectionStates};
#alert{} = Alert ->
Alert
@@ -193,13 +207,12 @@ decode_cipher_text(#ssl_tls{type = Type, version = Version,
decode_cipher_text(#ssl_tls{type = Type, version = Version,
fragment = CipherFragment} = CipherText,
- #connection_states{current_read =
- #connection_state{
- compression_state = CompressionS0,
- sequence_number = Seq,
- security_parameters=
- #security_parameters{compression_algorithm=CompAlg}
- } = ReadState0} = ConnnectionStates0, PaddingCheck) ->
+ #{current_read :=
+ #{compression_state := CompressionS0,
+ sequence_number := Seq,
+ security_parameters :=
+ #security_parameters{compression_algorithm = CompAlg}
+ } = ReadState0} = ConnnectionStates0, PaddingCheck) ->
case ssl_record:decipher(Version, CipherFragment, ReadState0, PaddingCheck) of
{PlainFragment, Mac, ReadState1} ->
MacHash = calc_mac_hash(Type, Version, PlainFragment, ReadState1),
@@ -207,10 +220,10 @@ decode_cipher_text(#ssl_tls{type = Type, version = Version,
true ->
{Plain, CompressionS1} = ssl_record:uncompress(CompAlg,
PlainFragment, CompressionS0),
- ConnnectionStates = ConnnectionStates0#connection_states{
- current_read = ReadState1#connection_state{
- sequence_number = Seq + 1,
- compression_state = CompressionS1}},
+ ConnnectionStates = ConnnectionStates0#{
+ current_read => ReadState1#{
+ sequence_number => Seq + 1,
+ compression_state => CompressionS1}},
{CipherText#ssl_tls{fragment = Plain}, ConnnectionStates};
false ->
?ALERT_REC(?FATAL, ?BAD_RECORD_MAC)
@@ -375,6 +388,18 @@ is_acceptable_version(_,_) ->
%%--------------------------------------------------------------------
%%% Internal functions
%%--------------------------------------------------------------------
+initial_connection_state(ConnectionEnd, BeastMitigation) ->
+ #{security_parameters =>
+ ssl_record:initial_security_params(ConnectionEnd),
+ sequence_number => 0,
+ beast_mitigation => BeastMitigation,
+ compression_state => undefined,
+ cipher_state => undefined,
+ mac_secret => undefined,
+ secure_renegotiation => undefined,
+ client_verify_data => undefined,
+ server_verify_data => undefined
+ }.
lowest_list_protocol_version(Ver, []) ->
Ver;
@@ -413,15 +438,15 @@ sufficient_tlsv1_2_crypto_support() ->
proplists:get_bool(sha256, proplists:get_value(hashs, CryptoSupport)).
calc_mac_hash(Type, Version,
- PlainFragment, #connection_state{sequence_number = SeqNo,
- mac_secret = MacSecret,
- security_parameters =
- SecPars}) ->
+ PlainFragment, #{sequence_number := SeqNo,
+ mac_secret := MacSecret,
+ security_parameters:=
+ SecPars}) ->
Length = erlang:iolist_size(PlainFragment),
mac_hash(Version, SecPars#security_parameters.mac_algorithm,
MacSecret, SeqNo, Type,
Length, PlainFragment).
calc_aad(Type, {MajVer, MinVer},
- #connection_state{sequence_number = SeqNo}) ->
+ #{sequence_number := SeqNo}) ->
<<SeqNo:64/integer, ?BYTE(Type), ?BYTE(MajVer), ?BYTE(MinVer)>>.
diff --git a/lib/ssl/test/ssl_basic_SUITE.erl b/lib/ssl/test/ssl_basic_SUITE.erl
index 38341f77aa..8ffee751fc 100644
--- a/lib/ssl/test/ssl_basic_SUITE.erl
+++ b/lib/ssl/test/ssl_basic_SUITE.erl
@@ -40,6 +40,7 @@
-define(SLEEP, 500).
-define(RENEGOTIATION_DISABLE_TIME, 12000).
-define(CLEAN_SESSION_DB, 60000).
+-define(SEC_RENEGOTIATION_TIMEOUT, 30).
%%--------------------------------------------------------------------
%% Common Test interface functions -----------------------------------
@@ -340,7 +341,7 @@ init_per_testcase(TestCase, Config) when TestCase == client_renegotiate;
TestCase == renegotiate_dos_mitigate_passive;
TestCase == renegotiate_dos_mitigate_absolute ->
ssl_test_lib:ct_log_supported_protocol_versions(Config),
- ct:timetrap({seconds, 90}),
+ ct:timetrap({seconds, ?SEC_RENEGOTIATION_TIMEOUT + 5}),
Config;
init_per_testcase(TestCase, Config) when TestCase == psk_cipher_suites;
@@ -440,7 +441,9 @@ init_per_testcase(accept_pool, Config) ->
ssl_test_lib:ct_log_supported_protocol_versions(Config),
Config
end;
-
+init_per_testcase(controller_dies, Config) ->
+ ct:timetrap({seconds, 10}),
+ Config;
init_per_testcase(_TestCase, Config) ->
ssl_test_lib:ct_log_supported_protocol_versions(Config),
ct:timetrap({seconds, 5}),
@@ -4298,7 +4301,7 @@ erlang_ssl_receive(Socket, Data) ->
erlang_ssl_receive(Socket, tl(Data));
Other ->
ct:fail({unexpected_message, Other})
- after ?SLEEP * 3 * test_server:timetrap_scale_factor() ->
+ after timer:seconds(?SEC_RENEGOTIATION_TIMEOUT) * test_server:timetrap_scale_factor() ->
ct:fail({did_not_get, Data})
end.
diff --git a/lib/ssl/test/ssl_npn_hello_SUITE.erl b/lib/ssl/test/ssl_npn_hello_SUITE.erl
index 6ae9efe5e9..69aeea10c5 100644
--- a/lib/ssl/test/ssl_npn_hello_SUITE.erl
+++ b/lib/ssl/test/ssl_npn_hello_SUITE.erl
@@ -135,15 +135,12 @@ create_server_handshake(Npn) ->
}, Vsn).
create_connection_states() ->
- #connection_states{
- pending_read = #connection_state{
- security_parameters = #security_parameters{
+ #{pending_read => #{security_parameters => #security_parameters{
server_random = <<1:256>>,
compression_algorithm = 1,
cipher_suite = ?TLS_DHE_DSS_WITH_DES_CBC_SHA
}
- },
- current_read = #connection_state {
- secure_renegotiation = false
- }
- }.
+ },
+ current_read => #{secure_renegotiation => false
+ }
+ }.
diff --git a/lib/ssl/test/ssl_test_lib.erl b/lib/ssl/test/ssl_test_lib.erl
index fd8af5efaa..a92b978ca9 100644
--- a/lib/ssl/test/ssl_test_lib.erl
+++ b/lib/ssl/test/ssl_test_lib.erl
@@ -807,22 +807,24 @@ send_selected_port(_,_,_) ->
rsa_suites(CounterPart) ->
ECC = is_sane_ecc(CounterPart),
FIPS = is_fips(CounterPart),
+ CryptoSupport = crypto:supports(),
+ Ciphers = proplists:get_value(ciphers, CryptoSupport),
lists:filter(fun({rsa, des_cbc, sha}) when FIPS == true ->
false;
({dhe_rsa, des_cbc, sha}) when FIPS == true ->
false;
- ({rsa, _, _}) ->
- true;
- ({dhe_rsa, _, _}) ->
- true;
- ({ecdhe_rsa, _, _}) when ECC == true ->
- true;
- ({rsa, _, _, _}) ->
- true;
- ({dhe_rsa, _, _,_}) ->
- true;
- ({ecdhe_rsa, _, _,_}) when ECC == true ->
- true;
+ ({rsa, Cipher, _}) ->
+ lists:member(Cipher, Ciphers);
+ ({dhe_rsa, Cipher, _}) ->
+ lists:member(Cipher, Ciphers);
+ ({ecdhe_rsa, Cipher, _}) when ECC == true ->
+ lists:member(Cipher, Ciphers);
+ ({rsa, Cipher, _, _}) ->
+ lists:member(Cipher, Ciphers);
+ ({dhe_rsa, Cipher, _,_}) ->
+ lists:member(Cipher, Ciphers);
+ ({ecdhe_rsa, Cipher, _,_}) when ECC == true ->
+ lists:member(Cipher, Ciphers);
(_) ->
false
end,
diff --git a/lib/ssl/test/ssl_to_openssl_SUITE.erl b/lib/ssl/test/ssl_to_openssl_SUITE.erl
index 83a4dae0a1..9ae032503a 100644
--- a/lib/ssl/test/ssl_to_openssl_SUITE.erl
+++ b/lib/ssl/test/ssl_to_openssl_SUITE.erl
@@ -55,7 +55,9 @@ groups() ->
basic_tests() ->
[basic_erlang_client_openssl_server,
basic_erlang_server_openssl_client,
- expired_session].
+ expired_session,
+ ssl2_erlang_server_openssl_client_comp
+ ].
all_versions_tests() ->
[
@@ -74,7 +76,8 @@ all_versions_tests() ->
ciphers_dsa_signed_certs,
erlang_client_bad_openssl_server,
expired_session,
- ssl2_erlang_server_openssl_client].
+ ssl2_erlang_server_openssl_client
+ ].
alpn_tests() ->
[erlang_client_alpn_openssl_server_alpn,
@@ -117,6 +120,10 @@ init_per_suite(Config0) ->
try crypto:start() of
ok ->
ssl:stop(),
+ application:load(ssl),
+ ct:pal("Before clean: Version: ~p", [ssl:versions()]),
+ application:unset_env(ssl, protocol_version),
+ ct:pal("After clean: Version: ~p", [ssl:versions()]),
ssl:start(),
{ok, _} = make_certs:all(proplists:get_value(data_dir, Config0),
proplists:get_value(priv_dir, Config0)),
@@ -181,7 +188,8 @@ special_init(TestCase, Config)
{ok, Version} = application:get_env(ssl, protocol_version),
check_sane_openssl_renegotaite(Config, Version);
-special_init(ssl2_erlang_server_openssl_client, Config) ->
+special_init(Case, Config) when Case == ssl2_erlang_server_openssl_client;
+ Case == ssl2_erlang_server_openssl_client_comp ->
case ssl_test_lib:supports_ssl_tls_version(sslv2) of
true ->
Config;
@@ -955,8 +963,52 @@ ssl2_erlang_server_openssl_client(Config) when is_list(Config) ->
Data = "From openssl to erlang",
Server = ssl_test_lib:start_server_error([{node, ServerNode}, {port, 0},
+ {from, self()},
+ {options, ServerOpts}]),
+ Port = ssl_test_lib:inet_port(Server),
+
+ Exe = "openssl",
+ Args = ["s_client", "-connect", "localhost:" ++ integer_to_list(Port),
+ "-ssl2", "-msg"],
+
+ OpenSslPort = ssl_test_lib:portable_open_port(Exe, Args),
+ true = port_command(OpenSslPort, Data),
+
+ ct:log("Ports ~p~n", [[erlang:port_info(P) || P <- erlang:ports()]]),
+ receive
+ {'EXIT', OpenSslPort, _} = Exit ->
+ ct:log("Received: ~p ~n", [Exit]),
+ ok
+ end,
+ receive
+ {'EXIT', _, _} = UnkownExit ->
+ Msg = lists:flatten(io_lib:format("Received: ~p ~n", [UnkownExit])),
+ ct:log(Msg),
+ ct:comment(Msg),
+ ok
+ after 0 ->
+ ok
+ end,
+ ssl_test_lib:check_result(Server, {error, {tls_alert, "handshake failure"}}),
+ process_flag(trap_exit, false).
+%%--------------------------------------------------------------------
+ssl2_erlang_server_openssl_client_comp() ->
+ [{doc,"Test that ssl v2 clients are rejected"}].
+
+ssl2_erlang_server_openssl_client_comp(Config) when is_list(Config) ->
+ process_flag(trap_exit, true),
+ ServerOpts = ssl_test_lib:ssl_options(server_opts, Config),
+ V2Compat = proplists:get_value(v2_hello_compatible, Config),
+
+ ServerOpts = ssl_test_lib:ssl_options(server_opts, Config),
+
+ {_, ServerNode, _} = ssl_test_lib:run_where(Config),
+
+ Data = "From openssl to erlang",
+
+ Server = ssl_test_lib:start_server_error([{node, ServerNode}, {port, 0},
{from, self()},
- {options, ServerOpts}]),
+ {options, [{v2_hello_compatible, V2Compat} | ServerOpts]}]),
Port = ssl_test_lib:inet_port(Server),
Exe = "openssl",
diff --git a/lib/stdlib/doc/src/dets.xml b/lib/stdlib/doc/src/dets.xml
index 3b134d00b7..2e4261d72e 100644
--- a/lib/stdlib/doc/src/dets.xml
+++ b/lib/stdlib/doc/src/dets.xml
@@ -391,7 +391,7 @@
<item>
<p><c>{hash, Hash}</c> - Describes which BIF is
used to calculate the hash values of the objects stored in the
- <c>dets</c> table. Possible values of <c>Hash</c>:</p>
+ Dets table. Possible values of <c>Hash</c>:</p>
<list>
<item>
<p><c>hash</c> - Implies that the <c>erlang:hash/2</c> BIF
diff --git a/lib/stdlib/doc/src/ets.xml b/lib/stdlib/doc/src/ets.xml
index 3653c6a632..5f5d2b7f36 100644
--- a/lib/stdlib/doc/src/ets.xml
+++ b/lib/stdlib/doc/src/ets.xml
@@ -369,7 +369,7 @@
variable that in turn is passed to the function.</p>
<p>The parse transform is provided in the <c>ms_transform</c>
module and the source <em>must</em> include
- file <c>ms_transform.hrl</c> in <c>STDLIB</c> for this
+ file <c>ms_transform.hrl</c> in STDLIB for this
pseudo function to work. Failing to include the hrl file in
the source results in a runtime error, not a compile
time error. The include file is easiest included by adding line
@@ -1644,7 +1644,7 @@ is_integer(X), is_integer(Y), X + Y < 4711]]></code>
</taglist>
<p>Whenever option <c>extended_info</c> is used, it
results in a file not readable by versions of ETS before
- that in <c>STDLIB</c> 1.15.1</p>
+ that in STDLIB 1.15.1</p>
<p>If option <c>sync</c> is set to <c>true</c>, it ensures that
the content of the file is written to the disk before
<c>tab2file</c> returns. Defaults to <c>{sync, false}</c>.</p>
@@ -1725,7 +1725,7 @@ is_integer(X), is_integer(Y), X + Y < 4711]]></code>
<p>A tuple <c>{<anno>Major</anno>,<anno>Minor</anno>}</c>
containing the major and
minor version of the file format for ETS table dumps. This
- version field was added beginning with <c>STDLIB</c> 1.5.1.
+ version field was added beginning with STDLIB 1.5.1.
Files dumped with older versions return <c>{0,0}</c> in this
field.</p>
</item>
diff --git a/lib/stdlib/doc/src/notes.xml b/lib/stdlib/doc/src/notes.xml
index d8fec1147f..f0347703e7 100644
--- a/lib/stdlib/doc/src/notes.xml
+++ b/lib/stdlib/doc/src/notes.xml
@@ -526,7 +526,7 @@
</item>
<item>
<p>
- The <c>stdlib</c> reference manual is updated to show
+ The STDLIB reference manual is updated to show
correct information about the return value of
<c>gen_fsm:reply/2</c>.</p>
<p>
@@ -6236,7 +6236,7 @@
documentation for <c>compile</c> on how to provide the key
for encrypting, and the documentation for <c>beam_lib</c>
on how to provide the key for decryption so that tools such
- as the Debugger, <c>xref</c>, or <c>cover</c> can be used.</p>
+ as the Debugger, Xref, or Cover can be used.</p>
<p>The <c>beam_lib:chunks/2</c> functions now accepts an
additional chunk type <c>compile_info</c> to retrieve
the compilation information directly as a term. (Thanks
diff --git a/lib/stdlib/doc/src/proc_lib.xml b/lib/stdlib/doc/src/proc_lib.xml
index 58ca5644cf..da03c39a26 100644
--- a/lib/stdlib/doc/src/proc_lib.xml
+++ b/lib/stdlib/doc/src/proc_lib.xml
@@ -59,9 +59,9 @@
<p>When a process that is started using <c>proc_lib</c> terminates
abnormally (that is, with another exit reason than <c>normal</c>,
<c>shutdown</c>, or <c>{shutdown,Term}</c>), a <em>crash report</em>
- is generated, which is written to terminal by the default <c>SASL</c>
+ is generated, which is written to terminal by the default SASL
event handler. That is, the crash report is normally only visible
- if the <c>SASL</c> application is started; see
+ if the SASL application is started; see
<seealso marker="sasl:sasl_app"><c>sasl(6)</c></seealso> and section
<seealso marker="sasl:error_logging">SASL Error Logging</seealso>
in the SASL User's Guide.</p>
diff --git a/lib/stdlib/doc/src/stdlib_app.xml b/lib/stdlib/doc/src/stdlib_app.xml
index cde73269a8..f857cc394b 100644
--- a/lib/stdlib/doc/src/stdlib_app.xml
+++ b/lib/stdlib/doc/src/stdlib_app.xml
@@ -31,14 +31,14 @@
<app>STDLIB</app>
<appsummary>The STDLIB application.</appsummary>
<description>
- <p>The <c>STDLIB</c> application is mandatory in the sense that the minimal
- system based on Erlang/OTP consists of <c>Kernel</c> and <c>STDLIB</c>.
- The <c>STDLIB</c> application contains no services.</p>
+ <p>The STDLIB application is mandatory in the sense that the minimal
+ system based on Erlang/OTP consists of Kernel and STDLIB.
+ The STDLIB application contains no services.</p>
</description>
<section>
<title>Configuration</title>
- <p>The following configuration parameters are defined for the <c>STDLIB</c>
+ <p>The following configuration parameters are defined for the STDLIB
application. For more information about configuration parameters, see the
<seealso marker="kernel:app"><c>app(4)</c></seealso> module in Kernel.</p>
diff --git a/lib/stdlib/doc/src/timer.xml b/lib/stdlib/doc/src/timer.xml
index 8f2ce36b06..fcaccdb2cb 100644
--- a/lib/stdlib/doc/src/timer.xml
+++ b/lib/stdlib/doc/src/timer.xml
@@ -253,7 +253,7 @@
is needed. This is useful during development, but in a
target system the server is to be started explicitly. Use
configuration parameters for
- <seealso marker="kernel:index"><c>Kernel</c></seealso> for this.</p>
+ <seealso marker="kernel:index">Kernel</seealso> for this.</p>
</desc>
</func>
diff --git a/lib/stdlib/doc/src/unicode_usage.xml b/lib/stdlib/doc/src/unicode_usage.xml
index 7f79ac88a1..efc8b75075 100644
--- a/lib/stdlib/doc/src/unicode_usage.xml
+++ b/lib/stdlib/doc/src/unicode_usage.xml
@@ -274,8 +274,8 @@
marker="stdlib:io"><c>io</c></seealso> module, the file
handling, the <seealso
marker="stdlib:unicode"><c>unicode</c></seealso> module, and
- the bit syntax). Today most modules in <c>Kernel</c> and
- <c>STDLIB</c>, as well as the VM are Unicode-aware.</p>
+ the bit syntax). Today most modules in Kernel and
+ STDLIB, as well as the VM are Unicode-aware.</p>
</item>
<tag>File I/O</tag>
<item>
@@ -765,7 +765,7 @@ Eshell V5.10.1 (abort with ^G)
file system). The Unicode character list is used to denote
filenames or directory names. If the file system content is
listed, you also get Unicode lists as return value. The support
- lies in the <c>Kernel</c> and <c>STDLIB</c> modules, which is why
+ lies in the Kernel and STDLIB modules, which is why
most applications (that does not explicitly require the filenames
to be in the ISO Latin-1 range) benefit from the Unicode support
without change.</p>
@@ -843,7 +843,7 @@ Eshell V5.10.1 (abort with ^G)
<title>Notes About Raw Filenames</title>
<marker id="notes-about-raw-filenames"/>
<p>Raw filenames were introduced together with Unicode filename support
- in <c>ERTS</c> 5.8.2 (Erlang/OTP R14B01). The reason &quot;raw
+ in ERTS 5.8.2 (Erlang/OTP R14B01). The reason &quot;raw
filenames&quot; were introduced in the system was
to be able to represent
filenames, specified in different encodings on the same system,
diff --git a/lib/stdlib/doc/src/zip.xml b/lib/stdlib/doc/src/zip.xml
index de23608046..0b5eac1e16 100644
--- a/lib/stdlib/doc/src/zip.xml
+++ b/lib/stdlib/doc/src/zip.xml
@@ -138,7 +138,7 @@
<p>File information as in
<seealso marker="kernel:file#read_file_info/1">
<c>file:read_file_info/1</c></seealso>
- in <c>Kernel</c></p>
+ in Kernel</p>
</item>
<tag><c>comment</c></tag>
<item>
@@ -345,7 +345,7 @@
prepended to filenames when extracting them from the
zip archive. (Acting like
<seealso marker="kernel:file#set_cwd/1">
- <c>file:set_cwd/1</c></seealso> in <c>Kernel</c>,
+ <c>file:set_cwd/1</c></seealso> in Kernel,
but without changing the global <c>cwd</c> property.)</p>
</item>
</taglist>
@@ -420,7 +420,7 @@
(<c>cwd</c>). This is prepended to filenames when adding them,
although not in the zip archive (acting like
<seealso marker="kernel:file#set_cwd/1">
- <c>file:set_cwd/1</c></seealso> in <c>Kernel</c>, but without
+ <c>file:set_cwd/1</c></seealso> in Kernel, but without
changing the global <c>cwd</c> property.).</p>
</item>
<tag><c>{compress, <anno>What</anno>}</c></tag>
diff --git a/lib/stdlib/src/beam_lib.erl b/lib/stdlib/src/beam_lib.erl
index fe9df601eb..d7ee5c1f5d 100644
--- a/lib/stdlib/src/beam_lib.erl
+++ b/lib/stdlib/src/beam_lib.erl
@@ -55,7 +55,7 @@
-type beam() :: module() | file:filename() | binary().
--type forms() :: [erl_parse:abstract_form()].
+-type forms() :: [erl_parse:abstract_form() | erl_parse:form_info()].
-type abst_code() :: {AbstVersion :: atom(), forms()} | 'no_abstract_code'.
-type dataB() :: binary().
diff --git a/lib/syntax_tools/src/erl_tidy.erl b/lib/syntax_tools/src/erl_tidy.erl
index 5d3fc6f062..9e273dfb84 100644
--- a/lib/syntax_tools/src/erl_tidy.erl
+++ b/lib/syntax_tools/src/erl_tidy.erl
@@ -210,7 +210,7 @@ file__defaults() ->
{verbose, false}].
default_printer() ->
- fun (Tree, Options) -> erl_prettypr:format(Tree, Options) end.
+ fun erl_prettypr:format/2.
%% =====================================================================
%% @spec file(Name) -> ok
@@ -257,7 +257,7 @@ file(Name) ->
%%
%% <dt>{printer, Function}</dt>
%% <dd><ul>
-%% <li>`Function = (syntaxTree()) -> string()'</li>
+%% <li>`Function = (syntaxTree(), [term()]) -> string()'</li>
%% </ul>
%%
%% Specifies a function for prettyprinting Erlang syntax trees.
diff --git a/lib/tools/doc/src/xref_chapter.xml b/lib/tools/doc/src/xref_chapter.xml
index 8b14e03064..872793bdcb 100644
--- a/lib/tools/doc/src/xref_chapter.xml
+++ b/lib/tools/doc/src/xref_chapter.xml
@@ -234,7 +234,7 @@
operand of the intersection operator <c>*</c> is implicitly
converted to the more special type of the second operand.</item>
<tag><c>xref:q(s, "(Mod) tools").</c></tag>
- <item>All modules of the <c>tools</c> application.</item>
+ <item>All modules of the Tools application.</item>
<tag><c>xref:q(s, '"xref_.*" : Mod').</c></tag>
<item>All modules with a name beginning with <c>xref_</c>.</item>
<tag><c>xref:q(s, "# E&nbsp;|&nbsp;X&nbsp;").</c></tag>
@@ -252,9 +252,9 @@
<tag><c>xref:q(s, "XC * (ME - strict ME)").</c></tag>
<item>External calls within some module.</item>
<tag><c>xref:q(s, "E&nbsp;|||&nbsp;kernel").</c></tag>
- <item>All calls within the <c>kernel</c> application. </item>
+ <item>All calls within the Kernel application. </item>
<tag><c>xref:q(s, "closure&nbsp;E&nbsp;|&nbsp;kernel&nbsp;||&nbsp;kernel").</c></tag>
- <item>All direct and indirect calls within the <c>kernel</c>
+ <item>All direct and indirect calls within the Kernel
application. Both the calling and the used functions of
indirect calls are defined in modules of the kernel
application, but it is possible that some functions outside